summaryrefslogtreecommitdiffstats
path: root/docs/pages/asking_for_input.rst
blob: 20619ac1fdd44ea923357f55266eba8c71b00e30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
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.