summaryrefslogtreecommitdiffstats
path: root/docs/pages
diff options
context:
space:
mode:
Diffstat (limited to 'docs/pages')
-rw-r--r--docs/pages/advanced_topics/architecture.rst97
-rw-r--r--docs/pages/advanced_topics/asyncio.rst30
-rw-r--r--docs/pages/advanced_topics/filters.rst169
-rw-r--r--docs/pages/advanced_topics/index.rst18
-rw-r--r--docs/pages/advanced_topics/input_hooks.rst41
-rw-r--r--docs/pages/advanced_topics/key_bindings.rst388
-rw-r--r--docs/pages/advanced_topics/rendering_flow.rst86
-rw-r--r--docs/pages/advanced_topics/rendering_pipeline.rst157
-rw-r--r--docs/pages/advanced_topics/styling.rst320
-rw-r--r--docs/pages/advanced_topics/unit_testing.rst125
-rw-r--r--docs/pages/asking_for_input.rst1034
-rw-r--r--docs/pages/dialogs.rst270
-rw-r--r--docs/pages/full_screen_apps.rst422
-rw-r--r--docs/pages/gallery.rst32
-rw-r--r--docs/pages/getting_started.rst84
-rw-r--r--docs/pages/printing_text.rst274
-rw-r--r--docs/pages/progress_bars.rst248
-rw-r--r--docs/pages/reference.rst393
-rw-r--r--docs/pages/related_projects.rst11
-rw-r--r--docs/pages/tutorials/index.rst10
-rw-r--r--docs/pages/tutorials/repl.rst341
-rw-r--r--docs/pages/upgrading/2.0.rst221
-rw-r--r--docs/pages/upgrading/3.0.rst118
-rw-r--r--docs/pages/upgrading/index.rst11
24 files changed, 4900 insertions, 0 deletions
diff --git a/docs/pages/advanced_topics/architecture.rst b/docs/pages/advanced_topics/architecture.rst
new file mode 100644
index 0000000..c690104
--- /dev/null
+++ b/docs/pages/advanced_topics/architecture.rst
@@ -0,0 +1,97 @@
+.. _architecture:
+
+
+Architecture
+============
+
+TODO: this is a little outdated.
+
+::
+
+ +---------------------------------------------------------------+
+ | InputStream |
+ | =========== |
+ | - Parses the input stream coming from a VT100 |
+ | compatible terminal. Translates it into data input |
+ | and control characters. Calls the corresponding |
+ | handlers of the `InputStreamHandler` instance. |
+ | |
+ | e.g. Translate '\x1b[6~' into "Keys.PageDown", call |
+ | the `feed_key` method of `InputProcessor`. |
+ +---------------------------------------------------------------+
+ |
+ v
+ +---------------------------------------------------------------+
+ | InputStreamHandler |
+ | ================== |
+ | - Has a `Registry` of key bindings, it calls the |
+ | bindings according to the received keys and the |
+ | input mode. |
+ | |
+ | We have Vi and Emacs bindings.
+ +---------------------------------------------------------------+
+ |
+ v
+ +---------------------------------------------------------------+
+ | Key bindings |
+ | ============ |
+ | - Every key binding consists of a function that |
+ | receives an `Event` and usually it operates on |
+ | the `Buffer` object. (It could insert data or |
+ | move the cursor for example.) |
+ +---------------------------------------------------------------+
+ |
+ | Most of the key bindings operate on a `Buffer` object, but
+ | they don't have to. They could also change the visibility
+ | of a menu for instance, or change the color scheme.
+ |
+ v
+ +---------------------------------------------------------------+
+ | Buffer |
+ | ====== |
+ | - Contains a data structure to hold the current |
+ | input (text and cursor position). This class |
+ | implements all text manipulations and cursor |
+ | movements (Like e.g. cursor_forward, insert_char |
+ | or delete_word.) |
+ | |
+ | +-----------------------------------------------+ |
+ | | Document (text, cursor_position) | |
+ | | ================================ | |
+ | | Accessed as the `document` property of the | |
+ | | `Buffer` class. This is a wrapper around the | |
+ | | text and cursor position, and contains | |
+ | | methods for querying this data , e.g. to give | |
+ | | the text before the cursor. | |
+ | +-----------------------------------------------+ |
+ +---------------------------------------------------------------+
+ |
+ | Normally after every key press, the output will be
+ | rendered again. This happens in the event loop of
+ | the `Application` where `Renderer.render` is called.
+ v
+ +---------------------------------------------------------------+
+ | Layout |
+ | ====== |
+ | - When the renderer should redraw, the renderer |
+ | asks the layout what the output should look like. |
+ | - The layout operates on a `Screen` object that he |
+ | received from the `Renderer` and will put the |
+ | toolbars, menus, highlighted content and prompt |
+ | in place. |
+ | |
+ | +-----------------------------------------------+ |
+ | | Menus, toolbars, prompt | |
+ | | ======================= | |
+ | | | |
+ | +-----------------------------------------------+ |
+ +---------------------------------------------------------------+
+ |
+ v
+ +---------------------------------------------------------------+
+ | Renderer |
+ | ======== |
+ | - Calculates the difference between the last output |
+ | and the new one and writes it to the terminal |
+ | output. |
+ +---------------------------------------------------------------+
diff --git a/docs/pages/advanced_topics/asyncio.rst b/docs/pages/advanced_topics/asyncio.rst
new file mode 100644
index 0000000..a692630
--- /dev/null
+++ b/docs/pages/advanced_topics/asyncio.rst
@@ -0,0 +1,30 @@
+.. _asyncio:
+
+Running on top of the `asyncio` event loop
+==========================================
+
+.. note::
+
+ New in prompt_toolkit 3.0. (In prompt_toolkit 2.0 this was possible using a
+ work-around).
+
+Prompt_toolkit 3.0 uses asyncio natively. Calling ``Application.run()`` will
+automatically run the asyncio event loop.
+
+If however you want to run a prompt_toolkit ``Application`` within an asyncio
+environment, you have to call the ``run_async`` method, like this:
+
+.. code:: python
+
+ from prompt_toolkit.application import Application
+
+ async def main():
+ # Define application.
+ application = Application(
+ ...
+ )
+
+ result = await application.run_async()
+ print(result)
+
+ asyncio.get_event_loop().run_until_complete(main())
diff --git a/docs/pages/advanced_topics/filters.rst b/docs/pages/advanced_topics/filters.rst
new file mode 100644
index 0000000..4788769
--- /dev/null
+++ b/docs/pages/advanced_topics/filters.rst
@@ -0,0 +1,169 @@
+.. _filters:
+
+Filters
+=======
+
+Many places in `prompt_toolkit` require a boolean value that can change over
+time. For instance:
+
+- to specify whether a part of the layout needs to be visible or not;
+- or to decide whether a certain key binding needs to be active or not;
+- or the ``wrap_lines`` option of
+ :class:`~prompt_toolkit.layout.BufferControl`;
+- etcetera.
+
+These booleans are often dynamic and can change at runtime. For instance, the
+search toolbar should only be visible when the user is actually searching (when
+the search buffer has the focus). The ``wrap_lines`` option could be changed
+with a certain key binding. And that key binding could only work when the
+default buffer got the focus.
+
+In `prompt_toolkit`, we decided to reduce the amount of state in the whole
+framework, and apply a simple kind of reactive programming to describe the flow
+of these booleans as expressions. (It's one-way only: if a key binding needs to
+know whether it's active or not, it can follow this flow by evaluating an
+expression.)
+
+The (abstract) base class is :class:`~prompt_toolkit.filters.Filter`, which
+wraps an expression that takes no input and evaluates to a boolean. Getting the
+state of a filter is done by simply calling it.
+
+
+An example
+----------
+
+The most obvious way to create such a :class:`~prompt_toolkit.filters.Filter`
+instance is by creating a :class:`~prompt_toolkit.filters.Condition` instance
+from a function. For instance, the following condition will evaluate to
+``True`` when the user is searching:
+
+.. code:: python
+
+ from prompt_toolkit.application.current import get_app
+ from prompt_toolkit.filters import Condition
+
+ is_searching = Condition(lambda: get_app().is_searching)
+
+A different way of writing this, is by using the decorator syntax:
+
+.. code:: python
+
+ from prompt_toolkit.application.current import get_app
+ from prompt_toolkit.filters import Condition
+
+ @Condition
+ def is_searching():
+ return get_app().is_searching
+
+This filter can then be used in a key binding, like in the following snippet:
+
+.. code:: python
+
+ from prompt_toolkit.key_binding import KeyBindings
+
+ kb = KeyBindings()
+
+ @kb.add('c-t', filter=is_searching)
+ def _(event):
+ # Do, something, but only when searching.
+ pass
+
+If we want to know the boolean value of this filter, we have to call it like a
+function:
+
+.. code:: python
+
+ print(is_searching())
+
+
+Built-in filters
+----------------
+
+There are many built-in filters, ready to use. All of them have a lowercase
+name, because they represent the wrapped function underneath, and can be called
+as a function.
+
+- :class:`~prompt_toolkit.filters.app.has_arg`
+- :class:`~prompt_toolkit.filters.app.has_completions`
+- :class:`~prompt_toolkit.filters.app.has_focus`
+- :class:`~prompt_toolkit.filters.app.buffer_has_focus`
+- :class:`~prompt_toolkit.filters.app.has_selection`
+- :class:`~prompt_toolkit.filters.app.has_validation_error`
+- :class:`~prompt_toolkit.filters.app.is_aborting`
+- :class:`~prompt_toolkit.filters.app.is_done`
+- :class:`~prompt_toolkit.filters.app.is_read_only`
+- :class:`~prompt_toolkit.filters.app.is_multiline`
+- :class:`~prompt_toolkit.filters.app.renderer_height_is_known`
+- :class:`~prompt_toolkit.filters.app.in_editing_mode`
+- :class:`~prompt_toolkit.filters.app.in_paste_mode`
+
+- :class:`~prompt_toolkit.filters.app.vi_mode`
+- :class:`~prompt_toolkit.filters.app.vi_navigation_mode`
+- :class:`~prompt_toolkit.filters.app.vi_insert_mode`
+- :class:`~prompt_toolkit.filters.app.vi_insert_multiple_mode`
+- :class:`~prompt_toolkit.filters.app.vi_replace_mode`
+- :class:`~prompt_toolkit.filters.app.vi_selection_mode`
+- :class:`~prompt_toolkit.filters.app.vi_waiting_for_text_object_mode`
+- :class:`~prompt_toolkit.filters.app.vi_digraph_mode`
+
+- :class:`~prompt_toolkit.filters.app.emacs_mode`
+- :class:`~prompt_toolkit.filters.app.emacs_insert_mode`
+- :class:`~prompt_toolkit.filters.app.emacs_selection_mode`
+
+- :class:`~prompt_toolkit.filters.app.is_searching`
+- :class:`~prompt_toolkit.filters.app.control_is_searchable`
+- :class:`~prompt_toolkit.filters.app.vi_search_direction_reversed`
+
+
+Combining filters
+-----------------
+
+Filters can be chained with the ``&`` (AND) and ``|`` (OR) operators and
+negated with the ``~`` (negation) operator.
+
+Some examples:
+
+.. code:: python
+
+ from prompt_toolkit.key_binding import KeyBindings
+ from prompt_toolkit.filters import has_selection, has_selection
+
+ kb = KeyBindings()
+
+ @kb.add('c-t', filter=~is_searching)
+ def _(event):
+ " Do something, but not while searching. "
+ pass
+
+ @kb.add('c-t', filter=has_search | has_selection)
+ def _(event):
+ " Do something, but only when searching or when there is a selection. "
+ pass
+
+
+to_filter
+---------
+
+Finally, in many situations you want your code to expose an API that is able to
+deal with both booleans as well as filters. For instance, when for most users a
+boolean works fine because they don't need to change the value over time, while
+some advanced users want to be able this value to a certain setting or event
+that does changes over time.
+
+In order to handle both use cases, there is a utility called
+:func:`~prompt_toolkit.filters.utils.to_filter`.
+
+This is a function that takes
+either a boolean or an actual :class:`~prompt_toolkit.filters.Filter`
+instance, and always returns a :class:`~prompt_toolkit.filters.Filter`.
+
+.. code:: python
+
+ from prompt_toolkit.filters.utils import to_filter
+
+ # In each of the following three examples, 'f' will be a `Filter`
+ # instance.
+ f = to_filter(True)
+ f = to_filter(False)
+ f = to_filter(Condition(lambda: True))
+ f = to_filter(has_search | has_selection)
diff --git a/docs/pages/advanced_topics/index.rst b/docs/pages/advanced_topics/index.rst
new file mode 100644
index 0000000..4c4fcc9
--- /dev/null
+++ b/docs/pages/advanced_topics/index.rst
@@ -0,0 +1,18 @@
+.. _advanced_topics:
+
+Advanced topics
+===============
+
+.. toctree::
+ :caption: Contents:
+ :maxdepth: 1
+
+ key_bindings
+ styling
+ filters
+ rendering_flow
+ asyncio
+ unit_testing
+ input_hooks
+ architecture
+ rendering_pipeline
diff --git a/docs/pages/advanced_topics/input_hooks.rst b/docs/pages/advanced_topics/input_hooks.rst
new file mode 100644
index 0000000..16c1bf5
--- /dev/null
+++ b/docs/pages/advanced_topics/input_hooks.rst
@@ -0,0 +1,41 @@
+.. _input_hooks:
+
+
+Input hooks
+===========
+
+Input hooks are a tool for inserting an external event loop into the
+prompt_toolkit event loop, so that the other loop can run as long as
+prompt_toolkit (actually asyncio) is idle. This is used in applications like
+`IPython <https://ipython.org/>`_, so that GUI toolkits can display their
+windows while we wait at the prompt for user input.
+
+As a consequence, we will "trampoline" back and forth between two event loops.
+
+.. note::
+
+ This will use a :class:`~asyncio.SelectorEventLoop`, not the :class:
+ :class:`~asyncio.ProactorEventLoop` (on Windows) due to the way the
+ implementation works (contributions are welcome to make that work).
+
+
+.. code:: python
+
+ from prompt_toolkit.eventloop.inputhook import set_eventloop_with_inputhook
+
+ def inputhook(inputhook_context):
+ # At this point, we run the other loop. This loop is supposed to run
+ # until either `inputhook_context.fileno` becomes ready for reading or
+ # `inputhook_context.input_is_ready()` returns True.
+
+ # A good way is to register this file descriptor in this other event
+ # loop with a callback that stops this loop when this FD becomes ready.
+ # There is no need to actually read anything from the FD.
+
+ while True:
+ ...
+
+ set_eventloop_with_inputhook(inputhook)
+
+ # Any asyncio code at this point will now use this new loop, with input
+ # hook installed.
diff --git a/docs/pages/advanced_topics/key_bindings.rst b/docs/pages/advanced_topics/key_bindings.rst
new file mode 100644
index 0000000..8b334fc
--- /dev/null
+++ b/docs/pages/advanced_topics/key_bindings.rst
@@ -0,0 +1,388 @@
+.. _key_bindings:
+
+More about key bindings
+=======================
+
+This page contains a few additional notes about key bindings.
+
+
+Key bindings can be defined as follows by creating a
+:class:`~prompt_toolkit.key_binding.KeyBindings` instance:
+
+
+.. code:: python
+
+ from prompt_toolkit.key_binding import KeyBindings
+
+ bindings = KeyBindings()
+
+ @bindings.add('a')
+ def _(event):
+ " Do something if 'a' has been pressed. "
+ ...
+
+
+ @bindings.add('c-t')
+ def _(event):
+ " Do something if Control-T has been pressed. "
+ ...
+
+.. note::
+
+ :kbd:`c-q` (control-q) and :kbd:`c-s` (control-s) are often captured by the
+ terminal, because they were used traditionally for software flow control.
+ When this is enabled, the application will automatically freeze when
+ :kbd:`c-s` is pressed, until :kbd:`c-q` is pressed. It won't be possible to
+ bind these keys.
+
+ In order to disable this, execute the following command in your shell, or even
+ add it to your `.bashrc`.
+
+ .. code::
+
+ stty -ixon
+
+Key bindings can even consist of a sequence of multiple keys. The binding is
+only triggered when all the keys in this sequence are pressed.
+
+.. code:: python
+
+ @bindings.add('a', 'b')
+ def _(event):
+ " Do something if 'a' is pressed and then 'b' is pressed. "
+ ...
+
+If the user presses only `a`, then nothing will happen until either a second
+key (like `b`) has been pressed or until the timeout expires (see later).
+
+
+List of special keys
+--------------------
+
+Besides literal characters, any of the following keys can be used in a key
+binding:
+
++-------------------+-----------------------------------------+
+| Name + Possible keys |
++===================+=========================================+
+| Escape | :kbd:`escape` |
+| Shift + escape | :kbd:`s-escape` |
++-------------------+-----------------------------------------+
+| Arrows | :kbd:`left`, |
+| | :kbd:`right`, |
+| | :kbd:`up`, |
+| | :kbd:`down` |
++-------------------+-----------------------------------------+
+| Navigation | :kbd:`home`, |
+| | :kbd:`end`, |
+| | :kbd:`delete`, |
+| | :kbd:`pageup`, |
+| | :kbd:`pagedown`, |
+| | :kbd:`insert` |
++-------------------+-----------------------------------------+
+| Control+letter | :kbd:`c-a`, :kbd:`c-b`, :kbd:`c-c`, |
+| | :kbd:`c-d`, :kbd:`c-e`, :kbd:`c-f`, |
+| | :kbd:`c-g`, :kbd:`c-h`, :kbd:`c-i`, |
+| | :kbd:`c-j`, :kbd:`c-k`, :kbd:`c-l`, |
+| | |
+| | :kbd:`c-m`, :kbd:`c-n`, :kbd:`c-o`, |
+| | :kbd:`c-p`, :kbd:`c-q`, :kbd:`c-r`, |
+| | :kbd:`c-s`, :kbd:`c-t`, :kbd:`c-u`, |
+| | :kbd:`c-v`, :kbd:`c-w`, :kbd:`c-x`, |
+| | |
+| | :kbd:`c-y`, :kbd:`c-z` |
++-------------------+-----------------------------------------+
+| Control + number | :kbd:`c-1`, :kbd:`c-2`, :kbd:`c-3`, |
+| | :kbd:`c-4`, :kbd:`c-5`, :kbd:`c-6`, |
+| | :kbd:`c-7`, :kbd:`c-8`, :kbd:`c-9`, |
+| | :kbd:`c-0` |
++-------------------+-----------------------------------------+
+| Control + arrow | :kbd:`c-left`, |
+| | :kbd:`c-right`, |
+| | :kbd:`c-up`, |
+| | :kbd:`c-down` |
++-------------------+-----------------------------------------+
+| Other control | :kbd:`c-@`, |
+| keys | :kbd:`c-\\`, |
+| | :kbd:`c-]`, |
+| | :kbd:`c-^`, |
+| | :kbd:`c-_`, |
+| | :kbd:`c-delete` |
++-------------------+-----------------------------------------+
+| Shift + arrow | :kbd:`s-left`, |
+| | :kbd:`s-right`, |
+| | :kbd:`s-up`, |
+| | :kbd:`s-down` |
++-------------------+-----------------------------------------+
+| Control + Shift + | :kbd:`c-s-left`, |
+| arrow | :kbd:`c-s-right`, |
+| | :kbd:`c-s-up`, |
+| | :kbd:`c-s-down` |
++-------------------+-----------------------------------------+
+| Other shift | :kbd:`s-delete`, |
+| keys | :kbd:`s-tab` |
++-------------------+-----------------------------------------+
+| F-keys | :kbd:`f1`, :kbd:`f2`, :kbd:`f3`, |
+| | :kbd:`f4`, :kbd:`f5`, :kbd:`f6`, |
+| | :kbd:`f7`, :kbd:`f8`, :kbd:`f9`, |
+| | :kbd:`f10`, :kbd:`f11`, :kbd:`f12`, |
+| | |
+| | :kbd:`f13`, :kbd:`f14`, :kbd:`f15`, |
+| | :kbd:`f16`, :kbd:`f17`, :kbd:`f18`, |
+| | :kbd:`f19`, :kbd:`f20`, :kbd:`f21`, |
+| | :kbd:`f22`, :kbd:`f23`, :kbd:`f24` |
++-------------------+-----------------------------------------+
+
+There are a couple of useful aliases as well:
+
++-------------------+-------------------+
+| :kbd:`c-h` | :kbd:`backspace` |
++-------------------+-------------------+
+| :kbd:`c-@` | :kbd:`c-space` |
++-------------------+-------------------+
+| :kbd:`c-m` | :kbd:`enter` |
++-------------------+-------------------+
+| :kbd:`c-i` | :kbd:`tab` |
++-------------------+-------------------+
+
+.. note::
+
+ Note that the supported keys are limited to what typical VT100 terminals
+ offer. Binding :kbd:`c-7` (control + number 7) for instance is not
+ supported.
+
+
+Binding alt+something, option+something or meta+something
+---------------------------------------------------------
+
+Vt100 terminals translate the alt key into a leading :kbd:`escape` key.
+For instance, in order to handle :kbd:`alt-f`, we have to handle
+:kbd:`escape` + :kbd:`f`. Notice that we receive this as two individual keys.
+This means that it's exactly the same as first typing :kbd:`escape` and then
+typing :kbd:`f`. Something this alt-key is also known as option or meta.
+
+In code that looks as follows:
+
+.. code:: python
+
+ @bindings.add('escape', 'f')
+ def _(event):
+ " Do something if alt-f or meta-f have been pressed. "
+
+
+Wildcards
+---------
+
+Sometimes you want to catch any key that follows after a certain key stroke.
+This is possible by binding the '<any>' key:
+
+.. code:: python
+
+ @bindings.add('a', '<any>')
+ def _(event):
+ ...
+
+This will handle `aa`, `ab`, `ac`, etcetera. The key binding can check the
+`event` object for which keys exactly have been pressed.
+
+
+Attaching a filter (condition)
+------------------------------
+
+In order to enable a key binding according to a certain condition, we have to
+pass it a :class:`~prompt_toolkit.filters.Filter`, usually a
+:class:`~prompt_toolkit.filters.Condition` instance. (:ref:`Read more about
+filters <filters>`.)
+
+.. code:: python
+
+ from prompt_toolkit.filters import Condition
+
+ @Condition
+ def is_active():
+ " Only activate key binding on the second half of each minute. "
+ return datetime.datetime.now().second > 30
+
+ @bindings.add('c-t', filter=is_active)
+ def _(event):
+ # ...
+ pass
+
+The key binding will be ignored when this condition is not satisfied.
+
+
+ConditionalKeyBindings: Disabling a set of key bindings
+-------------------------------------------------------
+
+Sometimes you want to enable or disable a whole set of key bindings according
+to a certain condition. This is possible by wrapping it in a
+:class:`~prompt_toolkit.key_binding.ConditionalKeyBindings` object.
+
+.. code:: python
+
+ from prompt_toolkit.key_binding import ConditionalKeyBindings
+
+ @Condition
+ def is_active():
+ " Only activate key binding on the second half of each minute. "
+ return datetime.datetime.now().second > 30
+
+ bindings = ConditionalKeyBindings(
+ key_bindings=my_bindings,
+ filter=is_active)
+
+If the condition is not satisfied, all the key bindings in `my_bindings` above
+will be ignored.
+
+
+Merging key bindings
+--------------------
+
+Sometimes you have different parts of your application generate a collection of
+key bindings. It is possible to merge them together through the
+:func:`~prompt_toolkit.key_binding.merge_key_bindings` function. This is
+preferred above passing a :class:`~prompt_toolkit.key_binding.KeyBindings`
+object around and having everyone populate it.
+
+.. code:: python
+
+ from prompt_toolkit.key_binding import merge_key_bindings
+
+ bindings = merge_key_bindings([
+ bindings1,
+ bindings2,
+ ])
+
+
+Eager
+-----
+
+Usually not required, but if ever you have to override an existing key binding,
+the `eager` flag can be useful.
+
+Suppose that there is already an active binding for `ab` and you'd like to add
+a second binding that only handles `a`. When the user presses only `a`,
+prompt_toolkit has to wait for the next key press in order to know which
+handler to call.
+
+By passing the `eager` flag to this second binding, we are actually saying that
+prompt_toolkit shouldn't wait for longer matches when all the keys in this key
+binding are matched. So, if `a` has been pressed, this second binding will be
+called, even if there's an active `ab` binding.
+
+.. code:: python
+
+ @bindings.add('a', 'b')
+ def binding_1(event):
+ ...
+
+ @bindings.add('a', eager=True)
+ def binding_2(event):
+ ...
+
+This is mainly useful in order to conditionally override another binding.
+
+Asyncio coroutines
+------------------
+
+Key binding handlers can be asyncio coroutines.
+
+.. code:: python
+
+ from prompt_toolkit.application import in_terminal
+
+ @bindings.add('x')
+ async def print_hello(event):
+ """
+ Pressing 'x' will print 5 times "hello" in the background above the
+ prompt.
+ """
+ for i in range(5):
+ # Print hello above the current prompt.
+ async with in_terminal():
+ print('hello')
+
+ # Sleep, but allow further input editing in the meantime.
+ await asyncio.sleep(1)
+
+If the user accepts the input on the prompt, while this coroutine is not yet
+finished , an `asyncio.CancelledError` exception will be thrown in this
+coroutine.
+
+
+Timeouts
+--------
+
+There are two timeout settings that effect the handling of keys.
+
+- ``Application.ttimeoutlen``: Like Vim's `ttimeoutlen` option.
+ When to flush the input (For flushing escape keys.) This is important on
+ terminals that use vt100 input. We can't distinguish the escape key from for
+ instance the left-arrow key, if we don't know what follows after "\x1b". This
+ little timer will consider "\x1b" to be escape if nothing did follow in this
+ time span. This seems to work like the `ttimeoutlen` option in Vim.
+
+- ``KeyProcessor.timeoutlen``: like Vim's `timeoutlen` option.
+ This can be `None` or a float. For instance, suppose that we have a key
+ binding AB and a second key binding A. If the uses presses A and then waits,
+ we don't handle this binding yet (unless it was marked 'eager'), because we
+ don't know what will follow. This timeout is the maximum amount of time that
+ we wait until we call the handlers anyway. Pass `None` to disable this
+ timeout.
+
+
+Recording macros
+----------------
+
+Both Emacs and Vi mode allow macro recording. By default, all key presses are
+recorded during a macro, but it is possible to exclude certain keys by setting
+the `record_in_macro` parameter to `False`:
+
+.. code:: python
+
+ @bindings.add('c-t', record_in_macro=False)
+ def _(event):
+ # ...
+ pass
+
+
+Creating new Vi text objects and operators
+------------------------------------------
+
+We tried very hard to ship prompt_toolkit with as many as possible Vi text
+objects and operators, so that text editing feels as natural as possible to Vi
+users.
+
+If you wish to create a new text object or key binding, that is actually
+possible. Check the `custom-vi-operator-and-text-object.py` example for more
+information.
+
+
+Handling SIGINT
+---------------
+
+The SIGINT Unix signal can be handled by binding ``<sigint>``. For instance:
+
+.. code:: python
+
+ @bindings.add('<sigint>')
+ def _(event):
+ # ...
+ pass
+
+This will handle a SIGINT that was sent by an external application into the
+process. Handling control-c should be done by binding ``c-c``. (The terminal
+input is set to raw mode, which means that a ``c-c`` won't be translated into a
+SIGINT.)
+
+For a ``PromptSession``, there is a default binding for ``<sigint>`` that
+corresponds to ``c-c``: it will exit the prompt, raising a
+``KeyboardInterrupt`` exception.
+
+
+Processing `.inputrc`
+---------------------
+
+GNU readline can be configured using an `.inputrc` configuration file. This file
+contains key bindings as well as certain settings. Right now, prompt_toolkit
+doesn't support `.inputrc`, but it should be possible in the future.
diff --git a/docs/pages/advanced_topics/rendering_flow.rst b/docs/pages/advanced_topics/rendering_flow.rst
new file mode 100644
index 0000000..0cd12c7
--- /dev/null
+++ b/docs/pages/advanced_topics/rendering_flow.rst
@@ -0,0 +1,86 @@
+.. _rendering_flow:
+
+The rendering flow
+==================
+
+Understanding the rendering flow is important for understanding how
+:class:`~prompt_toolkit.layout.Container` and
+:class:`~prompt_toolkit.layout.UIControl` objects interact. We will demonstrate
+it by explaining the flow around a
+:class:`~prompt_toolkit.layout.BufferControl`.
+
+.. note::
+
+ A :class:`~prompt_toolkit.layout.BufferControl` is a
+ :class:`~prompt_toolkit.layout.UIControl` for displaying the content of a
+ :class:`~prompt_toolkit.buffer.Buffer`. A buffer is the object that holds
+ any editable region of text. Like all controls, it has to be wrapped into a
+ :class:`~prompt_toolkit.layout.Window`.
+
+Let's take the following code:
+
+.. code:: python
+
+ from prompt_toolkit.enums import DEFAULT_BUFFER
+ from prompt_toolkit.layout.containers import Window
+ from prompt_toolkit.layout.controls import BufferControl
+ from prompt_toolkit.buffer import Buffer
+
+ b = Buffer(name=DEFAULT_BUFFER)
+ Window(content=BufferControl(buffer=b))
+
+What happens when a :class:`~prompt_toolkit.renderer.Renderer` objects wants a
+:class:`~prompt_toolkit.layout.Container` to be rendered on a certain
+:class:`~prompt_toolkit.layout.screen.Screen`?
+
+The visualization happens in several steps:
+
+1. The :class:`~prompt_toolkit.renderer.Renderer` calls the
+ :meth:`~prompt_toolkit.layout.Container.write_to_screen` method
+ of a :class:`~prompt_toolkit.layout.Container`.
+ This is a request to paint the layout in a rectangle of a certain size.
+
+ The :class:`~prompt_toolkit.layout.Window` object then requests
+ the :class:`~prompt_toolkit.layout.UIControl` to create a
+ :class:`~prompt_toolkit.layout.UIContent` instance (by calling
+ :meth:`~prompt_toolkit.layout.UIControl.create_content`).
+ The user control receives the dimensions of the window, but can still
+ decide to create more or less content.
+
+ Inside the :meth:`~prompt_toolkit.layout.UIControl.create_content`
+ method of :class:`~prompt_toolkit.layout.UIControl`, there are several
+ steps:
+
+ 2. First, the buffer's text is passed to the
+ :meth:`~prompt_toolkit.lexers.Lexer.lex_document` method of a
+ :class:`~prompt_toolkit.lexers.Lexer`. This returns a function which
+ for a given line number, returns a "formatted text list" for that line
+ (that's a list of ``(style_string, text)`` tuples).
+
+ 3. This list is passed through a list of
+ :class:`~prompt_toolkit.layout.processors.Processor` objects.
+ Each processor can do a transformation for each line.
+ (For instance, they can insert or replace some text, highlight the
+ selection or search string, etc...)
+
+ 4. The :class:`~prompt_toolkit.layout.UIControl` returns a
+ :class:`~prompt_toolkit.layout.UIContent` instance which
+ generates such a token lists for each lines.
+
+The :class:`~prompt_toolkit.layout.Window` receives the
+:class:`~prompt_toolkit.layout.UIContent` and then:
+
+5. It calculates the horizontal and vertical scrolling, if applicable
+ (if the content would take more space than what is available).
+
+6. The content is copied to the correct absolute position
+ :class:`~prompt_toolkit.layout.screen.Screen`, as requested by the
+ :class:`~prompt_toolkit.renderer.Renderer`. While doing this, the
+ :class:`~prompt_toolkit.layout.Window` can possible wrap the
+ lines, if line wrapping was configured.
+
+Note that this process is lazy: if a certain line is not displayed in the
+:class:`~prompt_toolkit.layout.Window`, then it is not requested
+from the :class:`~prompt_toolkit.layout.UIContent`. And from there, the line is
+not passed through the processors or even asked from the
+:class:`~prompt_toolkit.lexers.Lexer`.
diff --git a/docs/pages/advanced_topics/rendering_pipeline.rst b/docs/pages/advanced_topics/rendering_pipeline.rst
new file mode 100644
index 0000000..6b38ba5
--- /dev/null
+++ b/docs/pages/advanced_topics/rendering_pipeline.rst
@@ -0,0 +1,157 @@
+The rendering pipeline
+======================
+
+This document is an attempt to describe how prompt_toolkit applications are
+rendered. It's a complex but logical process that happens more or less after
+every key stroke. We'll go through all the steps from the point where the user
+hits a key, until the character appears on the screen.
+
+
+Waiting for user input
+----------------------
+
+Most of the time when a prompt_toolkit application is running, it is idle. It's
+sitting in the event loop, waiting for some I/O to happen. The most important
+kind of I/O we're waiting for is user input. So, within the event loop, we have
+one file descriptor that represents the input device from where we receive key
+presses. The details are a little different between operating systems, but it
+comes down to a selector (like select or epoll) which waits for one or more
+file descriptor. The event loop is then responsible for calling the appropriate
+feedback when one of the file descriptors becomes ready.
+
+It is like that when the user presses a key: the input device becomes ready for
+reading, and the appropriate callback is called. This is the `read_from_input`
+function somewhere in `application.py`. It will read the input from the
+:class:`~prompt_toolkit.input.Input` object, by calling
+:meth:`~prompt_toolkit.input.Input.read_keys`.
+
+
+Reading the user input
+----------------------
+
+The actual reading is also operating system dependent. For instance, on a Linux
+machine with a vt100 terminal, we read the input from the pseudo terminal
+device, by calling `os.read`. This however returns a sequence of bytes. There
+are two difficulties:
+
+- The input could be UTF-8 encoded, and there is always the possibility that we
+ receive only a portion of a multi-byte character.
+- vt100 key presses consist of multiple characters. For instance the "left
+ arrow" would generate something like ``\x1b[D``. It could be that when we
+ read this input stream, that at some point we only get the first part of such
+ a key press, and we have to wait for the rest to arrive.
+
+Both problems are implemented using state machines.
+
+- The UTF-8 problem is solved using `codecs.getincrementaldecoder`, which is an
+ object in which we can feed the incoming bytes, and it will only return the
+ complete UTF-8 characters that we have so far. The rest is buffered for the
+ next read operation.
+- Vt100 parsing is solved by the
+ :class:`~prompt_toolkit.input.vt100_parser.Vt100Parser` state machine. The
+ state machine itself is implemented using a generator. We feed the incoming
+ characters to the generator, and it will call the appropriate callback for
+ key presses once they arrive. One thing here to keep in mind is that the
+ characters for some key presses are a prefix of other key presses, like for
+ instance, escape (``\x1b``) is a prefix of the left arrow key (``\x1b[D``).
+ So for those, we don't know what key is pressed until more data arrives or
+ when the input is flushed because of a timeout.
+
+For Windows systems, it's a little different. Here we use Win32 syscalls for
+reading the console input.
+
+
+Processing the key presses
+--------------------------
+
+The ``Key`` objects that we receive are then passed to the
+:class:`~prompt_toolkit.key_binding.key_processor.KeyProcessor` for matching
+against the currently registered and active key bindings.
+
+This is another state machine, because key bindings are linked to a sequence of
+key presses. We cannot call the handler until all of these key presses arrive
+and until we're sure that this combination is not a prefix of another
+combination. For instance, sometimes people bind ``jj`` (a double ``j`` key
+press) to ``esc`` in Vi mode. This is convenient, but we want to make sure that
+pressing ``j`` once only, followed by a different key will still insert the
+``j`` character as usual.
+
+Now, there are hundreds of key bindings in prompt_toolkit (in ptpython, right
+now we have 585 bindings). This is mainly caused by the way that Vi key
+bindings are generated. In order to make this efficient, we keep a cache of
+handlers which match certain sequences of keys.
+
+Of course, key bindings also have filters attached for enabling/disabling them.
+So, if at some point, we get a list of handlers from that cache, we still have
+to discard the inactive bindings. Luckily, many bindings share exactly the same
+filter, and we have to check every filter only once.
+
+:ref:`Read more about key bindings ...<key_bindings>`
+
+
+The key handlers
+----------------
+
+Once a key sequence is matched, the handler is called. This can do things like
+text manipulation, changing the focus or anything else.
+
+After the handler is called, the user interface is invalidated and rendered
+again.
+
+
+Rendering the user interface
+----------------------------
+
+The rendering is pretty complex for several reasons:
+
+- We have to compute the dimensions of all user interface elements. Sometimes
+ they are given, but sometimes this requires calculating the size of
+ :class:`~prompt_toolkit.layout.UIControl` objects.
+- It needs to be very efficient, because it's something that happens on every
+ single key stroke.
+- We should output as little as possible on stdout in order to reduce latency
+ on slow network connections and older terminals.
+
+
+Calculating the total UI height
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Unless the application is a full screen application, we have to know how much
+vertical space is going to be consumed. The total available width is given, but
+the vertical space is more dynamic. We do this by asking the root
+:class:`~prompt_toolkit.layout.Container` object to calculate its preferred
+height. If this is a :class:`~prompt_toolkit.layout.VSplit` or
+:class:`~prompt_toolkit.layout.HSplit` then this involves recursively querying
+the child objects for their preferred widths and heights and either summing it
+up, or taking maximum values depending on the actual layout.
+In the end, we get the preferred height, for which we make sure it's at least
+the distance from the cursor position to the bottom of the screen.
+
+
+Painting to the screen
+^^^^^^^^^^^^^^^^^^^^^^
+
+Then we create a :class:`~prompt_toolkit.layout.screen.Screen` object. This is
+like a canvas on which user controls can paint their content. The
+:meth:`~prompt_toolkit.layout.Container.write_to_screen` method of the root
+`Container` is called with the screen dimensions. This will call recursively
+:meth:`~prompt_toolkit.layout.Container.write_to_screen` methods of nested
+child containers, each time passing smaller dimensions while we traverse what
+is a tree of `Container` objects.
+
+The most inner containers are :class:`~prompt_toolkit.layout.Window` objects,
+they will do the actual painting of the
+:class:`~prompt_toolkit.layout.UIControl` to the screen. This involves line
+wrapping the `UIControl`'s text and maybe scrolling the content horizontally or
+vertically.
+
+
+Rendering to stdout
+^^^^^^^^^^^^^^^^^^^
+
+Finally, when we have painted the screen, this needs to be rendered to stdout.
+This is done by taking the difference of the previously rendered screen and the
+new one. The algorithm that we have is heavily optimized to compute this
+difference as quickly as possible, and call the appropriate output functions of
+the :class:`~prompt_toolkit.output.Output` back-end. At the end, it will
+position the cursor in the right place.
diff --git a/docs/pages/advanced_topics/styling.rst b/docs/pages/advanced_topics/styling.rst
new file mode 100644
index 0000000..55cf6ee
--- /dev/null
+++ b/docs/pages/advanced_topics/styling.rst
@@ -0,0 +1,320 @@
+.. _styling:
+
+More about styling
+==================
+
+This page will attempt to explain in more detail how to use styling in
+prompt_toolkit.
+
+To some extent, it is very similar to how `Pygments <http://pygments.org/>`_
+styling works.
+
+
+Style strings
+-------------
+
+Many user interface controls, like :class:`~prompt_toolkit.layout.Window`
+accept a ``style`` argument which can be used to pass the formatting as a
+string. For instance, we can select a foreground color:
+
+- ``"fg:ansired"`` (ANSI color palette)
+- ``"fg:ansiblue"`` (ANSI color palette)
+- ``"fg:#ffaa33"`` (hexadecimal notation)
+- ``"fg:darkred"`` (named color)
+
+Or a background color:
+
+- ``"bg:ansired"`` (ANSI color palette)
+- ``"bg:#ffaa33"`` (hexadecimal notation)
+
+Or we can add one of the following flags:
+
+- ``"bold"``
+- ``"italic"``
+- ``"underline"``
+- ``"blink"``
+- ``"reverse"`` (reverse foreground and background on the terminal.)
+- ``"hidden"``
+
+Or their negative variants:
+
+- ``"nobold"``
+- ``"noitalic"``
+- ``"nounderline"``
+- ``"noblink"``
+- ``"noreverse"``
+- ``"nohidden"``
+
+All of these formatting options can be combined as well:
+
+- ``"fg:ansiyellow bg:black bold underline"``
+
+The style string can be given to any user control directly, or to a
+:class:`~prompt_toolkit.layout.Container` object from where it will propagate
+to all its children. A style defined by a parent user control can be overridden
+by any of its children. The parent can for instance say ``style="bold
+underline"`` where a child overrides this style partly by specifying
+``style="nobold bg:ansired"``.
+
+.. note::
+
+ These styles are actually compatible with
+ `Pygments <http://pygments.org/>`_ styles, with additional support for
+ `reverse` and `blink`. Further, we ignore flags like `roman`, `sans`,
+ `mono` and `border`.
+
+The following ANSI colors are available (both for foreground and background):
+
+.. code::
+
+ # Low intensity, dark. (One or two components 0x80, the other 0x00.)
+ ansiblack, ansired, ansigreen, ansiyellow, ansiblue
+ ansimagenta, ansicyan, ansigray
+
+ # High intensity, bright.
+ ansibrightblack, ansibrightred, ansibrightgreen, ansibrightyellow
+ ansibrightblue, ansibrightmagenta, ansibrightcyan, ansiwhite
+
+In order to know which styles are actually used in an application, it is
+possible to call :meth:`~Application.get_used_style_strings`, when the
+application is done.
+
+
+Class names
+-----------
+
+Like we do for web design, it is not a good habit to specify all styling
+inline. Instead, we can attach class names to UI controls and have a style
+sheet that refers to these class names. The
+:class:`~prompt_toolkit.styles.Style` can be passed as an argument to the
+:class:`~prompt_toolkit.application.Application`.
+
+.. code:: python
+
+ from prompt_toolkit.layout import VSplit, Window
+ from prompt_toolkit.styles import Style
+
+ layout = VSplit([
+ Window(BufferControl(...), style='class:left'),
+ HSplit([
+ Window(BufferControl(...), style='class:top'),
+ Window(BufferControl(...), style='class:bottom'),
+ ], style='class:right')
+ ])
+
+ style = Style([
+ ('left', 'bg:ansired'),
+ ('top', 'fg:#00aaaa'),
+ ('bottom', 'underline bold'),
+ ])
+
+It is possible to add multiple class names to an element. That way we'll
+combine the styling for these class names. Multiple classes can be passed by
+using a comma separated list, or by using the ``class:`` prefix twice.
+
+.. code:: python
+
+ Window(BufferControl(...), style='class:left,bottom'),
+ Window(BufferControl(...), style='class:left class:bottom'),
+
+It is possible to combine class names and inline styling. The order in which
+the class names and inline styling is specified determines the order of
+priority. In the following example for instance, we'll take first the style of
+the "header" class, and then override that with a red background color.
+
+.. code:: python
+
+ Window(BufferControl(...), style='class:header bg:red'),
+
+
+Dot notation in class names
+---------------------------
+
+The dot operator has a special meaning in a class name. If we write:
+``style="class:a.b.c"``, then this will actually expand to the following:
+``style="class:a class:a.b class:a.b.c"``.
+
+This is mainly added for `Pygments <http://pygments.org/>`_ lexers, which
+specify "Tokens" like this, but it's useful in other situations as well.
+
+
+Multiple classes in a style sheet
+---------------------------------
+
+A style sheet can be more complex as well. We can for instance specify two
+class names. The following will underline the left part within the header, or
+whatever has both the class "left" and the class "header" (the order doesn't
+matter).
+
+.. code:: python
+
+ style = Style([
+ ('header left', 'underline'),
+ ])
+
+
+If you have a dotted class, then it's required to specify the whole path in the
+style sheet (just typing ``c`` or ``b.c`` doesn't work if the class is
+``a.b.c``):
+
+.. code:: python
+
+ style = Style([
+ ('a.b.c', 'underline'),
+ ])
+
+It is possible to combine this:
+
+.. code:: python
+
+ style = Style([
+ ('header body left.text', 'underline'),
+ ])
+
+
+Evaluation order of rules in a style sheet
+------------------------------------------
+
+The style is determined as follows:
+
+- First, we concatenate all the style strings from the root control through all
+ the parents to the child in one big string. (Things at the right take
+ precedence anyway.)
+
+ E.g: ``class:body bg:#aaaaaa #000000 class:header.focused class:left.text.highlighted underline``
+
+- Then we go through this style from left to right, starting from the default
+ style. Inline styling is applied directly.
+
+ If we come across a class name, then we generate all combinations of the
+ class names that we collected so far (this one and all class names to the
+ left), and for each combination which includes the new class name, we look
+ for matching rules in our style sheet. All these rules are then applied
+ (later rules have higher priority).
+
+ If we find a dotted class name, this will be expanded in the individual names
+ (like ``class:left class:left.text class:left.text.highlighted``), and all
+ these are applied like any class names.
+
+- Then this final style is applied to this user interface element.
+
+
+Using a dictionary as a style sheet
+-----------------------------------
+
+The order of the rules in a style sheet is meaningful, so typically, we use a
+list of tuples to specify the style. But is also possible to use a dictionary
+as a style sheet. This makes sense for Python 3.6, where dictionaries remember
+their ordering. An ``OrderedDict`` works as well.
+
+.. code:: python
+
+ from prompt_toolkit.styles import Style
+
+ style = Style.from_dict({
+ 'header body left.text': 'underline',
+ })
+
+
+Loading a style from Pygments
+-----------------------------
+
+`Pygments <http://pygments.org/>`_ has a slightly different notation for
+specifying styles, because it maps styling to Pygments "Tokens". A Pygments
+style can however be loaded and used as follows:
+
+.. code:: python
+
+ from prompt_toolkit.styles.pygments import style_from_pygments_cls
+ from pygments.styles import get_style_by_name
+
+ style = style_from_pygments_cls(get_style_by_name('monokai'))
+
+
+Merging styles together
+-----------------------
+
+Multiple :class:`~prompt_toolkit.styles.Style` objects can be merged together as
+follows:
+
+.. code:: python
+
+ from prompt_toolkit.styles import merge_styles
+
+ style = merge_styles([
+ style1,
+ style2,
+ style3
+ ])
+
+
+Color depths
+------------
+
+There are four different levels of color depths available:
+
++--------+-----------------+-----------------------------+---------------------------------+
+| 1 bit | Black and white | ``ColorDepth.DEPTH_1_BIT`` | ``ColorDepth.MONOCHROME`` |
++--------+-----------------+-----------------------------+---------------------------------+
+| 4 bit | ANSI colors | ``ColorDepth.DEPTH_4_BIT`` | ``ColorDepth.ANSI_COLORS_ONLY`` |
++--------+-----------------+-----------------------------+---------------------------------+
+| 8 bit | 256 colors | ``ColorDepth.DEPTH_8_BIT`` | ``ColorDepth.DEFAULT`` |
++--------+-----------------+-----------------------------+---------------------------------+
+| 24 bit | True colors | ``ColorDepth.DEPTH_24_BIT`` | ``ColorDepth.TRUE_COLOR`` |
++--------+-----------------+-----------------------------+---------------------------------+
+
+By default, 256 colors are used, because this is what most terminals support
+these days. If the ``TERM`` environment variable is set to ``linux`` or
+``eterm-color``, then only ANSI colors are used, because of these terminals. The 24
+bit true color output needs to be enabled explicitly. When 4 bit color output
+is chosen, all colors will be mapped to the closest ANSI color.
+
+Setting the default color depth for any prompt_toolkit application can be done
+by setting the ``PROMPT_TOOLKIT_COLOR_DEPTH`` environment variable. You could
+for instance copy the following into your `.bashrc` file.
+
+.. code:: shell
+
+ # export PROMPT_TOOLKIT_COLOR_DEPTH=DEPTH_1_BIT
+ export PROMPT_TOOLKIT_COLOR_DEPTH=DEPTH_4_BIT
+ # export PROMPT_TOOLKIT_COLOR_DEPTH=DEPTH_8_BIT
+ # export PROMPT_TOOLKIT_COLOR_DEPTH=DEPTH_24_BIT
+
+An application can also decide to set the color depth manually by passing a
+:class:`~prompt_toolkit.output.ColorDepth` value to the
+:class:`~prompt_toolkit.application.Application` object:
+
+.. code:: python
+
+ from prompt_toolkit.output.color_depth import ColorDepth
+
+ app = Application(
+ color_depth=ColorDepth.ANSI_COLORS_ONLY,
+ # ...
+ )
+
+
+Style transformations
+---------------------
+
+Prompt_toolkit supports a way to apply certain transformations to the styles
+near the end of the rendering pipeline. This can be used for instance to change
+certain colors to improve the rendering in some terminals.
+
+One useful example is the
+:class:`~prompt_toolkit.styles.AdjustBrightnessStyleTransformation` class,
+which takes `min_brightness` and `max_brightness` as arguments which by default
+have 0.0 and 1.0 as values. In the following code snippet, we increase the
+minimum brightness to improve rendering on terminals with a dark background.
+
+.. code:: python
+
+ from prompt_toolkit.styles import AdjustBrightnessStyleTransformation
+
+ app = Application(
+ style_transformation=AdjustBrightnessStyleTransformation(
+ min_brightness=0.5, # Increase the minimum brightness.
+ max_brightness=1.0,
+ )
+ # ...
+ )
diff --git a/docs/pages/advanced_topics/unit_testing.rst b/docs/pages/advanced_topics/unit_testing.rst
new file mode 100644
index 0000000..2224bfc
--- /dev/null
+++ b/docs/pages/advanced_topics/unit_testing.rst
@@ -0,0 +1,125 @@
+.. _unit_testing:
+
+Unit testing
+============
+
+Testing user interfaces is not always obvious. Here are a few tricks for
+testing prompt_toolkit applications.
+
+
+`PosixPipeInput` and `DummyOutput`
+----------------------------------
+
+During the creation of a prompt_toolkit
+:class:`~prompt_toolkit.application.Application`, we can specify what input and
+output device to be used. By default, these are output objects that correspond
+with `sys.stdin` and `sys.stdout`. In unit tests however, we want to replace
+these.
+
+- For the input, we want a "pipe input". This is an input device, in which we
+ can programmatically send some input. It can be created with
+ :func:`~prompt_toolkit.input.create_pipe_input`, and that return either a
+ :class:`~prompt_toolkit.input.posix_pipe.PosixPipeInput` or a
+ :class:`~prompt_toolkit.input.win32_pipe.Win32PipeInput` depending on the
+ platform.
+- For the output, we want a :class:`~prompt_toolkit.output.DummyOutput`. This is
+ an output device that doesn't render anything. We don't want to render
+ anything to `sys.stdout` in the unit tests.
+
+.. note::
+
+ Typically, we don't want to test the bytes that are written to
+ `sys.stdout`, because these can change any time when the rendering
+ algorithm changes, and are not so meaningful anyway. Instead, we want to
+ test the return value from the
+ :class:`~prompt_toolkit.application.Application` or test how data
+ structures (like text buffers) change over time.
+
+So we programmatically feed some input to the input pipe, have the key
+bindings process the input and then test what comes out of it.
+
+In the following example we use a
+:class:`~prompt_toolkit.shortcuts.PromptSession`, but the same works for any
+:class:`~prompt_toolkit.application.Application`.
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import PromptSession
+ from prompt_toolkit.input import create_pipe_input
+ from prompt_toolkit.output import DummyOutput
+
+ def test_prompt_session():
+ with create_pipe_input() as inp:
+ inp.send_text("hello\n")
+ session = PromptSession(
+ input=inp,
+ output=DummyOutput(),
+ )
+
+ result = session.prompt()
+
+ assert result == "hello"
+
+In the above example, don't forget to send the `\\n` character to accept the
+prompt, otherwise the :class:`~prompt_toolkit.application.Application` will
+wait forever for some more input to receive.
+
+Using an :class:`~prompt_toolkit.application.current.AppSession`
+----------------------------------------------------------------
+
+Sometimes it's not convenient to pass input or output objects to the
+:class:`~prompt_toolkit.application.Application`, and in some situations it's
+not even possible at all.
+This happens when these parameters are not passed down the call stack, through
+all function calls.
+
+An easy way to specify which input/output to use for all applications, is by
+creating an :class:`~prompt_toolkit.application.current.AppSession` with this
+input/output and running all code in that
+:class:`~prompt_toolkit.application.current.AppSession`. This way, we don't
+need to inject it into every :class:`~prompt_toolkit.application.Application`
+or :func:`~prompt_toolkit.shortcuts.print_formatted_text` call.
+
+Here is an example where we use
+:func:`~prompt_toolkit.application.create_app_session`:
+
+.. code:: python
+
+ from prompt_toolkit.application import create_app_session
+ from prompt_toolkit.shortcuts import print_formatted_text
+ from prompt_toolkit.output import DummyOutput
+
+ def test_something():
+ with create_app_session(output=DummyOutput()):
+ ...
+ print_formatted_text('Hello world')
+ ...
+
+Pytest fixtures
+---------------
+
+In order to get rid of the boilerplate of creating the input, the
+:class:`~prompt_toolkit.output.DummyOutput`, and the
+:class:`~prompt_toolkit.application.current.AppSession`, we create a
+single fixture that does it for every test. Something like this:
+
+.. code:: python
+
+ import pytest
+ from prompt_toolkit.application import create_app_session
+ from prompt_toolkit.input import create_pipe_input
+ from prompt_toolkit.output import DummyOutput
+
+ @pytest.fixture(autouse=True, scope="function")
+ def mock_input():
+ with create_pipe_input() as pipe_input:
+ with create_app_session(input=pipe_input, output=DummyOutput()):
+ yield pipe_input
+
+
+Type checking
+-------------
+
+Prompt_toolkit 3.0 is fully type annotated. This means that if a
+prompt_toolkit application is typed too, it can be verified with mypy. This is
+complementary to unit tests, but also great for testing for correctness.
diff --git a/docs/pages/asking_for_input.rst b/docs/pages/asking_for_input.rst
new file mode 100644
index 0000000..20619ac
--- /dev/null
+++ b/docs/pages/asking_for_input.rst
@@ -0,0 +1,1034 @@
+.. _asking_for_input:
+
+Asking for input (prompts)
+==========================
+
+This page is about building prompts. Pieces of code that we can embed in a
+program for asking the user for input. Even if you want to use `prompt_toolkit`
+for building full screen terminal applications, it is probably still a good
+idea to read this first, before heading to the :ref:`building full screen
+applications <full_screen_applications>` page.
+
+In this page, we will cover autocompletion, syntax highlighting, key bindings,
+and so on.
+
+
+Hello world
+-----------
+
+The following snippet is the most simple example, it uses the
+:func:`~prompt_toolkit.shortcuts.prompt` function to ask the user for input
+and returns the text. Just like ``(raw_)input``.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+
+ text = prompt('Give me some input: ')
+ print('You said: %s' % text)
+
+.. image:: ../images/hello-world-prompt.png
+
+What we get here is a simple prompt that supports the Emacs key bindings like
+readline, but further nothing special. However,
+:func:`~prompt_toolkit.shortcuts.prompt` has a lot of configuration options.
+In the following sections, we will discover all these parameters.
+
+
+The `PromptSession` object
+--------------------------
+
+Instead of calling the :func:`~prompt_toolkit.shortcuts.prompt` function, it's
+also possible to create a :class:`~prompt_toolkit.shortcuts.PromptSession`
+instance followed by calling its
+:meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` method for every input
+call. This creates a kind of an input session.
+
+.. code:: python
+
+ from prompt_toolkit import PromptSession
+
+ # Create prompt object.
+ session = PromptSession()
+
+ # Do multiple input calls.
+ text1 = session.prompt()
+ text2 = session.prompt()
+
+This has mainly two advantages:
+
+- The input history will be kept between consecutive
+ :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` calls.
+
+- The :func:`~prompt_toolkit.shortcuts.PromptSession` instance and its
+ :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` method take about the
+ same arguments, like all the options described below (highlighting,
+ completion, etc...). So if you want to ask for multiple inputs, but each
+ input call needs about the same arguments, they can be passed to the
+ :func:`~prompt_toolkit.shortcuts.PromptSession` instance as well, and they
+ can be overridden by passing values to the
+ :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` method.
+
+
+Syntax highlighting
+-------------------
+
+Adding syntax highlighting is as simple as adding a lexer. All of the `Pygments
+<http://pygments.org/>`_ lexers can be used after wrapping them in a
+:class:`~prompt_toolkit.lexers.PygmentsLexer`. It is also possible to create a
+custom lexer by implementing the :class:`~prompt_toolkit.lexers.Lexer` abstract
+base class.
+
+.. code:: python
+
+ from pygments.lexers.html import HtmlLexer
+ from prompt_toolkit.shortcuts import prompt
+ from prompt_toolkit.lexers import PygmentsLexer
+
+ text = prompt('Enter HTML: ', lexer=PygmentsLexer(HtmlLexer))
+ print('You said: %s' % text)
+
+.. image:: ../images/html-input.png
+
+The default Pygments colorscheme is included as part of the default style in
+prompt_toolkit. If you want to use another Pygments style along with the lexer,
+you can do the following:
+
+.. code:: python
+
+ from pygments.lexers.html import HtmlLexer
+ from pygments.styles import get_style_by_name
+ from prompt_toolkit.shortcuts import prompt
+ from prompt_toolkit.lexers import PygmentsLexer
+ from prompt_toolkit.styles.pygments import style_from_pygments_cls
+
+ style = style_from_pygments_cls(get_style_by_name('monokai'))
+ text = prompt('Enter HTML: ', lexer=PygmentsLexer(HtmlLexer), style=style,
+ include_default_pygments_style=False)
+ print('You said: %s' % text)
+
+We pass ``include_default_pygments_style=False``, because otherwise, both
+styles will be merged, possibly giving slightly different colors in the outcome
+for cases where where our custom Pygments style doesn't specify a color.
+
+.. _colors:
+
+Colors
+------
+
+The colors for syntax highlighting are defined by a
+:class:`~prompt_toolkit.styles.Style` instance. By default, a neutral
+built-in style is used, but any style instance can be passed to the
+:func:`~prompt_toolkit.shortcuts.prompt` function. A simple way to create a
+style, is by using the :meth:`~prompt_toolkit.styles.Style.from_dict`
+function:
+
+.. code:: python
+
+ from pygments.lexers.html import HtmlLexer
+ from prompt_toolkit.shortcuts import prompt
+ from prompt_toolkit.styles import Style
+ from prompt_toolkit.lexers import PygmentsLexer
+
+ our_style = Style.from_dict({
+ 'pygments.comment': '#888888 bold',
+ 'pygments.keyword': '#ff88ff bold',
+ })
+
+ text = prompt('Enter HTML: ', lexer=PygmentsLexer(HtmlLexer),
+ style=our_style)
+
+
+The style dictionary is very similar to the Pygments ``styles`` dictionary,
+with a few differences:
+
+- The `roman`, `sans`, `mono` and `border` options are ignored.
+- The style has a few additions: ``blink``, ``noblink``, ``reverse`` and ``noreverse``.
+- Colors can be in the ``#ff0000`` format, but they can be one of the built-in
+ ANSI color names as well. In that case, they map directly to the 16 color
+ palette of the terminal.
+
+:ref:`Read more about styling <styling>`.
+
+
+Using a Pygments style
+^^^^^^^^^^^^^^^^^^^^^^
+
+All Pygments style classes can be used as well, when they are wrapped through
+:func:`~prompt_toolkit.styles.style_from_pygments_cls`.
+
+Suppose we'd like to use a Pygments style, for instance
+``pygments.styles.tango.TangoStyle``, that is possible like this:
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import prompt
+ from prompt_toolkit.styles import style_from_pygments_cls
+ from prompt_toolkit.lexers import PygmentsLexer
+ from pygments.styles.tango import TangoStyle
+ from pygments.lexers.html import HtmlLexer
+
+ tango_style = style_from_pygments_cls (TangoStyle)
+
+ text = prompt ('Enter HTML: ',
+ lexer=PygmentsLexer(HtmlLexer),
+ style=tango_style)
+
+Creating a custom style could be done like this:
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import prompt
+ from prompt_toolkit.styles import Style, style_from_pygments_cls, merge_styles
+ from prompt_toolkit.lexers import PygmentsLexer
+
+ from pygments.styles.tango import TangoStyle
+ from pygments.lexers.html import HtmlLexer
+
+ our_style = merge_styles([
+ style_from_pygments_cls(TangoStyle),
+ Style.from_dict({
+ 'pygments.comment': '#888888 bold',
+ 'pygments.keyword': '#ff88ff bold',
+ })
+ ])
+
+ text = prompt('Enter HTML: ', lexer=PygmentsLexer(HtmlLexer),
+ style=our_style)
+
+
+Coloring the prompt itself
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It is possible to add some colors to the prompt itself. For this, we need to
+build some :ref:`formatted text <formatted_text>`. One way of doing this is by
+creating a list of style/text tuples. In the following example, we use class
+names to refer to the style.
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import prompt
+ from prompt_toolkit.styles import Style
+
+ style = Style.from_dict({
+ # User input (default text).
+ '': '#ff0066',
+
+ # Prompt.
+ 'username': '#884444',
+ 'at': '#00aa00',
+ 'colon': '#0000aa',
+ 'pound': '#00aa00',
+ 'host': '#00ffff bg:#444400',
+ 'path': 'ansicyan underline',
+ })
+
+ message = [
+ ('class:username', 'john'),
+ ('class:at', '@'),
+ ('class:host', 'localhost'),
+ ('class:colon', ':'),
+ ('class:path', '/user/john'),
+ ('class:pound', '# '),
+ ]
+
+ text = prompt(message, style=style)
+
+.. image:: ../images/colored-prompt.png
+
+The `message` can be any kind of formatted text, as discussed :ref:`here
+<formatted_text>`. It can also be a callable that returns some formatted text.
+
+By default, colors are taken from the 256 color palette. If you want to have
+24bit true color, this is possible by adding the
+``color_depth=ColorDepth.TRUE_COLOR`` option to the
+:func:`~prompt_toolkit.shortcuts.prompt.prompt` function.
+
+.. code:: python
+
+ from prompt_toolkit.output import ColorDepth
+
+ text = prompt(message, style=style, color_depth=ColorDepth.TRUE_COLOR)
+
+
+Autocompletion
+--------------
+
+Autocompletion can be added by passing a ``completer`` parameter. This should
+be an instance of the :class:`~prompt_toolkit.completion.Completer` abstract
+base class. :class:`~prompt_toolkit.completion.WordCompleter` is an example of
+a completer that implements that interface.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ from prompt_toolkit.completion import WordCompleter
+
+ html_completer = WordCompleter(['<html>', '<body>', '<head>', '<title>'])
+ text = prompt('Enter HTML: ', completer=html_completer)
+ print('You said: %s' % text)
+
+:class:`~prompt_toolkit.completion.WordCompleter` is a simple completer that
+completes the last word before the cursor with any of the given words.
+
+.. image:: ../images/html-completion.png
+
+.. note::
+
+ Note that in prompt_toolkit 2.0, the auto completion became synchronous. This
+ means that if it takes a long time to compute the completions, that this
+ will block the event loop and the input processing.
+
+ For heavy completion algorithms, it is recommended to wrap the completer in
+ a :class:`~prompt_toolkit.completion.ThreadedCompleter` in order to run it
+ in a background thread.
+
+
+Nested completion
+^^^^^^^^^^^^^^^^^
+
+Sometimes you have a command line interface where the completion depends on the
+previous words from the input. Examples are the CLIs from routers and switches.
+A simple :class:`~prompt_toolkit.completion.WordCompleter` is not enough in
+that case. We want to to be able to define completions at multiple hierarchical
+levels. :class:`~prompt_toolkit.completion.NestedCompleter` solves this issue:
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ from prompt_toolkit.completion import NestedCompleter
+
+ completer = NestedCompleter.from_nested_dict({
+ 'show': {
+ 'version': None,
+ 'clock': None,
+ 'ip': {
+ 'interface': {'brief'}
+ }
+ },
+ 'exit': None,
+ })
+
+ text = prompt('# ', completer=completer)
+ print('You said: %s' % text)
+
+Whenever there is a ``None`` value in the dictionary, it means that there is no
+further nested completion at that point. When all values of a dictionary would
+be ``None``, it can also be replaced with a set.
+
+
+A custom completer
+^^^^^^^^^^^^^^^^^^
+
+For more complex examples, it makes sense to create a custom completer. For
+instance:
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ from prompt_toolkit.completion import Completer, Completion
+
+ class MyCustomCompleter(Completer):
+ def get_completions(self, document, complete_event):
+ yield Completion('completion', start_position=0)
+
+ text = prompt('> ', completer=MyCustomCompleter())
+
+A :class:`~prompt_toolkit.completion.Completer` class has to implement a
+generator named :meth:`~prompt_toolkit.completion.Completer.get_completions`
+that takes a :class:`~prompt_toolkit.document.Document` and yields the current
+:class:`~prompt_toolkit.completion.Completion` instances. Each completion
+contains a portion of text, and a position.
+
+The position is used for fixing text before the cursor. Pressing the tab key
+could for instance turn parts of the input from lowercase to uppercase. This
+makes sense for a case insensitive completer. Or in case of a fuzzy completion,
+it could fix typos. When ``start_position`` is something negative, this amount
+of characters will be deleted and replaced.
+
+
+Styling individual completions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Each completion can provide a custom style, which is used when it is rendered
+in the completion menu or toolbar. This is possible by passing a style to each
+:class:`~prompt_toolkit.completion.Completion` instance.
+
+.. code:: python
+
+ from prompt_toolkit.completion import Completer, Completion
+
+ class MyCustomCompleter(Completer):
+ def get_completions(self, document, complete_event):
+ # Display this completion, black on yellow.
+ yield Completion('completion1', start_position=0,
+ style='bg:ansiyellow fg:ansiblack')
+
+ # Underline completion.
+ yield Completion('completion2', start_position=0,
+ style='underline')
+
+ # Specify class name, which will be looked up in the style sheet.
+ yield Completion('completion3', start_position=0,
+ style='class:special-completion')
+
+The "colorful-prompts.py" example uses completion styling:
+
+.. image:: ../images/colorful-completions.png
+
+Finally, it is possible to pass :ref:`formatted text <formatted_text>` for the
+``display`` attribute of a :class:`~prompt_toolkit.completion.Completion`. This
+provides all the freedom you need to display the text in any possible way. It
+can also be combined with the ``style`` attribute. For instance:
+
+.. code:: python
+
+
+ from prompt_toolkit.completion import Completer, Completion
+ from prompt_toolkit.formatted_text import HTML
+
+ class MyCustomCompleter(Completer):
+ def get_completions(self, document, complete_event):
+ yield Completion(
+ 'completion1', start_position=0,
+ display=HTML('<b>completion</b><ansired>1</ansired>'),
+ style='bg:ansiyellow')
+
+
+Fuzzy completion
+^^^^^^^^^^^^^^^^
+
+If one possible completions is "django_migrations", a fuzzy completer would
+allow you to get this by typing "djm" only, a subset of characters for this
+string.
+
+Prompt_toolkit ships with a :class:`~prompt_toolkit.completion.FuzzyCompleter`
+and :class:`~prompt_toolkit.completion.FuzzyWordCompleter` class. These provide
+the means for doing this kind of "fuzzy completion". The first one can take any
+completer instance and wrap it so that it becomes a fuzzy completer. The second
+one behaves like a :class:`~prompt_toolkit.completion.WordCompleter` wrapped
+into a :class:`~prompt_toolkit.completion.FuzzyCompleter`.
+
+
+Complete while typing
+^^^^^^^^^^^^^^^^^^^^^
+
+Autcompletions can be generated automatically while typing or when the user
+presses the tab key. This can be configured with the ``complete_while_typing``
+option:
+
+.. code:: python
+
+ text = prompt('Enter HTML: ', completer=my_completer,
+ complete_while_typing=True)
+
+Notice that this setting is incompatible with the ``enable_history_search``
+option. The reason for this is that the up and down key bindings would conflict
+otherwise. So, make sure to disable history search for this.
+
+
+Asynchronous completion
+^^^^^^^^^^^^^^^^^^^^^^^
+
+When generating the completions takes a lot of time, it's better to do this in
+a background thread. This is possible by wrapping the completer in a
+:class:`~prompt_toolkit.completion.ThreadedCompleter`, but also by passing the
+`complete_in_thread=True` argument.
+
+
+.. code:: python
+
+ text = prompt('> ', completer=MyCustomCompleter(), complete_in_thread=True)
+
+
+Input validation
+----------------
+
+A prompt can have a validator attached. This is some code that will check
+whether the given input is acceptable and it will only return it if that's the
+case. Otherwise it will show an error message and move the cursor to a given
+position.
+
+A validator should implements the :class:`~prompt_toolkit.validation.Validator`
+abstract base class. This requires only one method, named ``validate`` that
+takes a :class:`~prompt_toolkit.document.Document` as input and raises
+:class:`~prompt_toolkit.validation.ValidationError` when the validation fails.
+
+.. code:: python
+
+ from prompt_toolkit.validation import Validator, ValidationError
+ from prompt_toolkit import prompt
+
+ class NumberValidator(Validator):
+ def validate(self, document):
+ text = document.text
+
+ if text and not text.isdigit():
+ i = 0
+
+ # Get index of first non numeric character.
+ # We want to move the cursor here.
+ for i, c in enumerate(text):
+ if not c.isdigit():
+ break
+
+ raise ValidationError(message='This input contains non-numeric characters',
+ cursor_position=i)
+
+ number = int(prompt('Give a number: ', validator=NumberValidator()))
+ print('You said: %i' % number)
+
+.. image:: ../images/number-validator.png
+
+By default, the input is validated in real-time while the user is typing, but
+prompt_toolkit can also validate after the user presses the enter key:
+
+.. code:: python
+
+ prompt('Give a number: ', validator=NumberValidator(),
+ validate_while_typing=False)
+
+If the input validation contains some heavy CPU intensive code, but you don't
+want to block the event loop, then it's recommended to wrap the validator class
+in a :class:`~prompt_toolkit.validation.ThreadedValidator`.
+
+Validator from a callable
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Instead of implementing the :class:`~prompt_toolkit.validation.Validator`
+abstract base class, it is also possible to start from a simple function and
+use the :meth:`~prompt_toolkit.validation.Validator.from_callable` classmethod.
+This is easier and sufficient for probably 90% of the validators. It looks as
+follows:
+
+.. code:: python
+
+ from prompt_toolkit.validation import Validator
+ from prompt_toolkit import prompt
+
+ def is_number(text):
+ return text.isdigit()
+
+ validator = Validator.from_callable(
+ is_number,
+ error_message='This input contains non-numeric characters',
+ move_cursor_to_end=True)
+
+ number = int(prompt('Give a number: ', validator=validator))
+ print('You said: %i' % number)
+
+We define a function that takes a string, and tells whether it's valid input or
+not by returning a boolean.
+:meth:`~prompt_toolkit.validation.Validator.from_callable` turns that into a
+:class:`~prompt_toolkit.validation.Validator` instance. Notice that setting the
+cursor position is not possible this way.
+
+
+History
+-------
+
+A :class:`~prompt_toolkit.history.History` object keeps track of all the
+previously entered strings, so that the up-arrow can reveal previously entered
+items.
+
+The recommended way is to use a
+:class:`~prompt_toolkit.shortcuts.PromptSession`, which uses an
+:class:`~prompt_toolkit.history.InMemoryHistory` for the entire session by
+default. The following example has a history out of the box:
+
+.. code:: python
+
+ from prompt_toolkit import PromptSession
+
+ session = PromptSession()
+
+ while True:
+ session.prompt()
+
+To persist a history to disk, use a :class:`~prompt_toolkit.history.FileHistory`
+instead of the default
+:class:`~prompt_toolkit.history.InMemoryHistory`. This history object can be
+passed either to a :class:`~prompt_toolkit.shortcuts.PromptSession` or to the
+:meth:`~prompt_toolkit.shortcuts.prompt` function. For instance:
+
+.. code:: python
+
+ from prompt_toolkit import PromptSession
+ from prompt_toolkit.history import FileHistory
+
+ session = PromptSession(history=FileHistory('~/.myhistory'))
+
+ while True:
+ session.prompt()
+
+
+Auto suggestion
+---------------
+
+Auto suggestion is a way to propose some input completions to the user like the
+`fish shell <http://fishshell.com/>`_.
+
+Usually, the input is compared to the history and when there is another entry
+starting with the given text, the completion will be shown as gray text behind
+the current input. Pressing the right arrow :kbd:`→` or :kbd:`c-e` will insert
+this suggestion, :kbd:`alt-f` will insert the first word of the suggestion.
+
+.. note::
+
+ When suggestions are based on the history, don't forget to share one
+ :class:`~prompt_toolkit.history.History` object between consecutive
+ :func:`~prompt_toolkit.shortcuts.prompt` calls. Using a
+ :class:`~prompt_toolkit.shortcuts.PromptSession` does this for you.
+
+Example:
+
+.. code:: python
+
+ from prompt_toolkit import PromptSession
+ from prompt_toolkit.history import InMemoryHistory
+ from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
+
+ session = PromptSession()
+
+ while True:
+ text = session.prompt('> ', auto_suggest=AutoSuggestFromHistory())
+ print('You said: %s' % text)
+
+.. image:: ../images/auto-suggestion.png
+
+A suggestion does not have to come from the history. Any implementation of the
+:class:`~prompt_toolkit.auto_suggest.AutoSuggest` abstract base class can be
+passed as an argument.
+
+
+Adding a bottom toolbar
+-----------------------
+
+Adding a bottom toolbar is as easy as passing a ``bottom_toolbar`` argument to
+:func:`~prompt_toolkit.shortcuts.prompt`. This argument be either plain text,
+:ref:`formatted text <formatted_text>` or a callable that returns plain or
+formatted text.
+
+When a function is given, it will be called every time the prompt is rendered,
+so the bottom toolbar can be used to display dynamic information.
+
+The toolbar is always erased when the prompt returns.
+Here we have an example of a callable that returns an
+:class:`~prompt_toolkit.formatted_text.HTML` object. By default, the toolbar
+has the **reversed style**, which is why we are setting the background instead
+of the foreground.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ from prompt_toolkit.formatted_text import HTML
+
+ def bottom_toolbar():
+ return HTML('This is a <b><style bg="ansired">Toolbar</style></b>!')
+
+ text = prompt('> ', bottom_toolbar=bottom_toolbar)
+ print('You said: %s' % text)
+
+.. image:: ../images/bottom-toolbar.png
+
+Similar, we could use a list of style/text tuples.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ from prompt_toolkit.styles import Style
+
+ def bottom_toolbar():
+ return [('class:bottom-toolbar', ' This is a toolbar. ')]
+
+ style = Style.from_dict({
+ 'bottom-toolbar': '#ffffff bg:#333333',
+ })
+
+ text = prompt('> ', bottom_toolbar=bottom_toolbar, style=style)
+ print('You said: %s' % text)
+
+The default class name is ``bottom-toolbar`` and that will also be used to fill
+the background of the toolbar.
+
+
+Adding a right prompt
+---------------------
+
+The :func:`~prompt_toolkit.shortcuts.prompt` function has out of the box
+support for right prompts as well. People familiar to ZSH could recognize this
+as the `RPROMPT` option.
+
+So, similar to adding a bottom toolbar, we can pass an ``rprompt`` argument.
+This can be either plain text, :ref:`formatted text <formatted_text>` or a
+callable which returns either.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ from prompt_toolkit.styles import Style
+
+ example_style = Style.from_dict({
+ 'rprompt': 'bg:#ff0066 #ffffff',
+ })
+
+ def get_rprompt():
+ return '<rprompt>'
+
+ answer = prompt('> ', rprompt=get_rprompt, style=example_style)
+
+.. image:: ../images/rprompt.png
+
+The ``get_rprompt`` function can return any kind of formatted text such as
+:class:`~prompt_toolkit.formatted_text.HTML`. it is also possible to pass text
+directly to the ``rprompt`` argument of the
+:func:`~prompt_toolkit.shortcuts.prompt` function. It does not have to be a
+callable.
+
+
+Vi input mode
+-------------
+
+Prompt-toolkit supports both Emacs and Vi key bindings, similar to Readline.
+The :func:`~prompt_toolkit.shortcuts.prompt` function will use Emacs bindings by
+default. This is done because on most operating systems, also the Bash shell
+uses Emacs bindings by default, and that is more intuitive. If however, Vi
+binding are required, just pass ``vi_mode=True``.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+
+ prompt('> ', vi_mode=True)
+
+
+Adding custom key bindings
+--------------------------
+
+By default, every prompt already has a set of key bindings which implements the
+usual Vi or Emacs behavior. We can extend this by passing another
+:class:`~prompt_toolkit.key_binding.KeyBindings` instance to the
+``key_bindings`` argument of the :func:`~prompt_toolkit.shortcuts.prompt`
+function or the :class:`~prompt_toolkit.shortcuts.PromptSession` class.
+
+An example of a prompt that prints ``'hello world'`` when :kbd:`Control-T` is pressed.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ from prompt_toolkit.application import run_in_terminal
+ from prompt_toolkit.key_binding import KeyBindings
+
+ bindings = KeyBindings()
+
+ @bindings.add('c-t')
+ def _(event):
+ " Say 'hello' when `c-t` is pressed. "
+ def print_hello():
+ print('hello world')
+ run_in_terminal(print_hello)
+
+ @bindings.add('c-x')
+ def _(event):
+ " Exit when `c-x` is pressed. "
+ event.app.exit()
+
+ text = prompt('> ', key_bindings=bindings)
+ print('You said: %s' % text)
+
+
+Note that we use
+:meth:`~prompt_toolkit.application.run_in_terminal` for the first key binding.
+This ensures that the output of the print-statement and the prompt don't mix
+up. If the key bindings doesn't print anything, then it can be handled directly
+without nesting functions.
+
+
+Enable key bindings according to a condition
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Often, some key bindings can be enabled or disabled according to a certain
+condition. For instance, the Emacs and Vi bindings will never be active at the
+same time, but it is possible to switch between Emacs and Vi bindings at run
+time.
+
+In order to enable a key binding according to a certain condition, we have to
+pass it a :class:`~prompt_toolkit.filters.Filter`, usually a
+:class:`~prompt_toolkit.filters.Condition` instance. (:ref:`Read more about
+filters <filters>`.)
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ from prompt_toolkit.filters import Condition
+ from prompt_toolkit.key_binding import KeyBindings
+
+ bindings = KeyBindings()
+
+ @Condition
+ def is_active():
+ " Only activate key binding on the second half of each minute. "
+ return datetime.datetime.now().second > 30
+
+ @bindings.add('c-t', filter=is_active)
+ def _(event):
+ # ...
+ pass
+
+ prompt('> ', key_bindings=bindings)
+
+
+Dynamically switch between Emacs and Vi mode
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The :class:`~prompt_toolkit.application.Application` has an ``editing_mode``
+attribute. We can change the key bindings by changing this attribute from
+``EditingMode.VI`` to ``EditingMode.EMACS``.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ from prompt_toolkit.application.current import get_app
+ from prompt_toolkit.enums import EditingMode
+ from prompt_toolkit.key_binding import KeyBindings
+
+ def run():
+ # Create a set of key bindings.
+ bindings = KeyBindings()
+
+ # Add an additional key binding for toggling this flag.
+ @bindings.add('f4')
+ def _(event):
+ " Toggle between Emacs and Vi mode. "
+ app = event.app
+
+ if app.editing_mode == EditingMode.VI:
+ app.editing_mode = EditingMode.EMACS
+ else:
+ app.editing_mode = EditingMode.VI
+
+ # Add a toolbar at the bottom to display the current input mode.
+ def bottom_toolbar():
+ " Display the current input mode. "
+ text = 'Vi' if get_app().editing_mode == EditingMode.VI else 'Emacs'
+ return [
+ ('class:toolbar', ' [F4] %s ' % text)
+ ]
+
+ prompt('> ', key_bindings=bindings, bottom_toolbar=bottom_toolbar)
+
+ run()
+
+:ref:`Read more about key bindings ...<key_bindings>`
+
+Using control-space for completion
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+An popular short cut that people sometimes use it to use control-space for
+opening the autocompletion menu instead of the tab key. This can be done with
+the following key binding.
+
+.. code:: python
+
+ kb = KeyBindings()
+
+ @kb.add('c-space')
+ def _(event):
+ " Initialize autocompletion, or select the next completion. "
+ buff = event.app.current_buffer
+ if buff.complete_state:
+ buff.complete_next()
+ else:
+ buff.start_completion(select_first=False)
+
+
+Other prompt options
+--------------------
+
+Multiline input
+^^^^^^^^^^^^^^^
+
+Reading multiline input is as easy as passing the ``multiline=True`` parameter.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+
+ prompt('> ', multiline=True)
+
+A side effect of this is that the enter key will now insert a newline instead
+of accepting and returning the input. The user will now have to press
+:kbd:`Meta+Enter` in order to accept the input. (Or :kbd:`Escape` followed by
+:kbd:`Enter`.)
+
+It is possible to specify a continuation prompt. This works by passing a
+``prompt_continuation`` callable to :func:`~prompt_toolkit.shortcuts.prompt`.
+This function is supposed to return :ref:`formatted text <formatted_text>`, or
+a list of ``(style, text)`` tuples. The width of the returned text should not
+exceed the given width. (The width of the prompt margin is defined by the
+prompt.)
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+
+ def prompt_continuation(width, line_number, is_soft_wrap):
+ return '.' * width
+ # Or: return [('', '.' * width)]
+
+ prompt('multiline input> ', multiline=True,
+ prompt_continuation=prompt_continuation)
+
+.. image:: ../images/multiline-input.png
+
+
+Passing a default
+^^^^^^^^^^^^^^^^^
+
+A default value can be given:
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ import getpass
+
+ prompt('What is your name: ', default='%s' % getpass.getuser())
+
+
+Mouse support
+^^^^^^^^^^^^^
+
+There is limited mouse support for positioning the cursor, for scrolling (in
+case of large multiline inputs) and for clicking in the autocompletion menu.
+
+Enabling can be done by passing the ``mouse_support=True`` option.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+
+ prompt('What is your name: ', mouse_support=True)
+
+
+Line wrapping
+^^^^^^^^^^^^^
+
+Line wrapping is enabled by default. This is what most people are used to and
+this is what GNU Readline does. When it is disabled, the input string will
+scroll horizontally.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+
+ prompt('What is your name: ', wrap_lines=False)
+
+
+Password input
+^^^^^^^^^^^^^^
+
+When the ``is_password=True`` flag has been given, the input is replaced by
+asterisks (``*`` characters).
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+
+ prompt('Enter password: ', is_password=True)
+
+
+Cursor shapes
+-------------
+
+Many terminals support displaying different types of cursor shapes. The most
+common are block, beam or underscore. Either blinking or not. It is possible to
+decide which cursor to display while asking for input, or in case of Vi input
+mode, have a modal prompt for which its cursor shape changes according to the
+input mode.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+ from prompt_toolkit.cursor_shapes import CursorShape, ModalCursorShapeConfig
+
+ # Several possible values for the `cursor_shape_config` parameter:
+ prompt('>', cursor=CursorShape.BLOCK)
+ prompt('>', cursor=CursorShape.UNDERLINE)
+ prompt('>', cursor=CursorShape.BEAM)
+ prompt('>', cursor=CursorShape.BLINKING_BLOCK)
+ prompt('>', cursor=CursorShape.BLINKING_UNDERLINE)
+ prompt('>', cursor=CursorShape.BLINKING_BEAM)
+ prompt('>', cursor=ModalCursorShapeConfig())
+
+
+Prompt in an `asyncio` application
+----------------------------------
+
+.. note::
+
+ New in prompt_toolkit 3.0. (In prompt_toolkit 2.0 this was possible using a
+ work-around).
+
+For `asyncio <https://docs.python.org/3/library/asyncio.html>`_ applications,
+it's very important to never block the eventloop. However,
+:func:`~prompt_toolkit.shortcuts.prompt` is blocking, and calling this would
+freeze the whole application. Asyncio actually won't even allow us to run that
+function within a coroutine.
+
+The answer is to call
+:meth:`~prompt_toolkit.shortcuts.PromptSession.prompt_async` instead of
+:meth:`~prompt_toolkit.shortcuts.PromptSession.prompt`. The async variation
+returns a coroutines and is awaitable.
+
+.. code:: python
+
+ from prompt_toolkit import PromptSession
+ from prompt_toolkit.patch_stdout import patch_stdout
+
+ async def my_coroutine():
+ session = PromptSession()
+ while True:
+ with patch_stdout():
+ result = await session.prompt_async('Say something: ')
+ print('You said: %s' % result)
+
+The :func:`~prompt_toolkit.patch_stdout.patch_stdout` context manager is
+optional, but it's recommended, because other coroutines could print to stdout.
+This ensures that other output won't destroy the prompt.
+
+
+Reading keys from stdin, one key at a time, but without a prompt
+----------------------------------------------------------------
+
+Suppose that you want to use prompt_toolkit to read the keys from stdin, one
+key at a time, but not render a prompt to the output, that is also possible:
+
+.. code:: python
+
+ import asyncio
+
+ from prompt_toolkit.input import create_input
+ from prompt_toolkit.keys import Keys
+
+
+ async def main() -> None:
+ done = asyncio.Event()
+ input = create_input()
+
+ def keys_ready():
+ for key_press in input.read_keys():
+ print(key_press)
+
+ if key_press.key == Keys.ControlC:
+ done.set()
+
+ with input.raw_mode():
+ with input.attach(keys_ready):
+ await done.wait()
+
+
+ if __name__ == "__main__":
+ asyncio.run(main())
+
+The above snippet will print the `KeyPress` object whenever a key is pressed.
+This is also cross platform, and should work on Windows.
diff --git a/docs/pages/dialogs.rst b/docs/pages/dialogs.rst
new file mode 100644
index 0000000..e171995
--- /dev/null
+++ b/docs/pages/dialogs.rst
@@ -0,0 +1,270 @@
+.. _dialogs:
+
+Dialogs
+=======
+
+Prompt_toolkit ships with a high level API for displaying dialogs, similar to
+the Whiptail program, but in pure Python.
+
+
+Message box
+-----------
+
+Use the :func:`~prompt_toolkit.shortcuts.message_dialog` function to display a
+simple message box. For instance:
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import message_dialog
+
+ message_dialog(
+ title='Example dialog window',
+ text='Do you want to continue?\nPress ENTER to quit.').run()
+
+.. image:: ../images/dialogs/messagebox.png
+
+
+Input box
+---------
+
+The :func:`~prompt_toolkit.shortcuts.input_dialog` function can display an
+input box. It will return the user input as a string.
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import input_dialog
+
+ text = input_dialog(
+ title='Input dialog example',
+ text='Please type your name:').run()
+
+.. image:: ../images/dialogs/inputbox.png
+
+
+The ``password=True`` option can be passed to the
+:func:`~prompt_toolkit.shortcuts.input_dialog` function to turn this into a
+password input box.
+
+
+Yes/No confirmation dialog
+--------------------------
+
+The :func:`~prompt_toolkit.shortcuts.yes_no_dialog` function displays a yes/no
+confirmation dialog. It will return a boolean according to the selection.
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import yes_no_dialog
+
+ result = yes_no_dialog(
+ title='Yes/No dialog example',
+ text='Do you want to confirm?').run()
+
+.. image:: ../images/dialogs/confirm.png
+
+
+Button dialog
+-------------
+
+The :func:`~prompt_toolkit.shortcuts.button_dialog` function displays a dialog
+with choices offered as buttons. Buttons are indicated as a list of tuples,
+each providing the label (first) and return value if clicked (second).
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import button_dialog
+
+ result = button_dialog(
+ title='Button dialog example',
+ text='Do you want to confirm?',
+ buttons=[
+ ('Yes', True),
+ ('No', False),
+ ('Maybe...', None)
+ ],
+ ).run()
+
+.. image:: ../images/dialogs/button.png
+
+
+Radio list dialog
+-----------------
+
+The :func:`~prompt_toolkit.shortcuts.radiolist_dialog` function displays a dialog
+with choices offered as a radio list. The values are provided as a list of tuples,
+each providing the return value (first element) and the displayed value (second element).
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import radiolist_dialog
+
+ result = radiolist_dialog(
+ title="RadioList dialog",
+ text="Which breakfast would you like ?",
+ values=[
+ ("breakfast1", "Eggs and beacon"),
+ ("breakfast2", "French breakfast"),
+ ("breakfast3", "Equestrian breakfast")
+ ]
+ ).run()
+
+
+Checkbox list dialog
+--------------------
+
+The :func:`~prompt_toolkit.shortcuts.checkboxlist_dialog` has the same usage and purpose than the Radiolist dialog, but allows several values to be selected and therefore returned.
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import checkboxlist_dialog
+
+ results_array = checkboxlist_dialog(
+ title="CheckboxList dialog",
+ text="What would you like in your breakfast ?",
+ values=[
+ ("eggs", "Eggs"),
+ ("bacon", "Bacon"),
+ ("croissants", "20 Croissants"),
+ ("daily", "The breakfast of the day")
+ ]
+ ).run()
+
+
+Styling of dialogs
+------------------
+
+A custom :class:`~prompt_toolkit.styles.Style` instance can be passed to all
+dialogs to override the default style. Also, text can be styled by passing an
+:class:`~prompt_toolkit.formatted_text.HTML` object.
+
+
+.. code:: python
+
+ from prompt_toolkit.formatted_text import HTML
+ from prompt_toolkit.shortcuts import message_dialog
+ from prompt_toolkit.styles import Style
+
+ example_style = Style.from_dict({
+ 'dialog': 'bg:#88ff88',
+ 'dialog frame.label': 'bg:#ffffff #000000',
+ 'dialog.body': 'bg:#000000 #00ff00',
+ 'dialog shadow': 'bg:#00aa00',
+ })
+
+ message_dialog(
+ title=HTML('<style bg="blue" fg="white">Styled</style> '
+ '<style fg="ansired">dialog</style> window'),
+ text='Do you want to continue?\nPress ENTER to quit.',
+ style=example_style).run()
+
+.. image:: ../images/dialogs/styled.png
+
+Styling reference sheet
+-----------------------
+
+In reality, the shortcut commands presented above build a full-screen frame by using a list of components. The two tables below allow you to get the classnames available for each shortcut, therefore you will be able to provide a custom style for every element that is displayed, using the method provided above.
+
+.. note:: All the shortcuts use the ``Dialog`` component, therefore it isn't specified explicitly below.
+
++--------------------------+-------------------------+
+| Shortcut | Components used |
++==========================+=========================+
+| ``yes_no_dialog`` | - ``Label`` |
+| | - ``Button`` (x2) |
++--------------------------+-------------------------+
+| ``button_dialog`` | - ``Label`` |
+| | - ``Button`` |
++--------------------------+-------------------------+
+| ``input_dialog`` | - ``TextArea`` |
+| | - ``Button`` (x2) |
++--------------------------+-------------------------+
+| ``message_dialog`` | - ``Label`` |
+| | - ``Button`` |
++--------------------------+-------------------------+
+| ``radiolist_dialog`` | - ``Label`` |
+| | - ``RadioList`` |
+| | - ``Button`` (x2) |
++--------------------------+-------------------------+
+| ``checkboxlist_dialog`` | - ``Label`` |
+| | - ``CheckboxList`` |
+| | - ``Button`` (x2) |
++--------------------------+-------------------------+
+| ``progress_dialog`` | - ``Label`` |
+| | - ``TextArea`` (locked) |
+| | - ``ProgressBar`` |
++--------------------------+-------------------------+
+
++----------------+-----------------------------+
+| Components | Available classnames |
++================+=============================+
+| Dialog | - ``dialog`` |
+| | - ``dialog.body`` |
++----------------+-----------------------------+
+| TextArea | - ``text-area`` |
+| | - ``text-area.prompt`` |
++----------------+-----------------------------+
+| Label | - ``label`` |
++----------------+-----------------------------+
+| Button | - ``button`` |
+| | - ``button.focused`` |
+| | - ``button.arrow`` |
+| | - ``button.text`` |
++----------------+-----------------------------+
+| Frame | - ``frame`` |
+| | - ``frame.border`` |
+| | - ``frame.label`` |
++----------------+-----------------------------+
+| Shadow | - ``shadow`` |
++----------------+-----------------------------+
+| RadioList | - ``radio-list`` |
+| | - ``radio`` |
+| | - ``radio-checked`` |
+| | - ``radio-selected`` |
++----------------+-----------------------------+
+| CheckboxList | - ``checkbox-list`` |
+| | - ``checkbox`` |
+| | - ``checkbox-checked`` |
+| | - ``checkbox-selected`` |
++----------------+-----------------------------+
+| VerticalLine | - ``line`` |
+| | - ``vertical-line`` |
++----------------+-----------------------------+
+| HorizontalLine | - ``line`` |
+| | - ``horizontal-line`` |
++----------------+-----------------------------+
+| ProgressBar | - ``progress-bar`` |
+| | - ``progress-bar.used`` |
++----------------+-----------------------------+
+
+Example
+_______
+
+Let's customize the example of the ``checkboxlist_dialog``.
+
+It uses 2 ``Button``, a ``CheckboxList`` and a ``Label``, packed inside a ``Dialog``.
+Therefore we can customize each of these elements separately, using for instance:
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import checkboxlist_dialog
+ from prompt_toolkit.styles import Style
+
+ results = checkboxlist_dialog(
+ title="CheckboxList dialog",
+ text="What would you like in your breakfast ?",
+ values=[
+ ("eggs", "Eggs"),
+ ("bacon", "Bacon"),
+ ("croissants", "20 Croissants"),
+ ("daily", "The breakfast of the day")
+ ],
+ style=Style.from_dict({
+ 'dialog': 'bg:#cdbbb3',
+ 'button': 'bg:#bf99a4',
+ 'checkbox': '#e8612c',
+ 'dialog.body': 'bg:#a9cfd0',
+ 'dialog shadow': 'bg:#c98982',
+ 'frame.label': '#fcaca3',
+ 'dialog.body label': '#fd8bb6',
+ })
+ ).run()
diff --git a/docs/pages/full_screen_apps.rst b/docs/pages/full_screen_apps.rst
new file mode 100644
index 0000000..805c8c7
--- /dev/null
+++ b/docs/pages/full_screen_apps.rst
@@ -0,0 +1,422 @@
+.. _full_screen_applications:
+
+Building full screen applications
+=================================
+
+`prompt_toolkit` can be used to create complex full screen terminal
+applications. Typically, an application consists of a layout (to describe the
+graphical part) and a set of key bindings.
+
+The sections below describe the components required for full screen
+applications (or custom, non full screen applications), and how to assemble
+them together.
+
+Before going through this page, it could be helpful to go through :ref:`asking
+for input <asking_for_input>` (prompts) first. Many things that apply to an
+input prompt, like styling, key bindings and so on, also apply to full screen
+applications.
+
+.. note::
+
+ Also remember that the ``examples`` directory of the prompt_toolkit
+ repository contains plenty of examples. Each example is supposed to explain
+ one idea. So, this as well should help you get started.
+
+ Don't hesitate to open a GitHub issue if you feel that a certain example is
+ missing.
+
+
+A simple application
+--------------------
+
+Every prompt_toolkit application is an instance of an
+:class:`~prompt_toolkit.application.Application` object. The simplest full
+screen example would look like this:
+
+.. code:: python
+
+ from prompt_toolkit import Application
+
+ app = Application(full_screen=True)
+ app.run()
+
+This will display a dummy application that says "No layout specified. Press
+ENTER to quit.".
+
+.. note::
+
+ If we wouldn't set the ``full_screen`` option, the application would
+ not run in the alternate screen buffer, and only consume the least
+ amount of space required for the layout.
+
+An application consists of several components. The most important are:
+
+- I/O objects: the input and output device.
+- The layout: this defines the graphical structure of the application. For
+ instance, a text box on the left side, and a button on the right side.
+ You can also think of the layout as a collection of 'widgets'.
+- A style: this defines what colors and underline/bold/italic styles are used
+ everywhere.
+- A set of key bindings.
+
+We will discuss all of these in more detail below.
+
+
+I/O objects
+-----------
+
+Every :class:`~prompt_toolkit.application.Application` instance requires an I/O
+object for input and output:
+
+ - An :class:`~prompt_toolkit.input.Input` instance, which is an abstraction
+ of the input stream (stdin).
+ - An :class:`~prompt_toolkit.output.Output` instance, which is an
+ abstraction of the output stream, and is called by the renderer.
+
+Both are optional and normally not needed to pass explicitly. Usually, the
+default works fine.
+
+There is a third I/O object which is also required by the application, but not
+passed inside. This is the event loop, an
+:class:`~prompt_toolkit.eventloop` instance. This is basically a
+while-true loop that waits for user input, and when it receives something (like
+a key press), it will send that to the the appropriate handler, like for
+instance, a key binding.
+
+When :func:`~prompt_toolkit.application.Application.run()` is called, the event
+loop will run until the application is done. An application will quit when
+:func:`~prompt_toolkit.application.Application.exit()` is called.
+
+
+The layout
+----------
+
+A layered layout architecture
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There are several ways to create a prompt_toolkit layout, depending on how
+customizable you want things to be. In fact, there are several layers of
+abstraction.
+
+- The most low-level way of creating a layout is by combining
+ :class:`~prompt_toolkit.layout.Container` and
+ :class:`~prompt_toolkit.layout.UIControl` objects.
+
+ Examples of :class:`~prompt_toolkit.layout.Container` objects are
+ :class:`~prompt_toolkit.layout.VSplit` (vertical split),
+ :class:`~prompt_toolkit.layout.HSplit` (horizontal split) and
+ :class:`~prompt_toolkit.layout.FloatContainer`. These containers arrange the
+ layout and can split it in multiple regions. Each container can recursively
+ contain multiple other containers. They can be combined in any way to define
+ the "shape" of the layout.
+
+ The :class:`~prompt_toolkit.layout.Window` object is a special kind of
+ container that can contain a :class:`~prompt_toolkit.layout.UIControl`
+ object. The :class:`~prompt_toolkit.layout.UIControl` object is responsible
+ for the generation of the actual content. The
+ :class:`~prompt_toolkit.layout.Window` object acts as an adaptor between the
+ :class:`~prompt_toolkit.layout.UIControl` and other containers, but it's also
+ responsible for the scrolling and line wrapping of the content.
+
+ Examples of :class:`~prompt_toolkit.layout.UIControl` objects are
+ :class:`~prompt_toolkit.layout.BufferControl` for showing the content of an
+ editable/scrollable buffer, and
+ :class:`~prompt_toolkit.layout.FormattedTextControl` for displaying
+ (:ref:`formatted <formatted_text>`) text.
+
+ Normally, it is never needed to create new
+ :class:`~prompt_toolkit.layout.UIControl` or
+ :class:`~prompt_toolkit.layout.Container` classes, but instead you would
+ create the layout by composing instances of the existing built-ins.
+
+- A higher level abstraction of building a layout is by using "widgets". A
+ widget is a reusable layout component that can contain multiple containers
+ and controls. Widgets have a ``__pt_container__`` function, which returns
+ the root container for this widget. Prompt_toolkit contains a couple of
+ widgets like :class:`~prompt_toolkit.widgets.TextArea`,
+ :class:`~prompt_toolkit.widgets.Button`,
+ :class:`~prompt_toolkit.widgets.Frame`,
+ :class:`~prompt_toolkit.widgets.VerticalLine` and so on.
+
+- The highest level abstractions can be found in the ``shortcuts`` module.
+ There we don't have to think about the layout, controls and containers at
+ all. This is the simplest way to use prompt_toolkit, but is only meant for
+ specific use cases, like a prompt or a simple dialog window.
+
+Containers and controls
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The biggest difference between containers and controls is that containers
+arrange the layout by splitting the screen in many regions, while controls are
+responsible for generating the actual content.
+
+.. note::
+
+ Under the hood, the difference is:
+
+ - containers use *absolute coordinates*, and paint on a
+ :class:`~prompt_toolkit.layout.screen.Screen` instance.
+ - user controls create a :class:`~prompt_toolkit.layout.controls.UIContent`
+ instance. This is a collection of lines that represent the actual
+ content. A :class:`~prompt_toolkit.layout.controls.UIControl` is not aware
+ of the screen.
+
++---------------------------------------------+------------------------------------------------------+
+| Abstract base class | Examples |
++=============================================+======================================================+
+| :class:`~prompt_toolkit.layout.Container` | :class:`~prompt_toolkit.layout.HSplit` |
+| | :class:`~prompt_toolkit.layout.VSplit` |
+| | :class:`~prompt_toolkit.layout.FloatContainer` |
+| | :class:`~prompt_toolkit.layout.Window` |
+| | :class:`~prompt_toolkit.layout.ScrollablePane` |
++---------------------------------------------+------------------------------------------------------+
+| :class:`~prompt_toolkit.layout.UIControl` | :class:`~prompt_toolkit.layout.BufferControl` |
+| | :class:`~prompt_toolkit.layout.FormattedTextControl` |
++---------------------------------------------+------------------------------------------------------+
+
+The :class:`~prompt_toolkit.layout.Window` class itself is
+particular: it is a :class:`~prompt_toolkit.layout.Container` that
+can contain a :class:`~prompt_toolkit.layout.UIControl`. Thus, it's the adaptor
+between the two. The :class:`~prompt_toolkit.layout.Window` class also takes
+care of scrolling the content and wrapping the lines if needed.
+
+Finally, there is the :class:`~prompt_toolkit.layout.Layout` class which wraps
+the whole layout. This is responsible for keeping track of which window has the
+focus.
+
+Here is an example of a layout that displays the content of the default buffer
+on the left, and displays ``"Hello world"`` on the right. In between it shows a
+vertical line:
+
+.. code:: python
+
+ from prompt_toolkit import Application
+ from prompt_toolkit.buffer import Buffer
+ from prompt_toolkit.layout.containers import VSplit, Window
+ from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
+ from prompt_toolkit.layout.layout import Layout
+
+ buffer1 = Buffer() # Editable buffer.
+
+ root_container = VSplit([
+ # One window that holds the BufferControl with the default buffer on
+ # the left.
+ Window(content=BufferControl(buffer=buffer1)),
+
+ # 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. The window will simply fill its
+ # content by repeating this character.
+ Window(width=1, char='|'),
+
+ # Display the text 'Hello world' on the right.
+ Window(content=FormattedTextControl(text='Hello world')),
+ ])
+
+ layout = Layout(root_container)
+
+ app = Application(layout=layout, full_screen=True)
+ app.run() # You won't be able to Exit this app
+
+Notice that if you execute this right now, there is no way to quit this
+application yet. This is something we explain in the next section below.
+
+More complex layouts can be achieved by nesting multiple
+:class:`~prompt_toolkit.layout.VSplit`,
+:class:`~prompt_toolkit.layout.HSplit` and
+:class:`~prompt_toolkit.layout.FloatContainer` objects.
+
+If you want to make some part of the layout only visible when a certain
+condition is satisfied, use a
+:class:`~prompt_toolkit.layout.ConditionalContainer`.
+
+Finally, there is :class:`~prompt_toolkit.layout.ScrollablePane`, a container
+class that can be used to create long forms or nested layouts that are
+scrollable as a whole.
+
+
+Focusing windows
+^^^^^^^^^^^^^^^^^
+
+Focusing something can be done by calling the
+:meth:`~prompt_toolkit.layout.Layout.focus` method. This method is very
+flexible and accepts a :class:`~prompt_toolkit.layout.Window`, a
+:class:`~prompt_toolkit.buffer.Buffer`, a
+:class:`~prompt_toolkit.layout.controls.UIControl` and more.
+
+In the following example, we use :func:`~prompt_toolkit.application.get_app`
+for getting the active application.
+
+.. code:: python
+
+ from prompt_toolkit.application import get_app
+
+ # This window was created earlier.
+ w = Window()
+
+ # ...
+
+ # Now focus it.
+ get_app().layout.focus(w)
+
+Changing the focus is something which is typically done in a key binding, so
+read on to see how to define key bindings.
+
+Key bindings
+------------
+
+In order to react to user actions, we need to create a
+:class:`~prompt_toolkit.key_binding.KeyBindings` object and pass
+that to our :class:`~prompt_toolkit.application.Application`.
+
+There are two kinds of key bindings:
+
+- Global key bindings, which are always active.
+- Key bindings that belong to a certain
+ :class:`~prompt_toolkit.layout.controls.UIControl` and are only active when
+ this control is focused. Both
+ :class:`~prompt_toolkit.layout.BufferControl`
+ :class:`~prompt_toolkit.layout.FormattedTextControl` take a ``key_bindings``
+ argument.
+
+
+Global key bindings
+^^^^^^^^^^^^^^^^^^^
+
+Key bindings can be passed to the application as follows:
+
+.. code:: python
+
+ from prompt_toolkit import Application
+ from prompt_toolkit.key_binding import KeyBindings
+
+ kb = KeyBindings()
+ app = Application(key_bindings=kb)
+ app.run()
+
+To register a new keyboard shortcut, we can use the
+:meth:`~prompt_toolkit.key_binding.KeyBindings.add` method as a decorator of
+the key handler:
+
+.. code:: python
+
+ from prompt_toolkit import Application
+ from prompt_toolkit.key_binding import KeyBindings
+
+ kb = KeyBindings()
+
+ @kb.add('c-q')
+ def exit_(event):
+ """
+ Pressing Ctrl-Q 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.
+ """
+ event.app.exit()
+
+ app = Application(key_bindings=kb, full_screen=True)
+ app.run()
+
+The callback function is named ``exit_`` for clarity, but it could have been
+named ``_`` (underscore) as well, because we won't refer to this name.
+
+:ref:`Read more about key bindings ...<key_bindings>`
+
+
+Modal containers
+^^^^^^^^^^^^^^^^
+
+The following container objects take a ``modal`` argument
+:class:`~prompt_toolkit.layout.VSplit`,
+:class:`~prompt_toolkit.layout.HSplit`, and
+:class:`~prompt_toolkit.layout.FloatContainer`.
+
+Setting ``modal=True`` makes what is called a **modal** container. Normally, a
+child container would inherit its parent key bindings. This does not apply to
+**modal** containers.
+
+Consider a **modal** container (e.g. :class:`~prompt_toolkit.layout.VSplit`)
+is child of another container, its parent. Any key bindings from the parent
+are not taken into account if the **modal** container (child) has the focus.
+
+This is useful in a complex layout, where many controls have their own key
+bindings, but you only want to enable the key bindings for a certain region of
+the layout.
+
+The global key bindings are always active.
+
+
+More about the Window class
+---------------------------
+
+As said earlier, a :class:`~prompt_toolkit.layout.Window` is a
+:class:`~prompt_toolkit.layout.Container` that wraps a
+:class:`~prompt_toolkit.layout.UIControl`, like a
+:class:`~prompt_toolkit.layout.BufferControl` or
+:class:`~prompt_toolkit.layout.FormattedTextControl`.
+
+.. note::
+
+ Basically, windows are the leafs in the tree structure that represent the UI.
+
+A :class:`~prompt_toolkit.layout.Window` provides a "view" on the
+:class:`~prompt_toolkit.layout.UIControl`, which provides lines of content. The
+window is in the first place responsible for the line wrapping and scrolling of
+the content, but there are much more options.
+
+- Adding left or right margins. These are used for displaying scroll bars or
+ line numbers.
+- There are the `cursorline` and `cursorcolumn` options. These allow
+ highlighting the line or column of the cursor position.
+- Alignment of the content. The content can be left aligned, right aligned or
+ centered.
+- Finally, the background can be filled with a default character.
+
+
+More about buffers and `BufferControl`
+--------------------------------------
+
+
+
+Input processors
+^^^^^^^^^^^^^^^^
+
+A :class:`~prompt_toolkit.layout.processors.Processor` is used to postprocess
+the content of a :class:`~prompt_toolkit.layout.BufferControl` before it's
+displayed. It can for instance highlight matching brackets or change the
+visualization of tabs and so on.
+
+A :class:`~prompt_toolkit.layout.processors.Processor` operates on individual
+lines. Basically, it takes a (formatted) line and produces a new (formatted)
+line.
+
+Some build-in processors:
+
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+| Processor | Usage: |
++============================================================================+===========================================================+
+| :class:`~prompt_toolkit.layout.processors.HighlightSearchProcessor` | Highlight the current search results. |
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+| :class:`~prompt_toolkit.layout.processors.HighlightSelectionProcessor` | Highlight the selection. |
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+| :class:`~prompt_toolkit.layout.processors.PasswordProcessor` | Display input as asterisks. (``*`` characters). |
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+| :class:`~prompt_toolkit.layout.processors.BracketsMismatchProcessor` | Highlight open/close mismatches for brackets. |
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+| :class:`~prompt_toolkit.layout.processors.BeforeInput` | Insert some text before. |
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+| :class:`~prompt_toolkit.layout.processors.AfterInput` | Insert some text after. |
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+| :class:`~prompt_toolkit.layout.processors.AppendAutoSuggestion` | Append auto suggestion text. |
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+| :class:`~prompt_toolkit.layout.processors.ShowLeadingWhiteSpaceProcessor` | Visualize leading whitespace. |
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+| :class:`~prompt_toolkit.layout.processors.ShowTrailingWhiteSpaceProcessor` | Visualize trailing whitespace. |
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+| :class:`~prompt_toolkit.layout.processors.TabsProcessor` | Visualize tabs as `n` spaces, or some symbols. |
++----------------------------------------------------------------------------+-----------------------------------------------------------+
+
+A :class:`~prompt_toolkit.layout.BufferControl` takes only one processor as
+input, but it is possible to "merge" multiple processors into one with the
+:func:`~prompt_toolkit.layout.processors.merge_processors` function.
diff --git a/docs/pages/gallery.rst b/docs/pages/gallery.rst
new file mode 100644
index 0000000..40b6917
--- /dev/null
+++ b/docs/pages/gallery.rst
@@ -0,0 +1,32 @@
+.. _gallery:
+
+Gallery
+=======
+
+Showcase, demonstrating the possibilities of prompt_toolkit.
+
+Ptpython, a Python REPL
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The prompt:
+
+.. image:: ../images/ptpython.png
+
+The configuration menu of ptpython.
+
+.. image:: ../images/ptpython-menu.png
+
+The history page with its help. (This is a full-screen layout.)
+
+.. image:: ../images/ptpython-history-help.png
+
+Pyvim, a Vim clone
+^^^^^^^^^^^^^^^^^^
+
+.. image:: ../images/pyvim.png
+
+
+Pymux, a terminal multiplexer (like tmux) in Python
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: ../images/pymux.png
diff --git a/docs/pages/getting_started.rst b/docs/pages/getting_started.rst
new file mode 100644
index 0000000..06287a0
--- /dev/null
+++ b/docs/pages/getting_started.rst
@@ -0,0 +1,84 @@
+.. _getting_started:
+
+Getting started
+===============
+
+Installation
+------------
+
+::
+
+ pip install prompt_toolkit
+
+For Conda, do:
+
+::
+
+ conda install -c https://conda.anaconda.org/conda-forge prompt_toolkit
+
+
+Several use cases: prompts versus full screen terminal applications
+--------------------------------------------------------------------
+
+`prompt_toolkit` was in the first place meant to be a replacement for readline.
+However, when it became more mature, we realized that all the components for
+full screen applications are there and `prompt_toolkit` is very capable of
+handling many use situations. `Pyvim
+<http://github.com/prompt-toolkit/pyvim>`_ and `pymux
+<http://github.com/prompt-toolkit/pymux>`_ are examples of full screen
+applications.
+
+.. image:: ../images/pyvim.png
+
+Basically, at the core, `prompt_toolkit` has a layout engine, that supports
+horizontal and vertical splits as well as floats, where each "window" can
+display a user control. The API for user controls is simple yet powerful.
+
+When `prompt_toolkit` is used as a readline replacement, (to simply read some
+input from the user), it uses a rather simple built-in layout. One that
+displays the default input buffer and the prompt, a float for the
+autocompletions and a toolbar for input validation which is hidden by default.
+
+For full screen applications, usually we build a custom layout ourselves.
+
+Further, there is a very flexible key binding system that can be programmed for
+all the needs of full screen applications.
+
+
+A simple prompt
+---------------
+
+The following snippet is the most simple example, it uses the
+:func:`~prompt_toolkit.shortcuts.prompt` function to asks the user for input
+and returns the text. Just like ``(raw_)input``.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+
+ text = prompt('Give me some input: ')
+ print('You said: %s' % text)
+
+
+Learning `prompt_toolkit`
+-------------------------
+
+In order to learn and understand `prompt_toolkit`, it is best to go through the
+all sections in the order below. Also don't forget to have a look at all the
+`examples
+<https://github.com/prompt-toolkit/python-prompt-toolkit/tree/master/examples>`_
+in the repository.
+
+- First, :ref:`learn how to print text <printing_text>`. This is important,
+ because it covers how to use "formatted text", which is something you'll use
+ whenever you want to use colors anywhere.
+
+- Secondly, go through the :ref:`asking for input <asking_for_input>` section.
+ This is useful for almost any use case, even for full screen applications.
+ It covers autocompletions, syntax highlighting, key bindings, and so on.
+
+- Then, learn about :ref:`dialogs`, which is easy and fun.
+
+- Finally, learn about :ref:`full screen applications
+ <full_screen_applications>` and read through :ref:`the advanced topics
+ <advanced_topics>`.
diff --git a/docs/pages/printing_text.rst b/docs/pages/printing_text.rst
new file mode 100644
index 0000000..8359d5f
--- /dev/null
+++ b/docs/pages/printing_text.rst
@@ -0,0 +1,274 @@
+.. _printing_text:
+
+Printing (and using) formatted text
+===================================
+
+Prompt_toolkit ships with a
+:func:`~prompt_toolkit.shortcuts.print_formatted_text` function that's meant to
+be (as much as possible) compatible with the built-in print function, but on
+top of that, also supports colors and formatting.
+
+On Linux systems, this will output VT100 escape sequences, while on Windows it
+will use Win32 API calls or VT100 sequences, depending on what is available.
+
+.. note::
+
+ This page is also useful if you'd like to learn how to use formatting
+ in other places, like in a prompt or a toolbar. Just like
+ :func:`~prompt_toolkit.shortcuts.print_formatted_text` takes any kind
+ of "formatted text" as input, prompts and toolbars also accept
+ "formatted text".
+
+Printing plain text
+-------------------
+
+The print function can be imported as follows:
+
+.. code:: python
+
+ from prompt_toolkit import print_formatted_text
+
+ print_formatted_text('Hello world')
+
+You can replace the built in ``print`` function as follows, if you want to.
+
+.. code:: python
+
+ from prompt_toolkit import print_formatted_text as print
+
+ print('Hello world')
+
+.. note::
+
+ If you're using Python 2, make sure to add ``from __future__ import
+ print_function``. Otherwise, it will not be possible to import a function
+ named ``print``.
+
+.. _formatted_text:
+
+Formatted text
+--------------
+
+There are several ways to display colors:
+
+- By creating an :class:`~prompt_toolkit.formatted_text.HTML` object.
+- By creating an :class:`~prompt_toolkit.formatted_text.ANSI` object that
+ contains ANSI escape sequences.
+- By creating a list of ``(style, text)`` tuples.
+- By creating a list of ``(pygments.Token, text)`` tuples, and wrapping it in
+ :class:`~prompt_toolkit.formatted_text.PygmentsTokens`.
+
+An instance of any of these four kinds of objects is called "formatted text".
+There are various places in prompt toolkit, where we accept not just plain text
+(as a string), but also formatted text.
+
+HTML
+^^^^
+
+:class:`~prompt_toolkit.formatted_text.HTML` can be used to indicate that a
+string contains HTML-like formatting. It recognizes the basic tags for bold,
+italic and underline: ``<b>``, ``<i>`` and ``<u>``.
+
+.. code:: python
+
+ from prompt_toolkit import print_formatted_text, HTML
+
+ print_formatted_text(HTML('<b>This is bold</b>'))
+ print_formatted_text(HTML('<i>This is italic</i>'))
+ print_formatted_text(HTML('<u>This is underlined</u>'))
+
+Further, it's possible to use tags for foreground colors:
+
+.. code:: python
+
+ # Colors from the ANSI palette.
+ print_formatted_text(HTML('<ansired>This is red</ansired>'))
+ print_formatted_text(HTML('<ansigreen>This is green</ansigreen>'))
+
+ # Named colors (256 color palette, or true color, depending on the output).
+ print_formatted_text(HTML('<skyblue>This is sky blue</skyblue>'))
+ print_formatted_text(HTML('<seagreen>This is sea green</seagreen>'))
+ print_formatted_text(HTML('<violet>This is violet</violet>'))
+
+Both foreground and background colors can also be specified setting the `fg`
+and `bg` attributes of any HTML tag:
+
+.. code:: python
+
+ # Colors from the ANSI palette.
+ print_formatted_text(HTML('<aaa fg="ansiwhite" bg="ansigreen">White on green</aaa>'))
+
+Underneath, all HTML tags are mapped to classes from a stylesheet, so you can
+assign a style for a custom tag.
+
+.. code:: python
+
+ from prompt_toolkit import print_formatted_text, HTML
+ from prompt_toolkit.styles import Style
+
+ style = Style.from_dict({
+ 'aaa': '#ff0066',
+ 'bbb': '#44ff00 italic',
+ })
+
+ print_formatted_text(HTML('<aaa>Hello</aaa> <bbb>world</bbb>!'), style=style)
+
+
+ANSI
+^^^^
+
+Some people like to use the VT100 ANSI escape sequences to generate output.
+Natively, this is however only supported on VT100 terminals, but prompt_toolkit
+can parse these, and map them to formatted text instances. This means that they
+will work on Windows as well. The :class:`~prompt_toolkit.formatted_text.ANSI`
+class takes care of that.
+
+.. code:: python
+
+ from prompt_toolkit import print_formatted_text, ANSI
+
+ print_formatted_text(ANSI('\x1b[31mhello \x1b[32mworld'))
+
+Keep in mind that even on a Linux VT100 terminal, the final output produced by
+prompt_toolkit, is not necessarily exactly the same. Depending on the color
+depth, it is possible that colors are mapped to different colors, and unknown
+tags will be removed.
+
+
+(style, text) tuples
+^^^^^^^^^^^^^^^^^^^^
+
+Internally, both :class:`~prompt_toolkit.formatted_text.HTML` and
+:class:`~prompt_toolkit.formatted_text.ANSI` objects are mapped to a list of
+``(style, text)`` tuples. It is however also possible to create such a list
+manually with :class:`~prompt_toolkit.formatted_text.FormattedText` class.
+This is a little more verbose, but it's probably the most powerful
+way of expressing formatted text.
+
+.. code:: python
+
+ from prompt_toolkit import print_formatted_text
+ from prompt_toolkit.formatted_text import FormattedText
+
+ text = FormattedText([
+ ('#ff0066', 'Hello'),
+ ('', ' '),
+ ('#44ff00 italic', 'World'),
+ ])
+
+ print_formatted_text(text)
+
+Similar to the :class:`~prompt_toolkit.formatted_text.HTML` example, it is also
+possible to use class names, and separate the styling in a style sheet.
+
+.. code:: python
+
+ from prompt_toolkit import print_formatted_text
+ from prompt_toolkit.formatted_text import FormattedText
+ from prompt_toolkit.styles import Style
+
+ # The text.
+ text = FormattedText([
+ ('class:aaa', 'Hello'),
+ ('', ' '),
+ ('class:bbb', 'World'),
+ ])
+
+ # The style sheet.
+ style = Style.from_dict({
+ 'aaa': '#ff0066',
+ 'bbb': '#44ff00 italic',
+ })
+
+ print_formatted_text(text, style=style)
+
+
+Pygments ``(Token, text)`` tuples
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+When you have a list of `Pygments <http://pygments.org/>`_ ``(Token, text)``
+tuples, then these can be printed by wrapping them in a
+:class:`~prompt_toolkit.formatted_text.PygmentsTokens` object.
+
+.. code:: python
+
+ from pygments.token import Token
+ from prompt_toolkit import print_formatted_text
+ from prompt_toolkit.formatted_text import PygmentsTokens
+
+ text = [
+ (Token.Keyword, 'print'),
+ (Token.Punctuation, '('),
+ (Token.Literal.String.Double, '"'),
+ (Token.Literal.String.Double, 'hello'),
+ (Token.Literal.String.Double, '"'),
+ (Token.Punctuation, ')'),
+ (Token.Text, '\n'),
+ ]
+
+ print_formatted_text(PygmentsTokens(text))
+
+
+Similarly, it is also possible to print the output of a Pygments lexer:
+
+.. code:: python
+
+ import pygments
+ from pygments.token import Token
+ from pygments.lexers.python import PythonLexer
+
+ from prompt_toolkit.formatted_text import PygmentsTokens
+ from prompt_toolkit import print_formatted_text
+
+ # Printing the output of a pygments lexer.
+ tokens = list(pygments.lex('print("Hello")', lexer=PythonLexer()))
+ print_formatted_text(PygmentsTokens(tokens))
+
+Prompt_toolkit ships with a default colorscheme which styles it just like
+Pygments would do, but if you'd like to change the colors, keep in mind that
+Pygments tokens map to classnames like this:
+
++-----------------------------------+---------------------------------------------+
+| pygments.Token | prompt_toolkit classname |
++===================================+=============================================+
+| - ``Token.Keyword`` | - ``"class:pygments.keyword"`` |
+| - ``Token.Punctuation`` | - ``"class:pygments.punctuation"`` |
+| - ``Token.Literal.String.Double`` | - ``"class:pygments.literal.string.double"``|
+| - ``Token.Text`` | - ``"class:pygments.text"`` |
+| - ``Token`` | - ``"class:pygments"`` |
++-----------------------------------+---------------------------------------------+
+
+A classname like ``pygments.literal.string.double`` is actually decomposed in
+the following four classnames: ``pygments``, ``pygments.literal``,
+``pygments.literal.string`` and ``pygments.literal.string.double``. The final
+style is computed by combining the style for these four classnames. So,
+changing the style from these Pygments tokens can be done as follows:
+
+.. code:: python
+
+ from prompt_toolkit.styles import Style
+
+ style = Style.from_dict({
+ 'pygments.keyword': 'underline',
+ 'pygments.literal.string': 'bg:#00ff00 #ffffff',
+ })
+ print_formatted_text(PygmentsTokens(tokens), style=style)
+
+
+to_formatted_text
+^^^^^^^^^^^^^^^^^
+
+A useful function to know about is
+:func:`~prompt_toolkit.formatted_text.to_formatted_text`. This ensures that the
+given input is valid formatted text. While doing so, an additional style can be
+applied as well.
+
+.. code:: python
+
+ from prompt_toolkit.formatted_text import to_formatted_text, HTML
+ from prompt_toolkit import print_formatted_text
+
+ html = HTML('<aaa>Hello</aaa> <bbb>world</bbb>!')
+ text = to_formatted_text(html, style='class:my_html bg:#00ff00 italic')
+
+ print_formatted_text(text)
diff --git a/docs/pages/progress_bars.rst b/docs/pages/progress_bars.rst
new file mode 100644
index 0000000..54a8ee1
--- /dev/null
+++ b/docs/pages/progress_bars.rst
@@ -0,0 +1,248 @@
+.. _progress_bars:
+
+Progress bars
+=============
+
+Prompt_toolkit ships with a high level API for displaying progress bars,
+inspired by `tqdm <https://github.com/tqdm/tqdm>`_
+
+.. warning::
+
+ The API for the prompt_toolkit progress bars is still very new and can
+ possibly change in the future. It is usable and tested, but keep this in
+ mind when upgrading.
+
+Remember that the `examples directory <https://github.com/prompt-toolkit/python-prompt-toolkit/tree/master/examples>`_
+of the prompt_toolkit repository ships with many progress bar examples as well.
+
+
+Simple progress bar
+-------------------
+
+Creating a new progress bar can be done by calling the
+:class:`~prompt_toolkit.shortcuts.ProgressBar` context manager.
+
+The progress can be displayed for any iterable. This works by wrapping the
+iterable (like ``range``) with the
+:class:`~prompt_toolkit.shortcuts.ProgressBar` context manager itself. This
+way, the progress bar knows when the next item is consumed by the forloop and
+when progress happens.
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import ProgressBar
+ import time
+
+
+ with ProgressBar() as pb:
+ for i in pb(range(800)):
+ time.sleep(.01)
+
+.. image:: ../images/progress-bars/simple-progress-bar.png
+
+Keep in mind that not all iterables can report their total length. This happens
+with a typical generator. In that case, you can still pass the total as follows
+in order to make displaying the progress possible:
+
+.. code:: python
+
+ def some_iterable():
+ yield ...
+
+ with ProgressBar() as pb:
+ for i in pb(some_iterable(), total=1000):
+ time.sleep(.01)
+
+
+Multiple parallel tasks
+-----------------------
+
+A prompt_toolkit :class:`~prompt_toolkit.shortcuts.ProgressBar` can display the
+progress of multiple tasks running in parallel. Each task can run in a separate
+thread and the :class:`~prompt_toolkit.shortcuts.ProgressBar` user interface
+runs in its own thread.
+
+Notice that we set the "daemon" flag for both threads that run the tasks. This
+is because control-c will stop the progress and quit our application. We don't
+want the application to wait for the background threads to finish. Whether you
+want this depends on the application.
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import ProgressBar
+ import time
+ import threading
+
+
+ with ProgressBar() as pb:
+ # Two parallel tasks.
+ def task_1():
+ for i in pb(range(100)):
+ time.sleep(.05)
+
+ def task_2():
+ for i in pb(range(150)):
+ time.sleep(.08)
+
+ # Start threads.
+ t1 = threading.Thread(target=task_1)
+ t2 = threading.Thread(target=task_2)
+ t1.daemon = True
+ t2.daemon = True
+ t1.start()
+ t2.start()
+
+ # Wait for the threads to finish. We use a timeout for the join() call,
+ # because on Windows, join cannot be interrupted by Control-C or any other
+ # signal.
+ for t in [t1, t2]:
+ while t.is_alive():
+ t.join(timeout=.5)
+
+.. image:: ../images/progress-bars/two-tasks.png
+
+
+Adding a title and label
+------------------------
+
+Each progress bar can have one title, and for each task an individual label.
+Both the title and the labels can be :ref:`formatted text <formatted_text>`.
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import ProgressBar
+ from prompt_toolkit.formatted_text import HTML
+ import time
+
+ title = HTML('Downloading <style bg="yellow" fg="black">4 files...</style>')
+ label = HTML('<ansired>some file</ansired>: ')
+
+ with ProgressBar(title=title) as pb:
+ for i in pb(range(800), label=label):
+ time.sleep(.01)
+
+.. image:: ../images/progress-bars/colored-title-and-label.png
+
+
+Formatting the progress bar
+---------------------------
+
+The visualization of a :class:`~prompt_toolkit.shortcuts.ProgressBar` can be
+customized by using a different sequence of formatters. The default formatting
+looks something like this:
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts.progress_bar.formatters import *
+
+ default_formatting = [
+ Label(),
+ Text(' '),
+ Percentage(),
+ Text(' '),
+ Bar(),
+ Text(' '),
+ Progress(),
+ Text(' '),
+ Text('eta [', style='class:time-left'),
+ TimeLeft(),
+ Text(']', style='class:time-left'),
+ Text(' '),
+ ]
+
+That sequence of
+:class:`~prompt_toolkit.shortcuts.progress_bar.formatters.Formatter` can be
+passed to the `formatter` argument of
+:class:`~prompt_toolkit.shortcuts.ProgressBar`. So, we could change this and
+modify the progress bar to look like an apt-get style progress bar:
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import ProgressBar
+ from prompt_toolkit.styles import Style
+ from prompt_toolkit.shortcuts.progress_bar import formatters
+ import time
+
+ style = Style.from_dict({
+ 'label': 'bg:#ffff00 #000000',
+ 'percentage': 'bg:#ffff00 #000000',
+ 'current': '#448844',
+ 'bar': '',
+ })
+
+
+ custom_formatters = [
+ formatters.Label(),
+ formatters.Text(': [', style='class:percentage'),
+ formatters.Percentage(),
+ formatters.Text(']', style='class:percentage'),
+ formatters.Text(' '),
+ formatters.Bar(sym_a='#', sym_b='#', sym_c='.'),
+ formatters.Text(' '),
+ ]
+
+ with ProgressBar(style=style, formatters=custom_formatters) as pb:
+ for i in pb(range(1600), label='Installing'):
+ time.sleep(.01)
+
+.. image:: ../images/progress-bars/apt-get.png
+
+
+Adding key bindings and toolbar
+-------------------------------
+
+Like other prompt_toolkit applications, we can add custom key bindings, by
+passing a :class:`~prompt_toolkit.key_binding.KeyBindings` object:
+
+.. code:: python
+
+ from prompt_toolkit import HTML
+ from prompt_toolkit.key_binding import KeyBindings
+ from prompt_toolkit.patch_stdout import patch_stdout
+ from prompt_toolkit.shortcuts import ProgressBar
+
+ import os
+ import time
+ import signal
+
+ bottom_toolbar = HTML(' <b>[f]</b> Print "f" <b>[x]</b> Abort.')
+
+ # Create custom key bindings first.
+ kb = KeyBindings()
+ cancel = [False]
+
+ @kb.add('f')
+ def _(event):
+ print('You pressed `f`.')
+
+ @kb.add('x')
+ def _(event):
+ " Send Abort (control-c) signal. "
+ cancel[0] = True
+ os.kill(os.getpid(), signal.SIGINT)
+
+ # Use `patch_stdout`, to make sure that prints go above the
+ # application.
+ with patch_stdout():
+ with ProgressBar(key_bindings=kb, bottom_toolbar=bottom_toolbar) as pb:
+ for i in pb(range(800)):
+ time.sleep(.01)
+
+ # Stop when the cancel flag has been set.
+ if cancel[0]:
+ break
+
+Notice that we use :func:`~prompt_toolkit.patch_stdout.patch_stdout` to make
+printing text possible while the progress bar is displayed. This ensures that
+printing happens above the progress bar.
+
+Further, when "x" is pressed, we set a cancel flag, which stops the progress.
+It would also be possible to send `SIGINT` to the mean thread, but that's not
+always considered a clean way of cancelling something.
+
+In the example above, we also display a toolbar at the bottom which shows the
+key bindings.
+
+.. image:: ../images/progress-bars/custom-key-bindings.png
+
+:ref:`Read more about key bindings ...<key_bindings>`
diff --git a/docs/pages/reference.rst b/docs/pages/reference.rst
new file mode 100644
index 0000000..d8a705e
--- /dev/null
+++ b/docs/pages/reference.rst
@@ -0,0 +1,393 @@
+Reference
+=========
+
+Application
+-----------
+
+.. automodule:: prompt_toolkit.application
+ :members: Application, get_app, get_app_or_none, set_app,
+ create_app_session, AppSession, get_app_session, DummyApplication,
+ in_terminal, run_in_terminal,
+
+
+Formatted text
+--------------
+
+.. automodule:: prompt_toolkit.formatted_text
+ :members:
+
+
+Buffer
+------
+
+.. automodule:: prompt_toolkit.buffer
+ :members:
+
+
+Selection
+---------
+
+.. automodule:: prompt_toolkit.selection
+ :members:
+
+
+Clipboard
+---------
+
+.. automodule:: prompt_toolkit.clipboard
+ :members: Clipboard, ClipboardData, DummyClipboard, DynamicClipboard, InMemoryClipboard
+
+.. automodule:: prompt_toolkit.clipboard.pyperclip
+ :members:
+
+
+Auto completion
+---------------
+
+.. automodule:: prompt_toolkit.completion
+ :members:
+
+
+Document
+--------
+
+.. automodule:: prompt_toolkit.document
+ :members:
+
+
+Enums
+-----
+
+.. automodule:: prompt_toolkit.enums
+ :members:
+
+
+History
+-------
+
+.. automodule:: prompt_toolkit.history
+ :members:
+
+
+Keys
+----
+
+.. automodule:: prompt_toolkit.keys
+ :members:
+
+
+Style
+-----
+
+.. automodule:: prompt_toolkit.styles
+ :members: Attrs, ANSI_COLOR_NAMES, BaseStyle, DummyStyle, DynamicStyle,
+ Style, Priority, merge_styles, style_from_pygments_cls,
+ style_from_pygments_dict, pygments_token_to_classname, NAMED_COLORS,
+ StyleTransformation, SwapLightAndDarkStyleTransformation,
+ AdjustBrightnessStyleTransformation, merge_style_transformations,
+ DummyStyleTransformation, ConditionalStyleTransformation,
+ DynamicStyleTransformation
+
+
+Shortcuts
+---------
+
+.. automodule:: prompt_toolkit.shortcuts
+ :members: prompt, PromptSession, confirm, CompleteStyle,
+ create_confirm_session, clear, clear_title, print_formatted_text,
+ set_title, ProgressBar, input_dialog, message_dialog, progress_dialog,
+ radiolist_dialog, yes_no_dialog, button_dialog
+
+.. automodule:: prompt_toolkit.shortcuts.progress_bar.formatters
+ :members:
+
+
+Validation
+----------
+
+.. automodule:: prompt_toolkit.validation
+ :members:
+
+
+Auto suggestion
+---------------
+
+.. automodule:: prompt_toolkit.auto_suggest
+ :members:
+
+
+Renderer
+--------
+
+.. automodule:: prompt_toolkit.renderer
+ :members:
+
+Lexers
+------
+
+.. automodule:: prompt_toolkit.lexers
+ :members:
+
+
+Layout
+------
+
+.. automodule:: prompt_toolkit.layout
+
+The layout class itself
+^^^^^^^^^^^^^^^^^^^^^^^
+
+.. autoclass:: prompt_toolkit.layout.Layout
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.InvalidLayoutError
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.walk
+ :members:
+
+Containers
+^^^^^^^^^^
+
+.. autoclass:: prompt_toolkit.layout.Container
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.HSplit
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.VSplit
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.FloatContainer
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.Float
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.Window
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.WindowAlign
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.ConditionalContainer
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.DynamicContainer
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.ScrollablePane
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.ScrollOffsets
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.ColorColumn
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.to_container
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.to_window
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.is_container
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.HorizontalAlign
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.VerticalAlign
+ :members:
+
+Controls
+^^^^^^^^
+
+.. autoclass:: prompt_toolkit.layout.BufferControl
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.SearchBufferControl
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.DummyControl
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.FormattedTextControl
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.UIControl
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.UIContent
+ :members:
+
+
+Other
+^^^^^
+
+
+Sizing
+""""""
+
+.. autoclass:: prompt_toolkit.layout.Dimension
+ :members:
+
+
+Margins
+"""""""
+
+.. autoclass:: prompt_toolkit.layout.Margin
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.NumberedMargin
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.ScrollbarMargin
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.ConditionalMargin
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.PromptMargin
+ :members:
+
+
+Completion Menus
+""""""""""""""""
+
+.. autoclass:: prompt_toolkit.layout.CompletionsMenu
+ :members:
+
+.. autoclass:: prompt_toolkit.layout.MultiColumnCompletionsMenu
+ :members:
+
+
+Processors
+""""""""""
+
+.. automodule:: prompt_toolkit.layout.processors
+ :members:
+
+
+Utils
+"""""
+
+.. automodule:: prompt_toolkit.layout.utils
+ :members:
+
+
+Screen
+""""""
+
+.. automodule:: prompt_toolkit.layout.screen
+ :members:
+
+
+Widgets
+-------
+
+.. automodule:: prompt_toolkit.widgets
+ :members: TextArea, Label, Button, Frame, Shadow, Box, VerticalLine,
+ HorizontalLine, RadioList, Checkbox, ProgressBar, CompletionsToolbar,
+ FormattedTextToolbar, SearchToolbar, SystemToolbar, ValidationToolbar,
+ MenuContainer, MenuItem
+
+
+Filters
+-------
+
+.. automodule:: prompt_toolkit.filters
+ :members:
+
+.. autoclass:: prompt_toolkit.filters.Filter
+ :members:
+
+.. autoclass:: prompt_toolkit.filters.Condition
+ :members:
+
+.. automodule:: prompt_toolkit.filters.utils
+ :members:
+
+.. automodule:: prompt_toolkit.filters.app
+ :members:
+
+
+Key binding
+-----------
+
+.. automodule:: prompt_toolkit.key_binding
+ :members: KeyBindingsBase, KeyBindings, ConditionalKeyBindings,
+ merge_key_bindings, DynamicKeyBindings
+
+.. automodule:: prompt_toolkit.key_binding.defaults
+ :members:
+
+.. automodule:: prompt_toolkit.key_binding.vi_state
+ :members:
+
+.. automodule:: prompt_toolkit.key_binding.key_processor
+ :members:
+
+
+Eventloop
+---------
+
+.. automodule:: prompt_toolkit.eventloop
+ :members: run_in_executor_with_context, call_soon_threadsafe,
+ get_traceback_from_context, get_event_loop
+
+.. automodule:: prompt_toolkit.eventloop.inputhook
+ :members:
+
+.. automodule:: prompt_toolkit.eventloop.utils
+ :members:
+
+
+Input
+-----
+
+.. automodule:: prompt_toolkit.input
+ :members: Input, DummyInput, create_input, create_pipe_input
+
+.. automodule:: prompt_toolkit.input.vt100
+ :members:
+
+.. automodule:: prompt_toolkit.input.vt100_parser
+ :members:
+
+.. automodule:: prompt_toolkit.input.ansi_escape_sequences
+ :members:
+
+.. automodule:: prompt_toolkit.input.win32
+ :members:
+
+Output
+------
+
+.. automodule:: prompt_toolkit.output
+ :members: Output, DummyOutput, ColorDepth, create_output
+
+.. automodule:: prompt_toolkit.output.vt100
+ :members:
+
+.. automodule:: prompt_toolkit.output.win32
+ :members:
+
+
+Data structures
+---------------
+
+.. autoclass:: prompt_toolkit.layout.WindowRenderInfo
+ :members:
+
+.. autoclass:: prompt_toolkit.data_structures.Point
+ :members:
+
+.. autoclass:: prompt_toolkit.data_structures.Size
+ :members:
+
+Patch stdout
+------------
+
+.. automodule:: prompt_toolkit.patch_stdout
+ :members: patch_stdout, StdoutProxy
diff --git a/docs/pages/related_projects.rst b/docs/pages/related_projects.rst
new file mode 100644
index 0000000..ad0a8af
--- /dev/null
+++ b/docs/pages/related_projects.rst
@@ -0,0 +1,11 @@
+.. _related_projects:
+
+Related projects
+================
+
+There are some other Python libraries that provide similar functionality that
+are also worth checking out:
+
+- `Urwid <http://urwid.org/>`_
+- `Textual <https://textual.textualize.io/>`_
+- `Rich <https://rich.readthedocs.io/>`_
diff --git a/docs/pages/tutorials/index.rst b/docs/pages/tutorials/index.rst
new file mode 100644
index 0000000..827b511
--- /dev/null
+++ b/docs/pages/tutorials/index.rst
@@ -0,0 +1,10 @@
+.. _tutorials:
+
+Tutorials
+=========
+
+.. toctree::
+ :caption: Contents:
+ :maxdepth: 1
+
+ repl
diff --git a/docs/pages/tutorials/repl.rst b/docs/pages/tutorials/repl.rst
new file mode 100644
index 0000000..946786f
--- /dev/null
+++ b/docs/pages/tutorials/repl.rst
@@ -0,0 +1,341 @@
+.. _tutorial_repl:
+
+Tutorial: Build an SQLite REPL
+==============================
+
+The aim of this tutorial is to build an interactive command line interface for
+an SQLite database using prompt_toolkit_.
+
+First, install the library using pip, if you haven't done this already.
+
+.. code::
+
+ pip install prompt_toolkit
+
+
+Read User Input
+---------------
+
+Let's start accepting input using the
+:func:`~prompt_toolkit.shortcuts.prompt()` function. This will ask the user for
+input, and echo back whatever the user typed. We wrap it in a ``main()``
+function as a good practice.
+
+.. code:: python
+
+ from prompt_toolkit import prompt
+
+ def main():
+ text = prompt('> ')
+ print('You entered:', text)
+
+ if __name__ == '__main__':
+ main()
+
+.. image:: ../../images/repl/sqlite-1.png
+
+
+Loop The REPL
+-------------
+
+Now we want to call the :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt`
+method in a loop. In order to keep the history, the easiest way to do it is to
+use a :class:`~prompt_toolkit.shortcuts.PromptSession`. This uses an
+:class:`~prompt_toolkit.history.InMemoryHistory` underneath that keeps track of
+the history, so that if the user presses the up-arrow, they'll see the previous
+entries.
+
+The :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` method raises
+``KeyboardInterrupt`` when ControlC has been pressed and ``EOFError`` when
+ControlD has been pressed. This is what people use for cancelling commands and
+exiting in a REPL. The try/except below handles these error conditions and make
+sure that we go to the next iteration of the loop or quit the loop
+respectively.
+
+.. code:: python
+
+ from prompt_toolkit import PromptSession
+
+ def main():
+ session = PromptSession()
+
+ while True:
+ try:
+ text = session.prompt('> ')
+ except KeyboardInterrupt:
+ continue
+ except EOFError:
+ break
+ else:
+ print('You entered:', text)
+ print('GoodBye!')
+
+ if __name__ == '__main__':
+ main()
+
+.. image:: ../../images/repl/sqlite-2.png
+
+
+Syntax Highlighting
+-------------------
+
+This is where things get really interesting. Let's step it up a notch by adding
+syntax highlighting to the user input. We know that users will be entering SQL
+statements, so we can leverage the Pygments_ library for coloring the input.
+The ``lexer`` parameter allows us to set the syntax lexer. We're going to use
+the ``SqlLexer`` from the Pygments_ library for highlighting.
+
+Notice that in order to pass a Pygments lexer to prompt_toolkit, it needs to be
+wrapped into a :class:`~prompt_toolkit.lexers.PygmentsLexer`.
+
+.. code:: python
+
+ from prompt_toolkit import PromptSession
+ from prompt_toolkit.lexers import PygmentsLexer
+ from pygments.lexers.sql import SqlLexer
+
+ def main():
+ session = PromptSession(lexer=PygmentsLexer(SqlLexer))
+
+ while True:
+ try:
+ text = session.prompt('> ')
+ except KeyboardInterrupt:
+ continue
+ except EOFError:
+ break
+ else:
+ print('You entered:', text)
+ print('GoodBye!')
+
+ if __name__ == '__main__':
+ main()
+
+.. image:: ../../images/repl/sqlite-3.png
+
+
+Auto-completion
+---------------
+
+Now we are going to add auto completion. We'd like to display a drop down menu
+of `possible keywords <https://www.sqlite.org/lang_keywords.html>`_ when the
+user starts typing.
+
+We can do this by creating an `sql_completer` object from the
+:class:`~prompt_toolkit.completion.WordCompleter` class, defining a set of
+`keywords` for the auto-completion.
+
+Like the lexer, this ``sql_completer`` instance can be passed to either the
+:class:`~prompt_toolkit.shortcuts.PromptSession` class or the
+:meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` method.
+
+.. code:: python
+
+ from prompt_toolkit import PromptSession
+ from prompt_toolkit.completion import WordCompleter
+ from prompt_toolkit.lexers import PygmentsLexer
+ from pygments.lexers.sql import SqlLexer
+
+ sql_completer = WordCompleter([
+ 'abort', 'action', 'add', 'after', 'all', 'alter', 'analyze', 'and',
+ 'as', 'asc', 'attach', 'autoincrement', 'before', 'begin', 'between',
+ 'by', 'cascade', 'case', 'cast', 'check', 'collate', 'column',
+ 'commit', 'conflict', 'constraint', 'create', 'cross', 'current_date',
+ 'current_time', 'current_timestamp', 'database', 'default',
+ 'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct',
+ 'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive',
+ 'exists', 'explain', 'fail', 'for', 'foreign', 'from', 'full', 'glob',
+ 'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index',
+ 'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect',
+ 'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit',
+ 'match', 'natural', 'no', 'not', 'notnull', 'null', 'of', 'offset',
+ 'on', 'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query',
+ 'raise', 'recursive', 'references', 'regexp', 'reindex', 'release',
+ 'rename', 'replace', 'restrict', 'right', 'rollback', 'row',
+ 'savepoint', 'select', 'set', 'table', 'temp', 'temporary', 'then',
+ 'to', 'transaction', 'trigger', 'union', 'unique', 'update', 'using',
+ 'vacuum', 'values', 'view', 'virtual', 'when', 'where', 'with',
+ 'without'], ignore_case=True)
+
+ def main():
+ session = PromptSession(
+ lexer=PygmentsLexer(SqlLexer), completer=sql_completer)
+
+ while True:
+ try:
+ text = session.prompt('> ')
+ except KeyboardInterrupt:
+ continue
+ except EOFError:
+ break
+ else:
+ print('You entered:', text)
+ print('GoodBye!')
+
+ if __name__ == '__main__':
+ main()
+
+.. image:: ../../images/repl/sqlite-4.png
+
+In about 30 lines of code we got ourselves an auto completing, syntax
+highlighting REPL. Let's make it even better.
+
+
+Styling the menus
+-----------------
+
+If we want, we can now change the colors of the completion menu. This is
+possible by creating a :class:`~prompt_toolkit.styles.Style` instance and
+passing it to the :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt`
+function.
+
+.. code:: python
+
+ from prompt_toolkit import PromptSession
+ from prompt_toolkit.completion import WordCompleter
+ from prompt_toolkit.lexers import PygmentsLexer
+ from prompt_toolkit.styles import Style
+ from pygments.lexers.sql import SqlLexer
+
+ sql_completer = WordCompleter([
+ 'abort', 'action', 'add', 'after', 'all', 'alter', 'analyze', 'and',
+ 'as', 'asc', 'attach', 'autoincrement', 'before', 'begin', 'between',
+ 'by', 'cascade', 'case', 'cast', 'check', 'collate', 'column',
+ 'commit', 'conflict', 'constraint', 'create', 'cross', 'current_date',
+ 'current_time', 'current_timestamp', 'database', 'default',
+ 'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct',
+ 'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive',
+ 'exists', 'explain', 'fail', 'for', 'foreign', 'from', 'full', 'glob',
+ 'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index',
+ 'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect',
+ 'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit',
+ 'match', 'natural', 'no', 'not', 'notnull', 'null', 'of', 'offset',
+ 'on', 'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query',
+ 'raise', 'recursive', 'references', 'regexp', 'reindex', 'release',
+ 'rename', 'replace', 'restrict', 'right', 'rollback', 'row',
+ 'savepoint', 'select', 'set', 'table', 'temp', 'temporary', 'then',
+ 'to', 'transaction', 'trigger', 'union', 'unique', 'update', 'using',
+ 'vacuum', 'values', 'view', 'virtual', 'when', 'where', 'with',
+ 'without'], ignore_case=True)
+
+ style = Style.from_dict({
+ 'completion-menu.completion': 'bg:#008888 #ffffff',
+ 'completion-menu.completion.current': 'bg:#00aaaa #000000',
+ 'scrollbar.background': 'bg:#88aaaa',
+ 'scrollbar.button': 'bg:#222222',
+ })
+
+ def main():
+ session = PromptSession(
+ lexer=PygmentsLexer(SqlLexer), completer=sql_completer, style=style)
+
+ while True:
+ try:
+ text = session.prompt('> ')
+ except KeyboardInterrupt:
+ continue
+ except EOFError:
+ break
+ else:
+ print('You entered:', text)
+ print('GoodBye!')
+
+ if __name__ == '__main__':
+ main()
+
+.. image:: ../../images/repl/sqlite-5.png
+
+All that's left is hooking up the sqlite backend, which is left as an exercise
+for the reader. Just kidding... Keep reading.
+
+
+Hook up Sqlite
+--------------
+
+This step is the final step to make the SQLite REPL actually work. It's time
+to relay the input to SQLite.
+
+Obviously I haven't done the due diligence to deal with the errors. But it
+gives a good idea of how to get started.
+
+.. code:: python
+
+ #!/usr/bin/env python
+ import sys
+ import sqlite3
+
+ from prompt_toolkit import PromptSession
+ from prompt_toolkit.completion import WordCompleter
+ from prompt_toolkit.lexers import PygmentsLexer
+ from prompt_toolkit.styles import Style
+ from pygments.lexers.sql import SqlLexer
+
+ sql_completer = WordCompleter([
+ 'abort', 'action', 'add', 'after', 'all', 'alter', 'analyze', 'and',
+ 'as', 'asc', 'attach', 'autoincrement', 'before', 'begin', 'between',
+ 'by', 'cascade', 'case', 'cast', 'check', 'collate', 'column',
+ 'commit', 'conflict', 'constraint', 'create', 'cross', 'current_date',
+ 'current_time', 'current_timestamp', 'database', 'default',
+ 'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct',
+ 'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive',
+ 'exists', 'explain', 'fail', 'for', 'foreign', 'from', 'full', 'glob',
+ 'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index',
+ 'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect',
+ 'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit',
+ 'match', 'natural', 'no', 'not', 'notnull', 'null', 'of', 'offset',
+ 'on', 'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query',
+ 'raise', 'recursive', 'references', 'regexp', 'reindex', 'release',
+ 'rename', 'replace', 'restrict', 'right', 'rollback', 'row',
+ 'savepoint', 'select', 'set', 'table', 'temp', 'temporary', 'then',
+ 'to', 'transaction', 'trigger', 'union', 'unique', 'update', 'using',
+ 'vacuum', 'values', 'view', 'virtual', 'when', 'where', 'with',
+ 'without'], ignore_case=True)
+
+ style = Style.from_dict({
+ 'completion-menu.completion': 'bg:#008888 #ffffff',
+ 'completion-menu.completion.current': 'bg:#00aaaa #000000',
+ 'scrollbar.background': 'bg:#88aaaa',
+ 'scrollbar.button': 'bg:#222222',
+ })
+
+ def main(database):
+ connection = sqlite3.connect(database)
+ session = PromptSession(
+ lexer=PygmentsLexer(SqlLexer), completer=sql_completer, style=style)
+
+ while True:
+ try:
+ text = session.prompt('> ')
+ except KeyboardInterrupt:
+ continue # Control-C pressed. Try again.
+ except EOFError:
+ break # Control-D pressed.
+
+ with connection:
+ try:
+ messages = connection.execute(text)
+ except Exception as e:
+ print(repr(e))
+ else:
+ for message in messages:
+ print(message)
+
+ print('GoodBye!')
+
+ if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ db = ':memory:'
+ else:
+ db = sys.argv[1]
+
+ main(db)
+
+.. image:: ../../images/repl/sqlite-6.png
+
+I hope that gives an idea of how to get started on building command line
+interfaces.
+
+The End.
+
+.. _prompt_toolkit: https://github.com/prompt-toolkit/python-prompt-toolkit
+.. _Pygments: http://pygments.org/
diff --git a/docs/pages/upgrading/2.0.rst b/docs/pages/upgrading/2.0.rst
new file mode 100644
index 0000000..6067057
--- /dev/null
+++ b/docs/pages/upgrading/2.0.rst
@@ -0,0 +1,221 @@
+.. _upgrading_2_0:
+
+Upgrading to prompt_toolkit 2.0
+===============================
+
+Prompt_toolkit 2.0 is not compatible with 1.0, however you probably want to
+upgrade your applications. This page explains why we have these differences and
+how to upgrade.
+
+If you experience some difficulties or you feel that some information is
+missing from this page, don't hesitate to open a GitHub issue for help.
+
+
+Why all these breaking changes?
+-------------------------------
+
+After more and more custom prompt_toolkit applications were developed, it
+became clear that prompt_toolkit 1.0 was not flexible enough for certain use
+cases. Mostly, the development of full screen applications was not really
+natural. All the important components, like the rendering, key bindings, input
+and output handling were present, but the API was in the first place designed
+for simple command line prompts. This was mostly notably in the following two
+places:
+
+- First, there was the focus which was always pointing to a
+ :class:`~prompt_toolkit.buffer.Buffer` (or text input widget), but in full
+ screen applications there are other widgets, like menus and buttons which
+ can be focused.
+- And secondly, it was impossible to make reusable UI components. All the key
+ bindings for the entire applications were stored together in one
+ ``KeyBindings`` object, and similar, all
+ :class:`~prompt_toolkit.buffer.Buffer` objects were stored together in one
+ dictionary. This didn't work well. You want reusable components to define
+ their own key bindings and everything. It's the idea of encapsulation.
+
+For simple prompts, the changes wouldn't be that invasive, but given that there
+would be some, I took the opportunity to fix a couple of other things. For
+instance:
+
+- In prompt_toolkit 1.0, we translated `\\r` into `\\n` during the input
+ processing. This was not a good idea, because some people wanted to handle
+ these keys individually. This makes sense if you keep in mind that they
+ correspond to `Control-M` and `Control-J`. However, we couldn't fix this
+ without breaking everyone's enter key, which happens to be the most important
+ key in prompts.
+
+Given that we were going to break compatibility anyway, we changed a couple of
+other important things that effect both simple prompt applications and
+full screen applications. These are the most important:
+
+- We no longer depend on Pygments for styling. While we like Pygments, it was
+ not flexible enough to provide all the styling options that we need, and the
+ Pygments tokens were not ideal for styling anything besides tokenized text.
+
+ Instead we created something similar to CSS. All UI components can attach
+ classnames to themselves, as well as define an inline style. The final style is
+ then computed by combining the inline styles, the classnames and the style
+ sheet.
+
+ There are still adaptors available for using Pygments lexers as well as for
+ Pygments styles.
+
+- The way that key bindings were defined was too complex.
+ ``KeyBindingsManager`` was too complex and no longer exists. Every set of key
+ bindings is now a
+ :class:`~prompt_toolkit.key_binding.KeyBindings` object and multiple of these
+ can be merged together at any time. The runtime performance remains the same,
+ but it's now easier for users.
+
+- The separation between the ``CommandLineInterface`` and
+ :class:`~prompt_toolkit.application.Application` class was confusing and in
+ the end, didn't really had an advantage. These two are now merged together in
+ one :class:`~prompt_toolkit.application.Application` class.
+
+- We no longer pass around the active ``CommandLineInterface``. This was one of
+ the most annoying things. Key bindings need it in order to change anything
+ and filters need it in order to evaluate their state. It was pretty annoying,
+ especially because there was usually only one application active at a time.
+ So, :class:`~prompt_toolkit.application.Application` became a ``TaskLocal``.
+ That is like a global variable, but scoped in the current coroutine or
+ context. The way this works is still not 100% correct, but good enough for
+ the projects that need it (like Pymux), and hopefully Python will get support
+ for this in the future thanks to PEP521, PEP550 or PEP555.
+
+All of these changes have been tested for many months, and I can say with
+confidence that prompt_toolkit 2.0 is a better prompt_toolkit.
+
+
+Some new features
+-----------------
+
+Apart from the breaking changes above, there are also some exciting new
+features.
+
+- We now support vt100 escape codes for Windows consoles on Windows 10. This
+ means much faster rendering, and full color support.
+
+- We have a concept of formatted text. This is an object that evaluates to
+ styled text. Every input that expects some text, like the message in a
+ prompt, or the text in a toolbar, can take any kind of formatted text as input.
+ This means you can pass in a plain string, but also a list of `(style,
+ text)` tuples (similar to a Pygments tokenized string), or an
+ :class:`~prompt_toolkit.formatted_text.HTML` object. This simplifies many
+ APIs.
+
+- New utilities were added. We now have function for printing formatted text
+ and an experimental module for displaying progress bars.
+
+- Autocompletion, input validation, and auto suggestion can now either be
+ asynchronous or synchronous. By default they are synchronous, but by wrapping
+ them in :class:`~prompt_toolkit.completion.ThreadedCompleter`,
+ :class:`~prompt_toolkit.validation.ThreadedValidator` or
+ :class:`~prompt_toolkit.auto_suggest.ThreadedAutoSuggest`, they will become
+ asynchronous by running in a background thread.
+
+ Further, if the autocompletion code runs in a background thread, we will show
+ the completions as soon as they arrive. This means that the autocompletion
+ algorithm could for instance first yield the most trivial completions and then
+ take time to produce the completions that take more time.
+
+
+Upgrading
+---------
+
+More guidelines on how to upgrade will follow.
+
+
+`AbortAction` has been removed
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Prompt_toolkit 1.0 had an argument ``abort_action`` for both the
+``Application`` class as well as for the ``prompt`` function. This has been
+removed. The recommended way to handle this now is by capturing
+``KeyboardInterrupt`` and ``EOFError`` manually.
+
+
+Calling `create_eventloop` usually not required anymore
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Prompt_toolkit 2.0 will automatically create the appropriate event loop when
+it's needed for the first time. There is no need to create one and pass it
+around. If you want to run an application on top of asyncio (without using an
+executor), it still needs to be activated by calling
+:func:`~prompt_toolkit.eventloop.use_asyncio_event_loop` at the beginning.
+
+
+Pygments styles and tokens
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+prompt_toolkit 2.0 no longer depends on `Pygments <http://pygments.org/>`_, but
+that definitely doesn't mean that you can't use any Pygments functionality
+anymore. The only difference is that Pygments stuff needs to be wrapped in an
+adaptor to make it compatible with the native prompt_toolkit objects.
+
+- For instance, if you have a list of ``(pygments.Token, text)`` tuples for
+ formatting, then this needs to be wrapped in a
+ :class:`~prompt_toolkit.formatted_text.PygmentsTokens` object. This is an
+ adaptor that turns it into prompt_toolkit "formatted text". Feel free to keep
+ using this.
+
+- Pygments lexers need to be wrapped in a
+ :class:`~prompt_toolkit.lexers.PygmentsLexer`. This will convert the list of
+ Pygments tokens into prompt_toolkit formatted text.
+
+- If you have a Pygments style, then this needs to be converted as well. A
+ Pygments style class can be converted in a prompt_toolkit
+ :class:`~prompt_toolkit.styles.Style` with the
+ :func:`~prompt_toolkit.styles.pygments.style_from_pygments_cls` function
+ (which used to be called ``style_from_pygments``). A Pygments style
+ dictionary can be converted using
+ :func:`~prompt_toolkit.styles.pygments.style_from_pygments_dict`.
+
+ Multiple styles can be merged together using
+ :func:`~prompt_toolkit.styles.merge_styles`.
+
+
+Wordcompleter
+^^^^^^^^^^^^^
+
+`WordCompleter` was moved from
+:class:`prompt_toolkit.contrib.completers.base.WordCompleter` to
+:class:`prompt_toolkit.completion.word_completer.WordCompleter`.
+
+
+Asynchronous autocompletion
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By default, prompt_toolkit 2.0 completion is now synchronous. If you still want
+asynchronous auto completion (which is often good thing), then you have to wrap
+the completer in a :class:`~prompt_toolkit.completion.ThreadedCompleter`.
+
+
+Filters
+^^^^^^^
+
+We don't distinguish anymore between `CLIFilter` and `SimpleFilter`, because the
+application object is no longer passed around. This means that all filters are
+a `Filter` from now on.
+
+All filters have been turned into functions. For instance, `IsDone` became
+`is_done` and `HasCompletions` became `has_completions`.
+
+This was done because almost all classes were called without any arguments in
+the `__init__` causing additional braces everywhere. This means that
+`HasCompletions()` has to be replaced by `has_completions` (without
+parenthesis).
+
+The few filters that took arguments as input, became functions, but still have
+to be called with the given arguments.
+
+For new filters, it is recommended to use the `@Condition` decorator,
+rather then inheriting from `Filter`. For instance:
+
+.. code:: python
+
+ from prompt_toolkit.filters import Condition
+
+ @Condition
+ def my_filter();
+ return True # Or False
+
diff --git a/docs/pages/upgrading/3.0.rst b/docs/pages/upgrading/3.0.rst
new file mode 100644
index 0000000..7a867c5
--- /dev/null
+++ b/docs/pages/upgrading/3.0.rst
@@ -0,0 +1,118 @@
+.. _upgrading_3_0:
+
+Upgrading to prompt_toolkit 3.0
+===============================
+
+There are two major changes in 3.0 to be aware of:
+
+- First, prompt_toolkit uses the asyncio event loop natively, rather then using
+ its own implementations of event loops. This means that all coroutines are
+ now asyncio coroutines, and all Futures are asyncio futures. Asynchronous
+ generators became real asynchronous generators as well.
+
+- Prompt_toolkit uses type annotations (almost) everywhere. This should not
+ break any code, but its very helpful in many ways.
+
+There are some minor breaking changes:
+
+- The dialogs API had to change (see below).
+
+
+Detecting the prompt_toolkit version
+------------------------------------
+
+Detecting whether version 3 is being used can be done as follows:
+
+.. code:: python
+
+ from prompt_toolkit import __version__ as ptk_version
+
+ PTK3 = ptk_version.startswith('3.')
+
+
+Fixing calls to `get_event_loop`
+--------------------------------
+
+Every usage of ``get_event_loop`` has to be fixed. An easy way to do this is by
+changing the imports like this:
+
+.. code:: python
+
+ if PTK3:
+ from asyncio import get_event_loop
+ else:
+ from prompt_toolkit.eventloop import get_event_loop
+
+Notice that for prompt_toolkit 2.0, ``get_event_loop`` returns a prompt_toolkit
+``EventLoop`` object. This is not an asyncio eventloop, but the API is
+similar.
+
+There are some changes to the eventloop API:
+
++-----------------------------------+--------------------------------------+
+| version 2.0 | version 3.0 (asyncio) |
++===================================+======================================+
+| loop.run_in_executor(callback) | loop.run_in_executor(None, callback) |
++-----------------------------------+--------------------------------------+
+| loop.call_from_executor(callback) | loop.call_soon_threadsafe(callback) |
++-----------------------------------+--------------------------------------+
+
+
+Running on top of asyncio
+-------------------------
+
+For 2.0, you had tell prompt_toolkit to run on top of the asyncio event loop.
+Now it's the default. So, you can simply remove the following two lines:
+
+.. code::
+
+ from prompt_toolkit.eventloop.defaults import use_asyncio_event_loop
+ use_asyncio_event_loop()
+
+There is a few little breaking changes though. The following:
+
+.. code::
+
+ # For 2.0
+ result = await PromptSession().prompt('Say something: ', async_=True)
+
+has to be changed into:
+
+.. code::
+
+ # For 3.0
+ result = await PromptSession().prompt_async('Say something: ')
+
+Further, it's impossible to call the `prompt()` function within an asyncio
+application (within a coroutine), because it will try to run the event loop
+again. In that case, always use `prompt_async()`.
+
+
+Changes to the dialog functions
+-------------------------------
+
+The original way of using dialog boxes looked like this:
+
+.. code:: python
+
+ from prompt_toolkit.shortcuts import input_dialog
+
+ result = input_dialog(title='...', text='...')
+
+Now, the dialog functions return a prompt_toolkit Application object. You have
+to call either its ``run`` or ``run_async`` method to display the dialog. The
+``async_`` parameter has been removed everywhere.
+
+.. code:: python
+
+ if PTK3:
+ result = input_dialog(title='...', text='...').run()
+ else:
+ result = input_dialog(title='...', text='...')
+
+ # Or
+
+ if PTK3:
+ result = await input_dialog(title='...', text='...').run_async()
+ else:
+ result = await input_dialog(title='...', text='...', async_=True)
diff --git a/docs/pages/upgrading/index.rst b/docs/pages/upgrading/index.rst
new file mode 100644
index 0000000..b790a64
--- /dev/null
+++ b/docs/pages/upgrading/index.rst
@@ -0,0 +1,11 @@
+.. _upgrading:
+
+Upgrading
+=========
+
+.. toctree::
+ :caption: Contents:
+ :maxdepth: 1
+
+ 2.0
+ 3.0