aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/prompt-toolkit/py2
diff options
context:
space:
mode:
authormonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
committermonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/python/prompt-toolkit/py2
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
downloadydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz
fix ya.make
Diffstat (limited to 'contrib/python/prompt-toolkit/py2')
-rw-r--r--contrib/python/prompt-toolkit/py2/.dist-info/METADATA198
-rw-r--r--contrib/python/prompt-toolkit/py2/.dist-info/top_level.txt1
-rw-r--r--contrib/python/prompt-toolkit/py2/AUTHORS.rst11
-rw-r--r--contrib/python/prompt-toolkit/py2/LICENSE27
-rw-r--r--contrib/python/prompt-toolkit/py2/README.rst171
-rw-r--r--contrib/python/prompt-toolkit/py2/patches/01-fix-tests.patch12
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/__init__.py22
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/application.py192
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/auto_suggest.py88
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py1415
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer_mapping.py92
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/cache.py111
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/__init__.py8
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/base.py62
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/in_memory.py42
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/pyperclip.py39
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/completion.py170
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/__init__.py0
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/__init__.py5
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/base.py61
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/filesystem.py105
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/system.py56
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/__init__.py76
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/compiler.py408
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/completion.py84
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/lexer.py90
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/regex_parser.py262
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/validation.py57
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/__init__.py2
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/application.py32
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/log.py11
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/protocol.py181
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/server.py407
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/__init__.py0
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/base.py34
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py1001
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/enums.py29
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/__init__.py0
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_base.py46
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py113
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py83
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py85
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/callbacks.py29
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py107
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py306
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py82
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py216
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/utils.py23
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py187
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/__init__.py36
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/base.py234
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/cli.py395
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/types.py55
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/utils.py39
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/history.py120
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/input.py135
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py1190
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/__init__.py1
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/__init__.py0
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/basic.py407
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/completion.py161
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/emacs.py452
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/named_commands.py578
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/scroll.py185
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/utils.py25
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/vi.py1903
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/defaults.py119
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/digraphs.py1378
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/input_processor.py372
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/manager.py96
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/registry.py350
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/vi_state.py61
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/keys.py129
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py51
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py1665
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py730
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/dimension.py92
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py320
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py253
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py496
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/mouse_handlers.py29
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py605
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py111
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py151
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py209
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py181
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/mouse_events.py48
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/output.py192
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/reactive.py56
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py535
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/search_state.py36
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py47
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py717
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/__init__.py21
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/base.py86
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/defaults.py95
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_dict.py151
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_pygments.py77
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/utils.py45
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/__init__.py0
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py42
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py520
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py632
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py364
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py556
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/token.py47
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/utils.py240
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/validation.py64
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/win32_types.py155
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_buffer.py111
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_cli.py629
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_contrib.py254
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_document.py74
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_filter.py168
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_inputstream.py142
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_key_binding.py140
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_layout.py60
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_print_tokens.py50
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_regular_languages.py110
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_shortcuts.py50
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_style.py40
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_utils.py39
-rw-r--r--contrib/python/prompt-toolkit/py2/tests/test_yank_nth_arg.py85
123 files changed, 0 insertions, 26831 deletions
diff --git a/contrib/python/prompt-toolkit/py2/.dist-info/METADATA b/contrib/python/prompt-toolkit/py2/.dist-info/METADATA
deleted file mode 100644
index 24d0343b30..0000000000
--- a/contrib/python/prompt-toolkit/py2/.dist-info/METADATA
+++ /dev/null
@@ -1,198 +0,0 @@
-Metadata-Version: 2.1
-Name: prompt-toolkit
-Version: 1.0.18
-Summary: Library for building powerful interactive command lines in Python
-Home-page: https://github.com/jonathanslenders/python-prompt-toolkit
-Author: Jonathan Slenders
-Author-email: UNKNOWN
-License: UNKNOWN
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: BSD License
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python
-Classifier: Topic :: Software Development
-Requires-Dist: six (>=1.9.0)
-Requires-Dist: wcwidth
-
-Python Prompt Toolkit
-=====================
-
-|Build Status| |PyPI|
-
-``prompt_toolkit`` is a library for building powerful interactive command lines
-and terminal applications in Python.
-
-Read the `documentation on readthedocs
-<http://python-prompt-toolkit.readthedocs.io/en/stable/>`_.
-
-
-Ptpython
-********
-
-`ptpython <http://github.com/jonathanslenders/ptpython/>`_ is an interactive
-Python Shell, build on top of prompt_toolkit.
-
-.. image :: https://github.com/jonathanslenders/python-prompt-toolkit/raw/master/docs/images/ptpython.png
-
-
-prompt_toolkit features
-***********************
-
-``prompt_toolkit`` could be a replacement for `GNU readline
-<http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html>`_, but it can be much
-more than that.
-
-Some features:
-
-- Pure Python.
-- Syntax highlighting of the input while typing. (For instance, with a Pygments lexer.)
-- Multi-line input editing.
-- Advanced code completion.
-- Both Emacs and Vi key bindings. (Similar to readline.)
-- Even some advanced Vi functionality, like named registers and digraphs.
-- Reverse and forward incremental search.
-- Runs on all Python versions from 2.6 up to 3.5.
-- Works well with Unicode double width characters. (Chinese input.)
-- Selecting text for copy/paste. (Both Emacs and Vi style.)
-- Support for `bracketed paste <https://cirw.in/blog/bracketed-paste>`_.
-- Mouse support for cursor positioning and scrolling.
-- Auto suggestions. (Like `fish shell <http://fishshell.com/>`_.)
-- Multiple input buffers.
-- No global state.
-- Lightweight, the only dependencies are Pygments, six and wcwidth.
-- Runs on Linux, OS X, FreeBSD, OpenBSD and Windows systems.
-- And much more...
-
-Feel free to create tickets for bugs and feature requests, and create pull
-requests if you have nice patches that you would like to share with others.
-
-
-About Windows support
-*********************
-
-``prompt_toolkit`` is cross platform, and everything that you build on top
-should run fine on both Unix and Windows systems. On Windows, it uses a
-different event loop (``WaitForMultipleObjects`` instead of ``select``), and
-another input and output system. (Win32 APIs instead of pseudo-terminals and
-VT100.)
-
-It's worth noting that the implementation is a "best effort of what is
-possible". Both Unix and Windows terminals have their limitations. But in
-general, the Unix experience will still be a little better.
-
-For Windows, it's recommended to use either `cmder
-<http://cmder.net/>`_ or `conemu <https://conemu.github.io/>`_.
-
-
-Installation
-************
-
-::
-
- pip install prompt_toolkit
-
-For Conda, do:
-
-::
-
- conda install -c https://conda.anaconda.org/conda-forge prompt_toolkit
-
-
-Getting started
-***************
-
-The most simple example of the library would look like this:
-
-.. code:: python
-
- from prompt_toolkit import prompt
-
- if __name__ == '__main__':
- answer = prompt('Give me some input: ')
- print('You said: %s' % answer)
-
-For more complex examples, have a look in the ``examples`` directory. All
-examples are chosen to demonstrate only one thing. Also, don't be afraid to
-look at the source code. The implementation of the ``prompt`` function could be
-a good start.
-
-Note for Python 2: all strings are expected to be unicode strings. So, either
-put a small ``u`` in front of every string or put ``from __future__ import
-unicode_literals`` at the start of the above example.
-
-
-Projects using prompt_toolkit
-*****************************
-
-Shells:
-
-- `ptpython <http://github.com/jonathanslenders/ptpython/>`_: Python REPL
-- `ptpdb <http://github.com/jonathanslenders/ptpdb/>`_: Python debugger (pdb replacement)
-- `pgcli <http://pgcli.com/>`_: Postgres client.
-- `mycli <http://mycli.net>`_: MySql client.
-- `wharfee <http://wharfee.com/>`_: A Docker command line.
-- `xonsh <http://xon.sh/>`_: A Python-ish, BASHwards-compatible shell.
-- `saws <https://github.com/donnemartin/saws>`_: A Supercharged AWS Command Line Interface.
-- `cycli <https://github.com/nicolewhite/cycli>`_: A Command Line Interface for Cypher.
-- `crash <https://github.com/crate/crash>`_: Crate command line client.
-- `vcli <https://github.com/dbcli/vcli>`_: Vertica client.
-- `aws-shell <https://github.com/awslabs/aws-shell>`_: An integrated shell for working with the AWS CLI.
-- `softlayer-python <https://github.com/softlayer/softlayer-python>`_: A command-line interface to manage various SoftLayer products and services.
-- `ipython <http://github.com/ipython/ipython/>`_: The IPython REPL
-- `click-repl <https://github.com/click-contrib/click-repl>`_: Subcommand REPL for click apps.
-- `haxor-news <https://github.com/donnemartin/haxor-news>`_: A Hacker News CLI.
-- `gitsome <https://github.com/donnemartin/gitsome>`_: A Git/Shell Autocompleter with GitHub Integration.
-- `http-prompt <https://github.com/eliangcs/http-prompt>`_: An interactive command-line HTTP client.
-- `coconut <http://coconut-lang.org/>`_: Functional programming in Python.
-- `Ergonomica <https://ergonomica.github.io/>`_: A Bash alternative written in Python.
-- `Kube-shell <https://github.com/cloudnativelabs/kube-shell>`_: Kubernetes shell: An integrated shell for working with the Kubernetes CLI
-
-Full screen applications:
-
-- `pymux <http://github.com/jonathanslenders/pymux/>`_: A terminal multiplexer (like tmux) in pure Python.
-- `pyvim <http://github.com/jonathanslenders/pyvim/>`_: A Vim clone in pure Python.
-
-(Want your own project to be listed here? Please create a GitHub issue.)
-
-
-Philosophy
-**********
-
-The source code of ``prompt_toolkit`` should be readable, concise and
-efficient. We prefer short functions focussing each on one task and for which
-the input and output types are clearly specified. We mostly prefer composition
-over inheritance, because inheritance can result in too much functionality in
-the same object. We prefer immutable objects where possible (objects don't
-change after initialisation). Reusability is important. We absolutely refrain
-from having a changing global state, it should be possible to have multiple
-independent instances of the same code in the same process. The architecture
-should be layered: the lower levels operate on primitive operations and data
-structures giving -- when correctly combined -- all the possible flexibility;
-while at the higher level, there should be a simpler API, ready-to-use and
-sufficient for most use cases. Thinking about algorithms and efficiency is
-important, but avoid premature optimization.
-
-
-Special thanks to
-*****************
-
-- `Pygments <http://pygments.org/>`_: Syntax highlighter.
-- `wcwidth <https://github.com/jquast/wcwidth>`_: Determine columns needed for a wide characters.
-
-.. |Build Status| image:: https://api.travis-ci.org/jonathanslenders/python-prompt-toolkit.svg?branch=master
- :target: https://travis-ci.org/jonathanslenders/python-prompt-toolkit#
-
-.. |PyPI| image:: https://img.shields.io/pypi/v/prompt_toolkit.svg
- :target: https://pypi.python.org/pypi/prompt-toolkit/
- :alt: Latest Version
-
-
diff --git a/contrib/python/prompt-toolkit/py2/.dist-info/top_level.txt b/contrib/python/prompt-toolkit/py2/.dist-info/top_level.txt
deleted file mode 100644
index 29392dfc5b..0000000000
--- a/contrib/python/prompt-toolkit/py2/.dist-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-prompt_toolkit
diff --git a/contrib/python/prompt-toolkit/py2/AUTHORS.rst b/contrib/python/prompt-toolkit/py2/AUTHORS.rst
deleted file mode 100644
index f7c8f60f40..0000000000
--- a/contrib/python/prompt-toolkit/py2/AUTHORS.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-Authors
-=======
-
-Creator
--------
-Jonathan Slenders <jonathan AT slenders.be>
-
-Contributors
-------------
-
-- Amjith Ramanujam <amjith.r AT gmail.com>
diff --git a/contrib/python/prompt-toolkit/py2/LICENSE b/contrib/python/prompt-toolkit/py2/LICENSE
deleted file mode 100644
index e1720e0fb7..0000000000
--- a/contrib/python/prompt-toolkit/py2/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2014, Jonathan Slenders
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice, this
- list of conditions and the following disclaimer in the documentation and/or
- other materials provided with the distribution.
-
-* Neither the name of the {organization} nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/contrib/python/prompt-toolkit/py2/README.rst b/contrib/python/prompt-toolkit/py2/README.rst
deleted file mode 100644
index 35b1745614..0000000000
--- a/contrib/python/prompt-toolkit/py2/README.rst
+++ /dev/null
@@ -1,171 +0,0 @@
-Python Prompt Toolkit
-=====================
-
-|Build Status| |PyPI|
-
-``prompt_toolkit`` is a library for building powerful interactive command lines
-and terminal applications in Python.
-
-Read the `documentation on readthedocs
-<http://python-prompt-toolkit.readthedocs.io/en/stable/>`_.
-
-
-Ptpython
-********
-
-`ptpython <http://github.com/jonathanslenders/ptpython/>`_ is an interactive
-Python Shell, build on top of prompt_toolkit.
-
-.. image :: https://github.com/jonathanslenders/python-prompt-toolkit/raw/master/docs/images/ptpython.png
-
-
-prompt_toolkit features
-***********************
-
-``prompt_toolkit`` could be a replacement for `GNU readline
-<http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html>`_, but it can be much
-more than that.
-
-Some features:
-
-- Pure Python.
-- Syntax highlighting of the input while typing. (For instance, with a Pygments lexer.)
-- Multi-line input editing.
-- Advanced code completion.
-- Both Emacs and Vi key bindings. (Similar to readline.)
-- Even some advanced Vi functionality, like named registers and digraphs.
-- Reverse and forward incremental search.
-- Runs on all Python versions from 2.6 up to 3.5.
-- Works well with Unicode double width characters. (Chinese input.)
-- Selecting text for copy/paste. (Both Emacs and Vi style.)
-- Support for `bracketed paste <https://cirw.in/blog/bracketed-paste>`_.
-- Mouse support for cursor positioning and scrolling.
-- Auto suggestions. (Like `fish shell <http://fishshell.com/>`_.)
-- Multiple input buffers.
-- No global state.
-- Lightweight, the only dependencies are Pygments, six and wcwidth.
-- Runs on Linux, OS X, FreeBSD, OpenBSD and Windows systems.
-- And much more...
-
-Feel free to create tickets for bugs and feature requests, and create pull
-requests if you have nice patches that you would like to share with others.
-
-
-About Windows support
-*********************
-
-``prompt_toolkit`` is cross platform, and everything that you build on top
-should run fine on both Unix and Windows systems. On Windows, it uses a
-different event loop (``WaitForMultipleObjects`` instead of ``select``), and
-another input and output system. (Win32 APIs instead of pseudo-terminals and
-VT100.)
-
-It's worth noting that the implementation is a "best effort of what is
-possible". Both Unix and Windows terminals have their limitations. But in
-general, the Unix experience will still be a little better.
-
-For Windows, it's recommended to use either `cmder
-<http://cmder.net/>`_ or `conemu <https://conemu.github.io/>`_.
-
-
-Installation
-************
-
-::
-
- pip install prompt_toolkit
-
-For Conda, do:
-
-::
-
- conda install -c https://conda.anaconda.org/conda-forge prompt_toolkit
-
-
-Getting started
-***************
-
-The most simple example of the library would look like this:
-
-.. code:: python
-
- from prompt_toolkit import prompt
-
- if __name__ == '__main__':
- answer = prompt('Give me some input: ')
- print('You said: %s' % answer)
-
-For more complex examples, have a look in the ``examples`` directory. All
-examples are chosen to demonstrate only one thing. Also, don't be afraid to
-look at the source code. The implementation of the ``prompt`` function could be
-a good start.
-
-Note for Python 2: all strings are expected to be unicode strings. So, either
-put a small ``u`` in front of every string or put ``from __future__ import
-unicode_literals`` at the start of the above example.
-
-
-Projects using prompt_toolkit
-*****************************
-
-Shells:
-
-- `ptpython <http://github.com/jonathanslenders/ptpython/>`_: Python REPL
-- `ptpdb <http://github.com/jonathanslenders/ptpdb/>`_: Python debugger (pdb replacement)
-- `pgcli <http://pgcli.com/>`_: Postgres client.
-- `mycli <http://mycli.net>`_: MySql client.
-- `wharfee <http://wharfee.com/>`_: A Docker command line.
-- `xonsh <http://xon.sh/>`_: A Python-ish, BASHwards-compatible shell.
-- `saws <https://github.com/donnemartin/saws>`_: A Supercharged AWS Command Line Interface.
-- `cycli <https://github.com/nicolewhite/cycli>`_: A Command Line Interface for Cypher.
-- `crash <https://github.com/crate/crash>`_: Crate command line client.
-- `vcli <https://github.com/dbcli/vcli>`_: Vertica client.
-- `aws-shell <https://github.com/awslabs/aws-shell>`_: An integrated shell for working with the AWS CLI.
-- `softlayer-python <https://github.com/softlayer/softlayer-python>`_: A command-line interface to manage various SoftLayer products and services.
-- `ipython <http://github.com/ipython/ipython/>`_: The IPython REPL
-- `click-repl <https://github.com/click-contrib/click-repl>`_: Subcommand REPL for click apps.
-- `haxor-news <https://github.com/donnemartin/haxor-news>`_: A Hacker News CLI.
-- `gitsome <https://github.com/donnemartin/gitsome>`_: A Git/Shell Autocompleter with GitHub Integration.
-- `http-prompt <https://github.com/eliangcs/http-prompt>`_: An interactive command-line HTTP client.
-- `coconut <http://coconut-lang.org/>`_: Functional programming in Python.
-- `Ergonomica <https://ergonomica.github.io/>`_: A Bash alternative written in Python.
-- `Kube-shell <https://github.com/cloudnativelabs/kube-shell>`_: Kubernetes shell: An integrated shell for working with the Kubernetes CLI
-
-Full screen applications:
-
-- `pymux <http://github.com/jonathanslenders/pymux/>`_: A terminal multiplexer (like tmux) in pure Python.
-- `pyvim <http://github.com/jonathanslenders/pyvim/>`_: A Vim clone in pure Python.
-
-(Want your own project to be listed here? Please create a GitHub issue.)
-
-
-Philosophy
-**********
-
-The source code of ``prompt_toolkit`` should be readable, concise and
-efficient. We prefer short functions focussing each on one task and for which
-the input and output types are clearly specified. We mostly prefer composition
-over inheritance, because inheritance can result in too much functionality in
-the same object. We prefer immutable objects where possible (objects don't
-change after initialisation). Reusability is important. We absolutely refrain
-from having a changing global state, it should be possible to have multiple
-independent instances of the same code in the same process. The architecture
-should be layered: the lower levels operate on primitive operations and data
-structures giving -- when correctly combined -- all the possible flexibility;
-while at the higher level, there should be a simpler API, ready-to-use and
-sufficient for most use cases. Thinking about algorithms and efficiency is
-important, but avoid premature optimization.
-
-
-Special thanks to
-*****************
-
-- `Pygments <http://pygments.org/>`_: Syntax highlighter.
-- `wcwidth <https://github.com/jquast/wcwidth>`_: Determine columns needed for a wide characters.
-
-.. |Build Status| image:: https://api.travis-ci.org/jonathanslenders/python-prompt-toolkit.svg?branch=master
- :target: https://travis-ci.org/jonathanslenders/python-prompt-toolkit#
-
-.. |PyPI| image:: https://img.shields.io/pypi/v/prompt_toolkit.svg
- :target: https://pypi.python.org/pypi/prompt-toolkit/
- :alt: Latest Version
diff --git a/contrib/python/prompt-toolkit/py2/patches/01-fix-tests.patch b/contrib/python/prompt-toolkit/py2/patches/01-fix-tests.patch
deleted file mode 100644
index 2830ea41db..0000000000
--- a/contrib/python/prompt-toolkit/py2/patches/01-fix-tests.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- contrib/python/prompt-toolkit/py2/tests/test_contrib.py (index)
-+++ contrib/python/prompt-toolkit/py2/tests/test_contrib.py (working tree)
-@@ -194,7 +194,8 @@ def test_pathcompleter_does_not_expanduser_by_default():
- assert [] == completions
-
-
--def test_pathcompleter_can_expanduser():
-+def test_pathcompleter_can_expanduser(monkeypatch):
-+ monkeypatch.setenv('HOME', '/tmp')
- completer = PathCompleter(expanduser=True)
- doc_text = '~'
- doc = Document(doc_text, len(doc_text))
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/__init__.py
deleted file mode 100644
index 6478ba4f9a..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""
-prompt_toolkit
-==============
-
-Author: Jonathan Slenders
-
-Description: prompt_toolkit is a Library for building powerful interactive
- command lines in Python. It can be a replacement for GNU
- readline, but it can be much more than that.
-
-See the examples directory to learn about the usage.
-
-Probably, to get started, you meight also want to have a look at
-`prompt_toolkit.shortcuts.prompt`.
-"""
-from .interface import CommandLineInterface
-from .application import AbortAction, Application
-from .shortcuts import prompt, prompt_async
-
-
-# Don't forget to update in `docs/conf.py`!
-__version__ = '1.0.18'
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/application.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/application.py
deleted file mode 100644
index 272d8bbcbb..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/application.py
+++ /dev/null
@@ -1,192 +0,0 @@
-from __future__ import unicode_literals
-
-from .buffer import Buffer, AcceptAction
-from .buffer_mapping import BufferMapping
-from .clipboard import Clipboard, InMemoryClipboard
-from .enums import DEFAULT_BUFFER, EditingMode
-from .filters import CLIFilter, to_cli_filter
-from .key_binding.bindings.basic import load_basic_bindings
-from .key_binding.bindings.emacs import load_emacs_bindings
-from .key_binding.bindings.vi import load_vi_bindings
-from .key_binding.registry import BaseRegistry
-from .key_binding.defaults import load_key_bindings
-from .layout import Window
-from .layout.containers import Container
-from .layout.controls import BufferControl
-from .styles import DEFAULT_STYLE, Style
-import six
-
-__all__ = (
- 'AbortAction',
- 'Application',
-)
-
-
-class AbortAction(object):
- """
- Actions to take on an Exit or Abort exception.
- """
- RETRY = 'retry'
- RAISE_EXCEPTION = 'raise-exception'
- RETURN_NONE = 'return-none'
-
- _all = (RETRY, RAISE_EXCEPTION, RETURN_NONE)
-
-
-class Application(object):
- """
- Application class to be passed to a
- :class:`~prompt_toolkit.interface.CommandLineInterface`.
-
- This contains all customizable logic that is not I/O dependent.
- (So, what is independent of event loops, input and output.)
-
- This way, such an :class:`.Application` can run easily on several
- :class:`~prompt_toolkit.interface.CommandLineInterface` instances, each
- with a different I/O backends. that runs for instance over telnet, SSH or
- any other I/O backend.
-
- :param layout: A :class:`~prompt_toolkit.layout.containers.Container` instance.
- :param buffer: A :class:`~prompt_toolkit.buffer.Buffer` instance for the default buffer.
- :param initial_focussed_buffer: Name of the buffer that is focussed during start-up.
- :param key_bindings_registry:
- :class:`~prompt_toolkit.key_binding.registry.BaseRegistry` instance for
- the key bindings.
- :param clipboard: :class:`~prompt_toolkit.clipboard.base.Clipboard` to use.
- :param on_abort: What to do when Control-C is pressed.
- :param on_exit: What to do when Control-D is pressed.
- :param use_alternate_screen: When True, run the application on the alternate screen buffer.
- :param get_title: Callable that returns the current title to be displayed in the terminal.
- :param erase_when_done: (bool) Clear the application output when it finishes.
- :param reverse_vi_search_direction: Normally, in Vi mode, a '/' searches
- forward and a '?' searches backward. In readline mode, this is usually
- reversed.
-
- Filters:
-
- :param mouse_support: (:class:`~prompt_toolkit.filters.CLIFilter` or
- boolean). When True, enable mouse support.
- :param paste_mode: :class:`~prompt_toolkit.filters.CLIFilter` or boolean.
- :param ignore_case: :class:`~prompt_toolkit.filters.CLIFilter` or boolean.
- :param editing_mode: :class:`~prompt_toolkit.enums.EditingMode`.
-
- Callbacks (all of these should accept a
- :class:`~prompt_toolkit.interface.CommandLineInterface` object as input.)
-
- :param on_input_timeout: Called when there is no input for x seconds.
- (Fired when any eventloop.onInputTimeout is fired.)
- :param on_start: Called when reading input starts.
- :param on_stop: Called when reading input ends.
- :param on_reset: Called during reset.
- :param on_buffer_changed: Called when the content of a buffer has been changed.
- :param on_initialize: Called after the
- :class:`~prompt_toolkit.interface.CommandLineInterface` initializes.
- :param on_render: Called right after rendering.
- :param on_invalidate: Called when the UI has been invalidated.
- """
- def __init__(self, layout=None, buffer=None, buffers=None,
- initial_focussed_buffer=DEFAULT_BUFFER,
- style=None,
- key_bindings_registry=None, clipboard=None,
- on_abort=AbortAction.RAISE_EXCEPTION, on_exit=AbortAction.RAISE_EXCEPTION,
- use_alternate_screen=False, mouse_support=False,
- get_title=None,
-
- paste_mode=False, ignore_case=False, editing_mode=EditingMode.EMACS,
- erase_when_done=False,
- reverse_vi_search_direction=False,
-
- on_input_timeout=None, on_start=None, on_stop=None,
- on_reset=None, on_initialize=None, on_buffer_changed=None,
- on_render=None, on_invalidate=None):
-
- paste_mode = to_cli_filter(paste_mode)
- ignore_case = to_cli_filter(ignore_case)
- mouse_support = to_cli_filter(mouse_support)
- reverse_vi_search_direction = to_cli_filter(reverse_vi_search_direction)
-
- assert layout is None or isinstance(layout, Container)
- assert buffer is None or isinstance(buffer, Buffer)
- assert buffers is None or isinstance(buffers, (dict, BufferMapping))
- assert key_bindings_registry is None or isinstance(key_bindings_registry, BaseRegistry)
- assert clipboard is None or isinstance(clipboard, Clipboard)
- assert on_abort in AbortAction._all
- assert on_exit in AbortAction._all
- assert isinstance(use_alternate_screen, bool)
- assert get_title is None or callable(get_title)
- assert isinstance(paste_mode, CLIFilter)
- assert isinstance(ignore_case, CLIFilter)
- assert isinstance(editing_mode, six.string_types)
- assert on_input_timeout is None or callable(on_input_timeout)
- assert style is None or isinstance(style, Style)
- assert isinstance(erase_when_done, bool)
-
- assert on_start is None or callable(on_start)
- assert on_stop is None or callable(on_stop)
- assert on_reset is None or callable(on_reset)
- assert on_buffer_changed is None or callable(on_buffer_changed)
- assert on_initialize is None or callable(on_initialize)
- assert on_render is None or callable(on_render)
- assert on_invalidate is None or callable(on_invalidate)
-
- self.layout = layout or Window(BufferControl())
-
- # Make sure that the 'buffers' dictionary is a BufferMapping.
- # NOTE: If no buffer is given, we create a default Buffer, with IGNORE as
- # default accept_action. This is what makes sense for most users
- # creating full screen applications. Doing nothing is the obvious
- # default. Those creating a REPL would use the shortcuts module that
- # passes in RETURN_DOCUMENT.
- self.buffer = buffer or Buffer(accept_action=AcceptAction.IGNORE)
- if not buffers or not isinstance(buffers, BufferMapping):
- self.buffers = BufferMapping(buffers, initial=initial_focussed_buffer)
- else:
- self.buffers = buffers
-
- if buffer:
- self.buffers[DEFAULT_BUFFER] = buffer
-
- self.initial_focussed_buffer = initial_focussed_buffer
-
- self.style = style or DEFAULT_STYLE
-
- if key_bindings_registry is None:
- key_bindings_registry = load_key_bindings()
-
- if get_title is None:
- get_title = lambda: None
-
- self.key_bindings_registry = key_bindings_registry
- self.clipboard = clipboard or InMemoryClipboard()
- self.on_abort = on_abort
- self.on_exit = on_exit
- self.use_alternate_screen = use_alternate_screen
- self.mouse_support = mouse_support
- self.get_title = get_title
-
- self.paste_mode = paste_mode
- self.ignore_case = ignore_case
- self.editing_mode = editing_mode
- self.erase_when_done = erase_when_done
- self.reverse_vi_search_direction = reverse_vi_search_direction
-
- def dummy_handler(cli):
- " Dummy event handler. "
-
- self.on_input_timeout = on_input_timeout or dummy_handler
- self.on_start = on_start or dummy_handler
- self.on_stop = on_stop or dummy_handler
- self.on_reset = on_reset or dummy_handler
- self.on_initialize = on_initialize or dummy_handler
- self.on_buffer_changed = on_buffer_changed or dummy_handler
- self.on_render = on_render or dummy_handler
- self.on_invalidate = on_invalidate or dummy_handler
-
- # List of 'extra' functions to execute before a CommandLineInterface.run.
- # Note: It's important to keep this here, and not in the
- # CommandLineInterface itself. shortcuts.run_application creates
- # a new Application instance everytime. (Which is correct, it
- # could be that we want to detach from one IO backend and attach
- # the UI on a different backend.) But important is to keep as
- # much state as possible between runs.
- self.pre_run_callables = []
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/auto_suggest.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/auto_suggest.py
deleted file mode 100644
index 1d5130521f..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/auto_suggest.py
+++ /dev/null
@@ -1,88 +0,0 @@
-"""
-`Fish-style <http://fishshell.com/>`_ like auto-suggestion.
-
-While a user types input in a certain buffer, suggestions are generated
-(asynchronously.) Usually, they are displayed after the input. When the cursor
-presses the right arrow and the cursor is at the end of the input, the
-suggestion will be inserted.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-
-from .filters import to_cli_filter
-
-__all__ = (
- 'Suggestion',
- 'AutoSuggest',
- 'AutoSuggestFromHistory',
- 'ConditionalAutoSuggest',
-)
-
-
-class Suggestion(object):
- """
- Suggestion returned by an auto-suggest algorithm.
-
- :param text: The suggestion text.
- """
- def __init__(self, text):
- self.text = text
-
- def __repr__(self):
- return 'Suggestion(%s)' % self.text
-
-
-class AutoSuggest(with_metaclass(ABCMeta, object)):
- """
- Base class for auto suggestion implementations.
- """
- @abstractmethod
- def get_suggestion(self, cli, buffer, document):
- """
- Return `None` or a :class:`.Suggestion` instance.
-
- We receive both ``buffer`` and ``document``. The reason is that auto
- suggestions are retrieved asynchronously. (Like completions.) The
- buffer text could be changed in the meantime, but ``document`` contains
- the buffer document like it was at the start of the auto suggestion
- call. So, from here, don't access ``buffer.text``, but use
- ``document.text`` instead.
-
- :param buffer: The :class:`~prompt_toolkit.buffer.Buffer` instance.
- :param document: The :class:`~prompt_toolkit.document.Document` instance.
- """
-
-
-class AutoSuggestFromHistory(AutoSuggest):
- """
- Give suggestions based on the lines in the history.
- """
- def get_suggestion(self, cli, buffer, document):
- history = buffer.history
-
- # Consider only the last line for the suggestion.
- text = document.text.rsplit('\n', 1)[-1]
-
- # Only create a suggestion when this is not an empty line.
- if text.strip():
- # Find first matching line in history.
- for string in reversed(list(history)):
- for line in reversed(string.splitlines()):
- if line.startswith(text):
- return Suggestion(line[len(text):])
-
-
-class ConditionalAutoSuggest(AutoSuggest):
- """
- Auto suggest that can be turned on and of according to a certain condition.
- """
- def __init__(self, auto_suggest, filter):
- assert isinstance(auto_suggest, AutoSuggest)
-
- self.auto_suggest = auto_suggest
- self.filter = to_cli_filter(filter)
-
- def get_suggestion(self, cli, buffer, document):
- if self.filter(cli):
- return self.auto_suggest.get_suggestion(cli, buffer, document)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py
deleted file mode 100644
index f5df289827..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py
+++ /dev/null
@@ -1,1415 +0,0 @@
-"""
-Data structures for the Buffer.
-It holds the text, cursor position, history, etc...
-"""
-from __future__ import unicode_literals
-
-from .auto_suggest import AutoSuggest
-from .clipboard import ClipboardData
-from .completion import Completer, Completion, CompleteEvent
-from .document import Document
-from .enums import IncrementalSearchDirection
-from .filters import to_simple_filter
-from .history import History, InMemoryHistory
-from .search_state import SearchState
-from .selection import SelectionType, SelectionState, PasteMode
-from .utils import Event
-from .cache import FastDictCache
-from .validation import ValidationError
-
-from six.moves import range
-
-import os
-import re
-import shlex
-import six
-import subprocess
-import tempfile
-
-__all__ = (
- 'EditReadOnlyBuffer',
- 'AcceptAction',
- 'Buffer',
- 'indent',
- 'unindent',
- 'reshape_text',
-)
-
-
-class EditReadOnlyBuffer(Exception):
- " Attempt editing of read-only :class:`.Buffer`. "
-
-
-class AcceptAction(object):
- """
- What to do when the input is accepted by the user.
- (When Enter was pressed in the command line.)
-
- :param handler: (optional) A callable which takes a
- :class:`~prompt_toolkit.interface.CommandLineInterface` and
- :class:`~prompt_toolkit.document.Document`. It is called when the user
- accepts input.
- """
- def __init__(self, handler=None):
- assert handler is None or callable(handler)
- self.handler = handler
-
- @classmethod
- def run_in_terminal(cls, handler, render_cli_done=False):
- """
- Create an :class:`.AcceptAction` that runs the given handler in the
- terminal.
-
- :param render_cli_done: When True, render the interface in the 'Done'
- state first, then execute the function. If False, erase the
- interface instead.
- """
- def _handler(cli, buffer):
- cli.run_in_terminal(lambda: handler(cli, buffer), render_cli_done=render_cli_done)
- return AcceptAction(handler=_handler)
-
- @property
- def is_returnable(self):
- """
- True when there is something handling accept.
- """
- return bool(self.handler)
-
- def validate_and_handle(self, cli, buffer):
- """
- Validate buffer and handle the accept action.
- """
- if buffer.validate():
- if self.handler:
- self.handler(cli, buffer)
-
- buffer.append_to_history()
-
-
-def _return_document_handler(cli, buffer):
- # Set return value.
- cli.set_return_value(buffer.document)
-
- # Make sure that if we run this UI again, that we reset this buffer, next
- # time.
- def reset_this_buffer():
- buffer.reset()
- cli.pre_run_callables.append(reset_this_buffer)
-
-
-AcceptAction.RETURN_DOCUMENT = AcceptAction(_return_document_handler)
-AcceptAction.IGNORE = AcceptAction(handler=None)
-
-
-class ValidationState(object):
- " The validation state of a buffer. This is set after the validation. "
- VALID = 'VALID'
- INVALID = 'INVALID'
- UNKNOWN = 'UNKNOWN'
-
-
-class CompletionState(object):
- """
- Immutable class that contains a completion state.
- """
- def __init__(self, original_document, current_completions=None, complete_index=None):
- #: Document as it was when the completion started.
- self.original_document = original_document
-
- #: List of all the current Completion instances which are possible at
- #: this point.
- self.current_completions = current_completions or []
-
- #: Position in the `current_completions` array.
- #: This can be `None` to indicate "no completion", the original text.
- self.complete_index = complete_index # Position in the `_completions` array.
-
- def __repr__(self):
- return '%s(%r, <%r> completions, index=%r)' % (
- self.__class__.__name__,
- self.original_document, len(self.current_completions), self.complete_index)
-
- def go_to_index(self, index):
- """
- Create a new :class:`.CompletionState` object with the new index.
- """
- return CompletionState(self.original_document, self.current_completions, complete_index=index)
-
- def new_text_and_position(self):
- """
- Return (new_text, new_cursor_position) for this completion.
- """
- if self.complete_index is None:
- return self.original_document.text, self.original_document.cursor_position
- else:
- original_text_before_cursor = self.original_document.text_before_cursor
- original_text_after_cursor = self.original_document.text_after_cursor
-
- c = self.current_completions[self.complete_index]
- if c.start_position == 0:
- before = original_text_before_cursor
- else:
- before = original_text_before_cursor[:c.start_position]
-
- new_text = before + c.text + original_text_after_cursor
- new_cursor_position = len(before) + len(c.text)
- return new_text, new_cursor_position
-
- @property
- def current_completion(self):
- """
- Return the current completion, or return `None` when no completion is
- selected.
- """
- if self.complete_index is not None:
- return self.current_completions[self.complete_index]
-
-
-_QUOTED_WORDS_RE = re.compile(r"""(\s+|".*?"|'.*?')""")
-
-
-class YankNthArgState(object):
- """
- For yank-last-arg/yank-nth-arg: Keep track of where we are in the history.
- """
- def __init__(self, history_position=0, n=-1, previous_inserted_word=''):
- self.history_position = history_position
- self.previous_inserted_word = previous_inserted_word
- self.n = n
-
- def __repr__(self):
- return '%s(history_position=%r, n=%r, previous_inserted_word=%r)' % (
- self.__class__.__name__, self.history_position, self.n,
- self.previous_inserted_word)
-
-
-class Buffer(object):
- """
- The core data structure that holds the text and cursor position of the
- current input line and implements all text manupulations on top of it. It
- also implements the history, undo stack and the completion state.
-
- :param completer: :class:`~prompt_toolkit.completion.Completer` instance.
- :param history: :class:`~prompt_toolkit.history.History` instance.
- :param tempfile_suffix: Suffix to be appended to the tempfile for the 'open
- in editor' function.
-
- Events:
-
- :param on_text_changed: When the buffer text changes. (Callable on None.)
- :param on_text_insert: When new text is inserted. (Callable on None.)
- :param on_cursor_position_changed: When the cursor moves. (Callable on None.)
-
- Filters:
-
- :param is_multiline: :class:`~prompt_toolkit.filters.SimpleFilter` to
- indicate whether we should consider this buffer a multiline input. If
- so, key bindings can decide to insert newlines when pressing [Enter].
- (Instead of accepting the input.)
- :param complete_while_typing: :class:`~prompt_toolkit.filters.SimpleFilter`
- instance. Decide whether or not to do asynchronous autocompleting while
- typing.
- :param enable_history_search: :class:`~prompt_toolkit.filters.SimpleFilter`
- to indicate when up-arrow partial string matching is enabled. It is
- adviced to not enable this at the same time as `complete_while_typing`,
- because when there is an autocompletion found, the up arrows usually
- browse through the completions, rather than through the history.
- :param read_only: :class:`~prompt_toolkit.filters.SimpleFilter`. When True,
- changes will not be allowed.
- """
- def __init__(self, completer=None, auto_suggest=None, history=None,
- validator=None, tempfile_suffix='',
- is_multiline=False, complete_while_typing=False,
- enable_history_search=False, initial_document=None,
- accept_action=AcceptAction.IGNORE, read_only=False,
- on_text_changed=None, on_text_insert=None, on_cursor_position_changed=None):
-
- # Accept both filters and booleans as input.
- enable_history_search = to_simple_filter(enable_history_search)
- is_multiline = to_simple_filter(is_multiline)
- complete_while_typing = to_simple_filter(complete_while_typing)
- read_only = to_simple_filter(read_only)
-
- # Validate input.
- assert completer is None or isinstance(completer, Completer)
- assert auto_suggest is None or isinstance(auto_suggest, AutoSuggest)
- assert history is None or isinstance(history, History)
- assert on_text_changed is None or callable(on_text_changed)
- assert on_text_insert is None or callable(on_text_insert)
- assert on_cursor_position_changed is None or callable(on_cursor_position_changed)
-
- self.completer = completer
- self.auto_suggest = auto_suggest
- self.validator = validator
- self.tempfile_suffix = tempfile_suffix
- self.accept_action = accept_action
-
- # Filters. (Usually, used by the key bindings to drive the buffer.)
- self.is_multiline = is_multiline
- self.complete_while_typing = complete_while_typing
- self.enable_history_search = enable_history_search
- self.read_only = read_only
-
- # Text width. (For wrapping, used by the Vi 'gq' operator.)
- self.text_width = 0
-
- #: The command buffer history.
- # Note that we shouldn't use a lazy 'or' here. bool(history) could be
- # False when empty.
- self.history = InMemoryHistory() if history is None else history
-
- self.__cursor_position = 0
-
- # Events
- self.on_text_changed = Event(self, on_text_changed)
- self.on_text_insert = Event(self, on_text_insert)
- self.on_cursor_position_changed = Event(self, on_cursor_position_changed)
-
- # Document cache. (Avoid creating new Document instances.)
- self._document_cache = FastDictCache(Document, size=10)
-
- self.reset(initial_document=initial_document)
-
- def reset(self, initial_document=None, append_to_history=False):
- """
- :param append_to_history: Append current input to history first.
- """
- assert initial_document is None or isinstance(initial_document, Document)
-
- if append_to_history:
- self.append_to_history()
-
- initial_document = initial_document or Document()
-
- self.__cursor_position = initial_document.cursor_position
-
- # `ValidationError` instance. (Will be set when the input is wrong.)
- self.validation_error = None
- self.validation_state = ValidationState.UNKNOWN
-
- # State of the selection.
- self.selection_state = None
-
- # Multiple cursor mode. (When we press 'I' or 'A' in visual-block mode,
- # we can insert text on multiple lines at once. This is implemented by
- # using multiple cursors.)
- self.multiple_cursor_positions = []
-
- # When doing consecutive up/down movements, prefer to stay at this column.
- self.preferred_column = None
-
- # State of complete browser
- self.complete_state = None # For interactive completion through Ctrl-N/Ctrl-P.
-
- # State of Emacs yank-nth-arg completion.
- self.yank_nth_arg_state = None # for yank-nth-arg.
-
- # Remember the document that we had *right before* the last paste
- # operation. This is used for rotating through the kill ring.
- self.document_before_paste = None
-
- # Current suggestion.
- self.suggestion = None
-
- # The history search text. (Used for filtering the history when we
- # browse through it.)
- self.history_search_text = None
-
- # Undo/redo stacks
- self._undo_stack = [] # Stack of (text, cursor_position)
- self._redo_stack = []
-
- #: The working lines. Similar to history, except that this can be
- #: modified. The user can press arrow_up and edit previous entries.
- #: Ctrl-C should reset this, and copy the whole history back in here.
- #: Enter should process the current command and append to the real
- #: history.
- self._working_lines = self.history.strings[:]
- self._working_lines.append(initial_document.text)
- self.__working_index = len(self._working_lines) - 1
-
- # <getters/setters>
-
- def _set_text(self, value):
- """ set text at current working_index. Return whether it changed. """
- working_index = self.working_index
- working_lines = self._working_lines
-
- original_value = working_lines[working_index]
- working_lines[working_index] = value
-
- # Return True when this text has been changed.
- if len(value) != len(original_value):
- # For Python 2, it seems that when two strings have a different
- # length and one is a prefix of the other, Python still scans
- # character by character to see whether the strings are different.
- # (Some benchmarking showed significant differences for big
- # documents. >100,000 of lines.)
- return True
- elif value != original_value:
- return True
- return False
-
- def _set_cursor_position(self, value):
- """ Set cursor position. Return whether it changed. """
- original_position = self.__cursor_position
- self.__cursor_position = max(0, value)
-
- return value != original_position
-
- @property
- def text(self):
- return self._working_lines[self.working_index]
-
- @text.setter
- def text(self, value):
- """
- Setting text. (When doing this, make sure that the cursor_position is
- valid for this text. text/cursor_position should be consistent at any time,
- otherwise set a Document instead.)
- """
- assert isinstance(value, six.text_type), 'Got %r' % value
- assert self.cursor_position <= len(value)
-
- # Don't allow editing of read-only buffers.
- if self.read_only():
- raise EditReadOnlyBuffer()
-
- changed = self._set_text(value)
-
- if changed:
- self._text_changed()
-
- # Reset history search text.
- self.history_search_text = None
-
- @property
- def cursor_position(self):
- return self.__cursor_position
-
- @cursor_position.setter
- def cursor_position(self, value):
- """
- Setting cursor position.
- """
- assert isinstance(value, int)
- assert value <= len(self.text)
-
- changed = self._set_cursor_position(value)
-
- if changed:
- self._cursor_position_changed()
-
- @property
- def working_index(self):
- return self.__working_index
-
- @working_index.setter
- def working_index(self, value):
- if self.__working_index != value:
- self.__working_index = value
- self._text_changed()
-
- def _text_changed(self):
- # Remove any validation errors and complete state.
- self.validation_error = None
- self.validation_state = ValidationState.UNKNOWN
- self.complete_state = None
- self.yank_nth_arg_state = None
- self.document_before_paste = None
- self.selection_state = None
- self.suggestion = None
- self.preferred_column = None
-
- # fire 'on_text_changed' event.
- self.on_text_changed.fire()
-
- def _cursor_position_changed(self):
- # Remove any validation errors and complete state.
- self.validation_error = None
- self.validation_state = ValidationState.UNKNOWN
- self.complete_state = None
- self.yank_nth_arg_state = None
- self.document_before_paste = None
-
- # Unset preferred_column. (Will be set after the cursor movement, if
- # required.)
- self.preferred_column = None
-
- # Note that the cursor position can change if we have a selection the
- # new position of the cursor determines the end of the selection.
-
- # fire 'on_cursor_position_changed' event.
- self.on_cursor_position_changed.fire()
-
- @property
- def document(self):
- """
- Return :class:`~prompt_toolkit.document.Document` instance from the
- current text, cursor position and selection state.
- """
- return self._document_cache[
- self.text, self.cursor_position, self.selection_state]
-
- @document.setter
- def document(self, value):
- """
- Set :class:`~prompt_toolkit.document.Document` instance.
-
- This will set both the text and cursor position at the same time, but
- atomically. (Change events will be triggered only after both have been set.)
- """
- self.set_document(value)
-
- def set_document(self, value, bypass_readonly=False):
- """
- Set :class:`~prompt_toolkit.document.Document` instance. Like the
- ``document`` property, but accept an ``bypass_readonly`` argument.
-
- :param bypass_readonly: When True, don't raise an
- :class:`.EditReadOnlyBuffer` exception, even
- when the buffer is read-only.
- """
- assert isinstance(value, Document)
-
- # Don't allow editing of read-only buffers.
- if not bypass_readonly and self.read_only():
- raise EditReadOnlyBuffer()
-
- # Set text and cursor position first.
- text_changed = self._set_text(value.text)
- cursor_position_changed = self._set_cursor_position(value.cursor_position)
-
- # Now handle change events. (We do this when text/cursor position is
- # both set and consistent.)
- if text_changed:
- self._text_changed()
-
- if cursor_position_changed:
- self._cursor_position_changed()
-
- # End of <getters/setters>
-
- def save_to_undo_stack(self, clear_redo_stack=True):
- """
- Safe current state (input text and cursor position), so that we can
- restore it by calling undo.
- """
- # Safe if the text is different from the text at the top of the stack
- # is different. If the text is the same, just update the cursor position.
- if self._undo_stack and self._undo_stack[-1][0] == self.text:
- self._undo_stack[-1] = (self._undo_stack[-1][0], self.cursor_position)
- else:
- self._undo_stack.append((self.text, self.cursor_position))
-
- # Saving anything to the undo stack, clears the redo stack.
- if clear_redo_stack:
- self._redo_stack = []
-
- def transform_lines(self, line_index_iterator, transform_callback):
- """
- Transforms the text on a range of lines.
- When the iterator yield an index not in the range of lines that the
- document contains, it skips them silently.
-
- To uppercase some lines::
-
- new_text = transform_lines(range(5,10), lambda text: text.upper())
-
- :param line_index_iterator: Iterator of line numbers (int)
- :param transform_callback: callable that takes the original text of a
- line, and return the new text for this line.
-
- :returns: The new text.
- """
- # Split lines
- lines = self.text.split('\n')
-
- # Apply transformation
- for index in line_index_iterator:
- try:
- lines[index] = transform_callback(lines[index])
- except IndexError:
- pass
-
- return '\n'.join(lines)
-
- def transform_current_line(self, transform_callback):
- """
- Apply the given transformation function to the current line.
-
- :param transform_callback: callable that takes a string and return a new string.
- """
- document = self.document
- a = document.cursor_position + document.get_start_of_line_position()
- b = document.cursor_position + document.get_end_of_line_position()
- self.text = (
- document.text[:a] +
- transform_callback(document.text[a:b]) +
- document.text[b:])
-
- def transform_region(self, from_, to, transform_callback):
- """
- Transform a part of the input string.
-
- :param from_: (int) start position.
- :param to: (int) end position.
- :param transform_callback: Callable which accepts a string and returns
- the transformed string.
- """
- assert from_ < to
-
- self.text = ''.join([
- self.text[:from_] +
- transform_callback(self.text[from_:to]) +
- self.text[to:]
- ])
-
- def cursor_left(self, count=1):
- self.cursor_position += self.document.get_cursor_left_position(count=count)
-
- def cursor_right(self, count=1):
- self.cursor_position += self.document.get_cursor_right_position(count=count)
-
- def cursor_up(self, count=1):
- """ (for multiline edit). Move cursor to the previous line. """
- original_column = self.preferred_column or self.document.cursor_position_col
- self.cursor_position += self.document.get_cursor_up_position(
- count=count, preferred_column=original_column)
-
- # Remember the original column for the next up/down movement.
- self.preferred_column = original_column
-
- def cursor_down(self, count=1):
- """ (for multiline edit). Move cursor to the next line. """
- original_column = self.preferred_column or self.document.cursor_position_col
- self.cursor_position += self.document.get_cursor_down_position(
- count=count, preferred_column=original_column)
-
- # Remember the original column for the next up/down movement.
- self.preferred_column = original_column
-
- def auto_up(self, count=1, go_to_start_of_line_if_history_changes=False):
- """
- If we're not on the first line (of a multiline input) go a line up,
- otherwise go back in history. (If nothing is selected.)
- """
- if self.complete_state:
- self.complete_previous(count=count)
- elif self.document.cursor_position_row > 0:
- self.cursor_up(count=count)
- elif not self.selection_state:
- self.history_backward(count=count)
-
- # Go to the start of the line?
- if go_to_start_of_line_if_history_changes:
- self.cursor_position += self.document.get_start_of_line_position()
-
- def auto_down(self, count=1, go_to_start_of_line_if_history_changes=False):
- """
- If we're not on the last line (of a multiline input) go a line down,
- otherwise go forward in history. (If nothing is selected.)
- """
- if self.complete_state:
- self.complete_next(count=count)
- elif self.document.cursor_position_row < self.document.line_count - 1:
- self.cursor_down(count=count)
- elif not self.selection_state:
- self.history_forward(count=count)
-
- # Go to the start of the line?
- if go_to_start_of_line_if_history_changes:
- self.cursor_position += self.document.get_start_of_line_position()
-
- def delete_before_cursor(self, count=1):
- """
- Delete specified number of characters before cursor and return the
- deleted text.
- """
- assert count >= 0
- deleted = ''
-
- if self.cursor_position > 0:
- deleted = self.text[self.cursor_position - count:self.cursor_position]
-
- new_text = self.text[:self.cursor_position - count] + self.text[self.cursor_position:]
- new_cursor_position = self.cursor_position - len(deleted)
-
- # Set new Document atomically.
- self.document = Document(new_text, new_cursor_position)
-
- return deleted
-
- def delete(self, count=1):
- """
- Delete specified number of characters and Return the deleted text.
- """
- if self.cursor_position < len(self.text):
- deleted = self.document.text_after_cursor[:count]
- self.text = self.text[:self.cursor_position] + \
- self.text[self.cursor_position + len(deleted):]
- return deleted
- else:
- return ''
-
- def join_next_line(self, separator=' '):
- """
- Join the next line to the current one by deleting the line ending after
- the current line.
- """
- if not self.document.on_last_line:
- self.cursor_position += self.document.get_end_of_line_position()
- self.delete()
-
- # Remove spaces.
- self.text = (self.document.text_before_cursor + separator +
- self.document.text_after_cursor.lstrip(' '))
-
- def join_selected_lines(self, separator=' '):
- """
- Join the selected lines.
- """
- assert self.selection_state
-
- # Get lines.
- from_, to = sorted([self.cursor_position, self.selection_state.original_cursor_position])
-
- before = self.text[:from_]
- lines = self.text[from_:to].splitlines()
- after = self.text[to:]
-
- # Replace leading spaces with just one space.
- lines = [l.lstrip(' ') + separator for l in lines]
-
- # Set new document.
- self.document = Document(text=before + ''.join(lines) + after,
- cursor_position=len(before + ''.join(lines[:-1])) - 1)
-
- def swap_characters_before_cursor(self):
- """
- Swap the last two characters before the cursor.
- """
- pos = self.cursor_position
-
- if pos >= 2:
- a = self.text[pos - 2]
- b = self.text[pos - 1]
-
- self.text = self.text[:pos-2] + b + a + self.text[pos:]
-
- def go_to_history(self, index):
- """
- Go to this item in the history.
- """
- if index < len(self._working_lines):
- self.working_index = index
- self.cursor_position = len(self.text)
-
- def complete_next(self, count=1, disable_wrap_around=False):
- """
- Browse to the next completions.
- (Does nothing if there are no completion.)
- """
- if self.complete_state:
- completions_count = len(self.complete_state.current_completions)
-
- if self.complete_state.complete_index is None:
- index = 0
- elif self.complete_state.complete_index == completions_count - 1:
- index = None
-
- if disable_wrap_around:
- return
- else:
- index = min(completions_count-1, self.complete_state.complete_index + count)
- self.go_to_completion(index)
-
- def complete_previous(self, count=1, disable_wrap_around=False):
- """
- Browse to the previous completions.
- (Does nothing if there are no completion.)
- """
- if self.complete_state:
- if self.complete_state.complete_index == 0:
- index = None
-
- if disable_wrap_around:
- return
- elif self.complete_state.complete_index is None:
- index = len(self.complete_state.current_completions) - 1
- else:
- index = max(0, self.complete_state.complete_index - count)
-
- self.go_to_completion(index)
-
- def cancel_completion(self):
- """
- Cancel completion, go back to the original text.
- """
- if self.complete_state:
- self.go_to_completion(None)
- self.complete_state = None
-
- def set_completions(self, completions, go_to_first=True, go_to_last=False):
- """
- Start completions. (Generate list of completions and initialize.)
- """
- assert not (go_to_first and go_to_last)
-
- # Generate list of all completions.
- if completions is None:
- if self.completer:
- completions = list(self.completer.get_completions(
- self.document,
- CompleteEvent(completion_requested=True)
- ))
- else:
- completions = []
-
- # Set `complete_state`.
- if completions:
- self.complete_state = CompletionState(
- original_document=self.document,
- current_completions=completions)
- if go_to_first:
- self.go_to_completion(0)
- elif go_to_last:
- self.go_to_completion(len(completions) - 1)
- else:
- self.go_to_completion(None)
-
- else:
- self.complete_state = None
-
- def start_history_lines_completion(self):
- """
- Start a completion based on all the other lines in the document and the
- history.
- """
- found_completions = set()
- completions = []
-
- # For every line of the whole history, find matches with the current line.
- current_line = self.document.current_line_before_cursor.lstrip()
-
- for i, string in enumerate(self._working_lines):
- for j, l in enumerate(string.split('\n')):
- l = l.strip()
- if l and l.startswith(current_line):
- # When a new line has been found.
- if l not in found_completions:
- found_completions.add(l)
-
- # Create completion.
- if i == self.working_index:
- display_meta = "Current, line %s" % (j+1)
- else:
- display_meta = "History %s, line %s" % (i+1, j+1)
-
- completions.append(Completion(
- l,
- start_position=-len(current_line),
- display_meta=display_meta))
-
- self.set_completions(completions=completions[::-1])
-
- def go_to_completion(self, index):
- """
- Select a completion from the list of current completions.
- """
- assert index is None or isinstance(index, int)
- assert self.complete_state
-
- # Set new completion
- state = self.complete_state.go_to_index(index)
-
- # Set text/cursor position
- new_text, new_cursor_position = state.new_text_and_position()
- self.document = Document(new_text, new_cursor_position)
-
- # (changing text/cursor position will unset complete_state.)
- self.complete_state = state
-
- def apply_completion(self, completion):
- """
- Insert a given completion.
- """
- assert isinstance(completion, Completion)
-
- # If there was already a completion active, cancel that one.
- if self.complete_state:
- self.go_to_completion(None)
- self.complete_state = None
-
- # Insert text from the given completion.
- self.delete_before_cursor(-completion.start_position)
- self.insert_text(completion.text)
-
- def _set_history_search(self):
- """ Set `history_search_text`. """
- if self.enable_history_search():
- if self.history_search_text is None:
- self.history_search_text = self.document.text_before_cursor
- else:
- self.history_search_text = None
-
- def _history_matches(self, i):
- """
- True when the current entry matches the history search.
- (when we don't have history search, it's also True.)
- """
- return (self.history_search_text is None or
- self._working_lines[i].startswith(self.history_search_text))
-
- def history_forward(self, count=1):
- """
- Move forwards through the history.
-
- :param count: Amount of items to move forward.
- """
- self._set_history_search()
-
- # Go forward in history.
- found_something = False
-
- for i in range(self.working_index + 1, len(self._working_lines)):
- if self._history_matches(i):
- self.working_index = i
- count -= 1
- found_something = True
- if count == 0:
- break
-
- # If we found an entry, move cursor to the end of the first line.
- if found_something:
- self.cursor_position = 0
- self.cursor_position += self.document.get_end_of_line_position()
-
- def history_backward(self, count=1):
- """
- Move backwards through history.
- """
- self._set_history_search()
-
- # Go back in history.
- found_something = False
-
- for i in range(self.working_index - 1, -1, -1):
- if self._history_matches(i):
- self.working_index = i
- count -= 1
- found_something = True
- if count == 0:
- break
-
- # If we move to another entry, move cursor to the end of the line.
- if found_something:
- self.cursor_position = len(self.text)
-
- def yank_nth_arg(self, n=None, _yank_last_arg=False):
- """
- Pick nth word from previous history entry (depending on current
- `yank_nth_arg_state`) and insert it at current position. Rotate through
- history if called repeatedly. If no `n` has been given, take the first
- argument. (The second word.)
-
- :param n: (None or int), The index of the word from the previous line
- to take.
- """
- assert n is None or isinstance(n, int)
-
- if not len(self.history):
- return
-
- # Make sure we have a `YankNthArgState`.
- if self.yank_nth_arg_state is None:
- state = YankNthArgState(n=-1 if _yank_last_arg else 1)
- else:
- state = self.yank_nth_arg_state
-
- if n is not None:
- state.n = n
-
- # Get new history position.
- new_pos = state.history_position - 1
- if -new_pos > len(self.history):
- new_pos = -1
-
- # Take argument from line.
- line = self.history[new_pos]
-
- words = [w.strip() for w in _QUOTED_WORDS_RE.split(line)]
- words = [w for w in words if w]
- try:
- word = words[state.n]
- except IndexError:
- word = ''
-
- # Insert new argument.
- if state.previous_inserted_word:
- self.delete_before_cursor(len(state.previous_inserted_word))
- self.insert_text(word)
-
- # Save state again for next completion. (Note that the 'insert'
- # operation from above clears `self.yank_nth_arg_state`.)
- state.previous_inserted_word = word
- state.history_position = new_pos
- self.yank_nth_arg_state = state
-
- def yank_last_arg(self, n=None):
- """
- Like `yank_nth_arg`, but if no argument has been given, yank the last
- word by default.
- """
- self.yank_nth_arg(n=n, _yank_last_arg=True)
-
- def start_selection(self, selection_type=SelectionType.CHARACTERS):
- """
- Take the current cursor position as the start of this selection.
- """
- self.selection_state = SelectionState(self.cursor_position, selection_type)
-
- def copy_selection(self, _cut=False):
- """
- Copy selected text and return :class:`.ClipboardData` instance.
- """
- new_document, clipboard_data = self.document.cut_selection()
- if _cut:
- self.document = new_document
-
- self.selection_state = None
- return clipboard_data
-
- def cut_selection(self):
- """
- Delete selected text and return :class:`.ClipboardData` instance.
- """
- return self.copy_selection(_cut=True)
-
- def paste_clipboard_data(self, data, paste_mode=PasteMode.EMACS, count=1):
- """
- Insert the data from the clipboard.
- """
- assert isinstance(data, ClipboardData)
- assert paste_mode in (PasteMode.VI_BEFORE, PasteMode.VI_AFTER, PasteMode.EMACS)
-
- original_document = self.document
- self.document = self.document.paste_clipboard_data(data, paste_mode=paste_mode, count=count)
-
- # Remember original document. This assignment should come at the end,
- # because assigning to 'document' will erase it.
- self.document_before_paste = original_document
-
- def newline(self, copy_margin=True):
- """
- Insert a line ending at the current position.
- """
- if copy_margin:
- self.insert_text('\n' + self.document.leading_whitespace_in_current_line)
- else:
- self.insert_text('\n')
-
- def insert_line_above(self, copy_margin=True):
- """
- Insert a new line above the current one.
- """
- if copy_margin:
- insert = self.document.leading_whitespace_in_current_line + '\n'
- else:
- insert = '\n'
-
- self.cursor_position += self.document.get_start_of_line_position()
- self.insert_text(insert)
- self.cursor_position -= 1
-
- def insert_line_below(self, copy_margin=True):
- """
- Insert a new line below the current one.
- """
- if copy_margin:
- insert = '\n' + self.document.leading_whitespace_in_current_line
- else:
- insert = '\n'
-
- self.cursor_position += self.document.get_end_of_line_position()
- self.insert_text(insert)
-
- def insert_text(self, data, overwrite=False, move_cursor=True, fire_event=True):
- """
- Insert characters at cursor position.
-
- :param fire_event: Fire `on_text_insert` event. This is mainly used to
- trigger autocompletion while typing.
- """
- # Original text & cursor position.
- otext = self.text
- ocpos = self.cursor_position
-
- # In insert/text mode.
- if overwrite:
- # Don't overwrite the newline itself. Just before the line ending,
- # it should act like insert mode.
- overwritten_text = otext[ocpos:ocpos + len(data)]
- if '\n' in overwritten_text:
- overwritten_text = overwritten_text[:overwritten_text.find('\n')]
-
- self.text = otext[:ocpos] + data + otext[ocpos + len(overwritten_text):]
- else:
- self.text = otext[:ocpos] + data + otext[ocpos:]
-
- if move_cursor:
- self.cursor_position += len(data)
-
- # Fire 'on_text_insert' event.
- if fire_event:
- self.on_text_insert.fire()
-
- def undo(self):
- # Pop from the undo-stack until we find a text that if different from
- # the current text. (The current logic of `save_to_undo_stack` will
- # cause that the top of the undo stack is usually the same as the
- # current text, so in that case we have to pop twice.)
- while self._undo_stack:
- text, pos = self._undo_stack.pop()
-
- if text != self.text:
- # Push current text to redo stack.
- self._redo_stack.append((self.text, self.cursor_position))
-
- # Set new text/cursor_position.
- self.document = Document(text, cursor_position=pos)
- break
-
- def redo(self):
- if self._redo_stack:
- # Copy current state on undo stack.
- self.save_to_undo_stack(clear_redo_stack=False)
-
- # Pop state from redo stack.
- text, pos = self._redo_stack.pop()
- self.document = Document(text, cursor_position=pos)
-
- def validate(self):
- """
- Returns `True` if valid.
- """
- # Don't call the validator again, if it was already called for the
- # current input.
- if self.validation_state != ValidationState.UNKNOWN:
- return self.validation_state == ValidationState.VALID
-
- # Validate first. If not valid, set validation exception.
- if self.validator:
- try:
- self.validator.validate(self.document)
- except ValidationError as e:
- # Set cursor position (don't allow invalid values.)
- cursor_position = e.cursor_position
- self.cursor_position = min(max(0, cursor_position), len(self.text))
-
- self.validation_state = ValidationState.INVALID
- self.validation_error = e
- return False
-
- self.validation_state = ValidationState.VALID
- self.validation_error = None
- return True
-
- def append_to_history(self):
- """
- Append the current input to the history.
- (Only if valid input.)
- """
- # Validate first. If not valid, set validation exception.
- if not self.validate():
- return
-
- # Save at the tail of the history. (But don't if the last entry the
- # history is already the same.)
- if self.text and (not len(self.history) or self.history[-1] != self.text):
- self.history.append(self.text)
-
- def _search(self, search_state, include_current_position=False, count=1):
- """
- Execute search. Return (working_index, cursor_position) tuple when this
- search is applied. Returns `None` when this text cannot be found.
- """
- assert isinstance(search_state, SearchState)
- assert isinstance(count, int) and count > 0
-
- text = search_state.text
- direction = search_state.direction
- ignore_case = search_state.ignore_case()
-
- def search_once(working_index, document):
- """
- Do search one time.
- Return (working_index, document) or `None`
- """
- if direction == IncrementalSearchDirection.FORWARD:
- # Try find at the current input.
- new_index = document.find(
- text, include_current_position=include_current_position,
- ignore_case=ignore_case)
-
- if new_index is not None:
- return (working_index,
- Document(document.text, document.cursor_position + new_index))
- else:
- # No match, go forward in the history. (Include len+1 to wrap around.)
- # (Here we should always include all cursor positions, because
- # it's a different line.)
- for i in range(working_index + 1, len(self._working_lines) + 1):
- i %= len(self._working_lines)
-
- document = Document(self._working_lines[i], 0)
- new_index = document.find(text, include_current_position=True,
- ignore_case=ignore_case)
- if new_index is not None:
- return (i, Document(document.text, new_index))
- else:
- # Try find at the current input.
- new_index = document.find_backwards(
- text, ignore_case=ignore_case)
-
- if new_index is not None:
- return (working_index,
- Document(document.text, document.cursor_position + new_index))
- else:
- # No match, go back in the history. (Include -1 to wrap around.)
- for i in range(working_index - 1, -2, -1):
- i %= len(self._working_lines)
-
- document = Document(self._working_lines[i], len(self._working_lines[i]))
- new_index = document.find_backwards(
- text, ignore_case=ignore_case)
- if new_index is not None:
- return (i, Document(document.text, len(document.text) + new_index))
-
- # Do 'count' search iterations.
- working_index = self.working_index
- document = self.document
- for _ in range(count):
- result = search_once(working_index, document)
- if result is None:
- return # Nothing found.
- else:
- working_index, document = result
-
- return (working_index, document.cursor_position)
-
- def document_for_search(self, search_state):
- """
- Return a :class:`~prompt_toolkit.document.Document` instance that has
- the text/cursor position for this search, if we would apply it. This
- will be used in the
- :class:`~prompt_toolkit.layout.controls.BufferControl` to display
- feedback while searching.
- """
- search_result = self._search(search_state, include_current_position=True)
-
- if search_result is None:
- return self.document
- else:
- working_index, cursor_position = search_result
-
- # Keep selection, when `working_index` was not changed.
- if working_index == self.working_index:
- selection = self.selection_state
- else:
- selection = None
-
- return Document(self._working_lines[working_index],
- cursor_position, selection=selection)
-
- def get_search_position(self, search_state, include_current_position=True, count=1):
- """
- Get the cursor position for this search.
- (This operation won't change the `working_index`. It's won't go through
- the history. Vi text objects can't span multiple items.)
- """
- search_result = self._search(
- search_state, include_current_position=include_current_position, count=count)
-
- if search_result is None:
- return self.cursor_position
- else:
- working_index, cursor_position = search_result
- return cursor_position
-
- def apply_search(self, search_state, include_current_position=True, count=1):
- """
- Apply search. If something is found, set `working_index` and
- `cursor_position`.
- """
- search_result = self._search(
- search_state, include_current_position=include_current_position, count=count)
-
- if search_result is not None:
- working_index, cursor_position = search_result
- self.working_index = working_index
- self.cursor_position = cursor_position
-
- def exit_selection(self):
- self.selection_state = None
-
- def open_in_editor(self, cli):
- """
- Open code in editor.
-
- :param cli: :class:`~prompt_toolkit.interface.CommandLineInterface`
- instance.
- """
- if self.read_only():
- raise EditReadOnlyBuffer()
-
- # Write to temporary file
- descriptor, filename = tempfile.mkstemp(self.tempfile_suffix)
- os.write(descriptor, self.text.encode('utf-8'))
- os.close(descriptor)
-
- # Open in editor
- # (We need to use `cli.run_in_terminal`, because not all editors go to
- # the alternate screen buffer, and some could influence the cursor
- # position.)
- succes = cli.run_in_terminal(lambda: self._open_file_in_editor(filename))
-
- # Read content again.
- if succes:
- with open(filename, 'rb') as f:
- text = f.read().decode('utf-8')
-
- # Drop trailing newline. (Editors are supposed to add it at the
- # end, but we don't need it.)
- if text.endswith('\n'):
- text = text[:-1]
-
- self.document = Document(
- text=text,
- cursor_position=len(text))
-
- # Clean up temp file.
- os.remove(filename)
-
- def _open_file_in_editor(self, filename):
- """
- Call editor executable.
-
- Return True when we received a zero return code.
- """
- # If the 'VISUAL' or 'EDITOR' environment variable has been set, use that.
- # Otherwise, fall back to the first available editor that we can find.
- visual = os.environ.get('VISUAL')
- editor = os.environ.get('EDITOR')
-
- editors = [
- visual,
- editor,
-
- # Order of preference.
- '/usr/bin/editor',
- '/usr/bin/nano',
- '/usr/bin/pico',
- '/usr/bin/vi',
- '/usr/bin/emacs',
- ]
-
- for e in editors:
- if e:
- try:
- # Use 'shlex.split()', because $VISUAL can contain spaces
- # and quotes.
- returncode = subprocess.call(shlex.split(e) + [filename])
- return returncode == 0
-
- except OSError:
- # Executable does not exist, try the next one.
- pass
-
- return False
-
-
-def indent(buffer, from_row, to_row, count=1):
- """
- Indent text of a :class:`.Buffer` object.
- """
- current_row = buffer.document.cursor_position_row
- line_range = range(from_row, to_row)
-
- # Apply transformation.
- new_text = buffer.transform_lines(line_range, lambda l: ' ' * count + l)
- buffer.document = Document(
- new_text,
- Document(new_text).translate_row_col_to_index(current_row, 0))
-
- # Go to the start of the line.
- buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=True)
-
-
-def unindent(buffer, from_row, to_row, count=1):
- """
- Unindent text of a :class:`.Buffer` object.
- """
- current_row = buffer.document.cursor_position_row
- line_range = range(from_row, to_row)
-
- def transform(text):
- remove = ' ' * count
- if text.startswith(remove):
- return text[len(remove):]
- else:
- return text.lstrip()
-
- # Apply transformation.
- new_text = buffer.transform_lines(line_range, transform)
- buffer.document = Document(
- new_text,
- Document(new_text).translate_row_col_to_index(current_row, 0))
-
- # Go to the start of the line.
- buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=True)
-
-
-def reshape_text(buffer, from_row, to_row):
- """
- Reformat text, taking the width into account.
- `to_row` is included.
- (Vi 'gq' operator.)
- """
- lines = buffer.text.splitlines(True)
- lines_before = lines[:from_row]
- lines_after = lines[to_row + 1:]
- lines_to_reformat = lines[from_row:to_row + 1]
-
- if lines_to_reformat:
- # Take indentation from the first line.
- length = re.search(r'^\s*', lines_to_reformat[0]).end()
- indent = lines_to_reformat[0][:length].replace('\n', '')
-
- # Now, take all the 'words' from the lines to be reshaped.
- words = ''.join(lines_to_reformat).split()
-
- # And reshape.
- width = (buffer.text_width or 80) - len(indent)
- reshaped_text = [indent]
- current_width = 0
- for w in words:
- if current_width:
- if len(w) + current_width + 1 > width:
- reshaped_text.append('\n')
- reshaped_text.append(indent)
- current_width = 0
- else:
- reshaped_text.append(' ')
- current_width += 1
-
- reshaped_text.append(w)
- current_width += len(w)
-
- if reshaped_text[-1] != '\n':
- reshaped_text.append('\n')
-
- # Apply result.
- buffer.document = Document(
- text=''.join(lines_before + reshaped_text + lines_after),
- cursor_position=len(''.join(lines_before + reshaped_text)))
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer_mapping.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer_mapping.py
deleted file mode 100644
index 34f443bd47..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer_mapping.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""
-The BufferMapping contains all the buffers for a command line interface, and it
-keeps track of which buffer gets the focus.
-"""
-from __future__ import unicode_literals
-from .enums import DEFAULT_BUFFER, SEARCH_BUFFER, SYSTEM_BUFFER, DUMMY_BUFFER
-from .buffer import Buffer, AcceptAction
-from .history import InMemoryHistory
-
-import six
-
-__all__ = (
- 'BufferMapping',
-)
-
-
-class BufferMapping(dict):
- """
- Dictionary that maps the name of the buffers to the
- :class:`~prompt_toolkit.buffer.Buffer` instances.
-
- This mapping also keeps track of which buffer currently has the focus.
- (Some methods receive a 'cli' parameter. This is useful for applications
- where this `BufferMapping` is shared between several applications.)
- """
- def __init__(self, buffers=None, initial=DEFAULT_BUFFER):
- assert buffers is None or isinstance(buffers, dict)
-
- # Start with an empty dict.
- super(BufferMapping, self).__init__()
-
- # Add default buffers.
- self.update({
- # For the 'search' and 'system' buffers, 'returnable' is False, in
- # order to block normal Enter/ControlC behaviour.
- DEFAULT_BUFFER: Buffer(accept_action=AcceptAction.RETURN_DOCUMENT),
- SEARCH_BUFFER: Buffer(history=InMemoryHistory(), accept_action=AcceptAction.IGNORE),
- SYSTEM_BUFFER: Buffer(history=InMemoryHistory(), accept_action=AcceptAction.IGNORE),
- DUMMY_BUFFER: Buffer(read_only=True),
- })
-
- # Add received buffers.
- if buffers is not None:
- self.update(buffers)
-
- # Focus stack.
- self.focus_stack = [initial or DEFAULT_BUFFER]
-
- def current(self, cli):
- """
- The active :class:`.Buffer`.
- """
- return self[self.focus_stack[-1]]
-
- def current_name(self, cli):
- """
- The name of the active :class:`.Buffer`.
- """
- return self.focus_stack[-1]
-
- def previous(self, cli):
- """
- Return the previously focussed :class:`.Buffer` or `None`.
- """
- if len(self.focus_stack) > 1:
- try:
- return self[self.focus_stack[-2]]
- except KeyError:
- pass
-
- def focus(self, cli, buffer_name):
- """
- Focus the buffer with the given name.
- """
- assert isinstance(buffer_name, six.text_type)
- self.focus_stack = [buffer_name]
-
- def push_focus(self, cli, buffer_name):
- """
- Push buffer on the focus stack.
- """
- assert isinstance(buffer_name, six.text_type)
- self.focus_stack.append(buffer_name)
-
- def pop_focus(self, cli):
- """
- Pop buffer from the focus stack.
- """
- if len(self.focus_stack) > 1:
- self.focus_stack.pop()
- else:
- raise IndexError('Cannot pop last item from the focus stack.')
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/cache.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/cache.py
deleted file mode 100644
index 55c7369c9c..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/cache.py
+++ /dev/null
@@ -1,111 +0,0 @@
-from __future__ import unicode_literals
-from collections import deque
-from functools import wraps
-
-__all__ = (
- 'SimpleCache',
- 'FastDictCache',
- 'memoized',
-)
-
-
-class SimpleCache(object):
- """
- Very simple cache that discards the oldest item when the cache size is
- exceeded.
-
- :param maxsize: Maximum size of the cache. (Don't make it too big.)
- """
- def __init__(self, maxsize=8):
- assert isinstance(maxsize, int) and maxsize > 0
-
- self._data = {}
- self._keys = deque()
- self.maxsize = maxsize
-
- def get(self, key, getter_func):
- """
- Get object from the cache.
- If not found, call `getter_func` to resolve it, and put that on the top
- of the cache instead.
- """
- # Look in cache first.
- try:
- return self._data[key]
- except KeyError:
- # Not found? Get it.
- value = getter_func()
- self._data[key] = value
- self._keys.append(key)
-
- # Remove the oldest key when the size is exceeded.
- if len(self._data) > self.maxsize:
- key_to_remove = self._keys.popleft()
- if key_to_remove in self._data:
- del self._data[key_to_remove]
-
- return value
-
- def clear(self):
- " Clear cache. "
- self._data = {}
- self._keys = deque()
-
-
-class FastDictCache(dict):
- """
- Fast, lightweight cache which keeps at most `size` items.
- It will discard the oldest items in the cache first.
-
- The cache is a dictionary, which doesn't keep track of access counts.
- It is perfect to cache little immutable objects which are not expensive to
- create, but where a dictionary lookup is still much faster than an object
- instantiation.
-
- :param get_value: Callable that's called in case of a missing key.
- """
- # NOTE: This cache is used to cache `prompt_toolkit.layout.screen.Char` and
- # `prompt_toolkit.Document`. Make sure to keep this really lightweight.
- # Accessing the cache should stay faster than instantiating new
- # objects.
- # (Dictionary lookups are really fast.)
- # SimpleCache is still required for cases where the cache key is not
- # the same as the arguments given to the function that creates the
- # value.)
- def __init__(self, get_value=None, size=1000000):
- assert callable(get_value)
- assert isinstance(size, int) and size > 0
-
- self._keys = deque()
- self.get_value = get_value
- self.size = size
-
- def __missing__(self, key):
- # Remove the oldest key when the size is exceeded.
- if len(self) > self.size:
- key_to_remove = self._keys.popleft()
- if key_to_remove in self:
- del self[key_to_remove]
-
- result = self.get_value(*key)
- self[key] = result
- self._keys.append(key)
- return result
-
-
-def memoized(maxsize=1024):
- """
- Momoization decorator for immutable classes and pure functions.
- """
- cache = SimpleCache(maxsize=maxsize)
-
- def decorator(obj):
- @wraps(obj)
- def new_callable(*a, **kw):
- def create_new():
- return obj(*a, **kw)
-
- key = (a, tuple(kw.items()))
- return cache.get(key, create_new)
- return new_callable
- return decorator
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/__init__.py
deleted file mode 100644
index 56202ddd3b..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from .base import Clipboard, ClipboardData
-from .in_memory import InMemoryClipboard
-
-
-# We are not importing `PyperclipClipboard` here, because it would require the
-# `pyperclip` module to be present.
-
-#from .pyperclip import PyperclipClipboard
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/base.py
deleted file mode 100644
index 803c0b0e7d..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/base.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""
-Clipboard for command line interface.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-import six
-
-from prompt_toolkit.selection import SelectionType
-
-__all__ = (
- 'Clipboard',
- 'ClipboardData',
-)
-
-
-class ClipboardData(object):
- """
- Text on the clipboard.
-
- :param text: string
- :param type: :class:`~prompt_toolkit.selection.SelectionType`
- """
- def __init__(self, text='', type=SelectionType.CHARACTERS):
- assert isinstance(text, six.string_types)
- assert type in (SelectionType.CHARACTERS, SelectionType.LINES, SelectionType.BLOCK)
-
- self.text = text
- self.type = type
-
-
-class Clipboard(with_metaclass(ABCMeta, object)):
- """
- Abstract baseclass for clipboards.
- (An implementation can be in memory, it can share the X11 or Windows
- keyboard, or can be persistent.)
- """
- @abstractmethod
- def set_data(self, data):
- """
- Set data to the clipboard.
-
- :param data: :class:`~.ClipboardData` instance.
- """
-
- def set_text(self, text): # Not abstract.
- """
- Shortcut for setting plain text on clipboard.
- """
- assert isinstance(text, six.string_types)
- self.set_data(ClipboardData(text))
-
- def rotate(self):
- """
- For Emacs mode, rotate the kill ring.
- """
-
- @abstractmethod
- def get_data(self):
- """
- Return clipboard data.
- """
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/in_memory.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/in_memory.py
deleted file mode 100644
index 081666ab80..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/in_memory.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from .base import Clipboard, ClipboardData
-
-from collections import deque
-
-__all__ = (
- 'InMemoryClipboard',
-)
-
-
-class InMemoryClipboard(Clipboard):
- """
- Default clipboard implementation.
- Just keep the data in memory.
-
- This implements a kill-ring, for Emacs mode.
- """
- def __init__(self, data=None, max_size=60):
- assert data is None or isinstance(data, ClipboardData)
- assert max_size >= 1
-
- self.max_size = max_size
- self._ring = deque()
- if data is not None:
- self.set_data(data)
-
- def set_data(self, data):
- assert isinstance(data, ClipboardData)
- self._ring.appendleft(data)
-
- while len(self._ring) > self.max_size:
- self._ring.pop()
-
- def get_data(self):
- if self._ring:
- return self._ring[0]
- else:
- return ClipboardData()
-
- def rotate(self):
- if self._ring:
- # Add the very first item at the end.
- self._ring.append(self._ring.popleft())
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/pyperclip.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/pyperclip.py
deleted file mode 100644
index 61ab3aac0a..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/pyperclip.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from __future__ import absolute_import, unicode_literals
-import pyperclip
-
-from prompt_toolkit.selection import SelectionType
-from .base import Clipboard, ClipboardData
-
-__all__ = (
- 'PyperclipClipboard',
-)
-
-
-class PyperclipClipboard(Clipboard):
- """
- Clipboard that synchronizes with the Windows/Mac/Linux system clipboard,
- using the pyperclip module.
- """
- def __init__(self):
- self._data = None
-
- def set_data(self, data):
- assert isinstance(data, ClipboardData)
- self._data = data
- pyperclip.copy(data.text)
-
- def get_data(self):
- text = pyperclip.paste()
-
- # When the clipboard data is equal to what we copied last time, reuse
- # the `ClipboardData` instance. That way we're sure to keep the same
- # `SelectionType`.
- if self._data and self._data.text == text:
- return self._data
-
- # Pyperclip returned something else. Create a new `ClipboardData`
- # instance.
- else:
- return ClipboardData(
- text=text,
- type=SelectionType.LINES if '\n' in text else SelectionType.LINES)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/completion.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/completion.py
deleted file mode 100644
index 339738ab97..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/completion.py
+++ /dev/null
@@ -1,170 +0,0 @@
-"""
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-
-__all__ = (
- 'Completion',
- 'Completer',
- 'CompleteEvent',
- 'get_common_complete_suffix',
-)
-
-
-class Completion(object):
- """
- :param text: The new string that will be inserted into the document.
- :param start_position: Position relative to the cursor_position where the
- new text will start. The text will be inserted between the
- start_position and the original cursor position.
- :param display: (optional string) If the completion has to be displayed
- differently in the completion menu.
- :param display_meta: (Optional string) Meta information about the
- completion, e.g. the path or source where it's coming from.
- :param get_display_meta: Lazy `display_meta`. Retrieve meta information
- only when meta is displayed.
- """
- def __init__(self, text, start_position=0, display=None, display_meta=None,
- get_display_meta=None):
- self.text = text
- self.start_position = start_position
- self._display_meta = display_meta
- self._get_display_meta = get_display_meta
-
- if display is None:
- self.display = text
- else:
- self.display = display
-
- assert self.start_position <= 0
-
- def __repr__(self):
- if self.display == self.text:
- return '%s(text=%r, start_position=%r)' % (
- self.__class__.__name__, self.text, self.start_position)
- else:
- return '%s(text=%r, start_position=%r, display=%r)' % (
- self.__class__.__name__, self.text, self.start_position,
- self.display)
-
- def __eq__(self, other):
- return (
- self.text == other.text and
- self.start_position == other.start_position and
- self.display == other.display and
- self.display_meta == other.display_meta)
-
- def __hash__(self):
- return hash((self.text, self.start_position, self.display, self.display_meta))
-
- @property
- def display_meta(self):
- # Return meta-text. (This is lazy when using "get_display_meta".)
- if self._display_meta is not None:
- return self._display_meta
-
- elif self._get_display_meta:
- self._display_meta = self._get_display_meta()
- return self._display_meta
-
- else:
- return ''
-
- def new_completion_from_position(self, position):
- """
- (Only for internal use!)
- Get a new completion by splitting this one. Used by
- `CommandLineInterface` when it needs to have a list of new completions
- after inserting the common prefix.
- """
- assert isinstance(position, int) and position - self.start_position >= 0
-
- return Completion(
- text=self.text[position - self.start_position:],
- display=self.display,
- display_meta=self._display_meta,
- get_display_meta=self._get_display_meta)
-
-
-class CompleteEvent(object):
- """
- Event that called the completer.
-
- :param text_inserted: When True, it means that completions are requested
- because of a text insert. (`Buffer.complete_while_typing`.)
- :param completion_requested: When True, it means that the user explicitely
- pressed the `Tab` key in order to view the completions.
-
- These two flags can be used for instance to implemented a completer that
- shows some completions when ``Tab`` has been pressed, but not
- automatically when the user presses a space. (Because of
- `complete_while_typing`.)
- """
- def __init__(self, text_inserted=False, completion_requested=False):
- assert not (text_inserted and completion_requested)
-
- #: Automatic completion while typing.
- self.text_inserted = text_inserted
-
- #: Used explicitely requested completion by pressing 'tab'.
- self.completion_requested = completion_requested
-
- def __repr__(self):
- return '%s(text_inserted=%r, completion_requested=%r)' % (
- self.__class__.__name__, self.text_inserted, self.completion_requested)
-
-
-class Completer(with_metaclass(ABCMeta, object)):
- """
- Base class for completer implementations.
- """
- @abstractmethod
- def get_completions(self, document, complete_event):
- """
- Yield :class:`.Completion` instances.
-
- :param document: :class:`~prompt_toolkit.document.Document` instance.
- :param complete_event: :class:`.CompleteEvent` instance.
- """
- while False:
- yield
-
-
-def get_common_complete_suffix(document, completions):
- """
- Return the common prefix for all completions.
- """
- # Take only completions that don't change the text before the cursor.
- def doesnt_change_before_cursor(completion):
- end = completion.text[:-completion.start_position]
- return document.text_before_cursor.endswith(end)
-
- completions2 = [c for c in completions if doesnt_change_before_cursor(c)]
-
- # When there is at least one completion that changes the text before the
- # cursor, don't return any common part.
- if len(completions2) != len(completions):
- return ''
-
- # Return the common prefix.
- def get_suffix(completion):
- return completion.text[-completion.start_position:]
-
- return _commonprefix([get_suffix(c) for c in completions2])
-
-
-def _commonprefix(strings):
- # Similar to os.path.commonprefix
- if not strings:
- return ''
-
- else:
- s1 = min(strings)
- s2 = max(strings)
-
- for i, c in enumerate(s1):
- if c != s2[i]:
- return s1[:i]
-
- return s1
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/__init__.py
+++ /dev/null
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/__init__.py
deleted file mode 100644
index 43893b8c8c..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import unicode_literals
-
-from .filesystem import PathCompleter
-from .base import WordCompleter
-from .system import SystemCompleter
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/base.py
deleted file mode 100644
index 65a69fede1..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/base.py
+++ /dev/null
@@ -1,61 +0,0 @@
-from __future__ import unicode_literals
-
-from six import string_types
-from prompt_toolkit.completion import Completer, Completion
-
-__all__ = (
- 'WordCompleter',
-)
-
-
-class WordCompleter(Completer):
- """
- Simple autocompletion on a list of words.
-
- :param words: List of words.
- :param ignore_case: If True, case-insensitive completion.
- :param meta_dict: Optional dict mapping words to their meta-information.
- :param WORD: When True, use WORD characters.
- :param sentence: When True, don't complete by comparing the word before the
- cursor, but by comparing all the text before the cursor. In this case,
- the list of words is just a list of strings, where each string can
- contain spaces. (Can not be used together with the WORD option.)
- :param match_middle: When True, match not only the start, but also in the
- middle of the word.
- """
- def __init__(self, words, ignore_case=False, meta_dict=None, WORD=False,
- sentence=False, match_middle=False):
- assert not (WORD and sentence)
-
- self.words = list(words)
- self.ignore_case = ignore_case
- self.meta_dict = meta_dict or {}
- self.WORD = WORD
- self.sentence = sentence
- self.match_middle = match_middle
- assert all(isinstance(w, string_types) for w in self.words)
-
- def get_completions(self, document, complete_event):
- # Get word/text before cursor.
- if self.sentence:
- word_before_cursor = document.text_before_cursor
- else:
- word_before_cursor = document.get_word_before_cursor(WORD=self.WORD)
-
- if self.ignore_case:
- word_before_cursor = word_before_cursor.lower()
-
- def word_matches(word):
- """ True when the word before the cursor matches. """
- if self.ignore_case:
- word = word.lower()
-
- if self.match_middle:
- return word_before_cursor in word
- else:
- return word.startswith(word_before_cursor)
-
- for a in self.words:
- if word_matches(a):
- display_meta = self.meta_dict.get(a, '')
- yield Completion(a, -len(word_before_cursor), display_meta=display_meta)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/filesystem.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/filesystem.py
deleted file mode 100644
index cbd74d8fea..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/filesystem.py
+++ /dev/null
@@ -1,105 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.completion import Completer, Completion
-import os
-
-__all__ = (
- 'PathCompleter',
- 'ExecutableCompleter',
-)
-
-
-class PathCompleter(Completer):
- """
- Complete for Path variables.
-
- :param get_paths: Callable which returns a list of directories to look into
- when the user enters a relative path.
- :param file_filter: Callable which takes a filename and returns whether
- this file should show up in the completion. ``None``
- when no filtering has to be done.
- :param min_input_len: Don't do autocompletion when the input string is shorter.
- """
- def __init__(self, only_directories=False, get_paths=None, file_filter=None,
- min_input_len=0, expanduser=False):
- assert get_paths is None or callable(get_paths)
- assert file_filter is None or callable(file_filter)
- assert isinstance(min_input_len, int)
- assert isinstance(expanduser, bool)
-
- self.only_directories = only_directories
- self.get_paths = get_paths or (lambda: ['.'])
- self.file_filter = file_filter or (lambda _: True)
- self.min_input_len = min_input_len
- self.expanduser = expanduser
-
- def get_completions(self, document, complete_event):
- text = document.text_before_cursor
-
- # Complete only when we have at least the minimal input length,
- # otherwise, we can too many results and autocompletion will become too
- # heavy.
- if len(text) < self.min_input_len:
- return
-
- try:
- # Do tilde expansion.
- if self.expanduser:
- text = os.path.expanduser(text)
-
- # Directories where to look.
- dirname = os.path.dirname(text)
- if dirname:
- directories = [os.path.dirname(os.path.join(p, text))
- for p in self.get_paths()]
- else:
- directories = self.get_paths()
-
- # Start of current file.
- prefix = os.path.basename(text)
-
- # Get all filenames.
- filenames = []
- for directory in directories:
- # Look for matches in this directory.
- if os.path.isdir(directory):
- for filename in os.listdir(directory):
- if filename.startswith(prefix):
- filenames.append((directory, filename))
-
- # Sort
- filenames = sorted(filenames, key=lambda k: k[1])
-
- # Yield them.
- for directory, filename in filenames:
- completion = filename[len(prefix):]
- full_name = os.path.join(directory, filename)
-
- if os.path.isdir(full_name):
- # For directories, add a slash to the filename.
- # (We don't add them to the `completion`. Users can type it
- # to trigger the autocompletion themself.)
- filename += '/'
- elif self.only_directories:
- continue
-
- if not self.file_filter(full_name):
- continue
-
- yield Completion(completion, 0, display=filename)
- except OSError:
- pass
-
-
-class ExecutableCompleter(PathCompleter):
- """
- Complete only excutable files in the current path.
- """
- def __init__(self):
- PathCompleter.__init__(
- self,
- only_directories=False,
- min_input_len=1,
- get_paths=lambda: os.environ.get('PATH', '').split(os.pathsep),
- file_filter=lambda name: os.access(name, os.X_OK),
- expanduser=True),
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/system.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/system.py
deleted file mode 100644
index 76d6c1f9b4..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/system.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.contrib.regular_languages.completion import GrammarCompleter
-from prompt_toolkit.contrib.regular_languages.compiler import compile
-
-from .filesystem import PathCompleter, ExecutableCompleter
-
-__all__ = (
- 'SystemCompleter',
-)
-
-
-class SystemCompleter(GrammarCompleter):
- """
- Completer for system commands.
- """
- def __init__(self):
- # Compile grammar.
- g = compile(
- r"""
- # First we have an executable.
- (?P<executable>[^\s]+)
-
- # Ignore literals in between.
- (
- \s+
- ("[^"]*" | '[^']*' | [^'"]+ )
- )*
-
- \s+
-
- # Filename as parameters.
- (
- (?P<filename>[^\s]+) |
- "(?P<double_quoted_filename>[^\s]+)" |
- '(?P<single_quoted_filename>[^\s]+)'
- )
- """,
- escape_funcs={
- 'double_quoted_filename': (lambda string: string.replace('"', '\\"')),
- 'single_quoted_filename': (lambda string: string.replace("'", "\\'")),
- },
- unescape_funcs={
- 'double_quoted_filename': (lambda string: string.replace('\\"', '"')), # XXX: not enterily correct.
- 'single_quoted_filename': (lambda string: string.replace("\\'", "'")),
- })
-
- # Create GrammarCompleter
- super(SystemCompleter, self).__init__(
- g,
- {
- 'executable': ExecutableCompleter(),
- 'filename': PathCompleter(only_directories=False, expanduser=True),
- 'double_quoted_filename': PathCompleter(only_directories=False, expanduser=True),
- 'single_quoted_filename': PathCompleter(only_directories=False, expanduser=True),
- })
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/__init__.py
deleted file mode 100644
index 314cb1f81d..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/__init__.py
+++ /dev/null
@@ -1,76 +0,0 @@
-r"""
-Tool for expressing the grammar of an input as a regular language.
-==================================================================
-
-The grammar for the input of many simple command line interfaces can be
-expressed by a regular language. Examples are PDB (the Python debugger); a
-simple (bash-like) shell with "pwd", "cd", "cat" and "ls" commands; arguments
-that you can pass to an executable; etc. It is possible to use regular
-expressions for validation and parsing of such a grammar. (More about regular
-languages: http://en.wikipedia.org/wiki/Regular_language)
-
-Example
--------
-
-Let's take the pwd/cd/cat/ls example. We want to have a shell that accepts
-these three commands. "cd" is followed by a quoted directory name and "cat" is
-followed by a quoted file name. (We allow quotes inside the filename when
-they're escaped with a backslash.) We could define the grammar using the
-following regular expression::
-
- grammar = \s* (
- pwd |
- ls |
- (cd \s+ " ([^"]|\.)+ ") |
- (cat \s+ " ([^"]|\.)+ ")
- ) \s*
-
-
-What can we do with this grammar?
----------------------------------
-
-- Syntax highlighting: We could use this for instance to give file names
- different colour.
-- Parse the result: .. We can extract the file names and commands by using a
- regular expression with named groups.
-- Input validation: .. Don't accept anything that does not match this grammar.
- When combined with a parser, we can also recursively do
- filename validation (and accept only existing files.)
-- Autocompletion: .... Each part of the grammar can have its own autocompleter.
- "cat" has to be completed using file names, while "cd"
- has to be completed using directory names.
-
-How does it work?
------------------
-
-As a user of this library, you have to define the grammar of the input as a
-regular expression. The parts of this grammar where autocompletion, validation
-or any other processing is required need to be marked using a regex named
-group. Like ``(?P<varname>...)`` for instance.
-
-When the input is processed for validation (for instance), the regex will
-execute, the named group is captured, and the validator associated with this
-named group will test the captured string.
-
-There is one tricky bit:
-
- Ofter we operate on incomplete input (this is by definition the case for
- autocompletion) and we have to decide for the cursor position in which
- possible state the grammar it could be and in which way variables could be
- matched up to that point.
-
-To solve this problem, the compiler takes the original regular expression and
-translates it into a set of other regular expressions which each match prefixes
-of strings that would match the first expression. (We translate it into
-multiple expression, because we want to have each possible state the regex
-could be in -- in case there are several or-clauses with each different
-completers.)
-
-
-TODO: some examples of:
- - How to create a highlighter from this grammar.
- - How to create a validator from this grammar.
- - How to create an autocompleter from this grammar.
- - How to create a parser from this grammar.
-"""
-from .compiler import compile
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/compiler.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/compiler.py
deleted file mode 100644
index 01476bf626..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/compiler.py
+++ /dev/null
@@ -1,408 +0,0 @@
-r"""
-Compiler for a regular grammar.
-
-Example usage::
-
- # Create and compile grammar.
- p = compile('add \s+ (?P<var1>[^\s]+) \s+ (?P<var2>[^\s]+)')
-
- # Match input string.
- m = p.match('add 23 432')
-
- # Get variables.
- m.variables().get('var1') # Returns "23"
- m.variables().get('var2') # Returns "432"
-
-
-Partial matches are possible::
-
- # Create and compile grammar.
- p = compile('''
- # Operators with two arguments.
- ((?P<operator1>[^\s]+) \s+ (?P<var1>[^\s]+) \s+ (?P<var2>[^\s]+)) |
-
- # Operators with only one arguments.
- ((?P<operator2>[^\s]+) \s+ (?P<var1>[^\s]+))
- ''')
-
- # Match partial input string.
- m = p.match_prefix('add 23')
-
- # Get variables. (Notice that both operator1 and operator2 contain the
- # value "add".) This is because our input is incomplete, and we don't know
- # yet in which rule of the regex we we'll end up. It could also be that
- # `operator1` and `operator2` have a different autocompleter and we want to
- # call all possible autocompleters that would result in valid input.)
- m.variables().get('var1') # Returns "23"
- m.variables().get('operator1') # Returns "add"
- m.variables().get('operator2') # Returns "add"
-
-"""
-from __future__ import unicode_literals
-import re
-
-from six.moves import range
-from .regex_parser import Any, Sequence, Regex, Variable, Repeat, Lookahead
-from .regex_parser import parse_regex, tokenize_regex
-
-__all__ = (
- 'compile',
-)
-
-
-# Name of the named group in the regex, matching trailing input.
-# (Trailing input is when the input contains characters after the end of the
-# expression has been matched.)
-_INVALID_TRAILING_INPUT = 'invalid_trailing'
-
-
-class _CompiledGrammar(object):
- """
- Compiles a grammar. This will take the parse tree of a regular expression
- and compile the grammar.
-
- :param root_node: :class~`.regex_parser.Node` instance.
- :param escape_funcs: `dict` mapping variable names to escape callables.
- :param unescape_funcs: `dict` mapping variable names to unescape callables.
- """
- def __init__(self, root_node, escape_funcs=None, unescape_funcs=None):
- self.root_node = root_node
- self.escape_funcs = escape_funcs or {}
- self.unescape_funcs = unescape_funcs or {}
-
- #: Dictionary that will map the redex names to Node instances.
- self._group_names_to_nodes = {} # Maps regex group names to varnames.
- counter = [0]
-
- def create_group_func(node):
- name = 'n%s' % counter[0]
- self._group_names_to_nodes[name] = node.varname
- counter[0] += 1
- return name
-
- # Compile regex strings.
- self._re_pattern = '^%s$' % self._transform(root_node, create_group_func)
- self._re_prefix_patterns = list(self._transform_prefix(root_node, create_group_func))
-
- # Compile the regex itself.
- flags = re.DOTALL # Note that we don't need re.MULTILINE! (^ and $
- # still represent the start and end of input text.)
- self._re = re.compile(self._re_pattern, flags)
- self._re_prefix = [re.compile(t, flags) for t in self._re_prefix_patterns]
-
- # We compile one more set of regexes, similar to `_re_prefix`, but accept any trailing
- # input. This will ensure that we can still highlight the input correctly, even when the
- # input contains some additional characters at the end that don't match the grammar.)
- self._re_prefix_with_trailing_input = [
- re.compile(r'(?:%s)(?P<%s>.*?)$' % (t.rstrip('$'), _INVALID_TRAILING_INPUT), flags)
- for t in self._re_prefix_patterns]
-
- def escape(self, varname, value):
- """
- Escape `value` to fit in the place of this variable into the grammar.
- """
- f = self.escape_funcs.get(varname)
- return f(value) if f else value
-
- def unescape(self, varname, value):
- """
- Unescape `value`.
- """
- f = self.unescape_funcs.get(varname)
- return f(value) if f else value
-
- @classmethod
- def _transform(cls, root_node, create_group_func):
- """
- Turn a :class:`Node` object into a regular expression.
-
- :param root_node: The :class:`Node` instance for which we generate the grammar.
- :param create_group_func: A callable which takes a `Node` and returns the next
- free name for this node.
- """
- def transform(node):
- # Turn `Any` into an OR.
- if isinstance(node, Any):
- return '(?:%s)' % '|'.join(transform(c) for c in node.children)
-
- # Concatenate a `Sequence`
- elif isinstance(node, Sequence):
- return ''.join(transform(c) for c in node.children)
-
- # For Regex and Lookahead nodes, just insert them literally.
- elif isinstance(node, Regex):
- return node.regex
-
- elif isinstance(node, Lookahead):
- before = ('(?!' if node.negative else '(=')
- return before + transform(node.childnode) + ')'
-
- # A `Variable` wraps the children into a named group.
- elif isinstance(node, Variable):
- return '(?P<%s>%s)' % (create_group_func(node), transform(node.childnode))
-
- # `Repeat`.
- elif isinstance(node, Repeat):
- return '(?:%s){%i,%s}%s' % (
- transform(node.childnode), node.min_repeat,
- ('' if node.max_repeat is None else str(node.max_repeat)),
- ('' if node.greedy else '?')
- )
- else:
- raise TypeError('Got %r' % (node, ))
-
- return transform(root_node)
-
- @classmethod
- def _transform_prefix(cls, root_node, create_group_func):
- """
- Yield all the regular expressions matching a prefix of the grammar
- defined by the `Node` instance.
-
- This can yield multiple expressions, because in the case of on OR
- operation in the grammar, we can have another outcome depending on
- which clause would appear first. E.g. "(A|B)C" is not the same as
- "(B|A)C" because the regex engine is lazy and takes the first match.
- However, because we the current input is actually a prefix of the
- grammar which meight not yet contain the data for "C", we need to know
- both intermediate states, in order to call the appropriate
- autocompletion for both cases.
-
- :param root_node: The :class:`Node` instance for which we generate the grammar.
- :param create_group_func: A callable which takes a `Node` and returns the next
- free name for this node.
- """
- def transform(node):
- # Generate regexes for all permutations of this OR. Each node
- # should be in front once.
- if isinstance(node, Any):
- for c in node.children:
- for r in transform(c):
- yield '(?:%s)?' % r
-
- # For a sequence. We can either have a match for the sequence
- # of all the children, or for an exact match of the first X
- # children, followed by a partial match of the next children.
- elif isinstance(node, Sequence):
- for i in range(len(node.children)):
- a = [cls._transform(c, create_group_func) for c in node.children[:i]]
- for c in transform(node.children[i]):
- yield '(?:%s)' % (''.join(a) + c)
-
- elif isinstance(node, Regex):
- yield '(?:%s)?' % node.regex
-
- elif isinstance(node, Lookahead):
- if node.negative:
- yield '(?!%s)' % cls._transform(node.childnode, create_group_func)
- else:
- # Not sure what the correct semantics are in this case.
- # (Probably it's not worth implementing this.)
- raise Exception('Positive lookahead not yet supported.')
-
- elif isinstance(node, Variable):
- # (Note that we should not append a '?' here. the 'transform'
- # method will already recursively do that.)
- for c in transform(node.childnode):
- yield '(?P<%s>%s)' % (create_group_func(node), c)
-
- elif isinstance(node, Repeat):
- # If we have a repetition of 8 times. That would mean that the
- # current input could have for instance 7 times a complete
- # match, followed by a partial match.
- prefix = cls._transform(node.childnode, create_group_func)
-
- for c in transform(node.childnode):
- if node.max_repeat:
- repeat_sign = '{,%i}' % (node.max_repeat - 1)
- else:
- repeat_sign = '*'
- yield '(?:%s)%s%s(?:%s)?' % (
- prefix,
- repeat_sign,
- ('' if node.greedy else '?'),
- c)
-
- else:
- raise TypeError('Got %r' % node)
-
- for r in transform(root_node):
- yield '^%s$' % r
-
- def match(self, string):
- """
- Match the string with the grammar.
- Returns a :class:`Match` instance or `None` when the input doesn't match the grammar.
-
- :param string: The input string.
- """
- m = self._re.match(string)
-
- if m:
- return Match(string, [(self._re, m)], self._group_names_to_nodes, self.unescape_funcs)
-
- def match_prefix(self, string):
- """
- Do a partial match of the string with the grammar. The returned
- :class:`Match` instance can contain multiple representations of the
- match. This will never return `None`. If it doesn't match at all, the "trailing input"
- part will capture all of the input.
-
- :param string: The input string.
- """
- # First try to match using `_re_prefix`. If nothing is found, use the patterns that
- # also accept trailing characters.
- for patterns in [self._re_prefix, self._re_prefix_with_trailing_input]:
- matches = [(r, r.match(string)) for r in patterns]
- matches = [(r, m) for r, m in matches if m]
-
- if matches != []:
- return Match(string, matches, self._group_names_to_nodes, self.unescape_funcs)
-
-
-class Match(object):
- """
- :param string: The input string.
- :param re_matches: List of (compiled_re_pattern, re_match) tuples.
- :param group_names_to_nodes: Dictionary mapping all the re group names to the matching Node instances.
- """
- def __init__(self, string, re_matches, group_names_to_nodes, unescape_funcs):
- self.string = string
- self._re_matches = re_matches
- self._group_names_to_nodes = group_names_to_nodes
- self._unescape_funcs = unescape_funcs
-
- def _nodes_to_regs(self):
- """
- Return a list of (varname, reg) tuples.
- """
- def get_tuples():
- for r, re_match in self._re_matches:
- for group_name, group_index in r.groupindex.items():
- if group_name != _INVALID_TRAILING_INPUT:
- reg = re_match.regs[group_index]
- node = self._group_names_to_nodes[group_name]
- yield (node, reg)
-
- return list(get_tuples())
-
- def _nodes_to_values(self):
- """
- Returns list of list of (Node, string_value) tuples.
- """
- def is_none(slice):
- return slice[0] == -1 and slice[1] == -1
-
- def get(slice):
- return self.string[slice[0]:slice[1]]
-
- return [(varname, get(slice), slice) for varname, slice in self._nodes_to_regs() if not is_none(slice)]
-
- def _unescape(self, varname, value):
- unwrapper = self._unescape_funcs.get(varname)
- return unwrapper(value) if unwrapper else value
-
- def variables(self):
- """
- Returns :class:`Variables` instance.
- """
- return Variables([(k, self._unescape(k, v), sl) for k, v, sl in self._nodes_to_values()])
-
- def trailing_input(self):
- """
- Get the `MatchVariable` instance, representing trailing input, if there is any.
- "Trailing input" is input at the end that does not match the grammar anymore, but
- when this is removed from the end of the input, the input would be a valid string.
- """
- slices = []
-
- # Find all regex group for the name _INVALID_TRAILING_INPUT.
- for r, re_match in self._re_matches:
- for group_name, group_index in r.groupindex.items():
- if group_name == _INVALID_TRAILING_INPUT:
- slices.append(re_match.regs[group_index])
-
- # Take the smallest part. (Smaller trailing text means that a larger input has
- # been matched, so that is better.)
- if slices:
- slice = [max(i[0] for i in slices), max(i[1] for i in slices)]
- value = self.string[slice[0]:slice[1]]
- return MatchVariable('<trailing_input>', value, slice)
-
- def end_nodes(self):
- """
- Yields `MatchVariable` instances for all the nodes having their end
- position at the end of the input string.
- """
- for varname, reg in self._nodes_to_regs():
- # If this part goes until the end of the input string.
- if reg[1] == len(self.string):
- value = self._unescape(varname, self.string[reg[0]: reg[1]])
- yield MatchVariable(varname, value, (reg[0], reg[1]))
-
-
-class Variables(object):
- def __init__(self, tuples):
- #: List of (varname, value, slice) tuples.
- self._tuples = tuples
-
- def __repr__(self):
- return '%s(%s)' % (
- self.__class__.__name__, ', '.join('%s=%r' % (k, v) for k, v, _ in self._tuples))
-
- def get(self, key, default=None):
- items = self.getall(key)
- return items[0] if items else default
-
- def getall(self, key):
- return [v for k, v, _ in self._tuples if k == key]
-
- def __getitem__(self, key):
- return self.get(key)
-
- def __iter__(self):
- """
- Yield `MatchVariable` instances.
- """
- for varname, value, slice in self._tuples:
- yield MatchVariable(varname, value, slice)
-
-
-class MatchVariable(object):
- """
- Represents a match of a variable in the grammar.
-
- :param varname: (string) Name of the variable.
- :param value: (string) Value of this variable.
- :param slice: (start, stop) tuple, indicating the position of this variable
- in the input string.
- """
- def __init__(self, varname, value, slice):
- self.varname = varname
- self.value = value
- self.slice = slice
-
- self.start = self.slice[0]
- self.stop = self.slice[1]
-
- def __repr__(self):
- return '%s(%r, %r)' % (self.__class__.__name__, self.varname, self.value)
-
-
-def compile(expression, escape_funcs=None, unescape_funcs=None):
- """
- Compile grammar (given as regex string), returning a `CompiledGrammar`
- instance.
- """
- return _compile_from_parse_tree(
- parse_regex(tokenize_regex(expression)),
- escape_funcs=escape_funcs,
- unescape_funcs=unescape_funcs)
-
-
-def _compile_from_parse_tree(root_node, *a, **kw):
- """
- Compile grammar (given as parse tree), returning a `CompiledGrammar`
- instance.
- """
- return _CompiledGrammar(root_node, *a, **kw)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/completion.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/completion.py
deleted file mode 100644
index bb49986a03..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/completion.py
+++ /dev/null
@@ -1,84 +0,0 @@
-"""
-Completer for a regular grammar.
-"""
-from __future__ import unicode_literals
-
-from prompt_toolkit.completion import Completer, Completion
-from prompt_toolkit.document import Document
-
-from .compiler import _CompiledGrammar
-
-__all__ = (
- 'GrammarCompleter',
-)
-
-
-class GrammarCompleter(Completer):
- """
- Completer which can be used for autocompletion according to variables in
- the grammar. Each variable can have a different autocompleter.
-
- :param compiled_grammar: `GrammarCompleter` instance.
- :param completers: `dict` mapping variable names of the grammar to the
- `Completer` instances to be used for each variable.
- """
- def __init__(self, compiled_grammar, completers):
- assert isinstance(compiled_grammar, _CompiledGrammar)
- assert isinstance(completers, dict)
-
- self.compiled_grammar = compiled_grammar
- self.completers = completers
-
- def get_completions(self, document, complete_event):
- m = self.compiled_grammar.match_prefix(document.text_before_cursor)
-
- if m:
- completions = self._remove_duplicates(
- self._get_completions_for_match(m, complete_event))
-
- for c in completions:
- yield c
-
- def _get_completions_for_match(self, match, complete_event):
- """
- Yield all the possible completions for this input string.
- (The completer assumes that the cursor position was at the end of the
- input string.)
- """
- for match_variable in match.end_nodes():
- varname = match_variable.varname
- start = match_variable.start
-
- completer = self.completers.get(varname)
-
- if completer:
- text = match_variable.value
-
- # Unwrap text.
- unwrapped_text = self.compiled_grammar.unescape(varname, text)
-
- # Create a document, for the completions API (text/cursor_position)
- document = Document(unwrapped_text, len(unwrapped_text))
-
- # Call completer
- for completion in completer.get_completions(document, complete_event):
- new_text = unwrapped_text[:len(text) + completion.start_position] + completion.text
-
- # Wrap again.
- yield Completion(
- text=self.compiled_grammar.escape(varname, new_text),
- start_position=start - len(match.string),
- display=completion.display,
- display_meta=completion.display_meta)
-
- def _remove_duplicates(self, items):
- """
- Remove duplicates, while keeping the order.
- (Sometimes we have duplicates, because the there several matches of the
- same grammar, each yielding similar completions.)
- """
- result = []
- for i in items:
- if i not in result:
- result.append(i)
- return result
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/lexer.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/lexer.py
deleted file mode 100644
index c166d84fd1..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/lexer.py
+++ /dev/null
@@ -1,90 +0,0 @@
-"""
-`GrammarLexer` is compatible with Pygments lexers and can be used to highlight
-the input using a regular grammar with token annotations.
-"""
-from __future__ import unicode_literals
-from prompt_toolkit.document import Document
-from prompt_toolkit.layout.lexers import Lexer
-from prompt_toolkit.layout.utils import split_lines
-from prompt_toolkit.token import Token
-
-from .compiler import _CompiledGrammar
-from six.moves import range
-
-__all__ = (
- 'GrammarLexer',
-)
-
-
-class GrammarLexer(Lexer):
- """
- Lexer which can be used for highlighting of tokens according to variables in the grammar.
-
- (It does not actual lexing of the string, but it exposes an API, compatible
- with the Pygments lexer class.)
-
- :param compiled_grammar: Grammar as returned by the `compile()` function.
- :param lexers: Dictionary mapping variable names of the regular grammar to
- the lexers that should be used for this part. (This can
- call other lexers recursively.) If you wish a part of the
- grammar to just get one token, use a
- `prompt_toolkit.layout.lexers.SimpleLexer`.
- """
- def __init__(self, compiled_grammar, default_token=None, lexers=None):
- assert isinstance(compiled_grammar, _CompiledGrammar)
- assert default_token is None or isinstance(default_token, tuple)
- assert lexers is None or all(isinstance(v, Lexer) for k, v in lexers.items())
- assert lexers is None or isinstance(lexers, dict)
-
- self.compiled_grammar = compiled_grammar
- self.default_token = default_token or Token
- self.lexers = lexers or {}
-
- def _get_tokens(self, cli, text):
- m = self.compiled_grammar.match_prefix(text)
-
- if m:
- characters = [[self.default_token, c] for c in text]
-
- for v in m.variables():
- # If we have a `Lexer` instance for this part of the input.
- # Tokenize recursively and apply tokens.
- lexer = self.lexers.get(v.varname)
-
- if lexer:
- document = Document(text[v.start:v.stop])
- lexer_tokens_for_line = lexer.lex_document(cli, document)
- lexer_tokens = []
- for i in range(len(document.lines)):
- lexer_tokens.extend(lexer_tokens_for_line(i))
- lexer_tokens.append((Token, '\n'))
- if lexer_tokens:
- lexer_tokens.pop()
-
- i = v.start
- for t, s in lexer_tokens:
- for c in s:
- if characters[i][0] == self.default_token:
- characters[i][0] = t
- i += 1
-
- # Highlight trailing input.
- trailing_input = m.trailing_input()
- if trailing_input:
- for i in range(trailing_input.start, trailing_input.stop):
- characters[i][0] = Token.TrailingInput
-
- return characters
- else:
- return [(Token, text)]
-
- def lex_document(self, cli, document):
- lines = list(split_lines(self._get_tokens(cli, document.text)))
-
- def get_line(lineno):
- try:
- return lines[lineno]
- except IndexError:
- return []
-
- return get_line
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/regex_parser.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/regex_parser.py
deleted file mode 100644
index e5909b241e..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/regex_parser.py
+++ /dev/null
@@ -1,262 +0,0 @@
-"""
-Parser for parsing a regular expression.
-Take a string representing a regular expression and return the root node of its
-parse tree.
-
-usage::
-
- root_node = parse_regex('(hello|world)')
-
-Remarks:
-- The regex parser processes multiline, it ignores all whitespace and supports
- multiple named groups with the same name and #-style comments.
-
-Limitations:
-- Lookahead is not supported.
-"""
-from __future__ import unicode_literals
-import re
-
-__all__ = (
- 'Repeat',
- 'Variable',
- 'Regex',
- 'Lookahead',
-
- 'tokenize_regex',
- 'parse_regex',
-)
-
-
-class Node(object):
- """
- Base class for all the grammar nodes.
- (You don't initialize this one.)
- """
- def __add__(self, other_node):
- return Sequence([self, other_node])
-
- def __or__(self, other_node):
- return Any([self, other_node])
-
-
-class Any(Node):
- """
- Union operation (OR operation) between several grammars. You don't
- initialize this yourself, but it's a result of a "Grammar1 | Grammar2"
- operation.
- """
- def __init__(self, children):
- self.children = children
-
- def __or__(self, other_node):
- return Any(self.children + [other_node])
-
- def __repr__(self):
- return '%s(%r)' % (self.__class__.__name__, self.children)
-
-
-class Sequence(Node):
- """
- Concatenation operation of several grammars. You don't initialize this
- yourself, but it's a result of a "Grammar1 + Grammar2" operation.
- """
- def __init__(self, children):
- self.children = children
-
- def __add__(self, other_node):
- return Sequence(self.children + [other_node])
-
- def __repr__(self):
- return '%s(%r)' % (self.__class__.__name__, self.children)
-
-
-class Regex(Node):
- """
- Regular expression.
- """
- def __init__(self, regex):
- re.compile(regex) # Validate
-
- self.regex = regex
-
- def __repr__(self):
- return '%s(/%s/)' % (self.__class__.__name__, self.regex)
-
-
-class Lookahead(Node):
- """
- Lookahead expression.
- """
- def __init__(self, childnode, negative=False):
- self.childnode = childnode
- self.negative = negative
-
- def __repr__(self):
- return '%s(%r)' % (self.__class__.__name__, self.childnode)
-
-
-class Variable(Node):
- """
- Mark a variable in the regular grammar. This will be translated into a
- named group. Each variable can have his own completer, validator, etc..
-
- :param childnode: The grammar which is wrapped inside this variable.
- :param varname: String.
- """
- def __init__(self, childnode, varname=None):
- self.childnode = childnode
- self.varname = varname
-
- def __repr__(self):
- return '%s(childnode=%r, varname=%r)' % (
- self.__class__.__name__, self.childnode, self.varname)
-
-
-class Repeat(Node):
- def __init__(self, childnode, min_repeat=0, max_repeat=None, greedy=True):
- self.childnode = childnode
- self.min_repeat = min_repeat
- self.max_repeat = max_repeat
- self.greedy = greedy
-
- def __repr__(self):
- return '%s(childnode=%r)' % (self.__class__.__name__, self.childnode)
-
-
-def tokenize_regex(input):
- """
- Takes a string, representing a regular expression as input, and tokenizes
- it.
-
- :param input: string, representing a regular expression.
- :returns: List of tokens.
- """
- # Regular expression for tokenizing other regular expressions.
- p = re.compile(r'''^(
- \(\?P\<[a-zA-Z0-9_-]+\> | # Start of named group.
- \(\?#[^)]*\) | # Comment
- \(\?= | # Start of lookahead assertion
- \(\?! | # Start of negative lookahead assertion
- \(\?<= | # If preceded by.
- \(\?< | # If not preceded by.
- \(?: | # Start of group. (non capturing.)
- \( | # Start of group.
- \(?[iLmsux] | # Flags.
- \(?P=[a-zA-Z]+\) | # Back reference to named group
- \) | # End of group.
- \{[^{}]*\} | # Repetition
- \*\? | \+\? | \?\?\ | # Non greedy repetition.
- \* | \+ | \? | # Repetition
- \#.*\n | # Comment
- \\. |
-
- # Character group.
- \[
- ( [^\]\\] | \\.)*
- \] |
-
- [^(){}] |
- .
- )''', re.VERBOSE)
-
- tokens = []
-
- while input:
- m = p.match(input)
- if m:
- token, input = input[:m.end()], input[m.end():]
- if not token.isspace():
- tokens.append(token)
- else:
- raise Exception('Could not tokenize input regex.')
-
- return tokens
-
-
-def parse_regex(regex_tokens):
- """
- Takes a list of tokens from the tokenizer, and returns a parse tree.
- """
- # We add a closing brace because that represents the final pop of the stack.
- tokens = [')'] + regex_tokens[::-1]
-
- def wrap(lst):
- """ Turn list into sequence when it contains several items. """
- if len(lst) == 1:
- return lst[0]
- else:
- return Sequence(lst)
-
- def _parse():
- or_list = []
- result = []
-
- def wrapped_result():
- if or_list == []:
- return wrap(result)
- else:
- or_list.append(result)
- return Any([wrap(i) for i in or_list])
-
- while tokens:
- t = tokens.pop()
-
- if t.startswith('(?P<'):
- variable = Variable(_parse(), varname=t[4:-1])
- result.append(variable)
-
- elif t in ('*', '*?'):
- greedy = (t == '*')
- result[-1] = Repeat(result[-1], greedy=greedy)
-
- elif t in ('+', '+?'):
- greedy = (t == '+')
- result[-1] = Repeat(result[-1], min_repeat=1, greedy=greedy)
-
- elif t in ('?', '??'):
- if result == []:
- raise Exception('Nothing to repeat.' + repr(tokens))
- else:
- greedy = (t == '?')
- result[-1] = Repeat(result[-1], min_repeat=0, max_repeat=1, greedy=greedy)
-
- elif t == '|':
- or_list.append(result)
- result = []
-
- elif t in ('(', '(?:'):
- result.append(_parse())
-
- elif t == '(?!':
- result.append(Lookahead(_parse(), negative=True))
-
- elif t == '(?=':
- result.append(Lookahead(_parse(), negative=False))
-
- elif t == ')':
- return wrapped_result()
-
- elif t.startswith('#'):
- pass
-
- elif t.startswith('{'):
- # TODO: implement!
- raise Exception('{}-style repitition not yet supported' % t)
-
- elif t.startswith('(?'):
- raise Exception('%r not supported' % t)
-
- elif t.isspace():
- pass
- else:
- result.append(Regex(t))
-
- raise Exception("Expecting ')' token")
-
- result = _parse()
-
- if len(tokens) != 0:
- raise Exception("Unmatched parantheses.")
- else:
- return result
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/validation.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/validation.py
deleted file mode 100644
index d5f8cfccc6..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/validation.py
+++ /dev/null
@@ -1,57 +0,0 @@
-"""
-Validator for a regular langage.
-"""
-from __future__ import unicode_literals
-
-from prompt_toolkit.validation import Validator, ValidationError
-from prompt_toolkit.document import Document
-
-from .compiler import _CompiledGrammar
-
-__all__ = (
- 'GrammarValidator',
-)
-
-
-class GrammarValidator(Validator):
- """
- Validator which can be used for validation according to variables in
- the grammar. Each variable can have its own validator.
-
- :param compiled_grammar: `GrammarCompleter` instance.
- :param validators: `dict` mapping variable names of the grammar to the
- `Validator` instances to be used for each variable.
- """
- def __init__(self, compiled_grammar, validators):
- assert isinstance(compiled_grammar, _CompiledGrammar)
- assert isinstance(validators, dict)
-
- self.compiled_grammar = compiled_grammar
- self.validators = validators
-
- def validate(self, document):
- # Parse input document.
- # We use `match`, not `match_prefix`, because for validation, we want
- # the actual, unambiguous interpretation of the input.
- m = self.compiled_grammar.match(document.text)
-
- if m:
- for v in m.variables():
- validator = self.validators.get(v.varname)
-
- if validator:
- # Unescape text.
- unwrapped_text = self.compiled_grammar.unescape(v.varname, v.value)
-
- # Create a document, for the completions API (text/cursor_position)
- inner_document = Document(unwrapped_text, len(unwrapped_text))
-
- try:
- validator.validate(inner_document)
- except ValidationError as e:
- raise ValidationError(
- cursor_position=v.start + e.cursor_position,
- message=e.message)
- else:
- raise ValidationError(cursor_position=len(document.text),
- message='Invalid command')
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/__init__.py
deleted file mode 100644
index 7b7aeec820..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from .server import *
-from .application import *
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/application.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/application.py
deleted file mode 100644
index 7fe6cc97b7..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/application.py
+++ /dev/null
@@ -1,32 +0,0 @@
-"""
-Interface for Telnet applications.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-
-__all__ = (
- 'TelnetApplication',
-)
-
-
-class TelnetApplication(with_metaclass(ABCMeta, object)):
- """
- The interface which has to be implemented for any telnet application.
- An instance of this class has to be passed to `TelnetServer`.
- """
- @abstractmethod
- def client_connected(self, telnet_connection):
- """
- Called when a new client was connected.
-
- Probably you want to call `telnet_connection.set_cli` here to set a
- the CommandLineInterface instance to be used.
- Hint: Use the following shortcut: `prompt_toolkit.shortcuts.create_cli`
- """
-
- @abstractmethod
- def client_leaving(self, telnet_connection):
- """
- Called when a client quits.
- """
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/log.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/log.py
deleted file mode 100644
index 10792ceed6..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/log.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""
-Python logger for the telnet server.
-"""
-from __future__ import unicode_literals
-import logging
-
-logger = logging.getLogger(__package__)
-
-__all__ = (
- 'logger',
-)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/protocol.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/protocol.py
deleted file mode 100644
index b1bb0ccbe8..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/protocol.py
+++ /dev/null
@@ -1,181 +0,0 @@
-"""
-Parser for the Telnet protocol. (Not a complete implementation of the telnet
-specification, but sufficient for a command line interface.)
-
-Inspired by `Twisted.conch.telnet`.
-"""
-from __future__ import unicode_literals
-
-import struct
-from six import int2byte, binary_type, iterbytes
-
-from .log import logger
-
-__all__ = (
- 'TelnetProtocolParser',
-)
-
-# Telnet constants.
-NOP = int2byte(0)
-SGA = int2byte(3)
-
-IAC = int2byte(255)
-DO = int2byte(253)
-DONT = int2byte(254)
-LINEMODE = int2byte(34)
-SB = int2byte(250)
-WILL = int2byte(251)
-WONT = int2byte(252)
-MODE = int2byte(1)
-SE = int2byte(240)
-ECHO = int2byte(1)
-NAWS = int2byte(31)
-LINEMODE = int2byte(34)
-SUPPRESS_GO_AHEAD = int2byte(3)
-
-DM = int2byte(242)
-BRK = int2byte(243)
-IP = int2byte(244)
-AO = int2byte(245)
-AYT = int2byte(246)
-EC = int2byte(247)
-EL = int2byte(248)
-GA = int2byte(249)
-
-
-class TelnetProtocolParser(object):
- """
- Parser for the Telnet protocol.
- Usage::
-
- def data_received(data):
- print(data)
-
- def size_received(rows, columns):
- print(rows, columns)
-
- p = TelnetProtocolParser(data_received, size_received)
- p.feed(binary_data)
- """
- def __init__(self, data_received_callback, size_received_callback):
- self.data_received_callback = data_received_callback
- self.size_received_callback = size_received_callback
-
- self._parser = self._parse_coroutine()
- self._parser.send(None)
-
- def received_data(self, data):
- self.data_received_callback(data)
-
- def do_received(self, data):
- """ Received telnet DO command. """
- logger.info('DO %r', data)
-
- def dont_received(self, data):
- """ Received telnet DONT command. """
- logger.info('DONT %r', data)
-
- def will_received(self, data):
- """ Received telnet WILL command. """
- logger.info('WILL %r', data)
-
- def wont_received(self, data):
- """ Received telnet WONT command. """
- logger.info('WONT %r', data)
-
- def command_received(self, command, data):
- if command == DO:
- self.do_received(data)
-
- elif command == DONT:
- self.dont_received(data)
-
- elif command == WILL:
- self.will_received(data)
-
- elif command == WONT:
- self.wont_received(data)
-
- else:
- logger.info('command received %r %r', command, data)
-
- def naws(self, data):
- """
- Received NAWS. (Window dimensions.)
- """
- if len(data) == 4:
- # NOTE: the first parameter of struct.unpack should be
- # a 'str' object. Both on Py2/py3. This crashes on OSX
- # otherwise.
- columns, rows = struct.unpack(str('!HH'), data)
- self.size_received_callback(rows, columns)
- else:
- logger.warning('Wrong number of NAWS bytes')
-
- def negotiate(self, data):
- """
- Got negotiate data.
- """
- command, payload = data[0:1], data[1:]
- assert isinstance(command, bytes)
-
- if command == NAWS:
- self.naws(payload)
- else:
- logger.info('Negotiate (%r got bytes)', len(data))
-
- def _parse_coroutine(self):
- """
- Parser state machine.
- Every 'yield' expression returns the next byte.
- """
- while True:
- d = yield
-
- if d == int2byte(0):
- pass # NOP
-
- # Go to state escaped.
- elif d == IAC:
- d2 = yield
-
- if d2 == IAC:
- self.received_data(d2)
-
- # Handle simple commands.
- elif d2 in (NOP, DM, BRK, IP, AO, AYT, EC, EL, GA):
- self.command_received(d2, None)
-
- # Handle IAC-[DO/DONT/WILL/WONT] commands.
- elif d2 in (DO, DONT, WILL, WONT):
- d3 = yield
- self.command_received(d2, d3)
-
- # Subnegotiation
- elif d2 == SB:
- # Consume everything until next IAC-SE
- data = []
-
- while True:
- d3 = yield
-
- if d3 == IAC:
- d4 = yield
- if d4 == SE:
- break
- else:
- data.append(d4)
- else:
- data.append(d3)
-
- self.negotiate(b''.join(data))
- else:
- self.received_data(d)
-
- def feed(self, data):
- """
- Feed data to the parser.
- """
- assert isinstance(data, binary_type)
- for b in iterbytes(data):
- self._parser.send(int2byte(b))
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/server.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/server.py
deleted file mode 100644
index d75a9572eb..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/server.py
+++ /dev/null
@@ -1,407 +0,0 @@
-"""
-Telnet server.
-
-Example usage::
-
- class MyTelnetApplication(TelnetApplication):
- def client_connected(self, telnet_connection):
- # Set CLI with simple prompt.
- telnet_connection.set_application(
- telnet_connection.create_prompt_application(...))
-
- def handle_command(self, telnet_connection, document):
- # When the client enters a command, just reply.
- telnet_connection.send('You said: %r\n\n' % document.text)
-
- ...
-
- a = MyTelnetApplication()
- TelnetServer(application=a, host='127.0.0.1', port=23).run()
-"""
-from __future__ import unicode_literals
-
-import socket
-import select
-
-import threading
-import os
-import fcntl
-
-from six import int2byte, text_type, binary_type
-from codecs import getincrementaldecoder
-
-from prompt_toolkit.enums import DEFAULT_BUFFER
-from prompt_toolkit.eventloop.base import EventLoop
-from prompt_toolkit.interface import CommandLineInterface, Application
-from prompt_toolkit.layout.screen import Size
-from prompt_toolkit.shortcuts import create_prompt_application
-from prompt_toolkit.terminal.vt100_input import InputStream
-from prompt_toolkit.terminal.vt100_output import Vt100_Output
-
-from .log import logger
-from .protocol import IAC, DO, LINEMODE, SB, MODE, SE, WILL, ECHO, NAWS, SUPPRESS_GO_AHEAD
-from .protocol import TelnetProtocolParser
-from .application import TelnetApplication
-
-__all__ = (
- 'TelnetServer',
-)
-
-
-def _initialize_telnet(connection):
- logger.info('Initializing telnet connection')
-
- # Iac Do Linemode
- connection.send(IAC + DO + LINEMODE)
-
- # Suppress Go Ahead. (This seems important for Putty to do correct echoing.)
- # This will allow bi-directional operation.
- connection.send(IAC + WILL + SUPPRESS_GO_AHEAD)
-
- # Iac sb
- connection.send(IAC + SB + LINEMODE + MODE + int2byte(0) + IAC + SE)
-
- # IAC Will Echo
- connection.send(IAC + WILL + ECHO)
-
- # Negotiate window size
- connection.send(IAC + DO + NAWS)
-
-
-class _ConnectionStdout(object):
- """
- Wrapper around socket which provides `write` and `flush` methods for the
- Vt100_Output output.
- """
- def __init__(self, connection, encoding):
- self._encoding = encoding
- self._connection = connection
- self._buffer = []
-
- def write(self, data):
- assert isinstance(data, text_type)
- self._buffer.append(data.encode(self._encoding))
- self.flush()
-
- def flush(self):
- try:
- self._connection.send(b''.join(self._buffer))
- except socket.error as e:
- logger.error("Couldn't send data over socket: %s" % e)
-
- self._buffer = []
-
-
-class TelnetConnection(object):
- """
- Class that represents one Telnet connection.
- """
- def __init__(self, conn, addr, application, server, encoding):
- assert isinstance(addr, tuple) # (addr, port) tuple
- assert isinstance(application, TelnetApplication)
- assert isinstance(server, TelnetServer)
- assert isinstance(encoding, text_type) # e.g. 'utf-8'
-
- self.conn = conn
- self.addr = addr
- self.application = application
- self.closed = False
- self.handling_command = True
- self.server = server
- self.encoding = encoding
- self.callback = None # Function that handles the CLI result.
-
- # Create "Output" object.
- self.size = Size(rows=40, columns=79)
-
- # Initialize.
- _initialize_telnet(conn)
-
- # Create output.
- def get_size():
- return self.size
- self.stdout = _ConnectionStdout(conn, encoding=encoding)
- self.vt100_output = Vt100_Output(self.stdout, get_size, write_binary=False)
-
- # Create an eventloop (adaptor) for the CommandLineInterface.
- self.eventloop = _TelnetEventLoopInterface(server)
-
- # Set default CommandLineInterface.
- self.set_application(create_prompt_application())
-
- # Call client_connected
- application.client_connected(self)
-
- # Draw for the first time.
- self.handling_command = False
- self.cli._redraw()
-
- def set_application(self, app, callback=None):
- """
- Set ``CommandLineInterface`` instance for this connection.
- (This can be replaced any time.)
-
- :param cli: CommandLineInterface instance.
- :param callback: Callable that takes the result of the CLI.
- """
- assert isinstance(app, Application)
- assert callback is None or callable(callback)
-
- self.cli = CommandLineInterface(
- application=app,
- eventloop=self.eventloop,
- output=self.vt100_output)
- self.callback = callback
-
- # Create a parser, and parser callbacks.
- cb = self.cli.create_eventloop_callbacks()
- inputstream = InputStream(cb.feed_key)
-
- # Input decoder for stdin. (Required when working with multibyte
- # characters, like chinese input.)
- stdin_decoder_cls = getincrementaldecoder(self.encoding)
- stdin_decoder = [stdin_decoder_cls()] # nonlocal
-
- # Tell the CLI that it's running. We don't start it through the run()
- # call, but will still want _redraw() to work.
- self.cli._is_running = True
-
- def data_received(data):
- """ TelnetProtocolParser 'data_received' callback """
- assert isinstance(data, binary_type)
-
- try:
- result = stdin_decoder[0].decode(data)
- inputstream.feed(result)
- except UnicodeDecodeError:
- stdin_decoder[0] = stdin_decoder_cls()
- return ''
-
- def size_received(rows, columns):
- """ TelnetProtocolParser 'size_received' callback """
- self.size = Size(rows=rows, columns=columns)
- cb.terminal_size_changed()
-
- self.parser = TelnetProtocolParser(data_received, size_received)
-
- def feed(self, data):
- """
- Handler for incoming data. (Called by TelnetServer.)
- """
- assert isinstance(data, binary_type)
-
- self.parser.feed(data)
-
- # Render again.
- self.cli._redraw()
-
- # When a return value has been set (enter was pressed), handle command.
- if self.cli.is_returning:
- try:
- return_value = self.cli.return_value()
- except (EOFError, KeyboardInterrupt) as e:
- # Control-D or Control-C was pressed.
- logger.info('%s, closing connection.', type(e).__name__)
- self.close()
- return
-
- # Handle CLI command
- self._handle_command(return_value)
-
- def _handle_command(self, command):
- """
- Handle command. This will run in a separate thread, in order not
- to block the event loop.
- """
- logger.info('Handle command %r', command)
-
- def in_executor():
- self.handling_command = True
- try:
- if self.callback is not None:
- self.callback(self, command)
- finally:
- self.server.call_from_executor(done)
-
- def done():
- self.handling_command = False
-
- # Reset state and draw again. (If the connection is still open --
- # the application could have called TelnetConnection.close()
- if not self.closed:
- self.cli.reset()
- self.cli.buffers[DEFAULT_BUFFER].reset()
- self.cli.renderer.request_absolute_cursor_position()
- self.vt100_output.flush()
- self.cli._redraw()
-
- self.server.run_in_executor(in_executor)
-
- def erase_screen(self):
- """
- Erase output screen.
- """
- self.vt100_output.erase_screen()
- self.vt100_output.cursor_goto(0, 0)
- self.vt100_output.flush()
-
- def send(self, data):
- """
- Send text to the client.
- """
- assert isinstance(data, text_type)
-
- # When data is send back to the client, we should replace the line
- # endings. (We didn't allocate a real pseudo terminal, and the telnet
- # connection is raw, so we are responsible for inserting \r.)
- self.stdout.write(data.replace('\n', '\r\n'))
- self.stdout.flush()
-
- def close(self):
- """
- Close the connection.
- """
- self.application.client_leaving(self)
-
- self.conn.close()
- self.closed = True
-
-
-class _TelnetEventLoopInterface(EventLoop):
- """
- Eventloop object to be assigned to `CommandLineInterface`.
- """
- def __init__(self, server):
- self._server = server
-
- def close(self):
- " Ignore. "
-
- def stop(self):
- " Ignore. "
-
- def run_in_executor(self, callback):
- self._server.run_in_executor(callback)
-
- def call_from_executor(self, callback, _max_postpone_until=None):
- self._server.call_from_executor(callback)
-
- def add_reader(self, fd, callback):
- raise NotImplementedError
-
- def remove_reader(self, fd):
- raise NotImplementedError
-
-
-class TelnetServer(object):
- """
- Telnet server implementation.
- """
- def __init__(self, host='127.0.0.1', port=23, application=None, encoding='utf-8'):
- assert isinstance(host, text_type)
- assert isinstance(port, int)
- assert isinstance(application, TelnetApplication)
- assert isinstance(encoding, text_type)
-
- self.host = host
- self.port = port
- self.application = application
- self.encoding = encoding
-
- self.connections = set()
-
- self._calls_from_executor = []
-
- # Create a pipe for inter thread communication.
- self._schedule_pipe = os.pipe()
- fcntl.fcntl(self._schedule_pipe[0], fcntl.F_SETFL, os.O_NONBLOCK)
-
- @classmethod
- def create_socket(cls, host, port):
- # Create and bind socket
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- s.bind((host, port))
-
- s.listen(4)
- return s
-
- def run_in_executor(self, callback):
- threading.Thread(target=callback).start()
-
- def call_from_executor(self, callback):
- self._calls_from_executor.append(callback)
-
- if self._schedule_pipe:
- os.write(self._schedule_pipe[1], b'x')
-
- def _process_callbacks(self):
- """
- Process callbacks from `call_from_executor` in eventloop.
- """
- # Flush all the pipe content.
- os.read(self._schedule_pipe[0], 1024)
-
- # Process calls from executor.
- calls_from_executor, self._calls_from_executor = self._calls_from_executor, []
- for c in calls_from_executor:
- c()
-
- def run(self):
- """
- Run the eventloop for the telnet server.
- """
- listen_socket = self.create_socket(self.host, self.port)
- logger.info('Listening for telnet connections on %s port %r', self.host, self.port)
-
- try:
- while True:
- # Removed closed connections.
- self.connections = set([c for c in self.connections if not c.closed])
-
- # Ignore connections handling commands.
- connections = set([c for c in self.connections if not c.handling_command])
-
- # Wait for next event.
- read_list = (
- [listen_socket, self._schedule_pipe[0]] +
- [c.conn for c in connections])
-
- read, _, _ = select.select(read_list, [], [])
-
- for s in read:
- # When the socket itself is ready, accept a new connection.
- if s == listen_socket:
- self._accept(listen_socket)
-
- # If we receive something on our "call_from_executor" pipe, process
- # these callbacks in a thread safe way.
- elif s == self._schedule_pipe[0]:
- self._process_callbacks()
-
- # Handle incoming data on socket.
- else:
- self._handle_incoming_data(s)
- finally:
- listen_socket.close()
-
- def _accept(self, listen_socket):
- """
- Accept new incoming connection.
- """
- conn, addr = listen_socket.accept()
- connection = TelnetConnection(conn, addr, self.application, self, encoding=self.encoding)
- self.connections.add(connection)
-
- logger.info('New connection %r %r', *addr)
-
- def _handle_incoming_data(self, conn):
- """
- Handle incoming data on socket.
- """
- connection = [c for c in self.connections if c.conn == conn][0]
- data = conn.recv(1024)
- if data:
- connection.feed(data)
- else:
- self.connections.remove(connection)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/__init__.py
+++ /dev/null
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/base.py
deleted file mode 100644
index 16c1539c52..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/base.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from __future__ import unicode_literals
-from prompt_toolkit.validation import Validator, ValidationError
-from six import string_types
-
-
-class SentenceValidator(Validator):
- """
- Validate input only when it appears in this list of sentences.
-
- :param sentences: List of sentences.
- :param ignore_case: If True, case-insensitive comparisons.
- """
- def __init__(self, sentences, ignore_case=False, error_message='Invalid input', move_cursor_to_end=False):
- assert all(isinstance(s, string_types) for s in sentences)
- assert isinstance(ignore_case, bool)
- assert isinstance(error_message, string_types)
-
- self.sentences = list(sentences)
- self.ignore_case = ignore_case
- self.error_message = error_message
- self.move_cursor_to_end = move_cursor_to_end
-
- if ignore_case:
- self.sentences = set([s.lower() for s in self.sentences])
-
- def validate(self, document):
- if document.text not in self.sentences:
- if self.move_cursor_to_end:
- index = len(document.text)
- else:
- index = 0
-
- raise ValidationError(cursor_position=index,
- message=self.error_message)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py
deleted file mode 100644
index 25d817ddd0..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py
+++ /dev/null
@@ -1,1001 +0,0 @@
-"""
-The `Document` that implements all the text operations/querying.
-"""
-from __future__ import unicode_literals
-
-import bisect
-import re
-import six
-import string
-import weakref
-from six.moves import range, map
-
-from .selection import SelectionType, SelectionState, PasteMode
-from .clipboard import ClipboardData
-
-__all__ = ('Document',)
-
-
-# Regex for finding "words" in documents. (We consider a group of alnum
-# characters a word, but also a group of special characters a word, as long as
-# it doesn't contain a space.)
-# (This is a 'word' in Vi.)
-_FIND_WORD_RE = re.compile(r'([a-zA-Z0-9_]+|[^a-zA-Z0-9_\s]+)')
-_FIND_CURRENT_WORD_RE = re.compile(r'^([a-zA-Z0-9_]+|[^a-zA-Z0-9_\s]+)')
-_FIND_CURRENT_WORD_INCLUDE_TRAILING_WHITESPACE_RE = re.compile(r'^(([a-zA-Z0-9_]+|[^a-zA-Z0-9_\s]+)\s*)')
-
-# Regex for finding "WORDS" in documents.
-# (This is a 'WORD in Vi.)
-_FIND_BIG_WORD_RE = re.compile(r'([^\s]+)')
-_FIND_CURRENT_BIG_WORD_RE = re.compile(r'^([^\s]+)')
-_FIND_CURRENT_BIG_WORD_INCLUDE_TRAILING_WHITESPACE_RE = re.compile(r'^([^\s]+\s*)')
-
-# Share the Document._cache between all Document instances.
-# (Document instances are considered immutable. That means that if another
-# `Document` is constructed with the same text, it should have the same
-# `_DocumentCache`.)
-_text_to_document_cache = weakref.WeakValueDictionary() # Maps document.text to DocumentCache instance.
-
-
-class _ImmutableLineList(list):
- """
- Some protection for our 'lines' list, which is assumed to be immutable in the cache.
- (Useful for detecting obvious bugs.)
- """
- def _error(self, *a, **kw):
- raise NotImplementedError('Attempt to modifiy an immutable list.')
-
- __setitem__ = _error
- append = _error
- clear = _error
- extend = _error
- insert = _error
- pop = _error
- remove = _error
- reverse = _error
- sort = _error
-
-
-class _DocumentCache(object):
- def __init__(self):
- #: List of lines for the Document text.
- self.lines = None
-
- #: List of index positions, pointing to the start of all the lines.
- self.line_indexes = None
-
-
-class Document(object):
- """
- This is a immutable class around the text and cursor position, and contains
- methods for querying this data, e.g. to give the text before the cursor.
-
- This class is usually instantiated by a :class:`~prompt_toolkit.buffer.Buffer`
- object, and accessed as the `document` property of that class.
-
- :param text: string
- :param cursor_position: int
- :param selection: :class:`.SelectionState`
- """
- __slots__ = ('_text', '_cursor_position', '_selection', '_cache')
-
- def __init__(self, text='', cursor_position=None, selection=None):
- assert isinstance(text, six.text_type), 'Got %r' % text
- assert selection is None or isinstance(selection, SelectionState)
-
- # Check cursor position. It can also be right after the end. (Where we
- # insert text.)
- assert cursor_position is None or cursor_position <= len(text), AssertionError(
- 'cursor_position=%r, len_text=%r' % (cursor_position, len(text)))
-
- # By default, if no cursor position was given, make sure to put the
- # cursor position is at the end of the document. This is what makes
- # sense in most places.
- if cursor_position is None:
- cursor_position = len(text)
-
- # Keep these attributes private. A `Document` really has to be
- # considered to be immutable, because otherwise the caching will break
- # things. Because of that, we wrap these into read-only properties.
- self._text = text
- self._cursor_position = cursor_position
- self._selection = selection
-
- # Cache for lines/indexes. (Shared with other Document instances that
- # contain the same text.
- try:
- self._cache = _text_to_document_cache[self.text]
- except KeyError:
- self._cache = _DocumentCache()
- _text_to_document_cache[self.text] = self._cache
-
- # XX: For some reason, above, we can't use 'WeakValueDictionary.setdefault'.
- # This fails in Pypy3. `self._cache` becomes None, because that's what
- # 'setdefault' returns.
- # self._cache = _text_to_document_cache.setdefault(self.text, _DocumentCache())
- # assert self._cache
-
- def __repr__(self):
- return '%s(%r, %r)' % (self.__class__.__name__, self.text, self.cursor_position)
-
- @property
- def text(self):
- " The document text. "
- return self._text
-
- @property
- def cursor_position(self):
- " The document cursor position. "
- return self._cursor_position
-
- @property
- def selection(self):
- " :class:`.SelectionState` object. "
- return self._selection
-
- @property
- def current_char(self):
- """ Return character under cursor or an empty string. """
- return self._get_char_relative_to_cursor(0) or ''
-
- @property
- def char_before_cursor(self):
- """ Return character before the cursor or an empty string. """
- return self._get_char_relative_to_cursor(-1) or ''
-
- @property
- def text_before_cursor(self):
- return self.text[:self.cursor_position:]
-
- @property
- def text_after_cursor(self):
- return self.text[self.cursor_position:]
-
- @property
- def current_line_before_cursor(self):
- """ Text from the start of the line until the cursor. """
- _, _, text = self.text_before_cursor.rpartition('\n')
- return text
-
- @property
- def current_line_after_cursor(self):
- """ Text from the cursor until the end of the line. """
- text, _, _ = self.text_after_cursor.partition('\n')
- return text
-
- @property
- def lines(self):
- """
- Array of all the lines.
- """
- # Cache, because this one is reused very often.
- if self._cache.lines is None:
- self._cache.lines = _ImmutableLineList(self.text.split('\n'))
-
- return self._cache.lines
-
- @property
- def _line_start_indexes(self):
- """
- Array pointing to the start indexes of all the lines.
- """
- # Cache, because this is often reused. (If it is used, it's often used
- # many times. And this has to be fast for editing big documents!)
- if self._cache.line_indexes is None:
- # Create list of line lengths.
- line_lengths = map(len, self.lines)
-
- # Calculate cumulative sums.
- indexes = [0]
- append = indexes.append
- pos = 0
-
- for line_length in line_lengths:
- pos += line_length + 1
- append(pos)
-
- # Remove the last item. (This is not a new line.)
- if len(indexes) > 1:
- indexes.pop()
-
- self._cache.line_indexes = indexes
-
- return self._cache.line_indexes
-
- @property
- def lines_from_current(self):
- """
- Array of the lines starting from the current line, until the last line.
- """
- return self.lines[self.cursor_position_row:]
-
- @property
- def line_count(self):
- r""" Return the number of lines in this document. If the document ends
- with a trailing \n, that counts as the beginning of a new line. """
- return len(self.lines)
-
- @property
- def current_line(self):
- """ Return the text on the line where the cursor is. (when the input
- consists of just one line, it equals `text`. """
- return self.current_line_before_cursor + self.current_line_after_cursor
-
- @property
- def leading_whitespace_in_current_line(self):
- """ The leading whitespace in the left margin of the current line. """
- current_line = self.current_line
- length = len(current_line) - len(current_line.lstrip())
- return current_line[:length]
-
- def _get_char_relative_to_cursor(self, offset=0):
- """
- Return character relative to cursor position, or empty string
- """
- try:
- return self.text[self.cursor_position + offset]
- except IndexError:
- return ''
-
- @property
- def on_first_line(self):
- """
- True when we are at the first line.
- """
- return self.cursor_position_row == 0
-
- @property
- def on_last_line(self):
- """
- True when we are at the last line.
- """
- return self.cursor_position_row == self.line_count - 1
-
- @property
- def cursor_position_row(self):
- """
- Current row. (0-based.)
- """
- row, _ = self._find_line_start_index(self.cursor_position)
- return row
-
- @property
- def cursor_position_col(self):
- """
- Current column. (0-based.)
- """
- # (Don't use self.text_before_cursor to calculate this. Creating
- # substrings and doing rsplit is too expensive for getting the cursor
- # position.)
- _, line_start_index = self._find_line_start_index(self.cursor_position)
- return self.cursor_position - line_start_index
-
- def _find_line_start_index(self, index):
- """
- For the index of a character at a certain line, calculate the index of
- the first character on that line.
-
- Return (row, index) tuple.
- """
- indexes = self._line_start_indexes
-
- pos = bisect.bisect_right(indexes, index) - 1
- return pos, indexes[pos]
-
- def translate_index_to_position(self, index):
- """
- Given an index for the text, return the corresponding (row, col) tuple.
- (0-based. Returns (0, 0) for index=0.)
- """
- # Find start of this line.
- row, row_index = self._find_line_start_index(index)
- col = index - row_index
-
- return row, col
-
-
- def translate_row_col_to_index(self, row, col):
- """
- Given a (row, col) tuple, return the corresponding index.
- (Row and col params are 0-based.)
-
- Negative row/col values are turned into zero.
- """
- try:
- result = self._line_start_indexes[row]
- line = self.lines[row]
- except IndexError:
- if row < 0:
- result = self._line_start_indexes[0]
- line = self.lines[0]
- else:
- result = self._line_start_indexes[-1]
- line = self.lines[-1]
-
- result += max(0, min(col, len(line)))
-
- # Keep in range. (len(self.text) is included, because the cursor can be
- # right after the end of the text as well.)
- result = max(0, min(result, len(self.text)))
- return result
-
- @property
- def is_cursor_at_the_end(self):
- """ True when the cursor is at the end of the text. """
- return self.cursor_position == len(self.text)
-
- @property
- def is_cursor_at_the_end_of_line(self):
- """ True when the cursor is at the end of this line. """
- return self.current_char in ('\n', '')
-
- def has_match_at_current_position(self, sub):
- """
- `True` when this substring is found at the cursor position.
- """
- return self.text.find(sub, self.cursor_position) == self.cursor_position
-
- def find(self, sub, in_current_line=False, include_current_position=False,
- ignore_case=False, count=1):
- """
- Find `text` after the cursor, return position relative to the cursor
- position. Return `None` if nothing was found.
-
- :param count: Find the n-th occurance.
- """
- assert isinstance(ignore_case, bool)
-
- if in_current_line:
- text = self.current_line_after_cursor
- else:
- text = self.text_after_cursor
-
- if not include_current_position:
- if len(text) == 0:
- return # (Otherwise, we always get a match for the empty string.)
- else:
- text = text[1:]
-
- flags = re.IGNORECASE if ignore_case else 0
- iterator = re.finditer(re.escape(sub), text, flags)
-
- try:
- for i, match in enumerate(iterator):
- if i + 1 == count:
- if include_current_position:
- return match.start(0)
- else:
- return match.start(0) + 1
- except StopIteration:
- pass
-
- def find_all(self, sub, ignore_case=False):
- """
- Find all occurances of the substring. Return a list of absolute
- positions in the document.
- """
- flags = re.IGNORECASE if ignore_case else 0
- return [a.start() for a in re.finditer(re.escape(sub), self.text, flags)]
-
- def find_backwards(self, sub, in_current_line=False, ignore_case=False, count=1):
- """
- Find `text` before the cursor, return position relative to the cursor
- position. Return `None` if nothing was found.
-
- :param count: Find the n-th occurance.
- """
- if in_current_line:
- before_cursor = self.current_line_before_cursor[::-1]
- else:
- before_cursor = self.text_before_cursor[::-1]
-
- flags = re.IGNORECASE if ignore_case else 0
- iterator = re.finditer(re.escape(sub[::-1]), before_cursor, flags)
-
- try:
- for i, match in enumerate(iterator):
- if i + 1 == count:
- return - match.start(0) - len(sub)
- except StopIteration:
- pass
-
- def get_word_before_cursor(self, WORD=False):
- """
- Give the word before the cursor.
- If we have whitespace before the cursor this returns an empty string.
- """
- if self.text_before_cursor[-1:].isspace():
- return ''
- else:
- return self.text_before_cursor[self.find_start_of_previous_word(WORD=WORD):]
-
- def find_start_of_previous_word(self, count=1, WORD=False):
- """
- Return an index relative to the cursor position pointing to the start
- of the previous word. Return `None` if nothing was found.
- """
- # Reverse the text before the cursor, in order to do an efficient
- # backwards search.
- text_before_cursor = self.text_before_cursor[::-1]
-
- regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE
- iterator = regex.finditer(text_before_cursor)
-
- try:
- for i, match in enumerate(iterator):
- if i + 1 == count:
- return - match.end(1)
- except StopIteration:
- pass
-
- def find_boundaries_of_current_word(self, WORD=False, include_leading_whitespace=False,
- include_trailing_whitespace=False):
- """
- Return the relative boundaries (startpos, endpos) of the current word under the
- cursor. (This is at the current line, because line boundaries obviously
- don't belong to any word.)
- If not on a word, this returns (0,0)
- """
- text_before_cursor = self.current_line_before_cursor[::-1]
- text_after_cursor = self.current_line_after_cursor
-
- def get_regex(include_whitespace):
- return {
- (False, False): _FIND_CURRENT_WORD_RE,
- (False, True): _FIND_CURRENT_WORD_INCLUDE_TRAILING_WHITESPACE_RE,
- (True, False): _FIND_CURRENT_BIG_WORD_RE,
- (True, True): _FIND_CURRENT_BIG_WORD_INCLUDE_TRAILING_WHITESPACE_RE,
- }[(WORD, include_whitespace)]
-
- match_before = get_regex(include_leading_whitespace).search(text_before_cursor)
- match_after = get_regex(include_trailing_whitespace).search(text_after_cursor)
-
- # When there is a match before and after, and we're not looking for
- # WORDs, make sure that both the part before and after the cursor are
- # either in the [a-zA-Z_] alphabet or not. Otherwise, drop the part
- # before the cursor.
- if not WORD and match_before and match_after:
- c1 = self.text[self.cursor_position - 1]
- c2 = self.text[self.cursor_position]
- alphabet = string.ascii_letters + '0123456789_'
-
- if (c1 in alphabet) != (c2 in alphabet):
- match_before = None
-
- return (
- - match_before.end(1) if match_before else 0,
- match_after.end(1) if match_after else 0
- )
-
- def get_word_under_cursor(self, WORD=False):
- """
- Return the word, currently below the cursor.
- This returns an empty string when the cursor is on a whitespace region.
- """
- start, end = self.find_boundaries_of_current_word(WORD=WORD)
- return self.text[self.cursor_position + start: self.cursor_position + end]
-
- def find_next_word_beginning(self, count=1, WORD=False):
- """
- Return an index relative to the cursor position pointing to the start
- of the next word. Return `None` if nothing was found.
- """
- if count < 0:
- return self.find_previous_word_beginning(count=-count, WORD=WORD)
-
- regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE
- iterator = regex.finditer(self.text_after_cursor)
-
- try:
- for i, match in enumerate(iterator):
- # Take first match, unless it's the word on which we're right now.
- if i == 0 and match.start(1) == 0:
- count += 1
-
- if i + 1 == count:
- return match.start(1)
- except StopIteration:
- pass
-
- def find_next_word_ending(self, include_current_position=False, count=1, WORD=False):
- """
- Return an index relative to the cursor position pointing to the end
- of the next word. Return `None` if nothing was found.
- """
- if count < 0:
- return self.find_previous_word_ending(count=-count, WORD=WORD)
-
- if include_current_position:
- text = self.text_after_cursor
- else:
- text = self.text_after_cursor[1:]
-
- regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE
- iterable = regex.finditer(text)
-
- try:
- for i, match in enumerate(iterable):
- if i + 1 == count:
- value = match.end(1)
-
- if include_current_position:
- return value
- else:
- return value + 1
-
- except StopIteration:
- pass
-
- def find_previous_word_beginning(self, count=1, WORD=False):
- """
- Return an index relative to the cursor position pointing to the start
- of the previous word. Return `None` if nothing was found.
- """
- if count < 0:
- return self.find_next_word_beginning(count=-count, WORD=WORD)
-
- regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE
- iterator = regex.finditer(self.text_before_cursor[::-1])
-
- try:
- for i, match in enumerate(iterator):
- if i + 1 == count:
- return - match.end(1)
- except StopIteration:
- pass
-
- def find_previous_word_ending(self, count=1, WORD=False):
- """
- Return an index relative to the cursor position pointing to the end
- of the previous word. Return `None` if nothing was found.
- """
- if count < 0:
- return self.find_next_word_ending(count=-count, WORD=WORD)
-
- text_before_cursor = self.text_after_cursor[:1] + self.text_before_cursor[::-1]
-
- regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE
- iterator = regex.finditer(text_before_cursor)
-
- try:
- for i, match in enumerate(iterator):
- # Take first match, unless it's the word on which we're right now.
- if i == 0 and match.start(1) == 0:
- count += 1
-
- if i + 1 == count:
- return -match.start(1) + 1
- except StopIteration:
- pass
-
- def find_next_matching_line(self, match_func, count=1):
- """
- Look downwards for empty lines.
- Return the line index, relative to the current line.
- """
- result = None
-
- for index, line in enumerate(self.lines[self.cursor_position_row + 1:]):
- if match_func(line):
- result = 1 + index
- count -= 1
-
- if count == 0:
- break
-
- return result
-
- def find_previous_matching_line(self, match_func, count=1):
- """
- Look upwards for empty lines.
- Return the line index, relative to the current line.
- """
- result = None
-
- for index, line in enumerate(self.lines[:self.cursor_position_row][::-1]):
- if match_func(line):
- result = -1 - index
- count -= 1
-
- if count == 0:
- break
-
- return result
-
- def get_cursor_left_position(self, count=1):
- """
- Relative position for cursor left.
- """
- if count < 0:
- return self.get_cursor_right_position(-count)
-
- return - min(self.cursor_position_col, count)
-
- def get_cursor_right_position(self, count=1):
- """
- Relative position for cursor_right.
- """
- if count < 0:
- return self.get_cursor_left_position(-count)
-
- return min(count, len(self.current_line_after_cursor))
-
- def get_cursor_up_position(self, count=1, preferred_column=None):
- """
- Return the relative cursor position (character index) where we would be if the
- user pressed the arrow-up button.
-
- :param preferred_column: When given, go to this column instead of
- staying at the current column.
- """
- assert count >= 1
- column = self.cursor_position_col if preferred_column is None else preferred_column
-
- return self.translate_row_col_to_index(
- max(0, self.cursor_position_row - count), column) - self.cursor_position
-
- def get_cursor_down_position(self, count=1, preferred_column=None):
- """
- Return the relative cursor position (character index) where we would be if the
- user pressed the arrow-down button.
-
- :param preferred_column: When given, go to this column instead of
- staying at the current column.
- """
- assert count >= 1
- column = self.cursor_position_col if preferred_column is None else preferred_column
-
- return self.translate_row_col_to_index(
- self.cursor_position_row + count, column) - self.cursor_position
-
- def find_enclosing_bracket_right(self, left_ch, right_ch, end_pos=None):
- """
- Find the right bracket enclosing current position. Return the relative
- position to the cursor position.
-
- When `end_pos` is given, don't look past the position.
- """
- if self.current_char == right_ch:
- return 0
-
- if end_pos is None:
- end_pos = len(self.text)
- else:
- end_pos = min(len(self.text), end_pos)
-
- stack = 1
-
- # Look forward.
- for i in range(self.cursor_position + 1, end_pos):
- c = self.text[i]
-
- if c == left_ch:
- stack += 1
- elif c == right_ch:
- stack -= 1
-
- if stack == 0:
- return i - self.cursor_position
-
- def find_enclosing_bracket_left(self, left_ch, right_ch, start_pos=None):
- """
- Find the left bracket enclosing current position. Return the relative
- position to the cursor position.
-
- When `start_pos` is given, don't look past the position.
- """
- if self.current_char == left_ch:
- return 0
-
- if start_pos is None:
- start_pos = 0
- else:
- start_pos = max(0, start_pos)
-
- stack = 1
-
- # Look backward.
- for i in range(self.cursor_position - 1, start_pos - 1, -1):
- c = self.text[i]
-
- if c == right_ch:
- stack += 1
- elif c == left_ch:
- stack -= 1
-
- if stack == 0:
- return i - self.cursor_position
-
- def find_matching_bracket_position(self, start_pos=None, end_pos=None):
- """
- Return relative cursor position of matching [, (, { or < bracket.
-
- When `start_pos` or `end_pos` are given. Don't look past the positions.
- """
-
- # Look for a match.
- for A, B in '()', '[]', '{}', '<>':
- if self.current_char == A:
- return self.find_enclosing_bracket_right(A, B, end_pos=end_pos) or 0
- elif self.current_char == B:
- return self.find_enclosing_bracket_left(A, B, start_pos=start_pos) or 0
-
- return 0
-
- def get_start_of_document_position(self):
- """ Relative position for the start of the document. """
- return - self.cursor_position
-
- def get_end_of_document_position(self):
- """ Relative position for the end of the document. """
- return len(self.text) - self.cursor_position
-
- def get_start_of_line_position(self, after_whitespace=False):
- """ Relative position for the start of this line. """
- if after_whitespace:
- current_line = self.current_line
- return len(current_line) - len(current_line.lstrip()) - self.cursor_position_col
- else:
- return - len(self.current_line_before_cursor)
-
- def get_end_of_line_position(self):
- """ Relative position for the end of this line. """
- return len(self.current_line_after_cursor)
-
- def last_non_blank_of_current_line_position(self):
- """
- Relative position for the last non blank character of this line.
- """
- return len(self.current_line.rstrip()) - self.cursor_position_col - 1
-
- def get_column_cursor_position(self, column):
- """
- Return the relative cursor position for this column at the current
- line. (It will stay between the boundaries of the line in case of a
- larger number.)
- """
- line_length = len(self.current_line)
- current_column = self.cursor_position_col
- column = max(0, min(line_length, column))
-
- return column - current_column
-
- def selection_range(self): # XXX: shouldn't this return `None` if there is no selection???
- """
- Return (from, to) tuple of the selection.
- start and end position are included.
-
- This doesn't take the selection type into account. Use
- `selection_ranges` instead.
- """
- if self.selection:
- from_, to = sorted([self.cursor_position, self.selection.original_cursor_position])
- else:
- from_, to = self.cursor_position, self.cursor_position
-
- return from_, to
-
- def selection_ranges(self):
- """
- Return a list of (from, to) tuples for the selection or none if nothing
- was selected. start and end position are always included in the
- selection.
-
- This will yield several (from, to) tuples in case of a BLOCK selection.
- """
- if self.selection:
- from_, to = sorted([self.cursor_position, self.selection.original_cursor_position])
-
- if self.selection.type == SelectionType.BLOCK:
- from_line, from_column = self.translate_index_to_position(from_)
- to_line, to_column = self.translate_index_to_position(to)
- from_column, to_column = sorted([from_column, to_column])
- lines = self.lines
-
- for l in range(from_line, to_line + 1):
- line_length = len(lines[l])
- if from_column < line_length:
- yield (self.translate_row_col_to_index(l, from_column),
- self.translate_row_col_to_index(l, min(line_length - 1, to_column)))
- else:
- # In case of a LINES selection, go to the start/end of the lines.
- if self.selection.type == SelectionType.LINES:
- from_ = max(0, self.text.rfind('\n', 0, from_) + 1)
-
- if self.text.find('\n', to) >= 0:
- to = self.text.find('\n', to)
- else:
- to = len(self.text) - 1
-
- yield from_, to
-
- def selection_range_at_line(self, row):
- """
- If the selection spans a portion of the given line, return a (from, to) tuple.
- Otherwise, return None.
- """
- if self.selection:
- row_start = self.translate_row_col_to_index(row, 0)
- row_end = self.translate_row_col_to_index(row, max(0, len(self.lines[row]) - 1))
-
- from_, to = sorted([self.cursor_position, self.selection.original_cursor_position])
-
- # Take the intersection of the current line and the selection.
- intersection_start = max(row_start, from_)
- intersection_end = min(row_end, to)
-
- if intersection_start <= intersection_end:
- if self.selection.type == SelectionType.LINES:
- intersection_start = row_start
- intersection_end = row_end
- elif self.selection.type == SelectionType.BLOCK:
- _, col1 = self.translate_index_to_position(from_)
- _, col2 = self.translate_index_to_position(to)
- col1, col2 = sorted([col1, col2])
- intersection_start = self.translate_row_col_to_index(row, col1)
- intersection_end = self.translate_row_col_to_index(row, col2)
-
- _, from_column = self.translate_index_to_position(intersection_start)
- _, to_column = self.translate_index_to_position(intersection_end)
-
- return from_column, to_column
-
- def cut_selection(self):
- """
- Return a (:class:`.Document`, :class:`.ClipboardData`) tuple, where the
- document represents the new document when the selection is cut, and the
- clipboard data, represents whatever has to be put on the clipboard.
- """
- if self.selection:
- cut_parts = []
- remaining_parts = []
- new_cursor_position = self.cursor_position
-
- last_to = 0
- for from_, to in self.selection_ranges():
- if last_to == 0:
- new_cursor_position = from_
-
- remaining_parts.append(self.text[last_to:from_])
- cut_parts.append(self.text[from_:to + 1])
- last_to = to + 1
-
- remaining_parts.append(self.text[last_to:])
-
- cut_text = '\n'.join(cut_parts)
- remaining_text = ''.join(remaining_parts)
-
- # In case of a LINES selection, don't include the trailing newline.
- if self.selection.type == SelectionType.LINES and cut_text.endswith('\n'):
- cut_text = cut_text[:-1]
-
- return (Document(text=remaining_text, cursor_position=new_cursor_position),
- ClipboardData(cut_text, self.selection.type))
- else:
- return self, ClipboardData('')
-
- def paste_clipboard_data(self, data, paste_mode=PasteMode.EMACS, count=1):
- """
- Return a new :class:`.Document` instance which contains the result if
- we would paste this data at the current cursor position.
-
- :param paste_mode: Where to paste. (Before/after/emacs.)
- :param count: When >1, Paste multiple times.
- """
- assert isinstance(data, ClipboardData)
- assert paste_mode in (PasteMode.VI_BEFORE, PasteMode.VI_AFTER, PasteMode.EMACS)
-
- before = (paste_mode == PasteMode.VI_BEFORE)
- after = (paste_mode == PasteMode.VI_AFTER)
-
- if data.type == SelectionType.CHARACTERS:
- if after:
- new_text = (self.text[:self.cursor_position + 1] + data.text * count +
- self.text[self.cursor_position + 1:])
- else:
- new_text = self.text_before_cursor + data.text * count + self.text_after_cursor
-
- new_cursor_position = self.cursor_position + len(data.text) * count
- if before:
- new_cursor_position -= 1
-
- elif data.type == SelectionType.LINES:
- l = self.cursor_position_row
- if before:
- lines = self.lines[:l] + [data.text] * count + self.lines[l:]
- new_text = '\n'.join(lines)
- new_cursor_position = len(''.join(self.lines[:l])) + l
- else:
- lines = self.lines[:l + 1] + [data.text] * count + self.lines[l + 1:]
- new_cursor_position = len(''.join(self.lines[:l + 1])) + l + 1
- new_text = '\n'.join(lines)
-
- elif data.type == SelectionType.BLOCK:
- lines = self.lines[:]
- start_line = self.cursor_position_row
- start_column = self.cursor_position_col + (0 if before else 1)
-
- for i, line in enumerate(data.text.split('\n')):
- index = i + start_line
- if index >= len(lines):
- lines.append('')
-
- lines[index] = lines[index].ljust(start_column)
- lines[index] = lines[index][:start_column] + line * count + lines[index][start_column:]
-
- new_text = '\n'.join(lines)
- new_cursor_position = self.cursor_position + (0 if before else 1)
-
- return Document(text=new_text, cursor_position=new_cursor_position)
-
- def empty_line_count_at_the_end(self):
- """
- Return number of empty lines at the end of the document.
- """
- count = 0
- for line in self.lines[::-1]:
- if not line or line.isspace():
- count += 1
- else:
- break
-
- return count
-
- def start_of_paragraph(self, count=1, before=False):
- """
- Return the start of the current paragraph. (Relative cursor position.)
- """
- def match_func(text):
- return not text or text.isspace()
-
- line_index = self.find_previous_matching_line(match_func=match_func, count=count)
-
- if line_index:
- add = 0 if before else 1
- return min(0, self.get_cursor_up_position(count=-line_index) + add)
- else:
- return -self.cursor_position
-
- def end_of_paragraph(self, count=1, after=False):
- """
- Return the end of the current paragraph. (Relative cursor position.)
- """
- def match_func(text):
- return not text or text.isspace()
-
- line_index = self.find_next_matching_line(match_func=match_func, count=count)
-
- if line_index:
- add = 0 if after else 1
- return max(0, self.get_cursor_down_position(count=line_index) - add)
- else:
- return len(self.text_after_cursor)
-
- # Modifiers.
-
- def insert_after(self, text):
- """
- Create a new document, with this text inserted after the buffer.
- It keeps selection ranges and cursor position in sync.
- """
- return Document(
- text=self.text + text,
- cursor_position=self.cursor_position,
- selection=self.selection)
-
- def insert_before(self, text):
- """
- Create a new document, with this text inserted before the buffer.
- It keeps selection ranges and cursor position in sync.
- """
- selection_state = self.selection
-
- if selection_state:
- selection_state = SelectionState(
- original_cursor_position=selection_state.original_cursor_position + len(text),
- type=selection_state.type)
-
- return Document(
- text=text + self.text,
- cursor_position=self.cursor_position + len(text),
- selection=selection_state)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/enums.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/enums.py
deleted file mode 100644
index 6945f44c96..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/enums.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-
-
-class IncrementalSearchDirection(object):
- FORWARD = 'FORWARD'
- BACKWARD = 'BACKWARD'
-
-
-class EditingMode(object):
- # The set of key bindings that is active.
- VI = 'VI'
- EMACS = 'EMACS'
-
-
-#: Name of the search buffer.
-SEARCH_BUFFER = 'SEARCH_BUFFER'
-
-#: Name of the default buffer.
-DEFAULT_BUFFER = 'DEFAULT_BUFFER'
-
-#: Name of the system buffer.
-SYSTEM_BUFFER = 'SYSTEM_BUFFER'
-
-# Dummy buffer. This is the buffer returned by
-# `CommandLineInterface.current_buffer` when the top of the `FocusStack` is
-# `None`. This could be the case when there is some widget has the focus and no
-# actual text editing is possible. This buffer should also never be displayed.
-# (It will never contain any actual text.)
-DUMMY_BUFFER = 'DUMMY_BUFFER'
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/__init__.py
+++ /dev/null
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_base.py
deleted file mode 100644
index ace2b8db49..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_base.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""
-Eventloop for integration with Python3 asyncio.
-
-Note that we can't use "yield from", because the package should be installable
-under Python 2.6 as well, and it should contain syntactically valid Python 2.6
-code.
-"""
-from __future__ import unicode_literals
-
-__all__ = (
- 'AsyncioTimeout',
-)
-
-
-class AsyncioTimeout(object):
- """
- Call the `timeout` function when the timeout expires.
- Every call of the `reset` method, resets the timeout and starts a new
- timer.
- """
- def __init__(self, timeout, callback, loop):
- self.timeout = timeout
- self.callback = callback
- self.loop = loop
-
- self.counter = 0
- self.running = True
-
- def reset(self):
- """
- Reset the timeout. Starts a new timer.
- """
- self.counter += 1
- local_counter = self.counter
-
- def timer_timeout():
- if self.counter == local_counter and self.running:
- self.callback()
-
- self.loop.call_later(self.timeout, timer_timeout)
-
- def stop(self):
- """
- Ignore timeout. Don't call the callback anymore.
- """
- self.running = False
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py
deleted file mode 100644
index 426ed96f67..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py
+++ /dev/null
@@ -1,113 +0,0 @@
-"""
-Posix asyncio event loop.
-"""
-from __future__ import unicode_literals
-
-from ..terminal.vt100_input import InputStream
-from .asyncio_base import AsyncioTimeout
-from .base import EventLoop, INPUT_TIMEOUT
-from .callbacks import EventLoopCallbacks
-from .posix_utils import PosixStdinReader
-
-import asyncio
-import signal
-
-__all__ = (
- 'PosixAsyncioEventLoop',
-)
-
-
-class PosixAsyncioEventLoop(EventLoop):
- def __init__(self, loop=None):
- self.loop = loop or asyncio.get_event_loop()
- self.closed = False
-
- self._stopped_f = asyncio.Future(loop=self.loop)
-
- @asyncio.coroutine
- def run_as_coroutine(self, stdin, callbacks):
- """
- The input 'event loop'.
- """
- assert isinstance(callbacks, EventLoopCallbacks)
-
- # Create reader class.
- stdin_reader = PosixStdinReader(stdin.fileno())
-
- if self.closed:
- raise Exception('Event loop already closed.')
-
- inputstream = InputStream(callbacks.feed_key)
-
- try:
- # Create a new Future every time.
- self._stopped_f = asyncio.Future(loop=self.loop)
-
- # Handle input timouts
- def timeout_handler():
- """
- When no input has been received for INPUT_TIMEOUT seconds,
- flush the input stream and fire the timeout event.
- """
- inputstream.flush()
-
- callbacks.input_timeout()
-
- timeout = AsyncioTimeout(INPUT_TIMEOUT, timeout_handler, self.loop)
-
- # Catch sigwinch
- def received_winch():
- self.call_from_executor(callbacks.terminal_size_changed)
-
- self.loop.add_signal_handler(signal.SIGWINCH, received_winch)
-
- # Read input data.
- def stdin_ready():
- data = stdin_reader.read()
- inputstream.feed(data)
- timeout.reset()
-
- # Quit when the input stream was closed.
- if stdin_reader.closed:
- self.stop()
-
- self.loop.add_reader(stdin.fileno(), stdin_ready)
-
- # Block this coroutine until stop() has been called.
- for f in self._stopped_f:
- yield f
-
- finally:
- # Clean up.
- self.loop.remove_reader(stdin.fileno())
- self.loop.remove_signal_handler(signal.SIGWINCH)
-
- # Don't trigger any timeout events anymore.
- timeout.stop()
-
- def stop(self):
- # Trigger the 'Stop' future.
- self._stopped_f.set_result(True)
-
- def close(self):
- # Note: we should not close the asyncio loop itself, because that one
- # was not created here.
- self.closed = True
-
- def run_in_executor(self, callback):
- self.loop.run_in_executor(None, callback)
-
- def call_from_executor(self, callback, _max_postpone_until=None):
- """
- Call this function in the main event loop.
- Similar to Twisted's ``callFromThread``.
- """
- self.loop.call_soon_threadsafe(callback)
-
- def add_reader(self, fd, callback):
- " Start watching the file descriptor for read availability. "
- self.loop.add_reader(fd, callback)
-
- def remove_reader(self, fd):
- " Stop watching the file descriptor for read availability. "
- self.loop.remove_reader(fd)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py
deleted file mode 100644
index 45f5f52679..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py
+++ /dev/null
@@ -1,83 +0,0 @@
-"""
-Win32 asyncio event loop.
-
-Windows notes:
-- Somehow it doesn't seem to work with the 'ProactorEventLoop'.
-"""
-from __future__ import unicode_literals
-
-from .base import EventLoop, INPUT_TIMEOUT
-from ..terminal.win32_input import ConsoleInputReader
-from .callbacks import EventLoopCallbacks
-from .asyncio_base import AsyncioTimeout
-
-import asyncio
-
-__all__ = (
- 'Win32AsyncioEventLoop',
-)
-
-
-class Win32AsyncioEventLoop(EventLoop):
- def __init__(self, loop=None):
- self._console_input_reader = ConsoleInputReader()
- self.running = False
- self.closed = False
- self.loop = loop or asyncio.get_event_loop()
-
- @asyncio.coroutine
- def run_as_coroutine(self, stdin, callbacks):
- """
- The input 'event loop'.
- """
- # Note: We cannot use "yield from", because this package also
- # installs on Python 2.
- assert isinstance(callbacks, EventLoopCallbacks)
-
- if self.closed:
- raise Exception('Event loop already closed.')
-
- timeout = AsyncioTimeout(INPUT_TIMEOUT, callbacks.input_timeout, self.loop)
- self.running = True
-
- try:
- while self.running:
- timeout.reset()
-
- # Get keys
- try:
- g = iter(self.loop.run_in_executor(None, self._console_input_reader.read))
- while True:
- yield next(g)
- except StopIteration as e:
- keys = e.args[0]
-
- # Feed keys to input processor.
- for k in keys:
- callbacks.feed_key(k)
- finally:
- timeout.stop()
-
- def stop(self):
- self.running = False
-
- def close(self):
- # Note: we should not close the asyncio loop itself, because that one
- # was not created here.
- self.closed = True
-
- self._console_input_reader.close()
-
- def run_in_executor(self, callback):
- self.loop.run_in_executor(None, callback)
-
- def call_from_executor(self, callback, _max_postpone_until=None):
- self.loop.call_soon_threadsafe(callback)
-
- def add_reader(self, fd, callback):
- " Start watching the file descriptor for read availability. "
- self.loop.add_reader(fd, callback)
-
- def remove_reader(self, fd):
- " Stop watching the file descriptor for read availability. "
- self.loop.remove_reader(fd)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py
deleted file mode 100644
index db86face66..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py
+++ /dev/null
@@ -1,85 +0,0 @@
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-
-__all__ = (
- 'EventLoop',
- 'INPUT_TIMEOUT',
-)
-
-
-#: When to trigger the `onInputTimeout` event.
-INPUT_TIMEOUT = .5
-
-
-class EventLoop(with_metaclass(ABCMeta, object)):
- """
- Eventloop interface.
- """
- def run(self, stdin, callbacks):
- """
- Run the eventloop until stop() is called. Report all
- input/timeout/terminal-resize events to the callbacks.
-
- :param stdin: :class:`~prompt_toolkit.input.Input` instance.
- :param callbacks: :class:`~prompt_toolkit.eventloop.callbacks.EventLoopCallbacks` instance.
- """
- raise NotImplementedError("This eventloop doesn't implement synchronous 'run()'.")
-
- def run_as_coroutine(self, stdin, callbacks):
- """
- Similar to `run`, but this is a coroutine. (For asyncio integration.)
- """
- raise NotImplementedError("This eventloop doesn't implement 'run_as_coroutine()'.")
-
- @abstractmethod
- def stop(self):
- """
- Stop the `run` call. (Normally called by
- :class:`~prompt_toolkit.interface.CommandLineInterface`, when a result
- is available, or Abort/Quit has been called.)
- """
-
- @abstractmethod
- def close(self):
- """
- Clean up of resources. Eventloop cannot be reused a second time after
- this call.
- """
-
- @abstractmethod
- def add_reader(self, fd, callback):
- """
- Start watching the file descriptor for read availability and then call
- the callback.
- """
-
- @abstractmethod
- def remove_reader(self, fd):
- """
- Stop watching the file descriptor for read availability.
- """
-
- @abstractmethod
- def run_in_executor(self, callback):
- """
- Run a long running function in a background thread. (This is
- recommended for code that could block the event loop.)
- Similar to Twisted's ``deferToThread``.
- """
-
- @abstractmethod
- def call_from_executor(self, callback, _max_postpone_until=None):
- """
- Call this function in the main event loop. Similar to Twisted's
- ``callFromThread``.
-
- :param _max_postpone_until: `None` or `time.time` value. For interal
- use. If the eventloop is saturated, consider this task to be low
- priority and postpone maximum until this timestamp. (For instance,
- repaint is done using low priority.)
-
- Note: In the past, this used to be a datetime.datetime instance,
- but apparently, executing `time.time` is more efficient: it
- does fewer system calls. (It doesn't read /etc/localtime.)
- """
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/callbacks.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/callbacks.py
deleted file mode 100644
index 04adab6fd4..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/callbacks.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-
-__all__ = (
- 'EventLoopCallbacks',
-)
-
-
-class EventLoopCallbacks(with_metaclass(ABCMeta, object)):
- """
- This is the glue between the :class:`~prompt_toolkit.eventloop.base.EventLoop`
- and :class:`~prompt_toolkit.interface.CommandLineInterface`.
-
- :meth:`~prompt_toolkit.eventloop.base.EventLoop.run` takes an
- :class:`.EventLoopCallbacks` instance and operates on that one, driving the
- interface.
- """
- @abstractmethod
- def terminal_size_changed(self):
- pass
-
- @abstractmethod
- def input_timeout(self):
- pass
-
- @abstractmethod
- def feed_key(self, key):
- pass
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py
deleted file mode 100644
index bab1f4c003..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py
+++ /dev/null
@@ -1,107 +0,0 @@
-"""
-Similar to `PyOS_InputHook` of the Python API. Some eventloops can have an
-inputhook to allow easy integration with other event loops.
-
-When the eventloop of prompt-toolkit is idle, it can call such a hook. This
-hook can call another eventloop that runs for a short while, for instance to
-keep a graphical user interface responsive.
-
-It's the responsibility of this hook to exit when there is input ready.
-There are two ways to detect when input is ready:
-
-- Call the `input_is_ready` method periodically. Quit when this returns `True`.
-
-- Add the `fileno` as a watch to the external eventloop. Quit when file descriptor
- becomes readable. (But don't read from it.)
-
- Note that this is not the same as checking for `sys.stdin.fileno()`. The
- eventloop of prompt-toolkit allows thread-based executors, for example for
- asynchronous autocompletion. When the completion for instance is ready, we
- also want prompt-toolkit to gain control again in order to display that.
-
-An alternative to using input hooks, is to create a custom `EventLoop` class that
-controls everything.
-"""
-from __future__ import unicode_literals
-import os
-import threading
-from prompt_toolkit.utils import is_windows
-from .select import select_fds
-
-__all__ = (
- 'InputHookContext',
-)
-
-
-class InputHookContext(object):
- """
- Given as a parameter to the inputhook.
- """
- def __init__(self, inputhook):
- assert callable(inputhook)
-
- self.inputhook = inputhook
- self._input_is_ready = None
-
- self._r, self._w = os.pipe()
-
- def input_is_ready(self):
- """
- Return True when the input is ready.
- """
- return self._input_is_ready(wait=False)
-
- def fileno(self):
- """
- File descriptor that will become ready when the event loop needs to go on.
- """
- return self._r
-
- def call_inputhook(self, input_is_ready_func):
- """
- Call the inputhook. (Called by a prompt-toolkit eventloop.)
- """
- self._input_is_ready = input_is_ready_func
-
- # Start thread that activates this pipe when there is input to process.
- def thread():
- input_is_ready_func(wait=True)
- os.write(self._w, b'x')
-
- threading.Thread(target=thread).start()
-
- # Call inputhook.
- self.inputhook(self)
-
- # Flush the read end of the pipe.
- try:
- # Before calling 'os.read', call select.select. This is required
- # when the gevent monkey patch has been applied. 'os.read' is never
- # monkey patched and won't be cooperative, so that would block all
- # other select() calls otherwise.
- # See: http://www.gevent.org/gevent.os.html
-
- # Note: On Windows, this is apparently not an issue.
- # However, if we would ever want to add a select call, it
- # should use `windll.kernel32.WaitForMultipleObjects`,
- # because `select.select` can't wait for a pipe on Windows.
- if not is_windows():
- select_fds([self._r], timeout=None)
-
- os.read(self._r, 1024)
- except OSError:
- # This happens when the window resizes and a SIGWINCH was received.
- # We get 'Error: [Errno 4] Interrupted system call'
- # Just ignore.
- pass
- self._input_is_ready = None
-
- def close(self):
- """
- Clean up resources.
- """
- if self._r:
- os.close(self._r)
- os.close(self._w)
-
- self._r = self._w = None
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py
deleted file mode 100644
index f631dbd891..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py
+++ /dev/null
@@ -1,306 +0,0 @@
-from __future__ import unicode_literals
-import fcntl
-import os
-import signal
-import threading
-import time
-
-from prompt_toolkit.terminal.vt100_input import InputStream
-from prompt_toolkit.utils import DummyContext, in_main_thread
-from prompt_toolkit.input import Input
-from .base import EventLoop, INPUT_TIMEOUT
-from .callbacks import EventLoopCallbacks
-from .inputhook import InputHookContext
-from .posix_utils import PosixStdinReader
-from .utils import TimeIt
-from .select import AutoSelector, Selector, fd_to_int
-
-__all__ = (
- 'PosixEventLoop',
-)
-
-_now = time.time
-
-
-class PosixEventLoop(EventLoop):
- """
- Event loop for posix systems (Linux, Mac os X).
- """
- def __init__(self, inputhook=None, selector=AutoSelector):
- assert inputhook is None or callable(inputhook)
- assert issubclass(selector, Selector)
-
- self.running = False
- self.closed = False
- self._running = False
- self._callbacks = None
-
- self._calls_from_executor = []
- self._read_fds = {} # Maps fd to handler.
- self.selector = selector()
-
- # Create a pipe for inter thread communication.
- self._schedule_pipe = os.pipe()
- fcntl.fcntl(self._schedule_pipe[0], fcntl.F_SETFL, os.O_NONBLOCK)
-
- # Create inputhook context.
- self._inputhook_context = InputHookContext(inputhook) if inputhook else None
-
- def run(self, stdin, callbacks):
- """
- The input 'event loop'.
- """
- assert isinstance(stdin, Input)
- assert isinstance(callbacks, EventLoopCallbacks)
- assert not self._running
-
- if self.closed:
- raise Exception('Event loop already closed.')
-
- self._running = True
- self._callbacks = callbacks
-
- inputstream = InputStream(callbacks.feed_key)
- current_timeout = [INPUT_TIMEOUT] # Nonlocal
-
- # Create reader class.
- stdin_reader = PosixStdinReader(stdin.fileno())
-
- # Only attach SIGWINCH signal handler in main thread.
- # (It's not possible to attach signal handlers in other threads. In
- # that case we should rely on a the main thread to call this manually
- # instead.)
- if in_main_thread():
- ctx = call_on_sigwinch(self.received_winch)
- else:
- ctx = DummyContext()
-
- def read_from_stdin():
- " Read user input. "
- # Feed input text.
- data = stdin_reader.read()
- inputstream.feed(data)
-
- # Set timeout again.
- current_timeout[0] = INPUT_TIMEOUT
-
- # Quit when the input stream was closed.
- if stdin_reader.closed:
- self.stop()
-
- self.add_reader(stdin, read_from_stdin)
- self.add_reader(self._schedule_pipe[0], None)
-
- with ctx:
- while self._running:
- # Call inputhook.
- if self._inputhook_context:
- with TimeIt() as inputhook_timer:
- def ready(wait):
- " True when there is input ready. The inputhook should return control. "
- return self._ready_for_reading(current_timeout[0] if wait else 0) != []
- self._inputhook_context.call_inputhook(ready)
- inputhook_duration = inputhook_timer.duration
- else:
- inputhook_duration = 0
-
- # Calculate remaining timeout. (The inputhook consumed some of the time.)
- if current_timeout[0] is None:
- remaining_timeout = None
- else:
- remaining_timeout = max(0, current_timeout[0] - inputhook_duration)
-
- # Wait until input is ready.
- fds = self._ready_for_reading(remaining_timeout)
-
- # When any of the FDs are ready. Call the appropriate callback.
- if fds:
- # Create lists of high/low priority tasks. The main reason
- # for this is to allow painting the UI to happen as soon as
- # possible, but when there are many events happening, we
- # don't want to call the UI renderer 1000x per second. If
- # the eventloop is completely saturated with many CPU
- # intensive tasks (like processing input/output), we say
- # that drawing the UI can be postponed a little, to make
- # CPU available. This will be a low priority task in that
- # case.
- tasks = []
- low_priority_tasks = []
- now = None # Lazy load time. (Fewer system calls.)
-
- for fd in fds:
- # For the 'call_from_executor' fd, put each pending
- # item on either the high or low priority queue.
- if fd == self._schedule_pipe[0]:
- for c, max_postpone_until in self._calls_from_executor:
- if max_postpone_until is None:
- # Execute now.
- tasks.append(c)
- else:
- # Execute soon, if `max_postpone_until` is in the future.
- now = now or _now()
- if max_postpone_until < now:
- tasks.append(c)
- else:
- low_priority_tasks.append((c, max_postpone_until))
- self._calls_from_executor = []
-
- # Flush all the pipe content.
- os.read(self._schedule_pipe[0], 1024)
- else:
- handler = self._read_fds.get(fd)
- if handler:
- tasks.append(handler)
-
- # When there are high priority tasks, run all these.
- # Schedule low priority tasks for the next iteration.
- if tasks:
- for t in tasks:
- t()
-
- # Postpone low priority tasks.
- for t, max_postpone_until in low_priority_tasks:
- self.call_from_executor(t, _max_postpone_until=max_postpone_until)
- else:
- # Currently there are only low priority tasks -> run them right now.
- for t, _ in low_priority_tasks:
- t()
-
- else:
- # Flush all pending keys on a timeout. (This is most
- # important to flush the vt100 'Escape' key early when
- # nothing else follows.)
- inputstream.flush()
-
- # Fire input timeout event.
- callbacks.input_timeout()
- current_timeout[0] = None
-
- self.remove_reader(stdin)
- self.remove_reader(self._schedule_pipe[0])
-
- self._callbacks = None
-
- def _ready_for_reading(self, timeout=None):
- """
- Return the file descriptors that are ready for reading.
- """
- fds = self.selector.select(timeout)
- return fds
-
- def received_winch(self):
- """
- Notify the event loop that SIGWINCH has been received
- """
- # Process signal asynchronously, because this handler can write to the
- # output, and doing this inside the signal handler causes easily
- # reentrant calls, giving runtime errors..
-
- # Furthur, this has to be thread safe. When the CommandLineInterface
- # runs not in the main thread, this function still has to be called
- # from the main thread. (The only place where we can install signal
- # handlers.)
- def process_winch():
- if self._callbacks:
- self._callbacks.terminal_size_changed()
-
- self.call_from_executor(process_winch)
-
- def run_in_executor(self, callback):
- """
- Run a long running function in a background thread.
- (This is recommended for code that could block the event loop.)
- Similar to Twisted's ``deferToThread``.
- """
- # Wait until the main thread is idle.
- # We start the thread by using `call_from_executor`. The event loop
- # favours processing input over `calls_from_executor`, so the thread
- # will not start until there is no more input to process and the main
- # thread becomes idle for an instant. This is good, because Python
- # threading favours CPU over I/O -- an autocompletion thread in the
- # background would cause a significantly slow down of the main thread.
- # It is mostly noticable when pasting large portions of text while
- # having real time autocompletion while typing on.
- def start_executor():
- threading.Thread(target=callback).start()
- self.call_from_executor(start_executor)
-
- def call_from_executor(self, callback, _max_postpone_until=None):
- """
- Call this function in the main event loop.
- Similar to Twisted's ``callFromThread``.
-
- :param _max_postpone_until: `None` or `time.time` value. For interal
- use. If the eventloop is saturated, consider this task to be low
- priority and postpone maximum until this timestamp. (For instance,
- repaint is done using low priority.)
- """
- assert _max_postpone_until is None or isinstance(_max_postpone_until, float)
- self._calls_from_executor.append((callback, _max_postpone_until))
-
- if self._schedule_pipe:
- try:
- os.write(self._schedule_pipe[1], b'x')
- except (AttributeError, IndexError, OSError):
- # Handle race condition. We're in a different thread.
- # - `_schedule_pipe` could have become None in the meantime.
- # - We catch `OSError` (actually BrokenPipeError), because the
- # main thread could have closed the pipe already.
- pass
-
- def stop(self):
- """
- Stop the event loop.
- """
- self._running = False
-
- def close(self):
- self.closed = True
-
- # Close pipes.
- schedule_pipe = self._schedule_pipe
- self._schedule_pipe = None
-
- if schedule_pipe:
- os.close(schedule_pipe[0])
- os.close(schedule_pipe[1])
-
- if self._inputhook_context:
- self._inputhook_context.close()
-
- def add_reader(self, fd, callback):
- " Add read file descriptor to the event loop. "
- fd = fd_to_int(fd)
- self._read_fds[fd] = callback
- self.selector.register(fd)
-
- def remove_reader(self, fd):
- " Remove read file descriptor from the event loop. "
- fd = fd_to_int(fd)
-
- if fd in self._read_fds:
- del self._read_fds[fd]
-
- self.selector.unregister(fd)
-
-
-class call_on_sigwinch(object):
- """
- Context manager which Installs a SIGWINCH callback.
- (This signal occurs when the terminal size changes.)
- """
- def __init__(self, callback):
- self.callback = callback
- self.previous_callback = None
-
- def __enter__(self):
- self.previous_callback = signal.signal(signal.SIGWINCH, lambda *a: self.callback())
-
- def __exit__(self, *a, **kw):
- if self.previous_callback is None:
- # Normally, `signal.signal` should never return `None`.
- # For some reason it happens here:
- # https://github.com/jonathanslenders/python-prompt-toolkit/pull/174
- signal.signal(signal.SIGWINCH, 0)
- else:
- signal.signal(signal.SIGWINCH, self.previous_callback)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py
deleted file mode 100644
index 320df438ca..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py
+++ /dev/null
@@ -1,82 +0,0 @@
-from __future__ import unicode_literals
-
-from codecs import getincrementaldecoder
-import os
-import six
-
-__all__ = (
- 'PosixStdinReader',
-)
-
-
-class PosixStdinReader(object):
- """
- Wrapper around stdin which reads (nonblocking) the next available 1024
- bytes and decodes it.
-
- Note that you can't be sure that the input file is closed if the ``read``
- function returns an empty string. When ``errors=ignore`` is passed,
- ``read`` can return an empty string if all malformed input was replaced by
- an empty string. (We can't block here and wait for more input.) So, because
- of that, check the ``closed`` attribute, to be sure that the file has been
- closed.
-
- :param stdin_fd: File descriptor from which we read.
- :param errors: Can be 'ignore', 'strict' or 'replace'.
- On Python3, this can be 'surrogateescape', which is the default.
-
- 'surrogateescape' is preferred, because this allows us to transfer
- unrecognised bytes to the key bindings. Some terminals, like lxterminal
- and Guake, use the 'Mxx' notation to send mouse events, where each 'x'
- can be any possible byte.
- """
- # By default, we want to 'ignore' errors here. The input stream can be full
- # of junk. One occurrence of this that I had was when using iTerm2 on OS X,
- # with "Option as Meta" checked (You should choose "Option as +Esc".)
-
- def __init__(self, stdin_fd,
- errors=('ignore' if six.PY2 else 'surrogateescape')):
- assert isinstance(stdin_fd, int)
- self.stdin_fd = stdin_fd
- self.errors = errors
-
- # Create incremental decoder for decoding stdin.
- # We can not just do `os.read(stdin.fileno(), 1024).decode('utf-8')`, because
- # it could be that we are in the middle of a utf-8 byte sequence.
- self._stdin_decoder_cls = getincrementaldecoder('utf-8')
- self._stdin_decoder = self._stdin_decoder_cls(errors=errors)
-
- #: True when there is nothing anymore to read.
- self.closed = False
-
- def read(self, count=1024):
- # By default we choose a rather small chunk size, because reading
- # big amounts of input at once, causes the event loop to process
- # all these key bindings also at once without going back to the
- # loop. This will make the application feel unresponsive.
- """
- Read the input and return it as a string.
-
- Return the text. Note that this can return an empty string, even when
- the input stream was not yet closed. This means that something went
- wrong during the decoding.
- """
- if self.closed:
- return b''
-
- # Note: the following works better than wrapping `self.stdin` like
- # `codecs.getreader('utf-8')(stdin)` and doing `read(1)`.
- # Somehow that causes some latency when the escape
- # character is pressed. (Especially on combination with the `select`.)
- try:
- data = os.read(self.stdin_fd, count)
-
- # Nothing more to read, stream is closed.
- if data == b'':
- self.closed = True
- return ''
- except OSError:
- # In case of SIGWINCH
- data = b''
-
- return self._stdin_decoder.decode(data)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py
deleted file mode 100644
index f678f84c55..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py
+++ /dev/null
@@ -1,216 +0,0 @@
-"""
-Selectors for the Posix event loop.
-"""
-from __future__ import unicode_literals, absolute_import
-import sys
-import abc
-import errno
-import select
-import six
-
-__all__ = (
- 'AutoSelector',
- 'PollSelector',
- 'SelectSelector',
- 'Selector',
- 'fd_to_int',
-)
-
-def fd_to_int(fd):
- assert isinstance(fd, int) or hasattr(fd, 'fileno')
-
- if isinstance(fd, int):
- return fd
- else:
- return fd.fileno()
-
-
-class Selector(six.with_metaclass(abc.ABCMeta, object)):
- @abc.abstractmethod
- def register(self, fd):
- assert isinstance(fd, int)
-
- @abc.abstractmethod
- def unregister(self, fd):
- assert isinstance(fd, int)
-
- @abc.abstractmethod
- def select(self, timeout):
- pass
-
- @abc.abstractmethod
- def close(self):
- pass
-
-
-class AutoSelector(Selector):
- def __init__(self):
- self._fds = []
-
- self._select_selector = SelectSelector()
- self._selectors = [self._select_selector]
-
- # When 'select.poll' exists, create a PollSelector.
- if hasattr(select, 'poll'):
- self._poll_selector = PollSelector()
- self._selectors.append(self._poll_selector)
- else:
- self._poll_selector = None
-
- # Use of the 'select' module, that was introduced in Python3.4. We don't
- # use it before 3.5 however, because this is the point where this module
- # retries interrupted system calls.
- if sys.version_info >= (3, 5):
- self._py3_selector = Python3Selector()
- self._selectors.append(self._py3_selector)
- else:
- self._py3_selector = None
-
- def register(self, fd):
- assert isinstance(fd, int)
-
- self._fds.append(fd)
-
- for sel in self._selectors:
- sel.register(fd)
-
- def unregister(self, fd):
- assert isinstance(fd, int)
-
- self._fds.remove(fd)
-
- for sel in self._selectors:
- sel.unregister(fd)
-
- def select(self, timeout):
- # Try Python 3 selector first.
- if self._py3_selector:
- try:
- return self._py3_selector.select(timeout)
- except PermissionError:
- # We had a situation (in pypager) where epoll raised a
- # PermissionError when a local file descriptor was registered,
- # however poll and select worked fine. So, in that case, just
- # try using select below.
- pass
-
- try:
- # Prefer 'select.select', if we don't have much file descriptors.
- # This is more universal.
- return self._select_selector.select(timeout)
- except ValueError:
- # When we have more than 1024 open file descriptors, we'll always
- # get a "ValueError: filedescriptor out of range in select()" for
- # 'select'. In this case, try, using 'poll' instead.
- if self._poll_selector is not None:
- return self._poll_selector.select(timeout)
- else:
- raise
-
- def close(self):
- for sel in self._selectors:
- sel.close()
-
-
-class Python3Selector(Selector):
- """
- Use of the Python3 'selectors' module.
-
- NOTE: Only use on Python 3.5 or newer!
- """
- def __init__(self):
- assert sys.version_info >= (3, 5)
-
- import selectors # Inline import: Python3 only!
- self._sel = selectors.DefaultSelector()
-
- def register(self, fd):
- assert isinstance(fd, int)
- import selectors # Inline import: Python3 only!
- self._sel.register(fd, selectors.EVENT_READ, None)
-
- def unregister(self, fd):
- assert isinstance(fd, int)
- self._sel.unregister(fd)
-
- def select(self, timeout):
- events = self._sel.select(timeout=timeout)
- return [key.fileobj for key, mask in events]
-
- def close(self):
- self._sel.close()
-
-
-class PollSelector(Selector):
- def __init__(self):
- self._poll = select.poll()
-
- def register(self, fd):
- assert isinstance(fd, int)
- self._poll.register(fd, select.POLLIN)
-
- def unregister(self, fd):
- assert isinstance(fd, int)
-
- def select(self, timeout):
- tuples = self._poll.poll(timeout) # Returns (fd, event) tuples.
- return [t[0] for t in tuples]
-
- def close(self):
- pass # XXX
-
-
-class SelectSelector(Selector):
- """
- Wrapper around select.select.
-
- When the SIGWINCH signal is handled, other system calls, like select
- are aborted in Python. This wrapper will retry the system call.
- """
- def __init__(self):
- self._fds = []
-
- def register(self, fd):
- self._fds.append(fd)
-
- def unregister(self, fd):
- self._fds.remove(fd)
-
- def select(self, timeout):
- while True:
- try:
- return select.select(self._fds, [], [], timeout)[0]
- except select.error as e:
- # Retry select call when EINTR
- if e.args and e.args[0] == errno.EINTR:
- continue
- else:
- raise
-
- def close(self):
- pass
-
-
-def select_fds(read_fds, timeout, selector=AutoSelector):
- """
- Wait for a list of file descriptors (`read_fds`) to become ready for
- reading. This chooses the most appropriate select-tool for use in
- prompt-toolkit.
- """
- # Map to ensure that we return the objects that were passed in originally.
- # Whether they are a fd integer or an object that has a fileno().
- # (The 'poll' implementation for instance, returns always integers.)
- fd_map = dict((fd_to_int(fd), fd) for fd in read_fds)
-
- # Wait, using selector.
- sel = selector()
- try:
- for fd in read_fds:
- sel.register(fd)
-
- result = sel.select(timeout)
-
- if result is not None:
- return [fd_map[fd_to_int(fd)] for fd in result]
- finally:
- sel.close()
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/utils.py
deleted file mode 100644
index ff3a4cfd69..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/utils.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from __future__ import unicode_literals
-import time
-
-__all__ = (
- 'TimeIt',
-)
-
-
-class TimeIt(object):
- """
- Context manager that times the duration of the code body.
- The `duration` attribute will contain the execution time in seconds.
- """
- def __init__(self):
- self.duration = None
-
- def __enter__(self):
- self.start = time.time()
- return self
-
- def __exit__(self, *args):
- self.end = time.time()
- self.duration = self.end - self.start
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py
deleted file mode 100644
index 18e356f088..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py
+++ /dev/null
@@ -1,187 +0,0 @@
-"""
-Win32 event loop.
-
-Windows notes:
- - Somehow it doesn't seem to work with the 'ProactorEventLoop'.
-"""
-from __future__ import unicode_literals
-
-from ..terminal.win32_input import ConsoleInputReader
-from ..win32_types import SECURITY_ATTRIBUTES
-from .base import EventLoop, INPUT_TIMEOUT
-from .inputhook import InputHookContext
-from .utils import TimeIt
-
-from ctypes import windll, pointer
-from ctypes.wintypes import DWORD, BOOL, HANDLE
-
-import msvcrt
-import threading
-
-__all__ = (
- 'Win32EventLoop',
-)
-
-WAIT_TIMEOUT = 0x00000102
-INPUT_TIMEOUT_MS = int(1000 * INPUT_TIMEOUT)
-
-
-class Win32EventLoop(EventLoop):
- """
- Event loop for Windows systems.
-
- :param recognize_paste: When True, try to discover paste actions and turn
- the event into a BracketedPaste.
- """
- def __init__(self, inputhook=None, recognize_paste=True):
- assert inputhook is None or callable(inputhook)
-
- self._event = HANDLE(_create_event())
- self._console_input_reader = ConsoleInputReader(recognize_paste=recognize_paste)
- self._calls_from_executor = []
-
- self.closed = False
- self._running = False
-
- # Additional readers.
- self._read_fds = {} # Maps fd to handler.
-
- # Create inputhook context.
- self._inputhook_context = InputHookContext(inputhook) if inputhook else None
-
- def run(self, stdin, callbacks):
- if self.closed:
- raise Exception('Event loop already closed.')
-
- current_timeout = INPUT_TIMEOUT_MS
- self._running = True
-
- while self._running:
- # Call inputhook.
- with TimeIt() as inputhook_timer:
- if self._inputhook_context:
- def ready(wait):
- " True when there is input ready. The inputhook should return control. "
- return bool(self._ready_for_reading(current_timeout if wait else 0))
- self._inputhook_context.call_inputhook(ready)
-
- # Calculate remaining timeout. (The inputhook consumed some of the time.)
- if current_timeout == -1:
- remaining_timeout = -1
- else:
- remaining_timeout = max(0, current_timeout - int(1000 * inputhook_timer.duration))
-
- # Wait for the next event.
- handle = self._ready_for_reading(remaining_timeout)
-
- if handle == self._console_input_reader.handle.value:
- # When stdin is ready, read input and reset timeout timer.
- keys = self._console_input_reader.read()
- for k in keys:
- callbacks.feed_key(k)
- current_timeout = INPUT_TIMEOUT_MS
-
- elif handle == self._event.value:
- # When the Windows Event has been trigger, process the messages in the queue.
- windll.kernel32.ResetEvent(self._event)
- self._process_queued_calls_from_executor()
-
- elif handle in self._read_fds:
- callback = self._read_fds[handle]
- callback()
- else:
- # Fire input timeout event.
- callbacks.input_timeout()
- current_timeout = -1
-
- def _ready_for_reading(self, timeout=None):
- """
- Return the handle that is ready for reading or `None` on timeout.
- """
- handles = [self._event, self._console_input_reader.handle]
- handles.extend(self._read_fds.keys())
- return _wait_for_handles(handles, timeout)
-
- def stop(self):
- self._running = False
-
- def close(self):
- self.closed = True
-
- # Clean up Event object.
- windll.kernel32.CloseHandle(self._event)
-
- if self._inputhook_context:
- self._inputhook_context.close()
-
- self._console_input_reader.close()
-
- def run_in_executor(self, callback):
- """
- Run a long running function in a background thread.
- (This is recommended for code that could block the event loop.)
- Similar to Twisted's ``deferToThread``.
- """
- # Wait until the main thread is idle for an instant before starting the
- # executor. (Like in eventloop/posix.py, we start the executor using
- # `call_from_executor`.)
- def start_executor():
- threading.Thread(target=callback).start()
- self.call_from_executor(start_executor)
-
- def call_from_executor(self, callback, _max_postpone_until=None):
- """
- Call this function in the main event loop.
- Similar to Twisted's ``callFromThread``.
- """
- # Append to list of pending callbacks.
- self._calls_from_executor.append(callback)
-
- # Set Windows event.
- windll.kernel32.SetEvent(self._event)
-
- def _process_queued_calls_from_executor(self):
- # Process calls from executor.
- calls_from_executor, self._calls_from_executor = self._calls_from_executor, []
- for c in calls_from_executor:
- c()
-
- def add_reader(self, fd, callback):
- " Start watching the file descriptor for read availability. "
- h = msvcrt.get_osfhandle(fd)
- self._read_fds[h] = callback
-
- def remove_reader(self, fd):
- " Stop watching the file descriptor for read availability. "
- h = msvcrt.get_osfhandle(fd)
- if h in self._read_fds:
- del self._read_fds[h]
-
-
-def _wait_for_handles(handles, timeout=-1):
- """
- Waits for multiple handles. (Similar to 'select') Returns the handle which is ready.
- Returns `None` on timeout.
-
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx
- """
- arrtype = HANDLE * len(handles)
- handle_array = arrtype(*handles)
-
- ret = windll.kernel32.WaitForMultipleObjects(
- len(handle_array), handle_array, BOOL(False), DWORD(timeout))
-
- if ret == WAIT_TIMEOUT:
- return None
- else:
- h = handle_array[ret]
- return h
-
-
-def _create_event():
- """
- Creates a Win32 unnamed Event .
-
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx
- """
- return windll.kernel32.CreateEventA(pointer(SECURITY_ATTRIBUTES()), BOOL(True), BOOL(False), None)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/__init__.py
deleted file mode 100644
index d3f14efc1c..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/__init__.py
+++ /dev/null
@@ -1,36 +0,0 @@
-"""
-Filters decide whether something is active or not (they decide about a boolean
-state). This is used to enable/disable features, like key bindings, parts of
-the layout and other stuff. For instance, we could have a `HasSearch` filter
-attached to some part of the layout, in order to show that part of the user
-interface only while the user is searching.
-
-Filters are made to avoid having to attach callbacks to all event in order to
-propagate state. However, they are lazy, they don't automatically propagate the
-state of what they are observing. Only when a filter is called (it's actually a
-callable), it will calculate its value. So, its not really reactive
-programming, but it's made to fit for this framework.
-
-One class of filters observe a `CommandLineInterface` instance. However, they
-are not attached to such an instance. (We have to pass this instance to the
-filter when calling it.) The reason for this is to allow declarative
-programming: for key bindings, we can attach a filter to a key binding without
-knowing yet which `CommandLineInterface` instance it will observe in the end.
-Examples are `HasSearch` or `IsExiting`.
-
-Another class of filters doesn't take anything as input. And a third class of
-filters are universal, for instance `Always` and `Never`.
-It is impossible to mix the first and the second class, because that would mean
-mixing filters with a different signature.
-
-Filters can be chained using ``&`` and ``|`` operations, and inverted using the
-``~`` operator, for instance::
-
- filter = HasFocus('default') & ~ HasSelection()
-"""
-from __future__ import unicode_literals
-
-from .base import *
-from .cli import *
-from .types import *
-from .utils import *
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/base.py
deleted file mode 100644
index 6a1a1d0b10..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/base.py
+++ /dev/null
@@ -1,234 +0,0 @@
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-
-from prompt_toolkit.utils import test_callable_args
-
-
-__all__ = (
- 'Filter',
- 'Never',
- 'Always',
- 'Condition',
-)
-
-
-class Filter(with_metaclass(ABCMeta, object)):
- """
- Filter to activate/deactivate a feature, depending on a condition.
- The return value of ``__call__`` will tell if the feature should be active.
- """
- @abstractmethod
- def __call__(self, *a, **kw):
- """
- The actual call to evaluate the filter.
- """
- return True
-
- def __and__(self, other):
- """
- Chaining of filters using the & operator.
- """
- return _and_cache[self, other]
-
- def __or__(self, other):
- """
- Chaining of filters using the | operator.
- """
- return _or_cache[self, other]
-
- def __invert__(self):
- """
- Inverting of filters using the ~ operator.
- """
- return _invert_cache[self]
-
- def __bool__(self):
- """
- By purpose, we don't allow bool(...) operations directly on a filter,
- because because the meaning is ambigue.
-
- Executing a filter has to be done always by calling it. Providing
- defaults for `None` values should be done through an `is None` check
- instead of for instance ``filter1 or Always()``.
- """
- raise TypeError
-
- __nonzero__ = __bool__ # For Python 2.
-
- def test_args(self, *args):
- """
- Test whether this filter can be called with the following argument list.
- """
- return test_callable_args(self.__call__, args)
-
-
-class _AndCache(dict):
- """
- Cache for And operation between filters.
- (Filter classes are stateless, so we can reuse them.)
-
- Note: This could be a memory leak if we keep creating filters at runtime.
- If that is True, the filters should be weakreffed (not the tuple of
- filters), and tuples should be removed when one of these filters is
- removed. In practise however, there is a finite amount of filters.
- """
- def __missing__(self, filters):
- a, b = filters
- assert isinstance(b, Filter), 'Expecting filter, got %r' % b
-
- if isinstance(b, Always) or isinstance(a, Never):
- return a
- elif isinstance(b, Never) or isinstance(a, Always):
- return b
-
- result = _AndList(filters)
- self[filters] = result
- return result
-
-
-class _OrCache(dict):
- """ Cache for Or operation between filters. """
- def __missing__(self, filters):
- a, b = filters
- assert isinstance(b, Filter), 'Expecting filter, got %r' % b
-
- if isinstance(b, Always) or isinstance(a, Never):
- return b
- elif isinstance(b, Never) or isinstance(a, Always):
- return a
-
- result = _OrList(filters)
- self[filters] = result
- return result
-
-
-class _InvertCache(dict):
- """ Cache for inversion operator. """
- def __missing__(self, filter):
- result = _Invert(filter)
- self[filter] = result
- return result
-
-
-_and_cache = _AndCache()
-_or_cache = _OrCache()
-_invert_cache = _InvertCache()
-
-
-class _AndList(Filter):
- """
- Result of &-operation between several filters.
- """
- def __init__(self, filters):
- all_filters = []
-
- for f in filters:
- if isinstance(f, _AndList): # Turn nested _AndLists into one.
- all_filters.extend(f.filters)
- else:
- all_filters.append(f)
-
- self.filters = all_filters
-
- def test_args(self, *args):
- return all(f.test_args(*args) for f in self.filters)
-
- def __call__(self, *a, **kw):
- return all(f(*a, **kw) for f in self.filters)
-
- def __repr__(self):
- return '&'.join(repr(f) for f in self.filters)
-
-
-class _OrList(Filter):
- """
- Result of |-operation between several filters.
- """
- def __init__(self, filters):
- all_filters = []
-
- for f in filters:
- if isinstance(f, _OrList): # Turn nested _OrLists into one.
- all_filters.extend(f.filters)
- else:
- all_filters.append(f)
-
- self.filters = all_filters
-
- def test_args(self, *args):
- return all(f.test_args(*args) for f in self.filters)
-
- def __call__(self, *a, **kw):
- return any(f(*a, **kw) for f in self.filters)
-
- def __repr__(self):
- return '|'.join(repr(f) for f in self.filters)
-
-
-class _Invert(Filter):
- """
- Negation of another filter.
- """
- def __init__(self, filter):
- self.filter = filter
-
- def __call__(self, *a, **kw):
- return not self.filter(*a, **kw)
-
- def __repr__(self):
- return '~%r' % self.filter
-
- def test_args(self, *args):
- return self.filter.test_args(*args)
-
-
-class Always(Filter):
- """
- Always enable feature.
- """
- def __call__(self, *a, **kw):
- return True
-
- def __invert__(self):
- return Never()
-
-
-class Never(Filter):
- """
- Never enable feature.
- """
- def __call__(self, *a, **kw):
- return False
-
- def __invert__(self):
- return Always()
-
-
-class Condition(Filter):
- """
- Turn any callable (which takes a cli and returns a boolean) into a Filter.
-
- This can be used as a decorator::
-
- @Condition
- def feature_is_active(cli): # `feature_is_active` becomes a Filter.
- return True
-
- :param func: Callable which takes either a
- :class:`~prompt_toolkit.interface.CommandLineInterface` or nothing and
- returns a boolean. (Depending on what it takes, this will become a
- :class:`.Filter` or :class:`~prompt_toolkit.filters.CLIFilter`.)
- """
- def __init__(self, func):
- assert callable(func)
- self.func = func
-
- def __call__(self, *a, **kw):
- return self.func(*a, **kw)
-
- def __repr__(self):
- return 'Condition(%r)' % self.func
-
- def test_args(self, *a):
- return test_callable_args(self.func, a)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/cli.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/cli.py
deleted file mode 100644
index c0b07317be..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/cli.py
+++ /dev/null
@@ -1,395 +0,0 @@
-"""
-Filters that accept a `CommandLineInterface` as argument.
-"""
-from __future__ import unicode_literals
-from .base import Filter
-from prompt_toolkit.enums import EditingMode
-from prompt_toolkit.key_binding.vi_state import InputMode as ViInputMode
-from prompt_toolkit.cache import memoized
-
-__all__ = (
- 'HasArg',
- 'HasCompletions',
- 'HasFocus',
- 'InFocusStack',
- 'HasSearch',
- 'HasSelection',
- 'HasValidationError',
- 'IsAborting',
- 'IsDone',
- 'IsMultiline',
- 'IsReadOnly',
- 'IsReturning',
- 'RendererHeightIsKnown',
- 'InEditingMode',
-
- # Vi modes.
- 'ViMode',
- 'ViNavigationMode',
- 'ViInsertMode',
- 'ViInsertMultipleMode',
- 'ViReplaceMode',
- 'ViSelectionMode',
- 'ViWaitingForTextObjectMode',
- 'ViDigraphMode',
-
- # Emacs modes.
- 'EmacsMode',
- 'EmacsInsertMode',
- 'EmacsSelectionMode',
-)
-
-
-@memoized()
-class HasFocus(Filter):
- """
- Enable when this buffer has the focus.
- """
- def __init__(self, buffer_name):
- self._buffer_name = buffer_name
-
- @property
- def buffer_name(self):
- " The given buffer name. (Read-only) "
- return self._buffer_name
-
- def __call__(self, cli):
- return cli.current_buffer_name == self.buffer_name
-
- def __repr__(self):
- return 'HasFocus(%r)' % self.buffer_name
-
-
-@memoized()
-class InFocusStack(Filter):
- """
- Enable when this buffer appears on the focus stack.
- """
- def __init__(self, buffer_name):
- self._buffer_name = buffer_name
-
- @property
- def buffer_name(self):
- " The given buffer name. (Read-only) "
- return self._buffer_name
-
- def __call__(self, cli):
- return self.buffer_name in cli.buffers.focus_stack
-
- def __repr__(self):
- return 'InFocusStack(%r)' % self.buffer_name
-
-
-@memoized()
-class HasSelection(Filter):
- """
- Enable when the current buffer has a selection.
- """
- def __call__(self, cli):
- return bool(cli.current_buffer.selection_state)
-
- def __repr__(self):
- return 'HasSelection()'
-
-
-@memoized()
-class HasCompletions(Filter):
- """
- Enable when the current buffer has completions.
- """
- def __call__(self, cli):
- return cli.current_buffer.complete_state is not None
-
- def __repr__(self):
- return 'HasCompletions()'
-
-
-@memoized()
-class IsMultiline(Filter):
- """
- Enable in multiline mode.
- """
- def __call__(self, cli):
- return cli.current_buffer.is_multiline()
-
- def __repr__(self):
- return 'IsMultiline()'
-
-
-@memoized()
-class IsReadOnly(Filter):
- """
- True when the current buffer is read only.
- """
- def __call__(self, cli):
- return cli.current_buffer.read_only()
-
- def __repr__(self):
- return 'IsReadOnly()'
-
-
-@memoized()
-class HasValidationError(Filter):
- """
- Current buffer has validation error.
- """
- def __call__(self, cli):
- return cli.current_buffer.validation_error is not None
-
- def __repr__(self):
- return 'HasValidationError()'
-
-
-@memoized()
-class HasArg(Filter):
- """
- Enable when the input processor has an 'arg'.
- """
- def __call__(self, cli):
- return cli.input_processor.arg is not None
-
- def __repr__(self):
- return 'HasArg()'
-
-
-@memoized()
-class HasSearch(Filter):
- """
- Incremental search is active.
- """
- def __call__(self, cli):
- return cli.is_searching
-
- def __repr__(self):
- return 'HasSearch()'
-
-
-@memoized()
-class IsReturning(Filter):
- """
- When a return value has been set.
- """
- def __call__(self, cli):
- return cli.is_returning
-
- def __repr__(self):
- return 'IsReturning()'
-
-
-@memoized()
-class IsAborting(Filter):
- """
- True when aborting. (E.g. Control-C pressed.)
- """
- def __call__(self, cli):
- return cli.is_aborting
-
- def __repr__(self):
- return 'IsAborting()'
-
-
-@memoized()
-class IsExiting(Filter):
- """
- True when exiting. (E.g. Control-D pressed.)
- """
- def __call__(self, cli):
- return cli.is_exiting
-
- def __repr__(self):
- return 'IsExiting()'
-
-
-@memoized()
-class IsDone(Filter):
- """
- True when the CLI is returning, aborting or exiting.
- """
- def __call__(self, cli):
- return cli.is_done
-
- def __repr__(self):
- return 'IsDone()'
-
-
-@memoized()
-class RendererHeightIsKnown(Filter):
- """
- Only True when the renderer knows it's real height.
-
- (On VT100 terminals, we have to wait for a CPR response, before we can be
- sure of the available height between the cursor position and the bottom of
- the terminal. And usually it's nicer to wait with drawing bottom toolbars
- until we receive the height, in order to avoid flickering -- first drawing
- somewhere in the middle, and then again at the bottom.)
- """
- def __call__(self, cli):
- return cli.renderer.height_is_known
-
- def __repr__(self):
- return 'RendererHeightIsKnown()'
-
-
-@memoized()
-class InEditingMode(Filter):
- """
- Check whether a given editing mode is active. (Vi or Emacs.)
- """
- def __init__(self, editing_mode):
- self._editing_mode = editing_mode
-
- @property
- def editing_mode(self):
- " The given editing mode. (Read-only) "
- return self._editing_mode
-
- def __call__(self, cli):
- return cli.editing_mode == self.editing_mode
-
- def __repr__(self):
- return 'InEditingMode(%r)' % (self.editing_mode, )
-
-
-@memoized()
-class ViMode(Filter):
- def __call__(self, cli):
- return cli.editing_mode == EditingMode.VI
-
- def __repr__(self):
- return 'ViMode()'
-
-
-@memoized()
-class ViNavigationMode(Filter):
- """
- Active when the set for Vi navigation key bindings are active.
- """
- def __call__(self, cli):
- if (cli.editing_mode != EditingMode.VI
- or cli.vi_state.operator_func
- or cli.vi_state.waiting_for_digraph
- or cli.current_buffer.selection_state):
- return False
-
- return (cli.vi_state.input_mode == ViInputMode.NAVIGATION or
- cli.current_buffer.read_only())
-
- def __repr__(self):
- return 'ViNavigationMode()'
-
-
-@memoized()
-class ViInsertMode(Filter):
- def __call__(self, cli):
- if (cli.editing_mode != EditingMode.VI
- or cli.vi_state.operator_func
- or cli.vi_state.waiting_for_digraph
- or cli.current_buffer.selection_state
- or cli.current_buffer.read_only()):
- return False
-
- return cli.vi_state.input_mode == ViInputMode.INSERT
-
- def __repr__(self):
- return 'ViInputMode()'
-
-
-@memoized()
-class ViInsertMultipleMode(Filter):
- def __call__(self, cli):
- if (cli.editing_mode != EditingMode.VI
- or cli.vi_state.operator_func
- or cli.vi_state.waiting_for_digraph
- or cli.current_buffer.selection_state
- or cli.current_buffer.read_only()):
- return False
-
- return cli.vi_state.input_mode == ViInputMode.INSERT_MULTIPLE
-
- def __repr__(self):
- return 'ViInsertMultipleMode()'
-
-
-@memoized()
-class ViReplaceMode(Filter):
- def __call__(self, cli):
- if (cli.editing_mode != EditingMode.VI
- or cli.vi_state.operator_func
- or cli.vi_state.waiting_for_digraph
- or cli.current_buffer.selection_state
- or cli.current_buffer.read_only()):
- return False
-
- return cli.vi_state.input_mode == ViInputMode.REPLACE
-
- def __repr__(self):
- return 'ViReplaceMode()'
-
-
-@memoized()
-class ViSelectionMode(Filter):
- def __call__(self, cli):
- if cli.editing_mode != EditingMode.VI:
- return False
-
- return bool(cli.current_buffer.selection_state)
-
- def __repr__(self):
- return 'ViSelectionMode()'
-
-
-@memoized()
-class ViWaitingForTextObjectMode(Filter):
- def __call__(self, cli):
- if cli.editing_mode != EditingMode.VI:
- return False
-
- return cli.vi_state.operator_func is not None
-
- def __repr__(self):
- return 'ViWaitingForTextObjectMode()'
-
-
-@memoized()
-class ViDigraphMode(Filter):
- def __call__(self, cli):
- if cli.editing_mode != EditingMode.VI:
- return False
-
- return cli.vi_state.waiting_for_digraph
-
- def __repr__(self):
- return 'ViDigraphMode()'
-
-
-@memoized()
-class EmacsMode(Filter):
- " When the Emacs bindings are active. "
- def __call__(self, cli):
- return cli.editing_mode == EditingMode.EMACS
-
- def __repr__(self):
- return 'EmacsMode()'
-
-
-@memoized()
-class EmacsInsertMode(Filter):
- def __call__(self, cli):
- if (cli.editing_mode != EditingMode.EMACS
- or cli.current_buffer.selection_state
- or cli.current_buffer.read_only()):
- return False
- return True
-
- def __repr__(self):
- return 'EmacsInsertMode()'
-
-
-@memoized()
-class EmacsSelectionMode(Filter):
- def __call__(self, cli):
- return (cli.editing_mode == EditingMode.EMACS
- and cli.current_buffer.selection_state)
-
- def __repr__(self):
- return 'EmacsSelectionMode()'
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/types.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/types.py
deleted file mode 100644
index 3e89c39c01..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/types.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from __future__ import unicode_literals
-from six import with_metaclass
-from collections import defaultdict
-import weakref
-
-__all__ = (
- 'CLIFilter',
- 'SimpleFilter',
-)
-
-# Cache for _FilterTypeMeta. (Don't test the same __instancecheck__ twice as
-# long as the object lives. -- We do this a lot and calling 'test_args' is
-# expensive.)
-_instance_check_cache = defaultdict(weakref.WeakKeyDictionary)
-
-
-class _FilterTypeMeta(type):
- def __instancecheck__(cls, instance):
- cache = _instance_check_cache[tuple(cls.arguments_list)]
-
- def get():
- " The actual test. "
- if not hasattr(instance, 'test_args'):
- return False
- return instance.test_args(*cls.arguments_list)
-
- try:
- return cache[instance]
- except KeyError:
- result = get()
- cache[instance] = result
- return result
-
-
-class _FilterType(with_metaclass(_FilterTypeMeta)):
- def __new__(cls):
- raise NotImplementedError('This class should not be initiated.')
-
-
-class CLIFilter(_FilterType):
- """
- Abstract base class for filters that accept a
- :class:`~prompt_toolkit.interface.CommandLineInterface` argument. It cannot
- be instantiated, it's only to be used for instance assertions, e.g.::
-
- isinstance(my_filter, CliFilter)
- """
- arguments_list = ['cli']
-
-
-class SimpleFilter(_FilterType):
- """
- Abstract base class for filters that don't accept any arguments.
- """
- arguments_list = []
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/utils.py
deleted file mode 100644
index 836d2956e7..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/utils.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from __future__ import unicode_literals
-from .base import Always, Never
-from .types import SimpleFilter, CLIFilter
-
-__all__ = (
- 'to_cli_filter',
- 'to_simple_filter',
-)
-
-_always = Always()
-_never = Never()
-
-
-def to_simple_filter(bool_or_filter):
- """
- Accept both booleans and CLIFilters as input and
- turn it into a SimpleFilter.
- """
- if not isinstance(bool_or_filter, (bool, SimpleFilter)):
- raise TypeError('Expecting a bool or a SimpleFilter instance. Got %r' % bool_or_filter)
-
- return {
- True: _always,
- False: _never,
- }.get(bool_or_filter, bool_or_filter)
-
-
-def to_cli_filter(bool_or_filter):
- """
- Accept both booleans and CLIFilters as input and
- turn it into a CLIFilter.
- """
- if not isinstance(bool_or_filter, (bool, CLIFilter)):
- raise TypeError('Expecting a bool or a CLIFilter instance. Got %r' % bool_or_filter)
-
- return {
- True: _always,
- False: _never,
- }.get(bool_or_filter, bool_or_filter)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/history.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/history.py
deleted file mode 100644
index d1eb5f2730..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/history.py
+++ /dev/null
@@ -1,120 +0,0 @@
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-
-import datetime
-import os
-
-__all__ = (
- 'FileHistory',
- 'History',
- 'InMemoryHistory',
-)
-
-
-class History(with_metaclass(ABCMeta, object)):
- """
- Base ``History`` interface.
- """
- @abstractmethod
- def append(self, string):
- " Append string to history. "
-
- @abstractmethod
- def __getitem__(self, key):
- " Return one item of the history. It should be accessible like a `list`. "
-
- @abstractmethod
- def __iter__(self):
- " Iterate through all the items of the history. Cronologically. "
-
- @abstractmethod
- def __len__(self):
- " Return the length of the history. "
-
- def __bool__(self):
- """
- Never evaluate to False, even when the history is empty.
- (Python calls __len__ if __bool__ is not implemented.)
- This is mainly to allow lazy evaluation::
-
- x = history or InMemoryHistory()
- """
- return True
-
- __nonzero__ = __bool__ # For Python 2.
-
-
-class InMemoryHistory(History):
- """
- :class:`.History` class that keeps a list of all strings in memory.
- """
- def __init__(self):
- self.strings = []
-
- def append(self, string):
- self.strings.append(string)
-
- def __getitem__(self, key):
- return self.strings[key]
-
- def __iter__(self):
- return iter(self.strings)
-
- def __len__(self):
- return len(self.strings)
-
-
-class FileHistory(History):
- """
- :class:`.History` class that stores all strings in a file.
- """
- def __init__(self, filename):
- self.strings = []
- self.filename = filename
-
- self._load()
-
- def _load(self):
- lines = []
-
- def add():
- if lines:
- # Join and drop trailing newline.
- string = ''.join(lines)[:-1]
-
- self.strings.append(string)
-
- if os.path.exists(self.filename):
- with open(self.filename, 'rb') as f:
- for line in f:
- line = line.decode('utf-8')
-
- if line.startswith('+'):
- lines.append(line[1:])
- else:
- add()
- lines = []
-
- add()
-
- def append(self, string):
- self.strings.append(string)
-
- # Save to file.
- with open(self.filename, 'ab') as f:
- def write(t):
- f.write(t.encode('utf-8'))
-
- write('\n# %s\n' % datetime.datetime.now())
- for line in string.split('\n'):
- write('+%s\n' % line)
-
- def __getitem__(self, key):
- return self.strings[key]
-
- def __iter__(self):
- return iter(self.strings)
-
- def __len__(self):
- return len(self.strings)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/input.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/input.py
deleted file mode 100644
index f123732560..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/input.py
+++ /dev/null
@@ -1,135 +0,0 @@
-"""
-Abstraction of CLI Input.
-"""
-from __future__ import unicode_literals
-
-from .utils import DummyContext, is_windows
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-
-import io
-import os
-import sys
-
-if is_windows():
- from .terminal.win32_input import raw_mode, cooked_mode
-else:
- from .terminal.vt100_input import raw_mode, cooked_mode
-
-__all__ = (
- 'Input',
- 'StdinInput',
- 'PipeInput',
-)
-
-
-class Input(with_metaclass(ABCMeta, object)):
- """
- Abstraction for any input.
-
- An instance of this class can be given to the constructor of a
- :class:`~prompt_toolkit.interface.CommandLineInterface` and will also be
- passed to the :class:`~prompt_toolkit.eventloop.base.EventLoop`.
- """
- @abstractmethod
- def fileno(self):
- """
- Fileno for putting this in an event loop.
- """
-
- @abstractmethod
- def read(self):
- """
- Return text from the input.
- """
-
- @abstractmethod
- def raw_mode(self):
- """
- Context manager that turns the input into raw mode.
- """
-
- @abstractmethod
- def cooked_mode(self):
- """
- Context manager that turns the input into cooked mode.
- """
-
-
-class StdinInput(Input):
- """
- Simple wrapper around stdin.
- """
- def __init__(self, stdin=None):
- self.stdin = stdin or sys.stdin
-
- # The input object should be a TTY.
- assert self.stdin.isatty()
-
- # Test whether the given input object has a file descriptor.
- # (Idle reports stdin to be a TTY, but fileno() is not implemented.)
- try:
- # This should not raise, but can return 0.
- self.stdin.fileno()
- except io.UnsupportedOperation:
- if 'idlelib.run' in sys.modules:
- raise io.UnsupportedOperation(
- 'Stdin is not a terminal. Running from Idle is not supported.')
- else:
- raise io.UnsupportedOperation('Stdin is not a terminal.')
-
- def __repr__(self):
- return 'StdinInput(stdin=%r)' % (self.stdin,)
-
- def raw_mode(self):
- return raw_mode(self.stdin.fileno())
-
- def cooked_mode(self):
- return cooked_mode(self.stdin.fileno())
-
- def fileno(self):
- return self.stdin.fileno()
-
- def read(self):
- return self.stdin.read()
-
-
-class PipeInput(Input):
- """
- Input that is send through a pipe.
- This is useful if we want to send the input programatically into the
- interface, but still use the eventloop.
-
- Usage::
-
- input = PipeInput()
- input.send('inputdata')
- """
- def __init__(self):
- self._r, self._w = os.pipe()
-
- def fileno(self):
- return self._r
-
- def read(self):
- return os.read(self._r)
-
- def send_text(self, data):
- " Send text to the input. "
- os.write(self._w, data.encode('utf-8'))
-
- # Deprecated alias for `send_text`.
- send = send_text
-
- def raw_mode(self):
- return DummyContext()
-
- def cooked_mode(self):
- return DummyContext()
-
- def close(self):
- " Close pipe fds. "
- os.close(self._r)
- os.close(self._w)
- self._r = None
- self._w = None
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py
deleted file mode 100644
index e1e0e56393..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py
+++ /dev/null
@@ -1,1190 +0,0 @@
-"""
-The main `CommandLineInterface` class and logic.
-"""
-from __future__ import unicode_literals
-
-import functools
-import os
-import signal
-import six
-import sys
-import textwrap
-import threading
-import time
-import types
-import weakref
-
-from subprocess import Popen
-
-from .application import Application, AbortAction
-from .buffer import Buffer
-from .buffer_mapping import BufferMapping
-from .completion import CompleteEvent, get_common_complete_suffix
-from .enums import SEARCH_BUFFER
-from .eventloop.base import EventLoop
-from .eventloop.callbacks import EventLoopCallbacks
-from .filters import Condition
-from .input import StdinInput, Input
-from .key_binding.input_processor import InputProcessor
-from .key_binding.input_processor import KeyPress
-from .key_binding.registry import Registry
-from .key_binding.vi_state import ViState
-from .keys import Keys
-from .output import Output
-from .renderer import Renderer, print_tokens
-from .search_state import SearchState
-from .utils import Event
-
-# Following import is required for backwards compatibility.
-from .buffer import AcceptAction
-
-__all__ = (
- 'AbortAction',
- 'CommandLineInterface',
-)
-
-
-class CommandLineInterface(object):
- """
- Wrapper around all the other classes, tying everything together.
-
- Typical usage::
-
- application = Application(...)
- cli = CommandLineInterface(application, eventloop)
- result = cli.run()
- print(result)
-
- :param application: :class:`~prompt_toolkit.application.Application` instance.
- :param eventloop: The :class:`~prompt_toolkit.eventloop.base.EventLoop` to
- be used when `run` is called. The easiest way to create
- an eventloop is by calling
- :meth:`~prompt_toolkit.shortcuts.create_eventloop`.
- :param input: :class:`~prompt_toolkit.input.Input` instance.
- :param output: :class:`~prompt_toolkit.output.Output` instance. (Probably
- Vt100_Output or Win32Output.)
- """
- def __init__(self, application, eventloop=None, input=None, output=None):
- assert isinstance(application, Application)
- assert isinstance(eventloop, EventLoop), 'Passing an eventloop is required.'
- assert output is None or isinstance(output, Output)
- assert input is None or isinstance(input, Input)
-
- from .shortcuts import create_output
-
- self.application = application
- self.eventloop = eventloop
- self._is_running = False
-
- # Inputs and outputs.
- self.output = output or create_output()
- self.input = input or StdinInput(sys.stdin)
-
- #: The input buffers.
- assert isinstance(application.buffers, BufferMapping)
- self.buffers = application.buffers
-
- #: EditingMode.VI or EditingMode.EMACS
- self.editing_mode = application.editing_mode
-
- #: Quoted insert. This flag is set if we go into quoted insert mode.
- self.quoted_insert = False
-
- #: Vi state. (For Vi key bindings.)
- self.vi_state = ViState()
-
- #: The `Renderer` instance.
- # Make sure that the same stdout is used, when a custom renderer has been passed.
- self.renderer = Renderer(
- self.application.style,
- self.output,
- use_alternate_screen=application.use_alternate_screen,
- mouse_support=application.mouse_support)
-
- #: Render counter. This one is increased every time the UI is rendered.
- #: It can be used as a key for caching certain information during one
- #: rendering.
- self.render_counter = 0
-
- #: When there is high CPU, postpone the renderering max x seconds.
- #: '0' means: don't postpone. '.5' means: try to draw at least twice a second.
- self.max_render_postpone_time = 0 # E.g. .5
-
- # Invalidate flag. When 'True', a repaint has been scheduled.
- self._invalidated = False
-
- #: The `InputProcessor` instance.
- self.input_processor = InputProcessor(application.key_bindings_registry, weakref.ref(self))
-
- self._async_completers = {} # Map buffer name to completer function.
-
- # Pointer to sub CLI. (In chain of CLI instances.)
- self._sub_cli = None # None or other CommandLineInterface instance.
-
- # Call `add_buffer` for each buffer.
- for name, b in self.buffers.items():
- self.add_buffer(name, b)
-
- # Events.
- self.on_buffer_changed = Event(self, application.on_buffer_changed)
- self.on_initialize = Event(self, application.on_initialize)
- self.on_input_timeout = Event(self, application.on_input_timeout)
- self.on_invalidate = Event(self, application.on_invalidate)
- self.on_render = Event(self, application.on_render)
- self.on_reset = Event(self, application.on_reset)
- self.on_start = Event(self, application.on_start)
- self.on_stop = Event(self, application.on_stop)
-
- # Trigger initialize callback.
- self.reset()
- self.on_initialize += self.application.on_initialize
- self.on_initialize.fire()
-
- @property
- def layout(self):
- return self.application.layout
-
- @property
- def clipboard(self):
- return self.application.clipboard
-
- @property
- def pre_run_callables(self):
- return self.application.pre_run_callables
-
- def add_buffer(self, name, buffer, focus=False):
- """
- Insert a new buffer.
- """
- assert isinstance(buffer, Buffer)
- self.buffers[name] = buffer
-
- if focus:
- self.buffers.focus(name)
-
- # Create asynchronous completer / auto suggestion.
- auto_suggest_function = self._create_auto_suggest_function(buffer)
- completer_function = self._create_async_completer(buffer)
- self._async_completers[name] = completer_function
-
- # Complete/suggest on text insert.
- def create_on_insert_handler():
- """
- Wrapper around the asynchronous completer and auto suggestion, that
- ensures that it's only called while typing if the
- `complete_while_typing` filter is enabled.
- """
- def on_text_insert(_):
- # Only complete when "complete_while_typing" is enabled.
- if buffer.completer and buffer.complete_while_typing():
- completer_function()
-
- # Call auto_suggest.
- if buffer.auto_suggest:
- auto_suggest_function()
-
- return on_text_insert
-
- buffer.on_text_insert += create_on_insert_handler()
-
- def buffer_changed(_):
- """
- When the text in a buffer changes.
- (A paste event is also a change, but not an insert. So we don't
- want to do autocompletions in this case, but we want to propagate
- the on_buffer_changed event.)
- """
- # Trigger on_buffer_changed.
- self.on_buffer_changed.fire()
-
- buffer.on_text_changed += buffer_changed
-
- def start_completion(self, buffer_name=None, select_first=False,
- select_last=False, insert_common_part=False,
- complete_event=None):
- """
- Start asynchronous autocompletion of this buffer.
- (This will do nothing if a previous completion was still in progress.)
- """
- buffer_name = buffer_name or self.current_buffer_name
- completer = self._async_completers.get(buffer_name)
-
- if completer:
- completer(select_first=select_first,
- select_last=select_last,
- insert_common_part=insert_common_part,
- complete_event=CompleteEvent(completion_requested=True))
-
- @property
- def current_buffer_name(self):
- """
- The name of the current :class:`.Buffer`. (Or `None`.)
- """
- return self.buffers.current_name(self)
-
- @property
- def current_buffer(self):
- """
- The currently focussed :class:`~.Buffer`.
-
- (This returns a dummy :class:`.Buffer` when none of the actual buffers
- has the focus. In this case, it's really not practical to check for
- `None` values or catch exceptions every time.)
- """
- return self.buffers.current(self)
-
- def focus(self, buffer_name):
- """
- Focus the buffer with the given name on the focus stack.
- """
- self.buffers.focus(self, buffer_name)
-
- def push_focus(self, buffer_name):
- """
- Push to the focus stack.
- """
- self.buffers.push_focus(self, buffer_name)
-
- def pop_focus(self):
- """
- Pop from the focus stack.
- """
- self.buffers.pop_focus(self)
-
- @property
- def terminal_title(self):
- """
- Return the current title to be displayed in the terminal.
- When this in `None`, the terminal title remains the original.
- """
- result = self.application.get_title()
-
- # Make sure that this function returns a unicode object,
- # and not a byte string.
- assert result is None or isinstance(result, six.text_type)
- return result
-
- @property
- def is_searching(self):
- """
- True when we are searching.
- """
- return self.current_buffer_name == SEARCH_BUFFER
-
- def reset(self, reset_current_buffer=False):
- """
- Reset everything, for reading the next input.
-
- :param reset_current_buffer: XXX: not used anymore. The reason for
- having this option in the past was when this CommandLineInterface
- is run multiple times, that we could reset the buffer content from
- the previous run. This is now handled in the AcceptAction.
- """
- # Notice that we don't reset the buffers. (This happens just before
- # returning, and when we have multiple buffers, we clearly want the
- # content in the other buffers to remain unchanged between several
- # calls of `run`. (And the same is true for the focus stack.)
-
- self._exit_flag = False
- self._abort_flag = False
-
- self._return_value = None
-
- self.renderer.reset()
- self.input_processor.reset()
- self.layout.reset()
- self.vi_state.reset()
-
- # Search new search state. (Does also remember what has to be
- # highlighted.)
- self.search_state = SearchState(ignore_case=Condition(lambda: self.is_ignoring_case))
-
- # Trigger reset event.
- self.on_reset.fire()
-
- @property
- def in_paste_mode(self):
- """ True when we are in paste mode. """
- return self.application.paste_mode(self)
-
- @property
- def is_ignoring_case(self):
- """ True when we currently ignore casing. """
- return self.application.ignore_case(self)
-
- def invalidate(self):
- """
- Thread safe way of sending a repaint trigger to the input event loop.
- """
- # Never schedule a second redraw, when a previous one has not yet been
- # executed. (This should protect against other threads calling
- # 'invalidate' many times, resulting in 100% CPU.)
- if self._invalidated:
- return
- else:
- self._invalidated = True
-
- # Trigger event.
- self.on_invalidate.fire()
-
- if self.eventloop is not None:
- def redraw():
- self._invalidated = False
- self._redraw()
-
- # Call redraw in the eventloop (thread safe).
- # Usually with the high priority, in order to make the application
- # feel responsive, but this can be tuned by changing the value of
- # `max_render_postpone_time`.
- if self.max_render_postpone_time:
- _max_postpone_until = time.time() + self.max_render_postpone_time
- else:
- _max_postpone_until = None
-
- self.eventloop.call_from_executor(
- redraw, _max_postpone_until=_max_postpone_until)
-
- # Depracated alias for 'invalidate'.
- request_redraw = invalidate
-
- def _redraw(self):
- """
- Render the command line again. (Not thread safe!) (From other threads,
- or if unsure, use :meth:`.CommandLineInterface.invalidate`.)
- """
- # Only draw when no sub application was started.
- if self._is_running and self._sub_cli is None:
- self.render_counter += 1
- self.renderer.render(self, self.layout, is_done=self.is_done)
-
- # Fire render event.
- self.on_render.fire()
-
- def _on_resize(self):
- """
- When the window size changes, we erase the current output and request
- again the cursor position. When the CPR answer arrives, the output is
- drawn again.
- """
- # Erase, request position (when cursor is at the start position)
- # and redraw again. -- The order is important.
- self.renderer.erase(leave_alternate_screen=False, erase_title=False)
- self.renderer.request_absolute_cursor_position()
- self._redraw()
-
- def _load_next_buffer_indexes(self):
- for buff, index in self._next_buffer_indexes.items():
- if buff in self.buffers:
- self.buffers[buff].working_index = index
-
- def _pre_run(self, pre_run=None):
- " Called during `run`. "
- if pre_run:
- pre_run()
-
- # Process registered "pre_run_callables" and clear list.
- for c in self.pre_run_callables:
- c()
- del self.pre_run_callables[:]
-
- def run(self, reset_current_buffer=False, pre_run=None):
- """
- Read input from the command line.
- This runs the eventloop until a return value has been set.
-
- :param reset_current_buffer: XXX: Not used anymore.
- :param pre_run: Callable that is called right after the reset has taken
- place. This allows custom initialisation.
- """
- assert pre_run is None or callable(pre_run)
-
- try:
- self._is_running = True
-
- self.on_start.fire()
- self.reset()
-
- # Call pre_run.
- self._pre_run(pre_run)
-
- # Run eventloop in raw mode.
- with self.input.raw_mode():
- self.renderer.request_absolute_cursor_position()
- self._redraw()
-
- self.eventloop.run(self.input, self.create_eventloop_callbacks())
- finally:
- # Clean up renderer. (This will leave the alternate screen, if we use
- # that.)
-
- # If exit/abort haven't been called set, but another exception was
- # thrown instead for some reason, make sure that we redraw in exit
- # mode.
- if not self.is_done:
- self._exit_flag = True
- self._redraw()
-
- self.renderer.reset()
- self.on_stop.fire()
- self._is_running = False
-
- # Return result.
- return self.return_value()
-
- try:
- # The following `run_async` function is compiled at runtime
- # because it contains syntax which is not supported on older Python
- # versions. (A 'return' inside a generator.)
- six.exec_(textwrap.dedent('''
- def run_async(self, reset_current_buffer=True, pre_run=None):
- """
- Same as `run`, but this returns a coroutine.
-
- This is only available on Python >3.3, with asyncio.
- """
- # Inline import, because it slows down startup when asyncio is not
- # needed.
- import asyncio
-
- @asyncio.coroutine
- def run():
- assert pre_run is None or callable(pre_run)
-
- try:
- self._is_running = True
-
- self.on_start.fire()
- self.reset()
-
- # Call pre_run.
- self._pre_run(pre_run)
-
- with self.input.raw_mode():
- self.renderer.request_absolute_cursor_position()
- self._redraw()
-
- yield from self.eventloop.run_as_coroutine(
- self.input, self.create_eventloop_callbacks())
-
- return self.return_value()
- finally:
- if not self.is_done:
- self._exit_flag = True
- self._redraw()
-
- self.renderer.reset()
- self.on_stop.fire()
- self._is_running = False
-
- return run()
- '''))
- except SyntaxError:
- # Python2, or early versions of Python 3.
- def run_async(self, reset_current_buffer=True, pre_run=None):
- """
- Same as `run`, but this returns a coroutine.
-
- This is only available on Python >3.3, with asyncio.
- """
- raise NotImplementedError
-
- def run_sub_application(self, application, done_callback=None, erase_when_done=False,
- _from_application_generator=False):
- # `erase_when_done` is deprecated, set Application.erase_when_done instead.
- """
- Run a sub :class:`~prompt_toolkit.application.Application`.
-
- This will suspend the main application and display the sub application
- until that one returns a value. The value is returned by calling
- `done_callback` with the result.
-
- The sub application will share the same I/O of the main application.
- That means, it uses the same input and output channels and it shares
- the same event loop.
-
- .. note:: Technically, it gets another Eventloop instance, but that is
- only a proxy to our main event loop. The reason is that calling
- 'stop' --which returns the result of an application when it's
- done-- is handled differently.
- """
- assert isinstance(application, Application)
- assert done_callback is None or callable(done_callback)
-
- if self._sub_cli is not None:
- raise RuntimeError('Another sub application started already.')
-
- # Erase current application.
- if not _from_application_generator:
- self.renderer.erase()
-
- # Callback when the sub app is done.
- def done():
- # Redraw sub app in done state.
- # and reset the renderer. (This reset will also quit the alternate
- # screen, if the sub application used that.)
- sub_cli._redraw()
- if erase_when_done or application.erase_when_done:
- sub_cli.renderer.erase()
- sub_cli.renderer.reset()
- sub_cli._is_running = False # Don't render anymore.
-
- self._sub_cli = None
-
- # Restore main application.
- if not _from_application_generator:
- self.renderer.request_absolute_cursor_position()
- self._redraw()
-
- # Deliver result.
- if done_callback:
- done_callback(sub_cli.return_value())
-
- # Create sub CommandLineInterface.
- sub_cli = CommandLineInterface(
- application=application,
- eventloop=_SubApplicationEventLoop(self, done),
- input=self.input,
- output=self.output)
- sub_cli._is_running = True # Allow rendering of sub app.
-
- sub_cli._redraw()
- self._sub_cli = sub_cli
-
- def exit(self):
- """
- Set exit. When Control-D has been pressed.
- """
- on_exit = self.application.on_exit
- self._exit_flag = True
- self._redraw()
-
- if on_exit == AbortAction.RAISE_EXCEPTION:
- def eof_error():
- raise EOFError()
- self._set_return_callable(eof_error)
-
- elif on_exit == AbortAction.RETRY:
- self.reset()
- self.renderer.request_absolute_cursor_position()
- self.current_buffer.reset()
-
- elif on_exit == AbortAction.RETURN_NONE:
- self.set_return_value(None)
-
- def abort(self):
- """
- Set abort. When Control-C has been pressed.
- """
- on_abort = self.application.on_abort
- self._abort_flag = True
- self._redraw()
-
- if on_abort == AbortAction.RAISE_EXCEPTION:
- def keyboard_interrupt():
- raise KeyboardInterrupt()
- self._set_return_callable(keyboard_interrupt)
-
- elif on_abort == AbortAction.RETRY:
- self.reset()
- self.renderer.request_absolute_cursor_position()
- self.current_buffer.reset()
-
- elif on_abort == AbortAction.RETURN_NONE:
- self.set_return_value(None)
-
- # Deprecated aliase for exit/abort.
- set_exit = exit
- set_abort = abort
-
- def set_return_value(self, document):
- """
- Set a return value. The eventloop can retrieve the result it by calling
- `return_value`.
- """
- self._set_return_callable(lambda: document)
- self._redraw() # Redraw in "done" state, after the return value has been set.
-
- def _set_return_callable(self, value):
- assert callable(value)
- self._return_value = value
-
- if self.eventloop:
- self.eventloop.stop()
-
- def run_in_terminal(self, func, render_cli_done=False, cooked_mode=True):
- """
- Run function on the terminal above the prompt.
-
- What this does is first hiding the prompt, then running this callable
- (which can safely output to the terminal), and then again rendering the
- prompt which causes the output of this function to scroll above the
- prompt.
-
- :param func: The callable to execute.
- :param render_cli_done: When True, render the interface in the
- 'Done' state first, then execute the function. If False,
- erase the interface first.
- :param cooked_mode: When True (the default), switch the input to
- cooked mode while executing the function.
-
- :returns: the result of `func`.
- """
- # Draw interface in 'done' state, or erase.
- if render_cli_done:
- self._return_value = True
- self._redraw()
- self.renderer.reset() # Make sure to disable mouse mode, etc...
- else:
- self.renderer.erase()
- self._return_value = None
-
- # Run system command.
- if cooked_mode:
- with self.input.cooked_mode():
- result = func()
- else:
- result = func()
-
- # Redraw interface again.
- self.renderer.reset()
- self.renderer.request_absolute_cursor_position()
- self._redraw()
-
- return result
-
- def run_application_generator(self, coroutine, render_cli_done=False):
- """
- EXPERIMENTAL
- Like `run_in_terminal`, but takes a generator that can yield Application instances.
-
- Example:
-
- def f():
- yield Application1(...)
- print('...')
- yield Application2(...)
- cli.run_in_terminal_async(f)
-
- The values which are yielded by the given coroutine are supposed to be
- `Application` instances that run in the current CLI, all other code is
- supposed to be CPU bound, so except for yielding the applications,
- there should not be any user interaction or I/O in the given function.
- """
- # Draw interface in 'done' state, or erase.
- if render_cli_done:
- self._return_value = True
- self._redraw()
- self.renderer.reset() # Make sure to disable mouse mode, etc...
- else:
- self.renderer.erase()
- self._return_value = None
-
- # Loop through the generator.
- g = coroutine()
- assert isinstance(g, types.GeneratorType)
-
- def step_next(send_value=None):
- " Execute next step of the coroutine."
- try:
- # Run until next yield, in cooked mode.
- with self.input.cooked_mode():
- result = g.send(send_value)
- except StopIteration:
- done()
- except:
- done()
- raise
- else:
- # Process yielded value from coroutine.
- assert isinstance(result, Application)
- self.run_sub_application(result, done_callback=step_next,
- _from_application_generator=True)
-
- def done():
- # Redraw interface again.
- self.renderer.reset()
- self.renderer.request_absolute_cursor_position()
- self._redraw()
-
- # Start processing coroutine.
- step_next()
-
- def run_system_command(self, command):
- """
- Run system command (While hiding the prompt. When finished, all the
- output will scroll above the prompt.)
-
- :param command: Shell command to be executed.
- """
- def wait_for_enter():
- """
- Create a sub application to wait for the enter key press.
- This has two advantages over using 'input'/'raw_input':
- - This will share the same input/output I/O.
- - This doesn't block the event loop.
- """
- from .shortcuts import create_prompt_application
-
- registry = Registry()
-
- @registry.add_binding(Keys.ControlJ)
- @registry.add_binding(Keys.ControlM)
- def _(event):
- event.cli.set_return_value(None)
-
- application = create_prompt_application(
- message='Press ENTER to continue...',
- key_bindings_registry=registry)
- self.run_sub_application(application)
-
- def run():
- # Try to use the same input/output file descriptors as the one,
- # used to run this application.
- try:
- input_fd = self.input.fileno()
- except AttributeError:
- input_fd = sys.stdin.fileno()
- try:
- output_fd = self.output.fileno()
- except AttributeError:
- output_fd = sys.stdout.fileno()
-
- # Run sub process.
- # XXX: This will still block the event loop.
- p = Popen(command, shell=True,
- stdin=input_fd, stdout=output_fd)
- p.wait()
-
- # Wait for the user to press enter.
- wait_for_enter()
-
- self.run_in_terminal(run)
-
- def suspend_to_background(self, suspend_group=True):
- """
- (Not thread safe -- to be called from inside the key bindings.)
- Suspend process.
-
- :param suspend_group: When true, suspend the whole process group.
- (This is the default, and probably what you want.)
- """
- # Only suspend when the opperating system supports it.
- # (Not on Windows.)
- if hasattr(signal, 'SIGTSTP'):
- def run():
- # Send `SIGSTP` to own process.
- # This will cause it to suspend.
-
- # Usually we want the whole process group to be suspended. This
- # handles the case when input is piped from another process.
- if suspend_group:
- os.kill(0, signal.SIGTSTP)
- else:
- os.kill(os.getpid(), signal.SIGTSTP)
-
- self.run_in_terminal(run)
-
- def print_tokens(self, tokens, style=None):
- """
- Print a list of (Token, text) tuples to the output.
- (When the UI is running, this method has to be called through
- `run_in_terminal`, otherwise it will destroy the UI.)
-
- :param style: Style class to use. Defaults to the active style in the CLI.
- """
- print_tokens(self.output, tokens, style or self.application.style)
-
- @property
- def is_exiting(self):
- """
- ``True`` when the exit flag as been set.
- """
- return self._exit_flag
-
- @property
- def is_aborting(self):
- """
- ``True`` when the abort flag as been set.
- """
- return self._abort_flag
-
- @property
- def is_returning(self):
- """
- ``True`` when a return value has been set.
- """
- return self._return_value is not None
-
- def return_value(self):
- """
- Get the return value. Not that this method can throw an exception.
- """
- # Note that it's a method, not a property, because it can throw
- # exceptions.
- if self._return_value:
- return self._return_value()
-
- @property
- def is_done(self):
- return self.is_exiting or self.is_aborting or self.is_returning
-
- def _create_async_completer(self, buffer):
- """
- Create function for asynchronous autocompletion.
- (Autocomplete in other thread.)
- """
- complete_thread_running = [False] # By ref.
-
- def completion_does_nothing(document, completion):
- """
- Return `True` if applying this completion doesn't have any effect.
- (When it doesn't insert any new text.
- """
- text_before_cursor = document.text_before_cursor
- replaced_text = text_before_cursor[
- len(text_before_cursor) + completion.start_position:]
- return replaced_text == completion.text
-
- def async_completer(select_first=False, select_last=False,
- insert_common_part=False, complete_event=None):
- document = buffer.document
- complete_event = complete_event or CompleteEvent(text_inserted=True)
-
- # Don't start two threads at the same time.
- if complete_thread_running[0]:
- return
-
- # Don't complete when we already have completions.
- if buffer.complete_state or not buffer.completer:
- return
-
- # Otherwise, get completions in other thread.
- complete_thread_running[0] = True
-
- def run():
- completions = list(buffer.completer.get_completions(document, complete_event))
-
- def callback():
- """
- Set the new complete_state in a safe way. Don't replace an
- existing complete_state if we had one. (The user could have
- pressed 'Tab' in the meantime. Also don't set it if the text
- was changed in the meantime.
- """
- complete_thread_running[0] = False
-
- # When there is only one completion, which has nothing to add, ignore it.
- if (len(completions) == 1 and
- completion_does_nothing(document, completions[0])):
- del completions[:]
-
- # Set completions if the text was not yet changed.
- if buffer.text == document.text and \
- buffer.cursor_position == document.cursor_position and \
- not buffer.complete_state:
-
- set_completions = True
- select_first_anyway = False
-
- # When the common part has to be inserted, and there
- # is a common part.
- if insert_common_part:
- common_part = get_common_complete_suffix(document, completions)
- if common_part:
- # Insert the common part, update completions.
- buffer.insert_text(common_part)
- if len(completions) > 1:
- # (Don't call `async_completer` again, but
- # recalculate completions. See:
- # https://github.com/ipython/ipython/issues/9658)
- completions[:] = [
- c.new_completion_from_position(len(common_part))
- for c in completions]
- else:
- set_completions = False
- else:
- # When we were asked to insert the "common"
- # prefix, but there was no common suffix but
- # still exactly one match, then select the
- # first. (It could be that we have a completion
- # which does * expansion, like '*.py', with
- # exactly one match.)
- if len(completions) == 1:
- select_first_anyway = True
-
- if set_completions:
- buffer.set_completions(
- completions=completions,
- go_to_first=select_first or select_first_anyway,
- go_to_last=select_last)
- self.invalidate()
- elif not buffer.complete_state:
- # Otherwise, restart thread.
- async_completer()
-
- if self.eventloop:
- self.eventloop.call_from_executor(callback)
-
- self.eventloop.run_in_executor(run)
- return async_completer
-
- def _create_auto_suggest_function(self, buffer):
- """
- Create function for asynchronous auto suggestion.
- (AutoSuggest in other thread.)
- """
- suggest_thread_running = [False] # By ref.
-
- def async_suggestor():
- document = buffer.document
-
- # Don't start two threads at the same time.
- if suggest_thread_running[0]:
- return
-
- # Don't suggest when we already have a suggestion.
- if buffer.suggestion or not buffer.auto_suggest:
- return
-
- # Otherwise, get completions in other thread.
- suggest_thread_running[0] = True
-
- def run():
- suggestion = buffer.auto_suggest.get_suggestion(self, buffer, document)
-
- def callback():
- suggest_thread_running[0] = False
-
- # Set suggestion only if the text was not yet changed.
- if buffer.text == document.text and \
- buffer.cursor_position == document.cursor_position:
-
- # Set suggestion and redraw interface.
- buffer.suggestion = suggestion
- self.invalidate()
- else:
- # Otherwise, restart thread.
- async_suggestor()
-
- if self.eventloop:
- self.eventloop.call_from_executor(callback)
-
- self.eventloop.run_in_executor(run)
- return async_suggestor
-
- def stdout_proxy(self, raw=False):
- """
- Create an :class:`_StdoutProxy` class which can be used as a patch for
- `sys.stdout`. Writing to this proxy will make sure that the text
- appears above the prompt, and that it doesn't destroy the output from
- the renderer.
-
- :param raw: (`bool`) When True, vt100 terminal escape sequences are not
- removed/escaped.
- """
- return _StdoutProxy(self, raw=raw)
-
- def patch_stdout_context(self, raw=False, patch_stdout=True, patch_stderr=True):
- """
- Return a context manager that will replace ``sys.stdout`` with a proxy
- that makes sure that all printed text will appear above the prompt, and
- that it doesn't destroy the output from the renderer.
-
- :param patch_stdout: Replace `sys.stdout`.
- :param patch_stderr: Replace `sys.stderr`.
- """
- return _PatchStdoutContext(
- self.stdout_proxy(raw=raw),
- patch_stdout=patch_stdout, patch_stderr=patch_stderr)
-
- def create_eventloop_callbacks(self):
- return _InterfaceEventLoopCallbacks(self)
-
-
-class _InterfaceEventLoopCallbacks(EventLoopCallbacks):
- """
- Callbacks on the :class:`.CommandLineInterface` object, to which an
- eventloop can talk.
- """
- def __init__(self, cli):
- assert isinstance(cli, CommandLineInterface)
- self.cli = cli
-
- @property
- def _active_cli(self):
- """
- Return the active `CommandLineInterface`.
- """
- cli = self.cli
-
- # If there is a sub CLI. That one is always active.
- while cli._sub_cli:
- cli = cli._sub_cli
-
- return cli
-
- def terminal_size_changed(self):
- """
- Report terminal size change. This will trigger a redraw.
- """
- self._active_cli._on_resize()
-
- def input_timeout(self):
- cli = self._active_cli
- cli.on_input_timeout.fire()
-
- def feed_key(self, key_press):
- """
- Feed a key press to the CommandLineInterface.
- """
- assert isinstance(key_press, KeyPress)
- cli = self._active_cli
-
- # Feed the key and redraw.
- # (When the CLI is in 'done' state, it should return to the event loop
- # as soon as possible. Ignore all key presses beyond this point.)
- if not cli.is_done:
- cli.input_processor.feed(key_press)
- cli.input_processor.process_keys()
-
-
-class _PatchStdoutContext(object):
- def __init__(self, new_stdout, patch_stdout=True, patch_stderr=True):
- self.new_stdout = new_stdout
- self.patch_stdout = patch_stdout
- self.patch_stderr = patch_stderr
-
- def __enter__(self):
- self.original_stdout = sys.stdout
- self.original_stderr = sys.stderr
-
- if self.patch_stdout:
- sys.stdout = self.new_stdout
- if self.patch_stderr:
- sys.stderr = self.new_stdout
-
- def __exit__(self, *a, **kw):
- if self.patch_stdout:
- sys.stdout = self.original_stdout
-
- if self.patch_stderr:
- sys.stderr = self.original_stderr
-
-
-class _StdoutProxy(object):
- """
- Proxy for stdout, as returned by
- :class:`CommandLineInterface.stdout_proxy`.
- """
- def __init__(self, cli, raw=False):
- assert isinstance(cli, CommandLineInterface)
- assert isinstance(raw, bool)
-
- self._lock = threading.RLock()
- self._cli = cli
- self._raw = raw
- self._buffer = []
-
- self.errors = sys.__stdout__.errors
- self.encoding = sys.__stdout__.encoding
-
- def _do(self, func):
- if self._cli._is_running:
- run_in_terminal = functools.partial(self._cli.run_in_terminal, func)
- self._cli.eventloop.call_from_executor(run_in_terminal)
- else:
- func()
-
- def _write(self, data):
- """
- Note: print()-statements cause to multiple write calls.
- (write('line') and write('\n')). Of course we don't want to call
- `run_in_terminal` for every individual call, because that's too
- expensive, and as long as the newline hasn't been written, the
- text itself is again overwritter by the rendering of the input
- command line. Therefor, we have a little buffer which holds the
- text until a newline is written to stdout.
- """
- if '\n' in data:
- # When there is a newline in the data, write everything before the
- # newline, including the newline itself.
- before, after = data.rsplit('\n', 1)
- to_write = self._buffer + [before, '\n']
- self._buffer = [after]
-
- def run():
- for s in to_write:
- if self._raw:
- self._cli.output.write_raw(s)
- else:
- self._cli.output.write(s)
- self._do(run)
- else:
- # Otherwise, cache in buffer.
- self._buffer.append(data)
-
- def write(self, data):
- with self._lock:
- self._write(data)
-
- def _flush(self):
- def run():
- for s in self._buffer:
- if self._raw:
- self._cli.output.write_raw(s)
- else:
- self._cli.output.write(s)
- self._buffer = []
- self._cli.output.flush()
- self._do(run)
-
- def flush(self):
- """
- Flush buffered output.
- """
- with self._lock:
- self._flush()
-
-
-class _SubApplicationEventLoop(EventLoop):
- """
- Eventloop used by sub applications.
-
- A sub application is an `Application` that is "spawned" by a parent
- application. The parent application is suspended temporarily and the sub
- application is displayed instead.
-
- It doesn't need it's own event loop. The `EventLoopCallbacks` from the
- parent application are redirected to the sub application. So if the event
- loop that is run by the parent application detects input, the callbacks
- will make sure that it's forwarded to the sub application.
-
- When the sub application has a return value set, it will terminate
- by calling the `stop` method of this event loop. This is used to
- transfer control back to the parent application.
- """
- def __init__(self, cli, stop_callback):
- assert isinstance(cli, CommandLineInterface)
- assert callable(stop_callback)
-
- self.cli = cli
- self.stop_callback = stop_callback
-
- def stop(self):
- self.stop_callback()
-
- def close(self):
- pass
-
- def run_in_executor(self, callback):
- self.cli.eventloop.run_in_executor(callback)
-
- def call_from_executor(self, callback, _max_postpone_until=None):
- self.cli.eventloop.call_from_executor(
- callback, _max_postpone_until=_max_postpone_until)
-
- def add_reader(self, fd, callback):
- self.cli.eventloop.add_reader(fd, callback)
-
- def remove_reader(self, fd):
- self.cli.eventloop.remove_reader(fd)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/__init__.py
+++ /dev/null
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/basic.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/basic.py
deleted file mode 100644
index 401135dec0..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/basic.py
+++ /dev/null
@@ -1,407 +0,0 @@
-# pylint: disable=function-redefined
-from __future__ import unicode_literals
-
-from prompt_toolkit.enums import DEFAULT_BUFFER
-from prompt_toolkit.filters import HasSelection, Condition, EmacsInsertMode, ViInsertMode
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.layout.screen import Point
-from prompt_toolkit.mouse_events import MouseEventType, MouseEvent
-from prompt_toolkit.renderer import HeightIsUnknownError
-from prompt_toolkit.utils import suspend_to_background_supported, is_windows
-
-from .named_commands import get_by_name
-from ..registry import Registry
-
-
-__all__ = (
- 'load_basic_bindings',
- 'load_abort_and_exit_bindings',
- 'load_basic_system_bindings',
- 'load_auto_suggestion_bindings',
-)
-
-def if_no_repeat(event):
- """ Callable that returns True when the previous event was delivered to
- another handler. """
- return not event.is_repeat
-
-
-def load_basic_bindings():
- registry = Registry()
- insert_mode = ViInsertMode() | EmacsInsertMode()
- handle = registry.add_binding
- has_selection = HasSelection()
-
- @handle(Keys.ControlA)
- @handle(Keys.ControlB)
- @handle(Keys.ControlC)
- @handle(Keys.ControlD)
- @handle(Keys.ControlE)
- @handle(Keys.ControlF)
- @handle(Keys.ControlG)
- @handle(Keys.ControlH)
- @handle(Keys.ControlI)
- @handle(Keys.ControlJ)
- @handle(Keys.ControlK)
- @handle(Keys.ControlL)
- @handle(Keys.ControlM)
- @handle(Keys.ControlN)
- @handle(Keys.ControlO)
- @handle(Keys.ControlP)
- @handle(Keys.ControlQ)
- @handle(Keys.ControlR)
- @handle(Keys.ControlS)
- @handle(Keys.ControlT)
- @handle(Keys.ControlU)
- @handle(Keys.ControlV)
- @handle(Keys.ControlW)
- @handle(Keys.ControlX)
- @handle(Keys.ControlY)
- @handle(Keys.ControlZ)
- @handle(Keys.F1)
- @handle(Keys.F2)
- @handle(Keys.F3)
- @handle(Keys.F4)
- @handle(Keys.F5)
- @handle(Keys.F6)
- @handle(Keys.F7)
- @handle(Keys.F8)
- @handle(Keys.F9)
- @handle(Keys.F10)
- @handle(Keys.F11)
- @handle(Keys.F12)
- @handle(Keys.F13)
- @handle(Keys.F14)
- @handle(Keys.F15)
- @handle(Keys.F16)
- @handle(Keys.F17)
- @handle(Keys.F18)
- @handle(Keys.F19)
- @handle(Keys.F20)
- @handle(Keys.ControlSpace)
- @handle(Keys.ControlBackslash)
- @handle(Keys.ControlSquareClose)
- @handle(Keys.ControlCircumflex)
- @handle(Keys.ControlUnderscore)
- @handle(Keys.Backspace)
- @handle(Keys.Up)
- @handle(Keys.Down)
- @handle(Keys.Right)
- @handle(Keys.Left)
- @handle(Keys.ShiftUp)
- @handle(Keys.ShiftDown)
- @handle(Keys.ShiftRight)
- @handle(Keys.ShiftLeft)
- @handle(Keys.Home)
- @handle(Keys.End)
- @handle(Keys.Delete)
- @handle(Keys.ShiftDelete)
- @handle(Keys.ControlDelete)
- @handle(Keys.PageUp)
- @handle(Keys.PageDown)
- @handle(Keys.BackTab)
- @handle(Keys.Tab)
- @handle(Keys.ControlLeft)
- @handle(Keys.ControlRight)
- @handle(Keys.ControlUp)
- @handle(Keys.ControlDown)
- @handle(Keys.Insert)
- @handle(Keys.Ignore)
- def _(event):
- """
- First, for any of these keys, Don't do anything by default. Also don't
- catch them in the 'Any' handler which will insert them as data.
-
- If people want to insert these characters as a literal, they can always
- do by doing a quoted insert. (ControlQ in emacs mode, ControlV in Vi
- mode.)
- """
- pass
-
- # Readline-style bindings.
- handle(Keys.Home)(get_by_name('beginning-of-line'))
- handle(Keys.End)(get_by_name('end-of-line'))
- handle(Keys.Left)(get_by_name('backward-char'))
- handle(Keys.Right)(get_by_name('forward-char'))
- handle(Keys.ControlUp)(get_by_name('previous-history'))
- handle(Keys.ControlDown)(get_by_name('next-history'))
- handle(Keys.ControlL)(get_by_name('clear-screen'))
-
- handle(Keys.ControlK, filter=insert_mode)(get_by_name('kill-line'))
- handle(Keys.ControlU, filter=insert_mode)(get_by_name('unix-line-discard'))
- handle(Keys.ControlH, filter=insert_mode, save_before=if_no_repeat)(
- get_by_name('backward-delete-char'))
- handle(Keys.Backspace, filter=insert_mode, save_before=if_no_repeat)(
- get_by_name('backward-delete-char'))
- handle(Keys.Delete, filter=insert_mode, save_before=if_no_repeat)(
- get_by_name('delete-char'))
- handle(Keys.ShiftDelete, filter=insert_mode, save_before=if_no_repeat)(
- get_by_name('delete-char'))
- handle(Keys.Any, filter=insert_mode, save_before=if_no_repeat)(
- get_by_name('self-insert'))
- handle(Keys.ControlT, filter=insert_mode)(get_by_name('transpose-chars'))
- handle(Keys.ControlW, filter=insert_mode)(get_by_name('unix-word-rubout'))
- handle(Keys.ControlI, filter=insert_mode)(get_by_name('menu-complete'))
- handle(Keys.BackTab, filter=insert_mode)(get_by_name('menu-complete-backward'))
-
- handle(Keys.PageUp, filter= ~has_selection)(get_by_name('previous-history'))
- handle(Keys.PageDown, filter= ~has_selection)(get_by_name('next-history'))
-
- # CTRL keys.
-
- text_before_cursor = Condition(lambda cli: cli.current_buffer.text)
- handle(Keys.ControlD, filter=text_before_cursor & insert_mode)(get_by_name('delete-char'))
-
- is_multiline = Condition(lambda cli: cli.current_buffer.is_multiline())
- is_returnable = Condition(lambda cli: cli.current_buffer.accept_action.is_returnable)
-
- @handle(Keys.ControlJ, filter=is_multiline & insert_mode)
- def _(event):
- " Newline (in case of multiline input. "
- event.current_buffer.newline(copy_margin=not event.cli.in_paste_mode)
-
- @handle(Keys.ControlJ, filter=~is_multiline & is_returnable)
- def _(event):
- " Enter, accept input. "
- buff = event.current_buffer
- buff.accept_action.validate_and_handle(event.cli, buff)
-
- # Delete the word before the cursor.
-
- @handle(Keys.Up)
- def _(event):
- event.current_buffer.auto_up(count=event.arg)
-
- @handle(Keys.Down)
- def _(event):
- event.current_buffer.auto_down(count=event.arg)
-
- @handle(Keys.Delete, filter=has_selection)
- def _(event):
- data = event.current_buffer.cut_selection()
- event.cli.clipboard.set_data(data)
-
- # Global bindings.
-
- @handle(Keys.ControlZ)
- def _(event):
- """
- By default, control-Z should literally insert Ctrl-Z.
- (Ansi Ctrl-Z, code 26 in MSDOS means End-Of-File.
- In a Python REPL for instance, it's possible to type
- Control-Z followed by enter to quit.)
-
- When the system bindings are loaded and suspend-to-background is
- supported, that will override this binding.
- """
- event.current_buffer.insert_text(event.data)
-
- @handle(Keys.CPRResponse, save_before=lambda e: False)
- def _(event):
- """
- Handle incoming Cursor-Position-Request response.
- """
- # The incoming data looks like u'\x1b[35;1R'
- # Parse row/col information.
- row, col = map(int, event.data[2:-1].split(';'))
-
- # Report absolute cursor position to the renderer.
- event.cli.renderer.report_absolute_cursor_row(row)
-
- @handle(Keys.BracketedPaste)
- def _(event):
- " Pasting from clipboard. "
- data = event.data
-
- # Be sure to use \n as line ending.
- # Some terminals (Like iTerm2) seem to paste \r\n line endings in a
- # bracketed paste. See: https://github.com/ipython/ipython/issues/9737
- data = data.replace('\r\n', '\n')
- data = data.replace('\r', '\n')
-
- event.current_buffer.insert_text(data)
-
- @handle(Keys.Any, filter=Condition(lambda cli: cli.quoted_insert), eager=True)
- def _(event):
- """
- Handle quoted insert.
- """
- event.current_buffer.insert_text(event.data, overwrite=False)
- event.cli.quoted_insert = False
-
- return registry
-
-
-def load_mouse_bindings():
- """
- Key bindings, required for mouse support.
- (Mouse events enter through the key binding system.)
- """
- registry = Registry()
-
- @registry.add_binding(Keys.Vt100MouseEvent)
- def _(event):
- """
- Handling of incoming mouse event.
- """
- # Typical: "Esc[MaB*"
- # Urxvt: "Esc[96;14;13M"
- # Xterm SGR: "Esc[<64;85;12M"
-
- # Parse incoming packet.
- if event.data[2] == 'M':
- # Typical.
- mouse_event, x, y = map(ord, event.data[3:])
- mouse_event = {
- 32: MouseEventType.MOUSE_DOWN,
- 35: MouseEventType.MOUSE_UP,
- 96: MouseEventType.SCROLL_UP,
- 97: MouseEventType.SCROLL_DOWN,
- }.get(mouse_event)
-
- # Handle situations where `PosixStdinReader` used surrogateescapes.
- if x >= 0xdc00: x-= 0xdc00
- if y >= 0xdc00: y-= 0xdc00
-
- x -= 32
- y -= 32
- else:
- # Urxvt and Xterm SGR.
- # When the '<' is not present, we are not using the Xterm SGR mode,
- # but Urxvt instead.
- data = event.data[2:]
- if data[:1] == '<':
- sgr = True
- data = data[1:]
- else:
- sgr = False
-
- # Extract coordinates.
- mouse_event, x, y = map(int, data[:-1].split(';'))
- m = data[-1]
-
- # Parse event type.
- if sgr:
- mouse_event = {
- (0, 'M'): MouseEventType.MOUSE_DOWN,
- (0, 'm'): MouseEventType.MOUSE_UP,
- (64, 'M'): MouseEventType.SCROLL_UP,
- (65, 'M'): MouseEventType.SCROLL_DOWN,
- }.get((mouse_event, m))
- else:
- mouse_event = {
- 32: MouseEventType.MOUSE_DOWN,
- 35: MouseEventType.MOUSE_UP,
- 96: MouseEventType.SCROLL_UP,
- 97: MouseEventType.SCROLL_DOWN,
- }.get(mouse_event)
-
- x -= 1
- y -= 1
-
- # Only handle mouse events when we know the window height.
- if event.cli.renderer.height_is_known and mouse_event is not None:
- # Take region above the layout into account. The reported
- # coordinates are absolute to the visible part of the terminal.
- try:
- y -= event.cli.renderer.rows_above_layout
- except HeightIsUnknownError:
- return
-
- # Call the mouse handler from the renderer.
- handler = event.cli.renderer.mouse_handlers.mouse_handlers[x,y]
- handler(event.cli, MouseEvent(position=Point(x=x, y=y),
- event_type=mouse_event))
-
- @registry.add_binding(Keys.WindowsMouseEvent)
- def _(event):
- """
- Handling of mouse events for Windows.
- """
- assert is_windows() # This key binding should only exist for Windows.
-
- # Parse data.
- event_type, x, y = event.data.split(';')
- x = int(x)
- y = int(y)
-
- # Make coordinates absolute to the visible part of the terminal.
- screen_buffer_info = event.cli.renderer.output.get_win32_screen_buffer_info()
- rows_above_cursor = screen_buffer_info.dwCursorPosition.Y - event.cli.renderer._cursor_pos.y
- y -= rows_above_cursor
-
- # Call the mouse event handler.
- handler = event.cli.renderer.mouse_handlers.mouse_handlers[x,y]
- handler(event.cli, MouseEvent(position=Point(x=x, y=y),
- event_type=event_type))
-
- return registry
-
-
-def load_abort_and_exit_bindings():
- """
- Basic bindings for abort (Ctrl-C) and exit (Ctrl-D).
- """
- registry = Registry()
- handle = registry.add_binding
-
- @handle(Keys.ControlC)
- def _(event):
- " Abort when Control-C has been pressed. "
- event.cli.abort()
-
- @Condition
- def ctrl_d_condition(cli):
- """ Ctrl-D binding is only active when the default buffer is selected
- and empty. """
- return (cli.current_buffer_name == DEFAULT_BUFFER and
- not cli.current_buffer.text)
-
- handle(Keys.ControlD, filter=ctrl_d_condition)(get_by_name('end-of-file'))
-
- return registry
-
-
-def load_basic_system_bindings():
- """
- Basic system bindings (For both Emacs and Vi mode.)
- """
- registry = Registry()
-
- suspend_supported = Condition(
- lambda cli: suspend_to_background_supported())
-
- @registry.add_binding(Keys.ControlZ, filter=suspend_supported)
- def _(event):
- """
- Suspend process to background.
- """
- event.cli.suspend_to_background()
-
- return registry
-
-
-def load_auto_suggestion_bindings():
- """
- Key bindings for accepting auto suggestion text.
- """
- registry = Registry()
- handle = registry.add_binding
-
- suggestion_available = Condition(
- lambda cli:
- cli.current_buffer.suggestion is not None and
- cli.current_buffer.document.is_cursor_at_the_end)
-
- @handle(Keys.ControlF, filter=suggestion_available)
- @handle(Keys.ControlE, filter=suggestion_available)
- @handle(Keys.Right, filter=suggestion_available)
- def _(event):
- " Accept suggestion. "
- b = event.current_buffer
- suggestion = b.suggestion
-
- if suggestion:
- b.insert_text(suggestion.text)
-
- return registry
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/completion.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/completion.py
deleted file mode 100644
index 4903900bc6..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/completion.py
+++ /dev/null
@@ -1,161 +0,0 @@
-"""
-Key binding handlers for displaying completions.
-"""
-from __future__ import unicode_literals
-from prompt_toolkit.completion import CompleteEvent, get_common_complete_suffix
-from prompt_toolkit.utils import get_cwidth
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.key_binding.registry import Registry
-
-import math
-
-__all__ = (
- 'generate_completions',
- 'display_completions_like_readline',
-)
-
-def generate_completions(event):
- r"""
- Tab-completion: where the first tab completes the common suffix and the
- second tab lists all the completions.
- """
- b = event.current_buffer
-
- # When already navigating through completions, select the next one.
- if b.complete_state:
- b.complete_next()
- else:
- event.cli.start_completion(insert_common_part=True, select_first=False)
-
-
-def display_completions_like_readline(event):
- """
- Key binding handler for readline-style tab completion.
- This is meant to be as similar as possible to the way how readline displays
- completions.
-
- Generate the completions immediately (blocking) and display them above the
- prompt in columns.
-
- Usage::
-
- # Call this handler when 'Tab' has been pressed.
- registry.add_binding(Keys.ControlI)(display_completions_like_readline)
- """
- # Request completions.
- b = event.current_buffer
- if b.completer is None:
- return
- complete_event = CompleteEvent(completion_requested=True)
- completions = list(b.completer.get_completions(b.document, complete_event))
-
- # Calculate the common suffix.
- common_suffix = get_common_complete_suffix(b.document, completions)
-
- # One completion: insert it.
- if len(completions) == 1:
- b.delete_before_cursor(-completions[0].start_position)
- b.insert_text(completions[0].text)
- # Multiple completions with common part.
- elif common_suffix:
- b.insert_text(common_suffix)
- # Otherwise: display all completions.
- elif completions:
- _display_completions_like_readline(event.cli, completions)
-
-
-def _display_completions_like_readline(cli, completions):
- """
- Display the list of completions in columns above the prompt.
- This will ask for a confirmation if there are too many completions to fit
- on a single page and provide a paginator to walk through them.
- """
- from prompt_toolkit.shortcuts import create_confirm_application
- assert isinstance(completions, list)
-
- # Get terminal dimensions.
- term_size = cli.output.get_size()
- term_width = term_size.columns
- term_height = term_size.rows
-
- # Calculate amount of required columns/rows for displaying the
- # completions. (Keep in mind that completions are displayed
- # alphabetically column-wise.)
- max_compl_width = min(term_width,
- max(get_cwidth(c.text) for c in completions) + 1)
- column_count = max(1, term_width // max_compl_width)
- completions_per_page = column_count * (term_height - 1)
- page_count = int(math.ceil(len(completions) / float(completions_per_page)))
- # Note: math.ceil can return float on Python2.
-
- def display(page):
- # Display completions.
- page_completions = completions[page * completions_per_page:
- (page+1) * completions_per_page]
-
- page_row_count = int(math.ceil(len(page_completions) / float(column_count)))
- page_columns = [page_completions[i * page_row_count:(i+1) * page_row_count]
- for i in range(column_count)]
-
- result = []
- for r in range(page_row_count):
- for c in range(column_count):
- try:
- result.append(page_columns[c][r].text.ljust(max_compl_width))
- except IndexError:
- pass
- result.append('\n')
- cli.output.write(''.join(result))
- cli.output.flush()
-
- # User interaction through an application generator function.
- def run():
- if len(completions) > completions_per_page:
- # Ask confirmation if it doesn't fit on the screen.
- message = 'Display all {} possibilities? (y on n) '.format(len(completions))
- confirm = yield create_confirm_application(message)
-
- if confirm:
- # Display pages.
- for page in range(page_count):
- display(page)
-
- if page != page_count - 1:
- # Display --MORE-- and go to the next page.
- show_more = yield _create_more_application()
- if not show_more:
- return
- else:
- cli.output.write('\n'); cli.output.flush()
- else:
- # Display all completions.
- display(0)
-
- cli.run_application_generator(run, render_cli_done=True)
-
-
-def _create_more_application():
- """
- Create an `Application` instance that displays the "--MORE--".
- """
- from prompt_toolkit.shortcuts import create_prompt_application
- registry = Registry()
-
- @registry.add_binding(' ')
- @registry.add_binding('y')
- @registry.add_binding('Y')
- @registry.add_binding(Keys.ControlJ)
- @registry.add_binding(Keys.ControlI) # Tab.
- def _(event):
- event.cli.set_return_value(True)
-
- @registry.add_binding('n')
- @registry.add_binding('N')
- @registry.add_binding('q')
- @registry.add_binding('Q')
- @registry.add_binding(Keys.ControlC)
- def _(event):
- event.cli.set_return_value(False)
-
- return create_prompt_application(
- '--MORE--', key_bindings_registry=registry, erase_when_done=True)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/emacs.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/emacs.py
deleted file mode 100644
index bccdb04ff3..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/emacs.py
+++ /dev/null
@@ -1,452 +0,0 @@
-# pylint: disable=function-redefined
-from __future__ import unicode_literals
-from prompt_toolkit.buffer import SelectionType, indent, unindent
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER, SYSTEM_BUFFER
-from prompt_toolkit.filters import Condition, EmacsMode, HasSelection, EmacsInsertMode, HasFocus, HasArg
-from prompt_toolkit.completion import CompleteEvent
-
-from .scroll import scroll_page_up, scroll_page_down
-from .named_commands import get_by_name
-from ..registry import Registry, ConditionalRegistry
-
-__all__ = (
- 'load_emacs_bindings',
- 'load_emacs_search_bindings',
- 'load_emacs_system_bindings',
- 'load_extra_emacs_page_navigation_bindings',
-)
-
-
-def load_emacs_bindings():
- """
- Some e-macs extensions.
- """
- # Overview of Readline emacs commands:
- # http://www.catonmat.net/download/readline-emacs-editing-mode-cheat-sheet.pdf
- registry = ConditionalRegistry(Registry(), EmacsMode())
- handle = registry.add_binding
-
- insert_mode = EmacsInsertMode()
- has_selection = HasSelection()
-
- @handle(Keys.Escape)
- def _(event):
- """
- By default, ignore escape key.
-
- (If we don't put this here, and Esc is followed by a key which sequence
- is not handled, we'll insert an Escape character in the input stream.
- Something we don't want and happens to easily in emacs mode.
- Further, people can always use ControlQ to do a quoted insert.)
- """
- pass
-
- handle(Keys.ControlA)(get_by_name('beginning-of-line'))
- handle(Keys.ControlB)(get_by_name('backward-char'))
- handle(Keys.ControlDelete, filter=insert_mode)(get_by_name('kill-word'))
- handle(Keys.ControlE)(get_by_name('end-of-line'))
- handle(Keys.ControlF)(get_by_name('forward-char'))
- handle(Keys.ControlLeft)(get_by_name('backward-word'))
- handle(Keys.ControlRight)(get_by_name('forward-word'))
- handle(Keys.ControlX, 'r', 'y', filter=insert_mode)(get_by_name('yank'))
- handle(Keys.ControlY, filter=insert_mode)(get_by_name('yank'))
- handle(Keys.Escape, 'b')(get_by_name('backward-word'))
- handle(Keys.Escape, 'c', filter=insert_mode)(get_by_name('capitalize-word'))
- handle(Keys.Escape, 'd', filter=insert_mode)(get_by_name('kill-word'))
- handle(Keys.Escape, 'f')(get_by_name('forward-word'))
- handle(Keys.Escape, 'l', filter=insert_mode)(get_by_name('downcase-word'))
- handle(Keys.Escape, 'u', filter=insert_mode)(get_by_name('uppercase-word'))
- handle(Keys.Escape, 'y', filter=insert_mode)(get_by_name('yank-pop'))
- handle(Keys.Escape, Keys.ControlH, filter=insert_mode)(get_by_name('backward-kill-word'))
- handle(Keys.Escape, Keys.Backspace, filter=insert_mode)(get_by_name('backward-kill-word'))
- handle(Keys.Escape, '\\', filter=insert_mode)(get_by_name('delete-horizontal-space'))
-
- handle(Keys.ControlUnderscore, save_before=(lambda e: False), filter=insert_mode)(
- get_by_name('undo'))
-
- handle(Keys.ControlX, Keys.ControlU, save_before=(lambda e: False), filter=insert_mode)(
- get_by_name('undo'))
-
-
- handle(Keys.Escape, '<', filter= ~has_selection)(get_by_name('beginning-of-history'))
- handle(Keys.Escape, '>', filter= ~has_selection)(get_by_name('end-of-history'))
-
- handle(Keys.Escape, '.', filter=insert_mode)(get_by_name('yank-last-arg'))
- handle(Keys.Escape, '_', filter=insert_mode)(get_by_name('yank-last-arg'))
- handle(Keys.Escape, Keys.ControlY, filter=insert_mode)(get_by_name('yank-nth-arg'))
- handle(Keys.Escape, '#', filter=insert_mode)(get_by_name('insert-comment'))
- handle(Keys.ControlO)(get_by_name('operate-and-get-next'))
-
- # ControlQ does a quoted insert. Not that for vt100 terminals, you have to
- # disable flow control by running ``stty -ixon``, otherwise Ctrl-Q and
- # Ctrl-S are captured by the terminal.
- handle(Keys.ControlQ, filter= ~has_selection)(get_by_name('quoted-insert'))
-
- handle(Keys.ControlX, '(')(get_by_name('start-kbd-macro'))
- handle(Keys.ControlX, ')')(get_by_name('end-kbd-macro'))
- handle(Keys.ControlX, 'e')(get_by_name('call-last-kbd-macro'))
-
- @handle(Keys.ControlN)
- def _(event):
- " Next line. "
- event.current_buffer.auto_down()
-
- @handle(Keys.ControlP)
- def _(event):
- " Previous line. "
- event.current_buffer.auto_up(count=event.arg)
-
- def handle_digit(c):
- """
- Handle input of arguments.
- The first number needs to be preceeded by escape.
- """
- @handle(c, filter=HasArg())
- @handle(Keys.Escape, c)
- def _(event):
- event.append_to_arg_count(c)
-
- for c in '0123456789':
- handle_digit(c)
-
- @handle(Keys.Escape, '-', filter=~HasArg())
- def _(event):
- """
- """
- if event._arg is None:
- event.append_to_arg_count('-')
-
- @handle('-', filter=Condition(lambda cli: cli.input_processor.arg == '-'))
- def _(event):
- """
- When '-' is typed again, after exactly '-' has been given as an
- argument, ignore this.
- """
- event.cli.input_processor.arg = '-'
-
- is_returnable = Condition(
- lambda cli: cli.current_buffer.accept_action.is_returnable)
-
- # Meta + Newline: always accept input.
- handle(Keys.Escape, Keys.ControlJ, filter=insert_mode & is_returnable)(
- get_by_name('accept-line'))
-
- def character_search(buff, char, count):
- if count < 0:
- match = buff.document.find_backwards(char, in_current_line=True, count=-count)
- else:
- match = buff.document.find(char, in_current_line=True, count=count)
-
- if match is not None:
- buff.cursor_position += match
-
- @handle(Keys.ControlSquareClose, Keys.Any)
- def _(event):
- " When Ctl-] + a character is pressed. go to that character. "
- # Also named 'character-search'
- character_search(event.current_buffer, event.data, event.arg)
-
- @handle(Keys.Escape, Keys.ControlSquareClose, Keys.Any)
- def _(event):
- " Like Ctl-], but backwards. "
- # Also named 'character-search-backward'
- character_search(event.current_buffer, event.data, -event.arg)
-
- @handle(Keys.Escape, 'a')
- def _(event):
- " Previous sentence. "
- # TODO:
-
- @handle(Keys.Escape, 'e')
- def _(event):
- " Move to end of sentence. "
- # TODO:
-
- @handle(Keys.Escape, 't', filter=insert_mode)
- def _(event):
- """
- Swap the last two words before the cursor.
- """
- # TODO
-
- @handle(Keys.Escape, '*', filter=insert_mode)
- def _(event):
- """
- `meta-*`: Insert all possible completions of the preceding text.
- """
- buff = event.current_buffer
-
- # List all completions.
- complete_event = CompleteEvent(text_inserted=False, completion_requested=True)
- completions = list(buff.completer.get_completions(buff.document, complete_event))
-
- # Insert them.
- text_to_insert = ' '.join(c.text for c in completions)
- buff.insert_text(text_to_insert)
-
- @handle(Keys.ControlX, Keys.ControlX)
- def _(event):
- """
- Move cursor back and forth between the start and end of the current
- line.
- """
- buffer = event.current_buffer
-
- if buffer.document.is_cursor_at_the_end_of_line:
- buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=False)
- else:
- buffer.cursor_position += buffer.document.get_end_of_line_position()
-
- @handle(Keys.ControlSpace)
- def _(event):
- """
- Start of the selection (if the current buffer is not empty).
- """
- # Take the current cursor position as the start of this selection.
- buff = event.current_buffer
- if buff.text:
- buff.start_selection(selection_type=SelectionType.CHARACTERS)
-
- @handle(Keys.ControlG, filter= ~has_selection)
- def _(event):
- """
- Control + G: Cancel completion menu and validation state.
- """
- event.current_buffer.complete_state = None
- event.current_buffer.validation_error = None
-
- @handle(Keys.ControlG, filter=has_selection)
- def _(event):
- """
- Cancel selection.
- """
- event.current_buffer.exit_selection()
-
- @handle(Keys.ControlW, filter=has_selection)
- @handle(Keys.ControlX, 'r', 'k', filter=has_selection)
- def _(event):
- """
- Cut selected text.
- """
- data = event.current_buffer.cut_selection()
- event.cli.clipboard.set_data(data)
-
- @handle(Keys.Escape, 'w', filter=has_selection)
- def _(event):
- """
- Copy selected text.
- """
- data = event.current_buffer.copy_selection()
- event.cli.clipboard.set_data(data)
-
- @handle(Keys.Escape, Keys.Left)
- def _(event):
- """
- Cursor to start of previous word.
- """
- buffer = event.current_buffer
- buffer.cursor_position += buffer.document.find_previous_word_beginning(count=event.arg) or 0
-
- @handle(Keys.Escape, Keys.Right)
- def _(event):
- """
- Cursor to start of next word.
- """
- buffer = event.current_buffer
- buffer.cursor_position += buffer.document.find_next_word_beginning(count=event.arg) or \
- buffer.document.get_end_of_document_position()
-
- @handle(Keys.Escape, '/', filter=insert_mode)
- def _(event):
- """
- M-/: Complete.
- """
- b = event.current_buffer
- if b.complete_state:
- b.complete_next()
- else:
- event.cli.start_completion(select_first=True)
-
- @handle(Keys.ControlC, '>', filter=has_selection)
- def _(event):
- """
- Indent selected text.
- """
- buffer = event.current_buffer
-
- buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=True)
-
- from_, to = buffer.document.selection_range()
- from_, _ = buffer.document.translate_index_to_position(from_)
- to, _ = buffer.document.translate_index_to_position(to)
-
- indent(buffer, from_, to + 1, count=event.arg)
-
- @handle(Keys.ControlC, '<', filter=has_selection)
- def _(event):
- """
- Unindent selected text.
- """
- buffer = event.current_buffer
-
- from_, to = buffer.document.selection_range()
- from_, _ = buffer.document.translate_index_to_position(from_)
- to, _ = buffer.document.translate_index_to_position(to)
-
- unindent(buffer, from_, to + 1, count=event.arg)
-
- return registry
-
-
-def load_emacs_open_in_editor_bindings():
- """
- Pressing C-X C-E will open the buffer in an external editor.
- """
- registry = Registry()
-
- registry.add_binding(Keys.ControlX, Keys.ControlE,
- filter=EmacsMode() & ~HasSelection())(
- get_by_name('edit-and-execute-command'))
-
- return registry
-
-
-def load_emacs_system_bindings():
- registry = ConditionalRegistry(Registry(), EmacsMode())
- handle = registry.add_binding
-
- has_focus = HasFocus(SYSTEM_BUFFER)
-
- @handle(Keys.Escape, '!', filter= ~has_focus)
- def _(event):
- """
- M-'!' opens the system prompt.
- """
- event.cli.push_focus(SYSTEM_BUFFER)
-
- @handle(Keys.Escape, filter=has_focus)
- @handle(Keys.ControlG, filter=has_focus)
- @handle(Keys.ControlC, filter=has_focus)
- def _(event):
- """
- Cancel system prompt.
- """
- event.cli.buffers[SYSTEM_BUFFER].reset()
- event.cli.pop_focus()
-
- @handle(Keys.ControlJ, filter=has_focus)
- def _(event):
- """
- Run system command.
- """
- system_line = event.cli.buffers[SYSTEM_BUFFER]
- event.cli.run_system_command(system_line.text)
- system_line.reset(append_to_history=True)
-
- # Focus previous buffer again.
- event.cli.pop_focus()
-
- return registry
-
-
-def load_emacs_search_bindings(get_search_state=None):
- registry = ConditionalRegistry(Registry(), EmacsMode())
- handle = registry.add_binding
-
- has_focus = HasFocus(SEARCH_BUFFER)
-
- assert get_search_state is None or callable(get_search_state)
-
- if not get_search_state:
- def get_search_state(cli): return cli.search_state
-
- @handle(Keys.ControlG, filter=has_focus)
- @handle(Keys.ControlC, filter=has_focus)
- # NOTE: the reason for not also binding Escape to this one, is that we want
- # Alt+Enter to accept input directly in incremental search mode.
- def _(event):
- """
- Abort an incremental search and restore the original line.
- """
- search_buffer = event.cli.buffers[SEARCH_BUFFER]
-
- search_buffer.reset()
- event.cli.pop_focus()
-
- @handle(Keys.ControlJ, filter=has_focus)
- @handle(Keys.Escape, filter=has_focus, eager=True)
- def _(event):
- """
- When enter pressed in isearch, quit isearch mode. (Multiline
- isearch would be too complicated.)
- """
- input_buffer = event.cli.buffers.previous(event.cli)
- search_buffer = event.cli.buffers[SEARCH_BUFFER]
-
- # Update search state.
- if search_buffer.text:
- get_search_state(event.cli).text = search_buffer.text
-
- # Apply search.
- input_buffer.apply_search(get_search_state(event.cli), include_current_position=True)
-
- # Add query to history of search line.
- search_buffer.append_to_history()
- search_buffer.reset()
-
- # Focus previous document again.
- event.cli.pop_focus()
-
- @handle(Keys.ControlR, filter= ~has_focus)
- def _(event):
- get_search_state(event.cli).direction = IncrementalSearchDirection.BACKWARD
- event.cli.push_focus(SEARCH_BUFFER)
-
- @handle(Keys.ControlS, filter= ~has_focus)
- def _(event):
- get_search_state(event.cli).direction = IncrementalSearchDirection.FORWARD
- event.cli.push_focus(SEARCH_BUFFER)
-
- def incremental_search(cli, direction, count=1):
- " Apply search, but keep search buffer focussed. "
- # Update search_state.
- search_state = get_search_state(cli)
- direction_changed = search_state.direction != direction
-
- search_state.text = cli.buffers[SEARCH_BUFFER].text
- search_state.direction = direction
-
- # Apply search to current buffer.
- if not direction_changed:
- input_buffer = cli.buffers.previous(cli)
- input_buffer.apply_search(search_state,
- include_current_position=False, count=count)
-
- @handle(Keys.ControlR, filter=has_focus)
- @handle(Keys.Up, filter=has_focus)
- def _(event):
- incremental_search(event.cli, IncrementalSearchDirection.BACKWARD, count=event.arg)
-
- @handle(Keys.ControlS, filter=has_focus)
- @handle(Keys.Down, filter=has_focus)
- def _(event):
- incremental_search(event.cli, IncrementalSearchDirection.FORWARD, count=event.arg)
-
- return registry
-
-
-def load_extra_emacs_page_navigation_bindings():
- """
- Key bindings, for scrolling up and down through pages.
- This are separate bindings, because GNU readline doesn't have them.
- """
- registry = ConditionalRegistry(Registry(), EmacsMode())
- handle = registry.add_binding
-
- handle(Keys.ControlV)(scroll_page_down)
- handle(Keys.PageDown)(scroll_page_down)
- handle(Keys.Escape, 'v')(scroll_page_up)
- handle(Keys.PageUp)(scroll_page_up)
-
- return registry
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/named_commands.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/named_commands.py
deleted file mode 100644
index f80c439fc6..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/named_commands.py
+++ /dev/null
@@ -1,578 +0,0 @@
-"""
-Key bindings which are also known by GNU readline by the given names.
-
-See: http://www.delorie.com/gnu/docs/readline/rlman_13.html
-"""
-from __future__ import unicode_literals
-from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER
-from prompt_toolkit.selection import PasteMode
-from six.moves import range
-import six
-
-from .completion import generate_completions, display_completions_like_readline
-from prompt_toolkit.document import Document
-from prompt_toolkit.enums import EditingMode
-from prompt_toolkit.key_binding.input_processor import KeyPress
-from prompt_toolkit.keys import Keys
-
-__all__ = (
- 'get_by_name',
-)
-
-
-# Registry that maps the Readline command names to their handlers.
-_readline_commands = {}
-
-def register(name):
- """
- Store handler in the `_readline_commands` dictionary.
- """
- assert isinstance(name, six.text_type)
- def decorator(handler):
- assert callable(handler)
-
- _readline_commands[name] = handler
- return handler
- return decorator
-
-
-def get_by_name(name):
- """
- Return the handler for the (Readline) command with the given name.
- """
- try:
- return _readline_commands[name]
- except KeyError:
- raise KeyError('Unknown readline command: %r' % name)
-
-#
-# Commands for moving
-# See: http://www.delorie.com/gnu/docs/readline/rlman_14.html
-#
-
-@register('beginning-of-line')
-def beginning_of_line(event):
- " Move to the start of the current line. "
- buff = event.current_buffer
- buff.cursor_position += buff.document.get_start_of_line_position(after_whitespace=False)
-
-
-@register('end-of-line')
-def end_of_line(event):
- " Move to the end of the line. "
- buff = event.current_buffer
- buff.cursor_position += buff.document.get_end_of_line_position()
-
-
-@register('forward-char')
-def forward_char(event):
- " Move forward a character. "
- buff = event.current_buffer
- buff.cursor_position += buff.document.get_cursor_right_position(count=event.arg)
-
-
-@register('backward-char')
-def backward_char(event):
- " Move back a character. "
- buff = event.current_buffer
- buff.cursor_position += buff.document.get_cursor_left_position(count=event.arg)
-
-
-@register('forward-word')
-def forward_word(event):
- """
- Move forward to the end of the next word. Words are composed of letters and
- digits.
- """
- buff = event.current_buffer
- pos = buff.document.find_next_word_ending(count=event.arg)
-
- if pos:
- buff.cursor_position += pos
-
-
-@register('backward-word')
-def backward_word(event):
- """
- Move back to the start of the current or previous word. Words are composed
- of letters and digits.
- """
- buff = event.current_buffer
- pos = buff.document.find_previous_word_beginning(count=event.arg)
-
- if pos:
- buff.cursor_position += pos
-
-
-@register('clear-screen')
-def clear_screen(event):
- """
- Clear the screen and redraw everything at the top of the screen.
- """
- event.cli.renderer.clear()
-
-
-@register('redraw-current-line')
-def redraw_current_line(event):
- """
- Refresh the current line.
- (Readline defines this command, but prompt-toolkit doesn't have it.)
- """
- pass
-
-#
-# Commands for manipulating the history.
-# See: http://www.delorie.com/gnu/docs/readline/rlman_15.html
-#
-
-@register('accept-line')
-def accept_line(event):
- " Accept the line regardless of where the cursor is. "
- b = event.current_buffer
- b.accept_action.validate_and_handle(event.cli, b)
-
-
-@register('previous-history')
-def previous_history(event):
- " Move `back` through the history list, fetching the previous command. "
- event.current_buffer.history_backward(count=event.arg)
-
-
-@register('next-history')
-def next_history(event):
- " Move `forward` through the history list, fetching the next command. "
- event.current_buffer.history_forward(count=event.arg)
-
-
-@register('beginning-of-history')
-def beginning_of_history(event):
- " Move to the first line in the history. "
- event.current_buffer.go_to_history(0)
-
-
-@register('end-of-history')
-def end_of_history(event):
- """
- Move to the end of the input history, i.e., the line currently being entered.
- """
- event.current_buffer.history_forward(count=10**100)
- buff = event.current_buffer
- buff.go_to_history(len(buff._working_lines) - 1)
-
-
-@register('reverse-search-history')
-def reverse_search_history(event):
- """
- Search backward starting at the current line and moving `up` through
- the history as necessary. This is an incremental search.
- """
- event.cli.current_search_state.direction = IncrementalSearchDirection.BACKWARD
- event.cli.push_focus(SEARCH_BUFFER)
-
-
-#
-# Commands for changing text
-#
-
-@register('end-of-file')
-def end_of_file(event):
- """
- Exit.
- """
- event.cli.exit()
-
-
-@register('delete-char')
-def delete_char(event):
- " Delete character before the cursor. "
- deleted = event.current_buffer.delete(count=event.arg)
- if not deleted:
- event.cli.output.bell()
-
-
-@register('backward-delete-char')
-def backward_delete_char(event):
- " Delete the character behind the cursor. "
- if event.arg < 0:
- # When a negative argument has been given, this should delete in front
- # of the cursor.
- deleted = event.current_buffer.delete(count=-event.arg)
- else:
- deleted = event.current_buffer.delete_before_cursor(count=event.arg)
-
- if not deleted:
- event.cli.output.bell()
-
-
-@register('self-insert')
-def self_insert(event):
- " Insert yourself. "
- event.current_buffer.insert_text(event.data * event.arg)
-
-
-@register('transpose-chars')
-def transpose_chars(event):
- """
- Emulate Emacs transpose-char behavior: at the beginning of the buffer,
- do nothing. At the end of a line or buffer, swap the characters before
- the cursor. Otherwise, move the cursor right, and then swap the
- characters before the cursor.
- """
- b = event.current_buffer
- p = b.cursor_position
- if p == 0:
- return
- elif p == len(b.text) or b.text[p] == '\n':
- b.swap_characters_before_cursor()
- else:
- b.cursor_position += b.document.get_cursor_right_position()
- b.swap_characters_before_cursor()
-
-
-@register('uppercase-word')
-def uppercase_word(event):
- """
- Uppercase the current (or following) word.
- """
- buff = event.current_buffer
-
- for i in range(event.arg):
- pos = buff.document.find_next_word_ending()
- words = buff.document.text_after_cursor[:pos]
- buff.insert_text(words.upper(), overwrite=True)
-
-
-@register('downcase-word')
-def downcase_word(event):
- """
- Lowercase the current (or following) word.
- """
- buff = event.current_buffer
-
- for i in range(event.arg): # XXX: not DRY: see meta_c and meta_u!!
- pos = buff.document.find_next_word_ending()
- words = buff.document.text_after_cursor[:pos]
- buff.insert_text(words.lower(), overwrite=True)
-
-
-@register('capitalize-word')
-def capitalize_word(event):
- """
- Capitalize the current (or following) word.
- """
- buff = event.current_buffer
-
- for i in range(event.arg):
- pos = buff.document.find_next_word_ending()
- words = buff.document.text_after_cursor[:pos]
- buff.insert_text(words.title(), overwrite=True)
-
-
-@register('quoted-insert')
-def quoted_insert(event):
- """
- Add the next character typed to the line verbatim. This is how to insert
- key sequences like C-q, for example.
- """
- event.cli.quoted_insert = True
-
-
-#
-# Killing and yanking.
-#
-
-@register('kill-line')
-def kill_line(event):
- """
- Kill the text from the cursor to the end of the line.
-
- If we are at the end of the line, this should remove the newline.
- (That way, it is possible to delete multiple lines by executing this
- command multiple times.)
- """
- buff = event.current_buffer
- if event.arg < 0:
- deleted = buff.delete_before_cursor(count=-buff.document.get_start_of_line_position())
- else:
- if buff.document.current_char == '\n':
- deleted = buff.delete(1)
- else:
- deleted = buff.delete(count=buff.document.get_end_of_line_position())
- event.cli.clipboard.set_text(deleted)
-
-
-@register('kill-word')
-def kill_word(event):
- """
- Kill from point to the end of the current word, or if between words, to the
- end of the next word. Word boundaries are the same as forward-word.
- """
- buff = event.current_buffer
- pos = buff.document.find_next_word_ending(count=event.arg)
-
- if pos:
- deleted = buff.delete(count=pos)
- event.cli.clipboard.set_text(deleted)
-
-
-@register('unix-word-rubout')
-def unix_word_rubout(event, WORD=True):
- """
- Kill the word behind point, using whitespace as a word boundary.
- Usually bound to ControlW.
- """
- buff = event.current_buffer
- pos = buff.document.find_start_of_previous_word(count=event.arg, WORD=WORD)
-
- if pos is None:
- # Nothing found? delete until the start of the document. (The
- # input starts with whitespace and no words were found before the
- # cursor.)
- pos = - buff.cursor_position
-
- if pos:
- deleted = buff.delete_before_cursor(count=-pos)
-
- # If the previous key press was also Control-W, concatenate deleted
- # text.
- if event.is_repeat:
- deleted += event.cli.clipboard.get_data().text
-
- event.cli.clipboard.set_text(deleted)
- else:
- # Nothing to delete. Bell.
- event.cli.output.bell()
-
-
-@register('backward-kill-word')
-def backward_kill_word(event):
- """
- Kills the word before point, using "not a letter nor a digit" as a word boundary.
- Usually bound to M-Del or M-Backspace.
- """
- unix_word_rubout(event, WORD=False)
-
-
-@register('delete-horizontal-space')
-def delete_horizontal_space(event):
- " Delete all spaces and tabs around point. "
- buff = event.current_buffer
- text_before_cursor = buff.document.text_before_cursor
- text_after_cursor = buff.document.text_after_cursor
-
- delete_before = len(text_before_cursor) - len(text_before_cursor.rstrip('\t '))
- delete_after = len(text_after_cursor) - len(text_after_cursor.lstrip('\t '))
-
- buff.delete_before_cursor(count=delete_before)
- buff.delete(count=delete_after)
-
-
-@register('unix-line-discard')
-def unix_line_discard(event):
- """
- Kill backward from the cursor to the beginning of the current line.
- """
- buff = event.current_buffer
-
- if buff.document.cursor_position_col == 0 and buff.document.cursor_position > 0:
- buff.delete_before_cursor(count=1)
- else:
- deleted = buff.delete_before_cursor(count=-buff.document.get_start_of_line_position())
- event.cli.clipboard.set_text(deleted)
-
-
-@register('yank')
-def yank(event):
- """
- Paste before cursor.
- """
- event.current_buffer.paste_clipboard_data(
- event.cli.clipboard.get_data(), count=event.arg, paste_mode=PasteMode.EMACS)
-
-@register('yank-nth-arg')
-def yank_nth_arg(event):
- """
- Insert the first argument of the previous command. With an argument, insert
- the nth word from the previous command (start counting at 0).
- """
- n = (event.arg if event.arg_present else None)
- event.current_buffer.yank_nth_arg(n)
-
-
-@register('yank-last-arg')
-def yank_last_arg(event):
- """
- Like `yank_nth_arg`, but if no argument has been given, yank the last word
- of each line.
- """
- n = (event.arg if event.arg_present else None)
- event.current_buffer.yank_last_arg(n)
-
-@register('yank-pop')
-def yank_pop(event):
- """
- Rotate the kill ring, and yank the new top. Only works following yank or
- yank-pop.
- """
- buff = event.current_buffer
- doc_before_paste = buff.document_before_paste
- clipboard = event.cli.clipboard
-
- if doc_before_paste is not None:
- buff.document = doc_before_paste
- clipboard.rotate()
- buff.paste_clipboard_data(
- clipboard.get_data(), paste_mode=PasteMode.EMACS)
-
-#
-# Completion.
-#
-
-@register('complete')
-def complete(event):
- " Attempt to perform completion. "
- display_completions_like_readline(event)
-
-
-@register('menu-complete')
-def menu_complete(event):
- """
- Generate completions, or go to the next completion. (This is the default
- way of completing input in prompt_toolkit.)
- """
- generate_completions(event)
-
-
-@register('menu-complete-backward')
-def menu_complete_backward(event):
- " Move backward through the list of possible completions. "
- event.current_buffer.complete_previous()
-
-#
-# Keyboard macros.
-#
-
-@register('start-kbd-macro')
-def start_kbd_macro(event):
- """
- Begin saving the characters typed into the current keyboard macro.
- """
- event.cli.input_processor.start_macro()
-
-
-@register('end-kbd-macro')
-def start_kbd_macro(event):
- """
- Stop saving the characters typed into the current keyboard macro and save
- the definition.
- """
- event.cli.input_processor.end_macro()
-
-
-@register('call-last-kbd-macro')
-def start_kbd_macro(event):
- """
- Re-execute the last keyboard macro defined, by making the characters in the
- macro appear as if typed at the keyboard.
- """
- event.cli.input_processor.call_macro()
-
-
-@register('print-last-kbd-macro')
-def print_last_kbd_macro(event):
- " Print the last keboard macro. "
- # TODO: Make the format suitable for the inputrc file.
- def print_macro():
- for k in event.cli.input_processor.macro:
- print(k)
- event.cli.run_in_terminal(print_macro)
-
-#
-# Miscellaneous Commands.
-#
-
-@register('undo')
-def undo(event):
- " Incremental undo. "
- event.current_buffer.undo()
-
-
-@register('insert-comment')
-def insert_comment(event):
- """
- Without numeric argument, comment all lines.
- With numeric argument, uncomment all lines.
- In any case accept the input.
- """
- buff = event.current_buffer
-
- # Transform all lines.
- if event.arg != 1:
- def change(line):
- return line[1:] if line.startswith('#') else line
- else:
- def change(line):
- return '#' + line
-
- buff.document = Document(
- text='\n'.join(map(change, buff.text.splitlines())),
- cursor_position=0)
-
- # Accept input.
- buff.accept_action.validate_and_handle(event.cli, buff)
-
-
-@register('vi-editing-mode')
-def vi_editing_mode(event):
- " Switch to Vi editing mode. "
- event.cli.editing_mode = EditingMode.VI
-
-
-@register('emacs-editing-mode')
-def emacs_editing_mode(event):
- " Switch to Emacs editing mode. "
- event.cli.editing_mode = EditingMode.EMACS
-
-
-@register('prefix-meta')
-def prefix_meta(event):
- """
- Metafy the next character typed. This is for keyboards without a meta key.
-
- Sometimes people also want to bind other keys to Meta, e.g. 'jj'::
-
- registry.add_key_binding('j', 'j', filter=ViInsertMode())(prefix_meta)
- """
- event.cli.input_processor.feed(KeyPress(Keys.Escape))
-
-
-@register('operate-and-get-next')
-def operate_and_get_next(event):
- """
- Accept the current line for execution and fetch the next line relative to
- the current line from the history for editing.
- """
- buff = event.current_buffer
- new_index = buff.working_index + 1
-
- # Accept the current input. (This will also redraw the interface in the
- # 'done' state.)
- buff.accept_action.validate_and_handle(event.cli, buff)
-
- # Set the new index at the start of the next run.
- def set_working_index():
- if new_index < len(buff._working_lines):
- buff.working_index = new_index
-
- event.cli.pre_run_callables.append(set_working_index)
-
-
-@register('edit-and-execute-command')
-def edit_and_execute(event):
- """
- Invoke an editor on the current command line, and accept the result.
- """
- buff = event.current_buffer
-
- buff.open_in_editor(event.cli)
- buff.accept_action.validate_and_handle(event.cli, buff)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/scroll.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/scroll.py
deleted file mode 100644
index 2cc58129ff..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/scroll.py
+++ /dev/null
@@ -1,185 +0,0 @@
-"""
-Key bindings, for scrolling up and down through pages.
-
-This are separate bindings, because GNU readline doesn't have them, but
-they are very useful for navigating through long multiline buffers, like in
-Vi, Emacs, etc...
-"""
-from __future__ import unicode_literals
-
-from prompt_toolkit.layout.utils import find_window_for_buffer_name
-from six.moves import range
-
-__all__ = (
- 'scroll_forward',
- 'scroll_backward',
- 'scroll_half_page_up',
- 'scroll_half_page_down',
- 'scroll_one_line_up',
- 'scroll_one_line_down',
-)
-
-
-def _current_window_for_event(event):
- """
- Return the `Window` for the currently focussed Buffer.
- """
- return find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
-
-
-def scroll_forward(event, half=False):
- """
- Scroll window down.
- """
- w = _current_window_for_event(event)
- b = event.cli.current_buffer
-
- if w and w.render_info:
- info = w.render_info
- ui_content = info.ui_content
-
- # Height to scroll.
- scroll_height = info.window_height
- if half:
- scroll_height //= 2
-
- # Calculate how many lines is equivalent to that vertical space.
- y = b.document.cursor_position_row + 1
- height = 0
- while y < ui_content.line_count:
- line_height = info.get_height_for_line(y)
-
- if height + line_height < scroll_height:
- height += line_height
- y += 1
- else:
- break
-
- b.cursor_position = b.document.translate_row_col_to_index(y, 0)
-
-
-def scroll_backward(event, half=False):
- """
- Scroll window up.
- """
- w = _current_window_for_event(event)
- b = event.cli.current_buffer
-
- if w and w.render_info:
- info = w.render_info
-
- # Height to scroll.
- scroll_height = info.window_height
- if half:
- scroll_height //= 2
-
- # Calculate how many lines is equivalent to that vertical space.
- y = max(0, b.document.cursor_position_row - 1)
- height = 0
- while y > 0:
- line_height = info.get_height_for_line(y)
-
- if height + line_height < scroll_height:
- height += line_height
- y -= 1
- else:
- break
-
- b.cursor_position = b.document.translate_row_col_to_index(y, 0)
-
-
-def scroll_half_page_down(event):
- """
- Same as ControlF, but only scroll half a page.
- """
- scroll_forward(event, half=True)
-
-
-def scroll_half_page_up(event):
- """
- Same as ControlB, but only scroll half a page.
- """
- scroll_backward(event, half=True)
-
-
-def scroll_one_line_down(event):
- """
- scroll_offset += 1
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- b = event.cli.current_buffer
-
- if w:
- # When the cursor is at the top, move to the next line. (Otherwise, only scroll.)
- if w.render_info:
- info = w.render_info
-
- if w.vertical_scroll < info.content_height - info.window_height:
- if info.cursor_position.y <= info.configured_scroll_offsets.top:
- b.cursor_position += b.document.get_cursor_down_position()
-
- w.vertical_scroll += 1
-
-
-def scroll_one_line_up(event):
- """
- scroll_offset -= 1
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- b = event.cli.current_buffer
-
- if w:
- # When the cursor is at the bottom, move to the previous line. (Otherwise, only scroll.)
- if w.render_info:
- info = w.render_info
-
- if w.vertical_scroll > 0:
- first_line_height = info.get_height_for_line(info.first_visible_line())
-
- cursor_up = info.cursor_position.y - (info.window_height - 1 - first_line_height -
- info.configured_scroll_offsets.bottom)
-
- # Move cursor up, as many steps as the height of the first line.
- # TODO: not entirely correct yet, in case of line wrapping and many long lines.
- for _ in range(max(0, cursor_up)):
- b.cursor_position += b.document.get_cursor_up_position()
-
- # Scroll window
- w.vertical_scroll -= 1
-
-
-def scroll_page_down(event):
- """
- Scroll page down. (Prefer the cursor at the top of the page, after scrolling.)
- """
- w = _current_window_for_event(event)
- b = event.cli.current_buffer
-
- if w and w.render_info:
- # Scroll down one page.
- line_index = max(w.render_info.last_visible_line(), w.vertical_scroll + 1)
- w.vertical_scroll = line_index
-
- b.cursor_position = b.document.translate_row_col_to_index(line_index, 0)
- b.cursor_position += b.document.get_start_of_line_position(after_whitespace=True)
-
-
-def scroll_page_up(event):
- """
- Scroll page up. (Prefer the cursor at the bottom of the page, after scrolling.)
- """
- w = _current_window_for_event(event)
- b = event.cli.current_buffer
-
- if w and w.render_info:
- # Put cursor at the first visible line. (But make sure that the cursor
- # moves at least one line up.)
- line_index = max(0, min(w.render_info.first_visible_line(),
- b.document.cursor_position_row - 1))
-
- b.cursor_position = b.document.translate_row_col_to_index(line_index, 0)
- b.cursor_position += b.document.get_start_of_line_position(after_whitespace=True)
-
- # Set the scroll offset. We can safely set it to zero; the Window will
- # make sure that it scrolls at least until the cursor becomes visible.
- w.vertical_scroll = 0
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/utils.py
deleted file mode 100644
index caf08c5c1b..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/utils.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from __future__ import unicode_literals
-from prompt_toolkit.filters import CLIFilter, Always
-
-__all__ = (
- 'create_handle_decorator',
-)
-
-def create_handle_decorator(registry, filter=Always()):
- """
- Create a key handle decorator, which is compatible with `Registry.handle`,
- but will chain the given filter to every key binding.
-
- :param filter: `CLIFilter`
- """
- assert isinstance(filter, CLIFilter)
-
- def handle(*keys, **kw):
- # Chain the given filter to the filter of this specific binding.
- if 'filter' in kw:
- kw['filter'] = kw['filter'] & filter
- else:
- kw['filter'] = filter
-
- return registry.add_binding(*keys, **kw)
- return handle
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/vi.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/vi.py
deleted file mode 100644
index 72568ee273..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/vi.py
+++ /dev/null
@@ -1,1903 +0,0 @@
-# pylint: disable=function-redefined
-from __future__ import unicode_literals
-from prompt_toolkit.buffer import ClipboardData, indent, unindent, reshape_text
-from prompt_toolkit.document import Document
-from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER, SYSTEM_BUFFER
-from prompt_toolkit.filters import Filter, Condition, HasArg, Always, IsReadOnly
-from prompt_toolkit.filters.cli import ViNavigationMode, ViInsertMode, ViInsertMultipleMode, ViReplaceMode, ViSelectionMode, ViWaitingForTextObjectMode, ViDigraphMode, ViMode
-from prompt_toolkit.key_binding.digraphs import DIGRAPHS
-from prompt_toolkit.key_binding.vi_state import CharacterFind, InputMode
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.layout.utils import find_window_for_buffer_name
-from prompt_toolkit.selection import SelectionType, SelectionState, PasteMode
-
-from .scroll import scroll_forward, scroll_backward, scroll_half_page_up, scroll_half_page_down, scroll_one_line_up, scroll_one_line_down, scroll_page_up, scroll_page_down
-from .named_commands import get_by_name
-from ..registry import Registry, ConditionalRegistry, BaseRegistry
-
-import prompt_toolkit.filters as filters
-from six.moves import range
-import codecs
-import six
-import string
-
-try:
- from itertools import accumulate
-except ImportError: # < Python 3.2
- def accumulate(iterable):
- " Super simpel 'accumulate' implementation. "
- total = 0
- for item in iterable:
- total += item
- yield total
-
-__all__ = (
- 'load_vi_bindings',
- 'load_vi_search_bindings',
- 'load_vi_system_bindings',
- 'load_extra_vi_page_navigation_bindings',
-)
-
-if six.PY2:
- ascii_lowercase = string.ascii_lowercase.decode('ascii')
-else:
- ascii_lowercase = string.ascii_lowercase
-
-vi_register_names = ascii_lowercase + '0123456789'
-
-
-class TextObjectType(object):
- EXCLUSIVE = 'EXCLUSIVE'
- INCLUSIVE = 'INCLUSIVE'
- LINEWISE = 'LINEWISE'
- BLOCK = 'BLOCK'
-
-
-class TextObject(object):
- """
- Return struct for functions wrapped in ``text_object``.
- Both `start` and `end` are relative to the current cursor position.
- """
- def __init__(self, start, end=0, type=TextObjectType.EXCLUSIVE):
- self.start = start
- self.end = end
- self.type = type
-
- @property
- def selection_type(self):
- if self.type == TextObjectType.LINEWISE:
- return SelectionType.LINES
- if self.type == TextObjectType.BLOCK:
- return SelectionType.BLOCK
- else:
- return SelectionType.CHARACTERS
-
- def sorted(self):
- """
- Return a (start, end) tuple where start <= end.
- """
- if self.start < self.end:
- return self.start, self.end
- else:
- return self.end, self.start
-
- def operator_range(self, document):
- """
- Return a (start, end) tuple with start <= end that indicates the range
- operators should operate on.
- `buffer` is used to get start and end of line positions.
- """
- start, end = self.sorted()
- doc = document
-
- if (self.type == TextObjectType.EXCLUSIVE and
- doc.translate_index_to_position(end + doc.cursor_position)[1] == 0):
- # If the motion is exclusive and the end of motion is on the first
- # column, the end position becomes end of previous line.
- end -= 1
- if self.type == TextObjectType.INCLUSIVE:
- end += 1
- if self.type == TextObjectType.LINEWISE:
- # Select whole lines
- row, col = doc.translate_index_to_position(start + doc.cursor_position)
- start = doc.translate_row_col_to_index(row, 0) - doc.cursor_position
- row, col = doc.translate_index_to_position(end + doc.cursor_position)
- end = doc.translate_row_col_to_index(row, len(doc.lines[row])) - doc.cursor_position
- return start, end
-
- def get_line_numbers(self, buffer):
- """
- Return a (start_line, end_line) pair.
- """
- # Get absolute cursor positions from the text object.
- from_, to = self.operator_range(buffer.document)
- from_ += buffer.cursor_position
- to += buffer.cursor_position
-
- # Take the start of the lines.
- from_, _ = buffer.document.translate_index_to_position(from_)
- to, _ = buffer.document.translate_index_to_position(to)
-
- return from_, to
-
- def cut(self, buffer):
- """
- Turn text object into `ClipboardData` instance.
- """
- from_, to = self.operator_range(buffer.document)
-
- from_ += buffer.cursor_position
- to += buffer.cursor_position
- to -= 1 # SelectionState does not include the end position, `operator_range` does.
-
- document = Document(buffer.text, to, SelectionState(
- original_cursor_position=from_, type=self.selection_type))
-
- new_document, clipboard_data = document.cut_selection()
- return new_document, clipboard_data
-
-
-def create_text_object_decorator(registry):
- """
- Create a decorator that can be used to register Vi text object implementations.
- """
- assert isinstance(registry, BaseRegistry)
-
- operator_given = ViWaitingForTextObjectMode()
- navigation_mode = ViNavigationMode()
- selection_mode = ViSelectionMode()
-
- def text_object_decorator(*keys, **kw):
- """
- Register a text object function.
-
- Usage::
-
- @text_object('w', filter=..., no_move_handler=False)
- def handler(event):
- # Return a text object for this key.
- return TextObject(...)
-
- :param no_move_handler: Disable the move handler in navigation mode.
- (It's still active in selection mode.)
- """
- filter = kw.pop('filter', Always())
- no_move_handler = kw.pop('no_move_handler', False)
- no_selection_handler = kw.pop('no_selection_handler', False)
- eager = kw.pop('eager', False)
- assert not kw
-
- def decorator(text_object_func):
- assert callable(text_object_func)
-
- @registry.add_binding(*keys, filter=operator_given & filter, eager=eager)
- def _(event):
- # Arguments are multiplied.
- vi_state = event.cli.vi_state
- event._arg = (vi_state.operator_arg or 1) * (event.arg or 1)
-
- # Call the text object handler.
- text_obj = text_object_func(event)
- if text_obj is not None:
- assert isinstance(text_obj, TextObject)
-
- # Call the operator function with the text object.
- vi_state.operator_func(event, text_obj)
-
- # Clear operator.
- event.cli.vi_state.operator_func = None
- event.cli.vi_state.operator_arg = None
-
- # Register a move operation. (Doesn't need an operator.)
- if not no_move_handler:
- @registry.add_binding(*keys, filter=~operator_given & filter & navigation_mode, eager=eager)
- def _(event):
- " Move handler for navigation mode. "
- text_object = text_object_func(event)
- event.current_buffer.cursor_position += text_object.start
-
- # Register a move selection operation.
- if not no_selection_handler:
- @registry.add_binding(*keys, filter=~operator_given & filter & selection_mode, eager=eager)
- def _(event):
- " Move handler for selection mode. "
- text_object = text_object_func(event)
- buff = event.current_buffer
-
- # When the text object has both a start and end position, like 'i(' or 'iw',
- # Turn this into a selection, otherwise the cursor.
- if text_object.end:
- # Take selection positions from text object.
- start, end = text_object.operator_range(buff.document)
- start += buff.cursor_position
- end += buff.cursor_position
-
- buff.selection_state.original_cursor_position = start
- buff.cursor_position = end
-
- # Take selection type from text object.
- if text_object.type == TextObjectType.LINEWISE:
- buff.selection_state.type = SelectionType.LINES
- else:
- buff.selection_state.type = SelectionType.CHARACTERS
- else:
- event.current_buffer.cursor_position += text_object.start
-
- # Make it possible to chain @text_object decorators.
- return text_object_func
-
- return decorator
- return text_object_decorator
-
-
-def create_operator_decorator(registry):
- """
- Create a decorator that can be used for registering Vi operators.
- """
- assert isinstance(registry, BaseRegistry)
-
- operator_given = ViWaitingForTextObjectMode()
- navigation_mode = ViNavigationMode()
- selection_mode = ViSelectionMode()
-
- def operator_decorator(*keys, **kw):
- """
- Register a Vi operator.
-
- Usage::
-
- @operator('d', filter=...)
- def handler(cli, text_object):
- # Do something with the text object here.
- """
- filter = kw.pop('filter', Always())
- eager = kw.pop('eager', False)
- assert not kw
-
- def decorator(operator_func):
- @registry.add_binding(*keys, filter=~operator_given & filter & navigation_mode, eager=eager)
- def _(event):
- """
- Handle operator in navigation mode.
- """
- # When this key binding is matched, only set the operator
- # function in the ViState. We should execute it after a text
- # object has been received.
- event.cli.vi_state.operator_func = operator_func
- event.cli.vi_state.operator_arg = event.arg
-
- @registry.add_binding(*keys, filter=~operator_given & filter & selection_mode, eager=eager)
- def _(event):
- """
- Handle operator in selection mode.
- """
- buff = event.current_buffer
- selection_state = buff.selection_state
-
- # Create text object from selection.
- if selection_state.type == SelectionType.LINES:
- text_obj_type = TextObjectType.LINEWISE
- elif selection_state.type == SelectionType.BLOCK:
- text_obj_type = TextObjectType.BLOCK
- else:
- text_obj_type = TextObjectType.INCLUSIVE
-
- text_object = TextObject(
- selection_state.original_cursor_position - buff.cursor_position,
- type=text_obj_type)
-
- # Execute operator.
- operator_func(event, text_object)
-
- # Quit selection mode.
- buff.selection_state = None
-
- return operator_func
- return decorator
- return operator_decorator
-
-
-def load_vi_bindings(get_search_state=None):
- """
- Vi extensions.
-
- # Overview of Readline Vi commands:
- # http://www.catonmat.net/download/bash-vi-editing-mode-cheat-sheet.pdf
-
- :param get_search_state: None or a callable that takes a
- CommandLineInterface and returns a SearchState.
- """
- # Note: Some key bindings have the "~IsReadOnly()" filter added. This
- # prevents the handler to be executed when the focus is on a
- # read-only buffer.
- # This is however only required for those that change the ViState to
- # INSERT mode. The `Buffer` class itself throws the
- # `EditReadOnlyBuffer` exception for any text operations which is
- # handled correctly. There is no need to add "~IsReadOnly" to all key
- # bindings that do text manipulation.
-
- registry = ConditionalRegistry(Registry(), ViMode())
- handle = registry.add_binding
-
- # Default get_search_state.
- if get_search_state is None:
- def get_search_state(cli): return cli.search_state
-
- # (Note: Always take the navigation bindings in read-only mode, even when
- # ViState says different.)
- navigation_mode = ViNavigationMode()
- insert_mode = ViInsertMode()
- insert_multiple_mode = ViInsertMultipleMode()
- replace_mode = ViReplaceMode()
- selection_mode = ViSelectionMode()
- operator_given = ViWaitingForTextObjectMode()
- digraph_mode = ViDigraphMode()
-
- vi_transform_functions = [
- # Rot 13 transformation
- (('g', '?'), Always(), lambda string: codecs.encode(string, 'rot_13')),
-
- # To lowercase
- (('g', 'u'), Always(), lambda string: string.lower()),
-
- # To uppercase.
- (('g', 'U'), Always(), lambda string: string.upper()),
-
- # Swap case.
- (('g', '~'), Always(), lambda string: string.swapcase()),
- (('~', ), Condition(lambda cli: cli.vi_state.tilde_operator), lambda string: string.swapcase()),
- ]
-
- # Insert a character literally (quoted insert).
- handle(Keys.ControlV, filter=insert_mode)(get_by_name('quoted-insert'))
-
- @handle(Keys.Escape)
- def _(event):
- """
- Escape goes to vi navigation mode.
- """
- buffer = event.current_buffer
- vi_state = event.cli.vi_state
-
- if vi_state.input_mode in (InputMode.INSERT, InputMode.REPLACE):
- buffer.cursor_position += buffer.document.get_cursor_left_position()
-
- vi_state.reset(InputMode.NAVIGATION)
-
- if bool(buffer.selection_state):
- buffer.exit_selection()
-
- @handle('k', filter=selection_mode)
- def _(event):
- """
- Arrow up in selection mode.
- """
- event.current_buffer.cursor_up(count=event.arg)
-
- @handle('j', filter=selection_mode)
- def _(event):
- """
- Arrow down in selection mode.
- """
- event.current_buffer.cursor_down(count=event.arg)
-
- @handle(Keys.Up, filter=navigation_mode)
- @handle(Keys.ControlP, filter=navigation_mode)
- def _(event):
- """
- Arrow up and ControlP in navigation mode go up.
- """
- event.current_buffer.auto_up(count=event.arg)
-
- @handle('k', filter=navigation_mode)
- def _(event):
- """
- Go up, but if we enter a new history entry, move to the start of the
- line.
- """
- event.current_buffer.auto_up(
- count=event.arg, go_to_start_of_line_if_history_changes=True)
-
- @handle(Keys.Down, filter=navigation_mode)
- @handle(Keys.ControlN, filter=navigation_mode)
- def _(event):
- """
- Arrow down and Control-N in navigation mode.
- """
- event.current_buffer.auto_down(count=event.arg)
-
- @handle('j', filter=navigation_mode)
- def _(event):
- """
- Go down, but if we enter a new history entry, go to the start of the line.
- """
- event.current_buffer.auto_down(
- count=event.arg, go_to_start_of_line_if_history_changes=True)
-
- @handle(Keys.ControlH, filter=navigation_mode)
- @handle(Keys.Backspace, filter=navigation_mode)
- def _(event):
- """
- In navigation-mode, move cursor.
- """
- event.current_buffer.cursor_position += \
- event.current_buffer.document.get_cursor_left_position(count=event.arg)
-
- @handle(Keys.ControlN, filter=insert_mode)
- def _(event):
- b = event.current_buffer
-
- if b.complete_state:
- b.complete_next()
- else:
- event.cli.start_completion(select_first=True)
-
- @handle(Keys.ControlP, filter=insert_mode)
- def _(event):
- """
- Control-P: To previous completion.
- """
- b = event.current_buffer
-
- if b.complete_state:
- b.complete_previous()
- else:
- event.cli.start_completion(select_last=True)
-
- @handle(Keys.ControlY, filter=insert_mode)
- def _(event):
- """
- Accept current completion.
- """
- event.current_buffer.complete_state = None
-
- @handle(Keys.ControlE, filter=insert_mode)
- def _(event):
- """
- Cancel completion. Go back to originally typed text.
- """
- event.current_buffer.cancel_completion()
-
- @handle(Keys.ControlJ, filter=navigation_mode) # XXX: only if the selected buffer has a return handler.
- def _(event):
- """
- In navigation mode, pressing enter will always return the input.
- """
- b = event.current_buffer
-
- if b.accept_action.is_returnable:
- b.accept_action.validate_and_handle(event.cli, b)
-
- # ** In navigation mode **
-
- # List of navigation commands: http://hea-www.harvard.edu/~fine/Tech/vi.html
-
- @handle(Keys.Insert, filter=navigation_mode)
- def _(event):
- " Presing the Insert key. "
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle('a', filter=navigation_mode & ~IsReadOnly())
- # ~IsReadOnly, because we want to stay in navigation mode for
- # read-only buffers.
- def _(event):
- event.current_buffer.cursor_position += event.current_buffer.document.get_cursor_right_position()
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle('A', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- event.current_buffer.cursor_position += event.current_buffer.document.get_end_of_line_position()
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle('C', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- """
- # Change to end of line.
- # Same as 'c$' (which is implemented elsewhere.)
- """
- buffer = event.current_buffer
-
- deleted = buffer.delete(count=buffer.document.get_end_of_line_position())
- event.cli.clipboard.set_text(deleted)
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle('c', 'c', filter=navigation_mode & ~IsReadOnly())
- @handle('S', filter=navigation_mode & ~IsReadOnly())
- def _(event): # TODO: implement 'arg'
- """
- Change current line
- """
- buffer = event.current_buffer
-
- # We copy the whole line.
- data = ClipboardData(buffer.document.current_line, SelectionType.LINES)
- event.cli.clipboard.set_data(data)
-
- # But we delete after the whitespace
- buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=True)
- buffer.delete(count=buffer.document.get_end_of_line_position())
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle('D', filter=navigation_mode)
- def _(event):
- buffer = event.current_buffer
- deleted = buffer.delete(count=buffer.document.get_end_of_line_position())
- event.cli.clipboard.set_text(deleted)
-
- @handle('d', 'd', filter=navigation_mode)
- def _(event):
- """
- Delete line. (Or the following 'n' lines.)
- """
- buffer = event.current_buffer
-
- # Split string in before/deleted/after text.
- lines = buffer.document.lines
-
- before = '\n'.join(lines[:buffer.document.cursor_position_row])
- deleted = '\n'.join(lines[buffer.document.cursor_position_row:
- buffer.document.cursor_position_row + event.arg])
- after = '\n'.join(lines[buffer.document.cursor_position_row + event.arg:])
-
- # Set new text.
- if before and after:
- before = before + '\n'
-
- # Set text and cursor position.
- buffer.document = Document(
- text=before + after,
- # Cursor At the start of the first 'after' line, after the leading whitespace.
- cursor_position = len(before) + len(after) - len(after.lstrip(' ')))
-
- # Set clipboard data
- event.cli.clipboard.set_data(ClipboardData(deleted, SelectionType.LINES))
-
- @handle('x', filter=selection_mode)
- def _(event):
- """
- Cut selection.
- ('x' is not an operator.)
- """
- clipboard_data = event.current_buffer.cut_selection()
- event.cli.clipboard.set_data(clipboard_data)
-
- @handle('i', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle('I', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- event.cli.vi_state.input_mode = InputMode.INSERT
- event.current_buffer.cursor_position += \
- event.current_buffer.document.get_start_of_line_position(after_whitespace=True)
-
- @Condition
- def in_block_selection(cli):
- buff = cli.current_buffer
- return buff.selection_state and buff.selection_state.type == SelectionType.BLOCK
-
- @handle('I', filter=in_block_selection & ~IsReadOnly())
- def go_to_block_selection(event, after=False):
- " Insert in block selection mode. "
- buff = event.current_buffer
-
- # Store all cursor positions.
- positions = []
-
- if after:
- def get_pos(from_to):
- return from_to[1] + 1
- else:
- def get_pos(from_to):
- return from_to[0]
-
- for i, from_to in enumerate(buff.document.selection_ranges()):
- positions.append(get_pos(from_to))
- if i == 0:
- buff.cursor_position = get_pos(from_to)
-
- buff.multiple_cursor_positions = positions
-
- # Go to 'INSERT_MULTIPLE' mode.
- event.cli.vi_state.input_mode = InputMode.INSERT_MULTIPLE
- buff.exit_selection()
-
- @handle('A', filter=in_block_selection & ~IsReadOnly())
- def _(event):
- go_to_block_selection(event, after=True)
-
- @handle('J', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- " Join lines. "
- for i in range(event.arg):
- event.current_buffer.join_next_line()
-
- @handle('g', 'J', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- " Join lines without space. "
- for i in range(event.arg):
- event.current_buffer.join_next_line(separator='')
-
- @handle('J', filter=selection_mode & ~IsReadOnly())
- def _(event):
- " Join selected lines. "
- event.current_buffer.join_selected_lines()
-
- @handle('g', 'J', filter=selection_mode & ~IsReadOnly())
- def _(event):
- " Join selected lines without space. "
- event.current_buffer.join_selected_lines(separator='')
-
- @handle('p', filter=navigation_mode)
- def _(event):
- """
- Paste after
- """
- event.current_buffer.paste_clipboard_data(
- event.cli.clipboard.get_data(),
- count=event.arg,
- paste_mode=PasteMode.VI_AFTER)
-
- @handle('P', filter=navigation_mode)
- def _(event):
- """
- Paste before
- """
- event.current_buffer.paste_clipboard_data(
- event.cli.clipboard.get_data(),
- count=event.arg,
- paste_mode=PasteMode.VI_BEFORE)
-
- @handle('"', Keys.Any, 'p', filter=navigation_mode)
- def _(event):
- " Paste from named register. "
- c = event.key_sequence[1].data
- if c in vi_register_names:
- data = event.cli.vi_state.named_registers.get(c)
- if data:
- event.current_buffer.paste_clipboard_data(
- data, count=event.arg, paste_mode=PasteMode.VI_AFTER)
-
- @handle('"', Keys.Any, 'P', filter=navigation_mode)
- def _(event):
- " Paste (before) from named register. "
- c = event.key_sequence[1].data
- if c in vi_register_names:
- data = event.cli.vi_state.named_registers.get(c)
- if data:
- event.current_buffer.paste_clipboard_data(
- data, count=event.arg, paste_mode=PasteMode.VI_BEFORE)
-
- @handle('r', Keys.Any, filter=navigation_mode)
- def _(event):
- """
- Replace single character under cursor
- """
- event.current_buffer.insert_text(event.data * event.arg, overwrite=True)
- event.current_buffer.cursor_position -= 1
-
- @handle('R', filter=navigation_mode)
- def _(event):
- """
- Go to 'replace'-mode.
- """
- event.cli.vi_state.input_mode = InputMode.REPLACE
-
- @handle('s', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- """
- Substitute with new text
- (Delete character(s) and go to insert mode.)
- """
- text = event.current_buffer.delete(count=event.arg)
- event.cli.clipboard.set_text(text)
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle('u', filter=navigation_mode, save_before=(lambda e: False))
- def _(event):
- for i in range(event.arg):
- event.current_buffer.undo()
-
- @handle('V', filter=navigation_mode)
- def _(event):
- """
- Start lines selection.
- """
- event.current_buffer.start_selection(selection_type=SelectionType.LINES)
-
- @handle(Keys.ControlV, filter=navigation_mode)
- def _(event):
- " Enter block selection mode. "
- event.current_buffer.start_selection(selection_type=SelectionType.BLOCK)
-
- @handle('V', filter=selection_mode)
- def _(event):
- """
- Exit line selection mode, or go from non line selection mode to line
- selection mode.
- """
- selection_state = event.current_buffer.selection_state
-
- if selection_state.type != SelectionType.LINES:
- selection_state.type = SelectionType.LINES
- else:
- event.current_buffer.exit_selection()
-
- @handle('v', filter=navigation_mode)
- def _(event):
- " Enter character selection mode. "
- event.current_buffer.start_selection(selection_type=SelectionType.CHARACTERS)
-
- @handle('v', filter=selection_mode)
- def _(event):
- """
- Exit character selection mode, or go from non-character-selection mode
- to character selection mode.
- """
- selection_state = event.current_buffer.selection_state
-
- if selection_state.type != SelectionType.CHARACTERS:
- selection_state.type = SelectionType.CHARACTERS
- else:
- event.current_buffer.exit_selection()
-
- @handle(Keys.ControlV, filter=selection_mode)
- def _(event):
- """
- Exit block selection mode, or go from non block selection mode to block
- selection mode.
- """
- selection_state = event.current_buffer.selection_state
-
- if selection_state.type != SelectionType.BLOCK:
- selection_state.type = SelectionType.BLOCK
- else:
- event.current_buffer.exit_selection()
-
-
- @handle('a', 'w', filter=selection_mode)
- @handle('a', 'W', filter=selection_mode)
- def _(event):
- """
- Switch from visual linewise mode to visual characterwise mode.
- """
- buffer = event.current_buffer
-
- if buffer.selection_state and buffer.selection_state.type == SelectionType.LINES:
- buffer.selection_state.type = SelectionType.CHARACTERS
-
- @handle('x', filter=navigation_mode)
- def _(event):
- """
- Delete character.
- """
- text = event.current_buffer.delete(count=event.arg)
- event.cli.clipboard.set_text(text)
-
- @handle('X', filter=navigation_mode)
- def _(event):
- text = event.current_buffer.delete_before_cursor()
- event.cli.clipboard.set_text(text)
-
- @handle('y', 'y', filter=navigation_mode)
- @handle('Y', filter=navigation_mode)
- def _(event):
- """
- Yank the whole line.
- """
- text = '\n'.join(event.current_buffer.document.lines_from_current[:event.arg])
- event.cli.clipboard.set_data(ClipboardData(text, SelectionType.LINES))
-
- @handle('+', filter=navigation_mode)
- def _(event):
- """
- Move to first non whitespace of next line
- """
- buffer = event.current_buffer
- buffer.cursor_position += buffer.document.get_cursor_down_position(count=event.arg)
- buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=True)
-
- @handle('-', filter=navigation_mode)
- def _(event):
- """
- Move to first non whitespace of previous line
- """
- buffer = event.current_buffer
- buffer.cursor_position += buffer.document.get_cursor_up_position(count=event.arg)
- buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=True)
-
- @handle('>', '>', filter=navigation_mode)
- def _(event):
- """
- Indent lines.
- """
- buffer = event.current_buffer
- current_row = buffer.document.cursor_position_row
- indent(buffer, current_row, current_row + event.arg)
-
- @handle('<', '<', filter=navigation_mode)
- def _(event):
- """
- Unindent lines.
- """
- current_row = event.current_buffer.document.cursor_position_row
- unindent(event.current_buffer, current_row, current_row + event.arg)
-
- @handle('O', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- """
- Open line above and enter insertion mode
- """
- event.current_buffer.insert_line_above(
- copy_margin=not event.cli.in_paste_mode)
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle('o', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- """
- Open line below and enter insertion mode
- """
- event.current_buffer.insert_line_below(
- copy_margin=not event.cli.in_paste_mode)
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle('~', filter=navigation_mode)
- def _(event):
- """
- Reverse case of current character and move cursor forward.
- """
- buffer = event.current_buffer
- c = buffer.document.current_char
-
- if c is not None and c != '\n':
- buffer.insert_text(c.swapcase(), overwrite=True)
-
- @handle('g', 'u', 'u', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- " Lowercase current line. "
- buff = event.current_buffer
- buff.transform_current_line(lambda s: s.lower())
-
- @handle('g', 'U', 'U', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- " Uppercase current line. "
- buff = event.current_buffer
- buff.transform_current_line(lambda s: s.upper())
-
- @handle('g', '~', '~', filter=navigation_mode & ~IsReadOnly())
- def _(event):
- " Swap case of the current line. "
- buff = event.current_buffer
- buff.transform_current_line(lambda s: s.swapcase())
-
- @handle('#', filter=navigation_mode)
- def _(event):
- """
- Go to previous occurence of this word.
- """
- b = event.cli.current_buffer
-
- search_state = get_search_state(event.cli)
- search_state.text = b.document.get_word_under_cursor()
- search_state.direction = IncrementalSearchDirection.BACKWARD
-
- b.apply_search(search_state, count=event.arg,
- include_current_position=False)
-
- @handle('*', filter=navigation_mode)
- def _(event):
- """
- Go to next occurence of this word.
- """
- b = event.cli.current_buffer
-
- search_state = get_search_state(event.cli)
- search_state.text = b.document.get_word_under_cursor()
- search_state.direction = IncrementalSearchDirection.FORWARD
-
- b.apply_search(search_state, count=event.arg,
- include_current_position=False)
-
- @handle('(', filter=navigation_mode)
- def _(event):
- # TODO: go to begin of sentence.
- # XXX: should become text_object.
- pass
-
- @handle(')', filter=navigation_mode)
- def _(event):
- # TODO: go to end of sentence.
- # XXX: should become text_object.
- pass
-
- operator = create_operator_decorator(registry)
- text_object = create_text_object_decorator(registry)
-
- @text_object(Keys.Any, filter=operator_given)
- def _(event):
- """
- Unknown key binding while waiting for a text object.
- """
- event.cli.output.bell()
-
- #
- # *** Operators ***
- #
-
- def create_delete_and_change_operators(delete_only, with_register=False):
- """
- Delete and change operators.
-
- :param delete_only: Create an operator that deletes, but doesn't go to insert mode.
- :param with_register: Copy the deleted text to this named register instead of the clipboard.
- """
- if with_register:
- handler_keys = ('"', Keys.Any, 'cd'[delete_only])
- else:
- handler_keys = 'cd'[delete_only]
-
- @operator(*handler_keys, filter=~IsReadOnly())
- def delete_or_change_operator(event, text_object):
- clipboard_data = None
- buff = event.current_buffer
-
- if text_object:
- new_document, clipboard_data = text_object.cut(buff)
- buff.document = new_document
-
- # Set deleted/changed text to clipboard or named register.
- if clipboard_data and clipboard_data.text:
- if with_register:
- reg_name = event.key_sequence[1].data
- if reg_name in vi_register_names:
- event.cli.vi_state.named_registers[reg_name] = clipboard_data
- else:
- event.cli.clipboard.set_data(clipboard_data)
-
- # Only go back to insert mode in case of 'change'.
- if not delete_only:
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- create_delete_and_change_operators(False, False)
- create_delete_and_change_operators(False, True)
- create_delete_and_change_operators(True, False)
- create_delete_and_change_operators(True, True)
-
- def create_transform_handler(filter, transform_func, *a):
- @operator(*a, filter=filter & ~IsReadOnly())
- def _(event, text_object):
- """
- Apply transformation (uppercase, lowercase, rot13, swap case).
- """
- buff = event.current_buffer
- start, end = text_object.operator_range(buff.document)
-
- if start < end:
- # Transform.
- buff.transform_region(
- buff.cursor_position + start,
- buff.cursor_position + end,
- transform_func)
-
- # Move cursor
- buff.cursor_position += (text_object.end or text_object.start)
-
- for k, f, func in vi_transform_functions:
- create_transform_handler(f, func, *k)
-
- @operator('y')
- def yank_handler(event, text_object):
- """
- Yank operator. (Copy text.)
- """
- _, clipboard_data = text_object.cut(event.current_buffer)
- if clipboard_data.text:
- event.cli.clipboard.set_data(clipboard_data)
-
- @operator('"', Keys.Any, 'y')
- def _(event, text_object):
- " Yank selection to named register. "
- c = event.key_sequence[1].data
- if c in vi_register_names:
- _, clipboard_data = text_object.cut(event.current_buffer)
- event.cli.vi_state.named_registers[c] = clipboard_data
-
- @operator('>')
- def _(event, text_object):
- """
- Indent.
- """
- buff = event.current_buffer
- from_, to = text_object.get_line_numbers(buff)
- indent(buff, from_, to + 1, count=event.arg)
-
- @operator('<')
- def _(event, text_object):
- """
- Unindent.
- """
- buff = event.current_buffer
- from_, to = text_object.get_line_numbers(buff)
- unindent(buff, from_, to + 1, count=event.arg)
-
- @operator('g', 'q')
- def _(event, text_object):
- """
- Reshape text.
- """
- buff = event.current_buffer
- from_, to = text_object.get_line_numbers(buff)
- reshape_text(buff, from_, to)
-
- #
- # *** Text objects ***
- #
-
- @text_object('b')
- def _(event):
- """ Move one word or token left. """
- return TextObject(event.current_buffer.document.find_start_of_previous_word(count=event.arg) or 0)
-
- @text_object('B')
- def _(event):
- """ Move one non-blank word left """
- return TextObject(event.current_buffer.document.find_start_of_previous_word(count=event.arg, WORD=True) or 0)
-
- @text_object('$')
- def key_dollar(event):
- """ 'c$', 'd$' and '$': Delete/change/move until end of line. """
- return TextObject(event.current_buffer.document.get_end_of_line_position())
-
- @text_object('w')
- def _(event):
- """ 'word' forward. 'cw', 'dw', 'w': Delete/change/move one word. """
- return TextObject(event.current_buffer.document.find_next_word_beginning(count=event.arg) or
- event.current_buffer.document.get_end_of_document_position())
-
- @text_object('W')
- def _(event):
- """ 'WORD' forward. 'cW', 'dW', 'W': Delete/change/move one WORD. """
- return TextObject(event.current_buffer.document.find_next_word_beginning(count=event.arg, WORD=True) or
- event.current_buffer.document.get_end_of_document_position())
-
- @text_object('e')
- def _(event):
- """ End of 'word': 'ce', 'de', 'e' """
- end = event.current_buffer.document.find_next_word_ending(count=event.arg)
- return TextObject(end - 1 if end else 0, type=TextObjectType.INCLUSIVE)
-
- @text_object('E')
- def _(event):
- """ End of 'WORD': 'cE', 'dE', 'E' """
- end = event.current_buffer.document.find_next_word_ending(count=event.arg, WORD=True)
- return TextObject(end - 1 if end else 0, type=TextObjectType.INCLUSIVE)
-
- @text_object('i', 'w', no_move_handler=True)
- def _(event):
- """ Inner 'word': ciw and diw """
- start, end = event.current_buffer.document.find_boundaries_of_current_word()
- return TextObject(start, end)
-
- @text_object('a', 'w', no_move_handler=True)
- def _(event):
- """ A 'word': caw and daw """
- start, end = event.current_buffer.document.find_boundaries_of_current_word(include_trailing_whitespace=True)
- return TextObject(start, end)
-
- @text_object('i', 'W', no_move_handler=True)
- def _(event):
- """ Inner 'WORD': ciW and diW """
- start, end = event.current_buffer.document.find_boundaries_of_current_word(WORD=True)
- return TextObject(start, end)
-
- @text_object('a', 'W', no_move_handler=True)
- def _(event):
- """ A 'WORD': caw and daw """
- start, end = event.current_buffer.document.find_boundaries_of_current_word(WORD=True, include_trailing_whitespace=True)
- return TextObject(start, end)
-
- @text_object('a', 'p', no_move_handler=True)
- def _(event):
- """
- Auto paragraph.
- """
- start = event.current_buffer.document.start_of_paragraph()
- end = event.current_buffer.document.end_of_paragraph(count=event.arg)
- return TextObject(start, end)
-
- @text_object('^')
- def key_circumflex(event):
- """ 'c^', 'd^' and '^': Soft start of line, after whitespace. """
- return TextObject(event.current_buffer.document.get_start_of_line_position(after_whitespace=True))
-
- @text_object('0')
- def key_zero(event):
- """
- 'c0', 'd0': Hard start of line, before whitespace.
- (The move '0' key is implemented elsewhere, because a '0' could also change the `arg`.)
- """
- return TextObject(event.current_buffer.document.get_start_of_line_position(after_whitespace=False))
-
- def create_ci_ca_handles(ci_start, ci_end, inner, key=None):
- # TODO: 'dat', 'dit', (tags (like xml)
- """
- Delete/Change string between this start and stop character. But keep these characters.
- This implements all the ci", ci<, ci{, ci(, di", di<, ca", ca<, ... combinations.
- """
- def handler(event):
- if ci_start == ci_end:
- # Quotes
- start = event.current_buffer.document.find_backwards(ci_start, in_current_line=False)
- end = event.current_buffer.document.find(ci_end, in_current_line=False)
- else:
- # Brackets
- start = event.current_buffer.document.find_enclosing_bracket_left(ci_start, ci_end)
- end = event.current_buffer.document.find_enclosing_bracket_right(ci_start, ci_end)
-
- if start is not None and end is not None:
- offset = 0 if inner else 1
- return TextObject(start + 1 - offset, end + offset)
- else:
- # Nothing found.
- return TextObject(0)
-
- if key is None:
- text_object('ai'[inner], ci_start, no_move_handler=True)(handler)
- text_object('ai'[inner], ci_end, no_move_handler=True)(handler)
- else:
- text_object('ai'[inner], key, no_move_handler=True)(handler)
-
- for inner in (False, True):
- for ci_start, ci_end in [('"', '"'), ("'", "'"), ("`", "`"),
- ('[', ']'), ('<', '>'), ('{', '}'), ('(', ')')]:
- create_ci_ca_handles(ci_start, ci_end, inner)
-
- create_ci_ca_handles('(', ')', inner, 'b') # 'dab', 'dib'
- create_ci_ca_handles('{', '}', inner, 'B') # 'daB', 'diB'
-
- @text_object('{')
- def _(event):
- """
- Move to previous blank-line separated section.
- Implements '{', 'c{', 'd{', 'y{'
- """
- index = event.current_buffer.document.start_of_paragraph(
- count=event.arg, before=True)
- return TextObject(index)
-
- @text_object('}')
- def _(event):
- """
- Move to next blank-line separated section.
- Implements '}', 'c}', 'd}', 'y}'
- """
- index = event.current_buffer.document.end_of_paragraph(count=event.arg, after=True)
- return TextObject(index)
-
- @text_object('f', Keys.Any)
- def _(event):
- """
- Go to next occurance of character. Typing 'fx' will move the
- cursor to the next occurance of character. 'x'.
- """
- event.cli.vi_state.last_character_find = CharacterFind(event.data, False)
- match = event.current_buffer.document.find(
- event.data, in_current_line=True, count=event.arg)
- if match:
- return TextObject(match, type=TextObjectType.INCLUSIVE)
- else:
- return TextObject(0)
-
- @text_object('F', Keys.Any)
- def _(event):
- """
- Go to previous occurance of character. Typing 'Fx' will move the
- cursor to the previous occurance of character. 'x'.
- """
- event.cli.vi_state.last_character_find = CharacterFind(event.data, True)
- return TextObject(event.current_buffer.document.find_backwards(
- event.data, in_current_line=True, count=event.arg) or 0)
-
- @text_object('t', Keys.Any)
- def _(event):
- """
- Move right to the next occurance of c, then one char backward.
- """
- event.cli.vi_state.last_character_find = CharacterFind(event.data, False)
- match = event.current_buffer.document.find(
- event.data, in_current_line=True, count=event.arg)
- if match:
- return TextObject(match - 1, type=TextObjectType.INCLUSIVE)
- else:
- return TextObject(0)
-
- @text_object('T', Keys.Any)
- def _(event):
- """
- Move left to the previous occurance of c, then one char forward.
- """
- event.cli.vi_state.last_character_find = CharacterFind(event.data, True)
- match = event.current_buffer.document.find_backwards(
- event.data, in_current_line=True, count=event.arg)
- return TextObject(match + 1 if match else 0)
-
- def repeat(reverse):
- """
- Create ',' and ';' commands.
- """
- @text_object(',' if reverse else ';')
- def _(event):
- # Repeat the last 'f'/'F'/'t'/'T' command.
- pos = 0
- vi_state = event.cli.vi_state
-
- type = TextObjectType.EXCLUSIVE
-
- if vi_state.last_character_find:
- char = vi_state.last_character_find.character
- backwards = vi_state.last_character_find.backwards
-
- if reverse:
- backwards = not backwards
-
- if backwards:
- pos = event.current_buffer.document.find_backwards(char, in_current_line=True, count=event.arg)
- else:
- pos = event.current_buffer.document.find(char, in_current_line=True, count=event.arg)
- type = TextObjectType.INCLUSIVE
- if pos:
- return TextObject(pos, type=type)
- else:
- return TextObject(0)
- repeat(True)
- repeat(False)
-
- @text_object('h')
- @text_object(Keys.Left)
- def _(event):
- """ Implements 'ch', 'dh', 'h': Cursor left. """
- return TextObject(event.current_buffer.document.get_cursor_left_position(count=event.arg))
-
- @text_object('j', no_move_handler=True, no_selection_handler=True)
- # Note: We also need `no_selection_handler`, because we in
- # selection mode, we prefer the other 'j' binding that keeps
- # `buffer.preferred_column`.
- def _(event):
- """ Implements 'cj', 'dj', 'j', ... Cursor up. """
- return TextObject(event.current_buffer.document.get_cursor_down_position(count=event.arg),
- type=TextObjectType.LINEWISE)
-
- @text_object('k', no_move_handler=True, no_selection_handler=True)
- def _(event):
- """ Implements 'ck', 'dk', 'k', ... Cursor up. """
- return TextObject(event.current_buffer.document.get_cursor_up_position(count=event.arg),
- type=TextObjectType.LINEWISE)
-
- @text_object('l')
- @text_object(' ')
- @text_object(Keys.Right)
- def _(event):
- """ Implements 'cl', 'dl', 'l', 'c ', 'd ', ' '. Cursor right. """
- return TextObject(event.current_buffer.document.get_cursor_right_position(count=event.arg))
-
- @text_object('H')
- def _(event):
- """
- Moves to the start of the visible region. (Below the scroll offset.)
- Implements 'cH', 'dH', 'H'.
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- b = event.current_buffer
-
- if w and w.render_info:
- # When we find a Window that has BufferControl showing this window,
- # move to the start of the visible area.
- pos = (b.document.translate_row_col_to_index(
- w.render_info.first_visible_line(after_scroll_offset=True), 0) -
- b.cursor_position)
-
- else:
- # Otherwise, move to the start of the input.
- pos = -len(b.document.text_before_cursor)
- return TextObject(pos, type=TextObjectType.LINEWISE)
-
- @text_object('M')
- def _(event):
- """
- Moves cursor to the vertical center of the visible region.
- Implements 'cM', 'dM', 'M'.
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- b = event.current_buffer
-
- if w and w.render_info:
- # When we find a Window that has BufferControl showing this window,
- # move to the center of the visible area.
- pos = (b.document.translate_row_col_to_index(
- w.render_info.center_visible_line(), 0) -
- b.cursor_position)
-
- else:
- # Otherwise, move to the start of the input.
- pos = -len(b.document.text_before_cursor)
- return TextObject(pos, type=TextObjectType.LINEWISE)
-
- @text_object('L')
- def _(event):
- """
- Moves to the end of the visible region. (Above the scroll offset.)
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- b = event.current_buffer
-
- if w and w.render_info:
- # When we find a Window that has BufferControl showing this window,
- # move to the end of the visible area.
- pos = (b.document.translate_row_col_to_index(
- w.render_info.last_visible_line(before_scroll_offset=True), 0) -
- b.cursor_position)
-
- else:
- # Otherwise, move to the end of the input.
- pos = len(b.document.text_after_cursor)
- return TextObject(pos, type=TextObjectType.LINEWISE)
-
- @text_object('n', no_move_handler=True)
- def _(event):
- " Search next. "
- buff = event.current_buffer
- cursor_position = buff.get_search_position(
- get_search_state(event.cli), include_current_position=False,
- count=event.arg)
- return TextObject(cursor_position - buff.cursor_position)
-
- @handle('n', filter=navigation_mode)
- def _(event):
- " Search next in navigation mode. (This goes through the history.) "
- event.current_buffer.apply_search(
- get_search_state(event.cli), include_current_position=False,
- count=event.arg)
-
- @text_object('N', no_move_handler=True)
- def _(event):
- " Search previous. "
- buff = event.current_buffer
- cursor_position = buff.get_search_position(
- ~get_search_state(event.cli), include_current_position=False,
- count=event.arg)
- return TextObject(cursor_position - buff.cursor_position)
-
- @handle('N', filter=navigation_mode)
- def _(event):
- " Search previous in navigation mode. (This goes through the history.) "
- event.current_buffer.apply_search(
- ~get_search_state(event.cli), include_current_position=False,
- count=event.arg)
-
- @handle('z', '+', filter=navigation_mode|selection_mode)
- @handle('z', 't', filter=navigation_mode|selection_mode)
- @handle('z', Keys.ControlJ, filter=navigation_mode|selection_mode)
- def _(event):
- """
- Scrolls the window to makes the current line the first line in the visible region.
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- b = event.cli.current_buffer
- w.vertical_scroll = b.document.cursor_position_row
-
- @handle('z', '-', filter=navigation_mode|selection_mode)
- @handle('z', 'b', filter=navigation_mode|selection_mode)
- def _(event):
- """
- Scrolls the window to makes the current line the last line in the visible region.
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
-
- # We can safely set the scroll offset to zero; the Window will meke
- # sure that it scrolls at least enough to make the cursor visible
- # again.
- w.vertical_scroll = 0
-
- @handle('z', 'z', filter=navigation_mode|selection_mode)
- def _(event):
- """
- Center Window vertically around cursor.
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- b = event.cli.current_buffer
-
- if w and w.render_info:
- info = w.render_info
-
- # Calculate the offset that we need in order to position the row
- # containing the cursor in the center.
- scroll_height = info.window_height // 2
-
- y = max(0, b.document.cursor_position_row - 1)
- height = 0
- while y > 0:
- line_height = info.get_height_for_line(y)
-
- if height + line_height < scroll_height:
- height += line_height
- y -= 1
- else:
- break
-
- w.vertical_scroll = y
-
- @text_object('%')
- def _(event):
- """
- Implements 'c%', 'd%', '%, 'y%' (Move to corresponding bracket.)
- If an 'arg' has been given, go this this % position in the file.
- """
- buffer = event.current_buffer
-
- if event._arg:
- # If 'arg' has been given, the meaning of % is to go to the 'x%'
- # row in the file.
- if 0 < event.arg <= 100:
- absolute_index = buffer.document.translate_row_col_to_index(
- int((event.arg * buffer.document.line_count - 1) / 100), 0)
- return TextObject(absolute_index - buffer.document.cursor_position, type=TextObjectType.LINEWISE)
- else:
- return TextObject(0) # Do nothing.
-
- else:
- # Move to the corresponding opening/closing bracket (()'s, []'s and {}'s).
- match = buffer.document.find_matching_bracket_position()
- if match:
- return TextObject(match, type=TextObjectType.INCLUSIVE)
- else:
- return TextObject(0)
-
- @text_object('|')
- def _(event):
- # Move to the n-th column (you may specify the argument n by typing
- # it on number keys, for example, 20|).
- return TextObject(event.current_buffer.document.get_column_cursor_position(event.arg - 1))
-
- @text_object('g', 'g')
- def _(event):
- """
- Implements 'gg', 'cgg', 'ygg'
- """
- d = event.current_buffer.document
-
- if event._arg:
- # Move to the given line.
- return TextObject(d.translate_row_col_to_index(event.arg - 1, 0) - d.cursor_position, type=TextObjectType.LINEWISE)
- else:
- # Move to the top of the input.
- return TextObject(d.get_start_of_document_position(), type=TextObjectType.LINEWISE)
-
- @text_object('g', '_')
- def _(event):
- """
- Go to last non-blank of line.
- 'g_', 'cg_', 'yg_', etc..
- """
- return TextObject(
- event.current_buffer.document.last_non_blank_of_current_line_position(), type=TextObjectType.INCLUSIVE)
-
- @text_object('g', 'e')
- def _(event):
- """
- Go to last character of previous word.
- 'ge', 'cge', 'yge', etc..
- """
- prev_end = event.current_buffer.document.find_previous_word_ending(count=event.arg)
- return TextObject(prev_end - 1 if prev_end is not None else 0, type=TextObjectType.INCLUSIVE)
-
- @text_object('g', 'E')
- def _(event):
- """
- Go to last character of previous WORD.
- 'gE', 'cgE', 'ygE', etc..
- """
- prev_end = event.current_buffer.document.find_previous_word_ending(count=event.arg, WORD=True)
- return TextObject(prev_end - 1 if prev_end is not None else 0, type=TextObjectType.INCLUSIVE)
-
- @text_object('g', 'm')
- def _(event):
- """
- Like g0, but half a screenwidth to the right. (Or as much as possible.)
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- buff = event.current_buffer
-
- if w and w.render_info:
- width = w.render_info.window_width
- start = buff.document.get_start_of_line_position(after_whitespace=False)
- start += int(min(width / 2, len(buff.document.current_line)))
-
- return TextObject(start, type=TextObjectType.INCLUSIVE)
- return TextObject(0)
-
- @text_object('G')
- def _(event):
- """
- Go to the end of the document. (If no arg has been given.)
- """
- buf = event.current_buffer
- return TextObject(buf.document.translate_row_col_to_index(buf.document.line_count - 1, 0) -
- buf.cursor_position, type=TextObjectType.LINEWISE)
-
- #
- # *** Other ***
- #
-
- @handle('G', filter=HasArg())
- def _(event):
- """
- If an argument is given, move to this line in the history. (for
- example, 15G)
- """
- event.current_buffer.go_to_history(event.arg - 1)
-
- for n in '123456789':
- @handle(n, filter=navigation_mode|selection_mode|operator_given)
- def _(event):
- """
- Always handle numberics in navigation mode as arg.
- """
- event.append_to_arg_count(event.data)
-
- @handle('0', filter=(navigation_mode|selection_mode|operator_given) & HasArg())
- def _(event):
- " Zero when an argument was already give. "
- event.append_to_arg_count(event.data)
-
- @handle(Keys.Any, filter=replace_mode)
- def _(event):
- """
- Insert data at cursor position.
- """
- event.current_buffer.insert_text(event.data, overwrite=True)
-
- @handle(Keys.Any, filter=insert_multiple_mode,
- save_before=(lambda e: not e.is_repeat))
- def _(event):
- """
- Insert data at multiple cursor positions at once.
- (Usually a result of pressing 'I' or 'A' in block-selection mode.)
- """
- buff = event.current_buffer
- original_text = buff.text
-
- # Construct new text.
- text = []
- p = 0
-
- for p2 in buff.multiple_cursor_positions:
- text.append(original_text[p:p2])
- text.append(event.data)
- p = p2
-
- text.append(original_text[p:])
-
- # Shift all cursor positions.
- new_cursor_positions = [
- p + i + 1 for i, p in enumerate(buff.multiple_cursor_positions)]
-
- # Set result.
- buff.text = ''.join(text)
- buff.multiple_cursor_positions = new_cursor_positions
- buff.cursor_position += 1
-
- @handle(Keys.Backspace, filter=insert_multiple_mode)
- def _(event):
- " Backspace, using multiple cursors. "
- buff = event.current_buffer
- original_text = buff.text
-
- # Construct new text.
- deleted_something = False
- text = []
- p = 0
-
- for p2 in buff.multiple_cursor_positions:
- if p2 > 0 and original_text[p2 - 1] != '\n': # Don't delete across lines.
- text.append(original_text[p:p2 - 1])
- deleted_something = True
- else:
- text.append(original_text[p:p2])
- p = p2
-
- text.append(original_text[p:])
-
- if deleted_something:
- # Shift all cursor positions.
- lengths = [len(part) for part in text[:-1]]
- new_cursor_positions = list(accumulate(lengths))
-
- # Set result.
- buff.text = ''.join(text)
- buff.multiple_cursor_positions = new_cursor_positions
- buff.cursor_position -= 1
- else:
- event.cli.output.bell()
-
- @handle(Keys.Delete, filter=insert_multiple_mode)
- def _(event):
- " Delete, using multiple cursors. "
- buff = event.current_buffer
- original_text = buff.text
-
- # Construct new text.
- deleted_something = False
- text = []
- new_cursor_positions = []
- p = 0
-
- for p2 in buff.multiple_cursor_positions:
- text.append(original_text[p:p2])
- if p2 >= len(original_text) or original_text[p2] == '\n':
- # Don't delete across lines.
- p = p2
- else:
- p = p2 + 1
- deleted_something = True
-
- text.append(original_text[p:])
-
- if deleted_something:
- # Shift all cursor positions.
- lengths = [len(part) for part in text[:-1]]
- new_cursor_positions = list(accumulate(lengths))
-
- # Set result.
- buff.text = ''.join(text)
- buff.multiple_cursor_positions = new_cursor_positions
- else:
- event.cli.output.bell()
-
-
- @handle(Keys.ControlX, Keys.ControlL, filter=insert_mode)
- def _(event):
- """
- Pressing the ControlX - ControlL sequence in Vi mode does line
- completion based on the other lines in the document and the history.
- """
- event.current_buffer.start_history_lines_completion()
-
- @handle(Keys.ControlX, Keys.ControlF, filter=insert_mode)
- def _(event):
- """
- Complete file names.
- """
- # TODO
- pass
-
- @handle(Keys.ControlK, filter=insert_mode|replace_mode)
- def _(event):
- " Go into digraph mode. "
- event.cli.vi_state.waiting_for_digraph = True
-
- @Condition
- def digraph_symbol_1_given(cli):
- return cli.vi_state.digraph_symbol1 is not None
-
- @handle(Keys.Any, filter=digraph_mode & ~digraph_symbol_1_given)
- def _(event):
- event.cli.vi_state.digraph_symbol1 = event.data
-
- @handle(Keys.Any, filter=digraph_mode & digraph_symbol_1_given)
- def _(event):
- " Insert digraph. "
- try:
- # Lookup.
- code = (event.cli.vi_state.digraph_symbol1, event.data)
- if code not in DIGRAPHS:
- code = code[::-1] # Try reversing.
- symbol = DIGRAPHS[code]
- except KeyError:
- # Unkown digraph.
- event.cli.output.bell()
- else:
- # Insert digraph.
- overwrite = event.cli.vi_state.input_mode == InputMode.REPLACE
- event.current_buffer.insert_text(
- six.unichr(symbol), overwrite=overwrite)
- event.cli.vi_state.waiting_for_digraph = False
- finally:
- event.cli.vi_state.waiting_for_digraph = False
- event.cli.vi_state.digraph_symbol1 = None
-
- return registry
-
-
-def load_vi_open_in_editor_bindings():
- """
- Pressing 'v' in navigation mode will open the buffer in an external editor.
- """
- registry = Registry()
- navigation_mode = ViNavigationMode()
-
- registry.add_binding('v', filter=navigation_mode)(
- get_by_name('edit-and-execute-command'))
- return registry
-
-
-def load_vi_system_bindings():
- registry = ConditionalRegistry(Registry(), ViMode())
- handle = registry.add_binding
-
- has_focus = filters.HasFocus(SYSTEM_BUFFER)
- navigation_mode = ViNavigationMode()
-
- @handle('!', filter=~has_focus & navigation_mode)
- def _(event):
- """
- '!' opens the system prompt.
- """
- event.cli.push_focus(SYSTEM_BUFFER)
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle(Keys.Escape, filter=has_focus)
- @handle(Keys.ControlC, filter=has_focus)
- def _(event):
- """
- Cancel system prompt.
- """
- event.cli.vi_state.input_mode = InputMode.NAVIGATION
- event.cli.buffers[SYSTEM_BUFFER].reset()
- event.cli.pop_focus()
-
- @handle(Keys.ControlJ, filter=has_focus)
- def _(event):
- """
- Run system command.
- """
- event.cli.vi_state.input_mode = InputMode.NAVIGATION
-
- system_buffer = event.cli.buffers[SYSTEM_BUFFER]
- event.cli.run_system_command(system_buffer.text)
- system_buffer.reset(append_to_history=True)
-
- # Focus previous buffer again.
- event.cli.pop_focus()
-
- return registry
-
-
-def load_vi_search_bindings(get_search_state=None,
- search_buffer_name=SEARCH_BUFFER):
- assert get_search_state is None or callable(get_search_state)
-
- if not get_search_state:
- def get_search_state(cli): return cli.search_state
-
- registry = ConditionalRegistry(Registry(), ViMode())
- handle = registry.add_binding
-
- has_focus = filters.HasFocus(search_buffer_name)
- navigation_mode = ViNavigationMode()
- selection_mode = ViSelectionMode()
-
- reverse_vi_search_direction = Condition(
- lambda cli: cli.application.reverse_vi_search_direction(cli))
-
- @handle('/', filter=(navigation_mode|selection_mode)&~reverse_vi_search_direction)
- @handle('?', filter=(navigation_mode|selection_mode)&reverse_vi_search_direction)
- @handle(Keys.ControlS, filter=~has_focus)
- def _(event):
- """
- Vi-style forward search.
- """
- # Set the ViState.
- get_search_state(event.cli).direction = IncrementalSearchDirection.FORWARD
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- # Focus search buffer.
- event.cli.push_focus(search_buffer_name)
-
- @handle('?', filter=(navigation_mode|selection_mode)&~reverse_vi_search_direction)
- @handle('/', filter=(navigation_mode|selection_mode)&reverse_vi_search_direction)
- @handle(Keys.ControlR, filter=~has_focus)
- def _(event):
- """
- Vi-style backward search.
- """
- # Set the ViState.
- get_search_state(event.cli).direction = IncrementalSearchDirection.BACKWARD
-
- # Focus search buffer.
- event.cli.push_focus(search_buffer_name)
- event.cli.vi_state.input_mode = InputMode.INSERT
-
- @handle(Keys.ControlJ, filter=has_focus)
- @handle(Keys.Escape, filter=has_focus)
- def _(event):
- """
- Apply the search. (At the / or ? prompt.)
- """
- input_buffer = event.cli.buffers.previous(event.cli)
- search_buffer = event.cli.buffers[search_buffer_name]
-
- # Update search state.
- if search_buffer.text:
- get_search_state(event.cli).text = search_buffer.text
-
- # Apply search.
- input_buffer.apply_search(get_search_state(event.cli))
-
- # Add query to history of search line.
- search_buffer.append_to_history()
- search_buffer.reset()
-
- # Focus previous document again.
- event.cli.vi_state.input_mode = InputMode.NAVIGATION
- event.cli.pop_focus()
-
- def incremental_search(cli, direction, count=1):
- " Apply search, but keep search buffer focussed. "
- # Update search_state.
- search_state = get_search_state(cli)
- direction_changed = search_state.direction != direction
-
- search_state.text = cli.buffers[search_buffer_name].text
- search_state.direction = direction
-
- # Apply search to current buffer.
- if not direction_changed:
- input_buffer = cli.buffers.previous(cli)
- input_buffer.apply_search(search_state,
- include_current_position=False, count=count)
-
- @handle(Keys.ControlR, filter=has_focus)
- def _(event):
- incremental_search(event.cli, IncrementalSearchDirection.BACKWARD, count=event.arg)
-
- @handle(Keys.ControlS, filter=has_focus)
- def _(event):
- incremental_search(event.cli, IncrementalSearchDirection.FORWARD, count=event.arg)
-
- def search_buffer_is_empty(cli):
- """ Returns True when the search buffer is empty. """
- return cli.buffers[search_buffer_name].text == ''
-
- @handle(Keys.ControlC, filter=has_focus)
- @handle(Keys.ControlH, filter=has_focus & Condition(search_buffer_is_empty))
- @handle(Keys.Backspace, filter=has_focus & Condition(search_buffer_is_empty))
- def _(event):
- """
- Cancel search.
- """
- event.cli.vi_state.input_mode = InputMode.NAVIGATION
-
- event.cli.pop_focus()
- event.cli.buffers[search_buffer_name].reset()
-
- return registry
-
-
-def load_extra_vi_page_navigation_bindings():
- """
- Key bindings, for scrolling up and down through pages.
- This are separate bindings, because GNU readline doesn't have them.
- """
- registry = ConditionalRegistry(Registry(), ViMode())
- handle = registry.add_binding
-
- handle(Keys.ControlF)(scroll_forward)
- handle(Keys.ControlB)(scroll_backward)
- handle(Keys.ControlD)(scroll_half_page_down)
- handle(Keys.ControlU)(scroll_half_page_up)
- handle(Keys.ControlE)(scroll_one_line_down)
- handle(Keys.ControlY)(scroll_one_line_up)
- handle(Keys.PageDown)(scroll_page_down)
- handle(Keys.PageUp)(scroll_page_up)
-
- return registry
-
-
-class ViStateFilter(Filter):
- " Deprecated! "
- def __init__(self, get_vi_state, mode):
- self.get_vi_state = get_vi_state
- self.mode = mode
-
- def __call__(self, cli):
- return self.get_vi_state(cli).input_mode == self.mode
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/defaults.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/defaults.py
deleted file mode 100644
index fb2c1070f7..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/defaults.py
+++ /dev/null
@@ -1,119 +0,0 @@
-"""
-Default key bindings.::
-
- registry = load_key_bindings()
- app = Application(key_bindings_registry=registry)
-"""
-from __future__ import unicode_literals
-from prompt_toolkit.key_binding.registry import ConditionalRegistry, MergedRegistry
-from prompt_toolkit.key_binding.bindings.basic import load_basic_bindings, load_abort_and_exit_bindings, load_basic_system_bindings, load_auto_suggestion_bindings, load_mouse_bindings
-from prompt_toolkit.key_binding.bindings.emacs import load_emacs_bindings, load_emacs_system_bindings, load_emacs_search_bindings, load_emacs_open_in_editor_bindings, load_extra_emacs_page_navigation_bindings
-from prompt_toolkit.key_binding.bindings.vi import load_vi_bindings, load_vi_system_bindings, load_vi_search_bindings, load_vi_open_in_editor_bindings, load_extra_vi_page_navigation_bindings
-from prompt_toolkit.filters import to_cli_filter
-
-__all__ = (
- 'load_key_bindings',
- 'load_key_bindings_for_prompt',
-)
-
-
-def load_key_bindings(
- get_search_state=None,
- enable_abort_and_exit_bindings=False,
- enable_system_bindings=False,
- enable_search=False,
- enable_open_in_editor=False,
- enable_extra_page_navigation=False,
- enable_auto_suggest_bindings=False):
- """
- Create a Registry object that contains the default key bindings.
-
- :param enable_abort_and_exit_bindings: Filter to enable Ctrl-C and Ctrl-D.
- :param enable_system_bindings: Filter to enable the system bindings (meta-!
- prompt and Control-Z suspension.)
- :param enable_search: Filter to enable the search bindings.
- :param enable_open_in_editor: Filter to enable open-in-editor.
- :param enable_open_in_editor: Filter to enable open-in-editor.
- :param enable_extra_page_navigation: Filter for enabling extra page
- navigation. (Bindings for up/down scrolling through long pages, like in
- Emacs or Vi.)
- :param enable_auto_suggest_bindings: Filter to enable fish-style suggestions.
- """
-
- assert get_search_state is None or callable(get_search_state)
-
- # Accept both Filters and booleans as input.
- enable_abort_and_exit_bindings = to_cli_filter(enable_abort_and_exit_bindings)
- enable_system_bindings = to_cli_filter(enable_system_bindings)
- enable_search = to_cli_filter(enable_search)
- enable_open_in_editor = to_cli_filter(enable_open_in_editor)
- enable_extra_page_navigation = to_cli_filter(enable_extra_page_navigation)
- enable_auto_suggest_bindings = to_cli_filter(enable_auto_suggest_bindings)
-
- registry = MergedRegistry([
- # Load basic bindings.
- load_basic_bindings(),
- load_mouse_bindings(),
-
- ConditionalRegistry(load_abort_and_exit_bindings(),
- enable_abort_and_exit_bindings),
-
- ConditionalRegistry(load_basic_system_bindings(),
- enable_system_bindings),
-
- # Load emacs bindings.
- load_emacs_bindings(),
-
- ConditionalRegistry(load_emacs_open_in_editor_bindings(),
- enable_open_in_editor),
-
- ConditionalRegistry(load_emacs_search_bindings(get_search_state=get_search_state),
- enable_search),
-
- ConditionalRegistry(load_emacs_system_bindings(),
- enable_system_bindings),
-
- ConditionalRegistry(load_extra_emacs_page_navigation_bindings(),
- enable_extra_page_navigation),
-
- # Load Vi bindings.
- load_vi_bindings(get_search_state=get_search_state),
-
- ConditionalRegistry(load_vi_open_in_editor_bindings(),
- enable_open_in_editor),
-
- ConditionalRegistry(load_vi_search_bindings(get_search_state=get_search_state),
- enable_search),
-
- ConditionalRegistry(load_vi_system_bindings(),
- enable_system_bindings),
-
- ConditionalRegistry(load_extra_vi_page_navigation_bindings(),
- enable_extra_page_navigation),
-
- # Suggestion bindings.
- # (This has to come at the end, because the Vi bindings also have an
- # implementation for the "right arrow", but we really want the
- # suggestion binding when a suggestion is available.)
- ConditionalRegistry(load_auto_suggestion_bindings(),
- enable_auto_suggest_bindings),
- ])
-
- return registry
-
-
-def load_key_bindings_for_prompt(**kw):
- """
- Create a ``Registry`` object with the defaults key bindings for an input
- prompt.
-
- This activates the key bindings for abort/exit (Ctrl-C/Ctrl-D),
- incremental search and auto suggestions.
-
- (Not for full screen applications.)
- """
- kw.setdefault('enable_abort_and_exit_bindings', True)
- kw.setdefault('enable_search', True)
- kw.setdefault('enable_auto_suggest_bindings', True)
-
- return load_key_bindings(**kw)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/digraphs.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/digraphs.py
deleted file mode 100644
index 36c6b15103..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/digraphs.py
+++ /dev/null
@@ -1,1378 +0,0 @@
-# encoding: utf-8
-from __future__ import unicode_literals
-"""
-Vi Digraphs.
-This is a list of special characters that can be inserted in Vi insert mode by
-pressing Control-K followed by to normal characters.
-
-Taken from Neovim and translated to Python:
-https://raw.githubusercontent.com/neovim/neovim/master/src/nvim/digraph.c
-"""
-__all__ = ('DIGRAPHS', )
-
-# digraphs for Unicode from RFC1345
-# (also work for ISO-8859-1 aka latin1)
-DIGRAPHS = {
- ('N', 'U'): 0x00,
- ('S', 'H'): 0x01,
- ('S', 'X'): 0x02,
- ('E', 'X'): 0x03,
- ('E', 'T'): 0x04,
- ('E', 'Q'): 0x05,
- ('A', 'K'): 0x06,
- ('B', 'L'): 0x07,
- ('B', 'S'): 0x08,
- ('H', 'T'): 0x09,
- ('L', 'F'): 0x0a,
- ('V', 'T'): 0x0b,
- ('F', 'F'): 0x0c,
- ('C', 'R'): 0x0d,
- ('S', 'O'): 0x0e,
- ('S', 'I'): 0x0f,
- ('D', 'L'): 0x10,
- ('D', '1'): 0x11,
- ('D', '2'): 0x12,
- ('D', '3'): 0x13,
- ('D', '4'): 0x14,
- ('N', 'K'): 0x15,
- ('S', 'Y'): 0x16,
- ('E', 'B'): 0x17,
- ('C', 'N'): 0x18,
- ('E', 'M'): 0x19,
- ('S', 'B'): 0x1a,
- ('E', 'C'): 0x1b,
- ('F', 'S'): 0x1c,
- ('G', 'S'): 0x1d,
- ('R', 'S'): 0x1e,
- ('U', 'S'): 0x1f,
- ('S', 'P'): 0x20,
- ('N', 'b'): 0x23,
- ('D', 'O'): 0x24,
- ('A', 't'): 0x40,
- ('<', '('): 0x5b,
- ('/', '/'): 0x5c,
- (')', '>'): 0x5d,
- ('\'', '>'): 0x5e,
- ('\'', '!'): 0x60,
- ('(', '!'): 0x7b,
- ('!', '!'): 0x7c,
- ('!', ')'): 0x7d,
- ('\'', '?'): 0x7e,
- ('D', 'T'): 0x7f,
- ('P', 'A'): 0x80,
- ('H', 'O'): 0x81,
- ('B', 'H'): 0x82,
- ('N', 'H'): 0x83,
- ('I', 'N'): 0x84,
- ('N', 'L'): 0x85,
- ('S', 'A'): 0x86,
- ('E', 'S'): 0x87,
- ('H', 'S'): 0x88,
- ('H', 'J'): 0x89,
- ('V', 'S'): 0x8a,
- ('P', 'D'): 0x8b,
- ('P', 'U'): 0x8c,
- ('R', 'I'): 0x8d,
- ('S', '2'): 0x8e,
- ('S', '3'): 0x8f,
- ('D', 'C'): 0x90,
- ('P', '1'): 0x91,
- ('P', '2'): 0x92,
- ('T', 'S'): 0x93,
- ('C', 'C'): 0x94,
- ('M', 'W'): 0x95,
- ('S', 'G'): 0x96,
- ('E', 'G'): 0x97,
- ('S', 'S'): 0x98,
- ('G', 'C'): 0x99,
- ('S', 'C'): 0x9a,
- ('C', 'I'): 0x9b,
- ('S', 'T'): 0x9c,
- ('O', 'C'): 0x9d,
- ('P', 'M'): 0x9e,
- ('A', 'C'): 0x9f,
- ('N', 'S'): 0xa0,
- ('!', 'I'): 0xa1,
- ('C', 't'): 0xa2,
- ('P', 'd'): 0xa3,
- ('C', 'u'): 0xa4,
- ('Y', 'e'): 0xa5,
- ('B', 'B'): 0xa6,
- ('S', 'E'): 0xa7,
- ('\'', ':'): 0xa8,
- ('C', 'o'): 0xa9,
- ('-', 'a'): 0xaa,
- ('<', '<'): 0xab,
- ('N', 'O'): 0xac,
- ('-', '-'): 0xad,
- ('R', 'g'): 0xae,
- ('\'', 'm'): 0xaf,
- ('D', 'G'): 0xb0,
- ('+', '-'): 0xb1,
- ('2', 'S'): 0xb2,
- ('3', 'S'): 0xb3,
- ('\'', '\''): 0xb4,
- ('M', 'y'): 0xb5,
- ('P', 'I'): 0xb6,
- ('.', 'M'): 0xb7,
- ('\'', ','): 0xb8,
- ('1', 'S'): 0xb9,
- ('-', 'o'): 0xba,
- ('>', '>'): 0xbb,
- ('1', '4'): 0xbc,
- ('1', '2'): 0xbd,
- ('3', '4'): 0xbe,
- ('?', 'I'): 0xbf,
- ('A', '!'): 0xc0,
- ('A', '\''): 0xc1,
- ('A', '>'): 0xc2,
- ('A', '?'): 0xc3,
- ('A', ':'): 0xc4,
- ('A', 'A'): 0xc5,
- ('A', 'E'): 0xc6,
- ('C', ','): 0xc7,
- ('E', '!'): 0xc8,
- ('E', '\''): 0xc9,
- ('E', '>'): 0xca,
- ('E', ':'): 0xcb,
- ('I', '!'): 0xcc,
- ('I', '\''): 0xcd,
- ('I', '>'): 0xce,
- ('I', ':'): 0xcf,
- ('D', '-'): 0xd0,
- ('N', '?'): 0xd1,
- ('O', '!'): 0xd2,
- ('O', '\''): 0xd3,
- ('O', '>'): 0xd4,
- ('O', '?'): 0xd5,
- ('O', ':'): 0xd6,
- ('*', 'X'): 0xd7,
- ('O', '/'): 0xd8,
- ('U', '!'): 0xd9,
- ('U', '\''): 0xda,
- ('U', '>'): 0xdb,
- ('U', ':'): 0xdc,
- ('Y', '\''): 0xdd,
- ('T', 'H'): 0xde,
- ('s', 's'): 0xdf,
- ('a', '!'): 0xe0,
- ('a', '\''): 0xe1,
- ('a', '>'): 0xe2,
- ('a', '?'): 0xe3,
- ('a', ':'): 0xe4,
- ('a', 'a'): 0xe5,
- ('a', 'e'): 0xe6,
- ('c', ','): 0xe7,
- ('e', '!'): 0xe8,
- ('e', '\''): 0xe9,
- ('e', '>'): 0xea,
- ('e', ':'): 0xeb,
- ('i', '!'): 0xec,
- ('i', '\''): 0xed,
- ('i', '>'): 0xee,
- ('i', ':'): 0xef,
- ('d', '-'): 0xf0,
- ('n', '?'): 0xf1,
- ('o', '!'): 0xf2,
- ('o', '\''): 0xf3,
- ('o', '>'): 0xf4,
- ('o', '?'): 0xf5,
- ('o', ':'): 0xf6,
- ('-', ':'): 0xf7,
- ('o', '/'): 0xf8,
- ('u', '!'): 0xf9,
- ('u', '\''): 0xfa,
- ('u', '>'): 0xfb,
- ('u', ':'): 0xfc,
- ('y', '\''): 0xfd,
- ('t', 'h'): 0xfe,
- ('y', ':'): 0xff,
-
- ('A', '-'): 0x0100,
- ('a', '-'): 0x0101,
- ('A', '('): 0x0102,
- ('a', '('): 0x0103,
- ('A', ';'): 0x0104,
- ('a', ';'): 0x0105,
- ('C', '\''): 0x0106,
- ('c', '\''): 0x0107,
- ('C', '>'): 0x0108,
- ('c', '>'): 0x0109,
- ('C', '.'): 0x010a,
- ('c', '.'): 0x010b,
- ('C', '<'): 0x010c,
- ('c', '<'): 0x010d,
- ('D', '<'): 0x010e,
- ('d', '<'): 0x010f,
- ('D', '/'): 0x0110,
- ('d', '/'): 0x0111,
- ('E', '-'): 0x0112,
- ('e', '-'): 0x0113,
- ('E', '('): 0x0114,
- ('e', '('): 0x0115,
- ('E', '.'): 0x0116,
- ('e', '.'): 0x0117,
- ('E', ';'): 0x0118,
- ('e', ';'): 0x0119,
- ('E', '<'): 0x011a,
- ('e', '<'): 0x011b,
- ('G', '>'): 0x011c,
- ('g', '>'): 0x011d,
- ('G', '('): 0x011e,
- ('g', '('): 0x011f,
- ('G', '.'): 0x0120,
- ('g', '.'): 0x0121,
- ('G', ','): 0x0122,
- ('g', ','): 0x0123,
- ('H', '>'): 0x0124,
- ('h', '>'): 0x0125,
- ('H', '/'): 0x0126,
- ('h', '/'): 0x0127,
- ('I', '?'): 0x0128,
- ('i', '?'): 0x0129,
- ('I', '-'): 0x012a,
- ('i', '-'): 0x012b,
- ('I', '('): 0x012c,
- ('i', '('): 0x012d,
- ('I', ';'): 0x012e,
- ('i', ';'): 0x012f,
- ('I', '.'): 0x0130,
- ('i', '.'): 0x0131,
- ('I', 'J'): 0x0132,
- ('i', 'j'): 0x0133,
- ('J', '>'): 0x0134,
- ('j', '>'): 0x0135,
- ('K', ','): 0x0136,
- ('k', ','): 0x0137,
- ('k', 'k'): 0x0138,
- ('L', '\''): 0x0139,
- ('l', '\''): 0x013a,
- ('L', ','): 0x013b,
- ('l', ','): 0x013c,
- ('L', '<'): 0x013d,
- ('l', '<'): 0x013e,
- ('L', '.'): 0x013f,
- ('l', '.'): 0x0140,
- ('L', '/'): 0x0141,
- ('l', '/'): 0x0142,
- ('N', '\''): 0x0143,
- ('n', '\''): 0x0144,
- ('N', ','): 0x0145,
- ('n', ','): 0x0146,
- ('N', '<'): 0x0147,
- ('n', '<'): 0x0148,
- ('\'', 'n'): 0x0149,
- ('N', 'G'): 0x014a,
- ('n', 'g'): 0x014b,
- ('O', '-'): 0x014c,
- ('o', '-'): 0x014d,
- ('O', '('): 0x014e,
- ('o', '('): 0x014f,
- ('O', '"'): 0x0150,
- ('o', '"'): 0x0151,
- ('O', 'E'): 0x0152,
- ('o', 'e'): 0x0153,
- ('R', '\''): 0x0154,
- ('r', '\''): 0x0155,
- ('R', ','): 0x0156,
- ('r', ','): 0x0157,
- ('R', '<'): 0x0158,
- ('r', '<'): 0x0159,
- ('S', '\''): 0x015a,
- ('s', '\''): 0x015b,
- ('S', '>'): 0x015c,
- ('s', '>'): 0x015d,
- ('S', ','): 0x015e,
- ('s', ','): 0x015f,
- ('S', '<'): 0x0160,
- ('s', '<'): 0x0161,
- ('T', ','): 0x0162,
- ('t', ','): 0x0163,
- ('T', '<'): 0x0164,
- ('t', '<'): 0x0165,
- ('T', '/'): 0x0166,
- ('t', '/'): 0x0167,
- ('U', '?'): 0x0168,
- ('u', '?'): 0x0169,
- ('U', '-'): 0x016a,
- ('u', '-'): 0x016b,
- ('U', '('): 0x016c,
- ('u', '('): 0x016d,
- ('U', '0'): 0x016e,
- ('u', '0'): 0x016f,
- ('U', '"'): 0x0170,
- ('u', '"'): 0x0171,
- ('U', ';'): 0x0172,
- ('u', ';'): 0x0173,
- ('W', '>'): 0x0174,
- ('w', '>'): 0x0175,
- ('Y', '>'): 0x0176,
- ('y', '>'): 0x0177,
- ('Y', ':'): 0x0178,
- ('Z', '\''): 0x0179,
- ('z', '\''): 0x017a,
- ('Z', '.'): 0x017b,
- ('z', '.'): 0x017c,
- ('Z', '<'): 0x017d,
- ('z', '<'): 0x017e,
- ('O', '9'): 0x01a0,
- ('o', '9'): 0x01a1,
- ('O', 'I'): 0x01a2,
- ('o', 'i'): 0x01a3,
- ('y', 'r'): 0x01a6,
- ('U', '9'): 0x01af,
- ('u', '9'): 0x01b0,
- ('Z', '/'): 0x01b5,
- ('z', '/'): 0x01b6,
- ('E', 'D'): 0x01b7,
- ('A', '<'): 0x01cd,
- ('a', '<'): 0x01ce,
- ('I', '<'): 0x01cf,
- ('i', '<'): 0x01d0,
- ('O', '<'): 0x01d1,
- ('o', '<'): 0x01d2,
- ('U', '<'): 0x01d3,
- ('u', '<'): 0x01d4,
- ('A', '1'): 0x01de,
- ('a', '1'): 0x01df,
- ('A', '7'): 0x01e0,
- ('a', '7'): 0x01e1,
- ('A', '3'): 0x01e2,
- ('a', '3'): 0x01e3,
- ('G', '/'): 0x01e4,
- ('g', '/'): 0x01e5,
- ('G', '<'): 0x01e6,
- ('g', '<'): 0x01e7,
- ('K', '<'): 0x01e8,
- ('k', '<'): 0x01e9,
- ('O', ';'): 0x01ea,
- ('o', ';'): 0x01eb,
- ('O', '1'): 0x01ec,
- ('o', '1'): 0x01ed,
- ('E', 'Z'): 0x01ee,
- ('e', 'z'): 0x01ef,
- ('j', '<'): 0x01f0,
- ('G', '\''): 0x01f4,
- ('g', '\''): 0x01f5,
- (';', 'S'): 0x02bf,
- ('\'', '<'): 0x02c7,
- ('\'', '('): 0x02d8,
- ('\'', '.'): 0x02d9,
- ('\'', '0'): 0x02da,
- ('\'', ';'): 0x02db,
- ('\'', '"'): 0x02dd,
- ('A', '%'): 0x0386,
- ('E', '%'): 0x0388,
- ('Y', '%'): 0x0389,
- ('I', '%'): 0x038a,
- ('O', '%'): 0x038c,
- ('U', '%'): 0x038e,
- ('W', '%'): 0x038f,
- ('i', '3'): 0x0390,
- ('A', '*'): 0x0391,
- ('B', '*'): 0x0392,
- ('G', '*'): 0x0393,
- ('D', '*'): 0x0394,
- ('E', '*'): 0x0395,
- ('Z', '*'): 0x0396,
- ('Y', '*'): 0x0397,
- ('H', '*'): 0x0398,
- ('I', '*'): 0x0399,
- ('K', '*'): 0x039a,
- ('L', '*'): 0x039b,
- ('M', '*'): 0x039c,
- ('N', '*'): 0x039d,
- ('C', '*'): 0x039e,
- ('O', '*'): 0x039f,
- ('P', '*'): 0x03a0,
- ('R', '*'): 0x03a1,
- ('S', '*'): 0x03a3,
- ('T', '*'): 0x03a4,
- ('U', '*'): 0x03a5,
- ('F', '*'): 0x03a6,
- ('X', '*'): 0x03a7,
- ('Q', '*'): 0x03a8,
- ('W', '*'): 0x03a9,
- ('J', '*'): 0x03aa,
- ('V', '*'): 0x03ab,
- ('a', '%'): 0x03ac,
- ('e', '%'): 0x03ad,
- ('y', '%'): 0x03ae,
- ('i', '%'): 0x03af,
- ('u', '3'): 0x03b0,
- ('a', '*'): 0x03b1,
- ('b', '*'): 0x03b2,
- ('g', '*'): 0x03b3,
- ('d', '*'): 0x03b4,
- ('e', '*'): 0x03b5,
- ('z', '*'): 0x03b6,
- ('y', '*'): 0x03b7,
- ('h', '*'): 0x03b8,
- ('i', '*'): 0x03b9,
- ('k', '*'): 0x03ba,
- ('l', '*'): 0x03bb,
- ('m', '*'): 0x03bc,
- ('n', '*'): 0x03bd,
- ('c', '*'): 0x03be,
- ('o', '*'): 0x03bf,
- ('p', '*'): 0x03c0,
- ('r', '*'): 0x03c1,
- ('*', 's'): 0x03c2,
- ('s', '*'): 0x03c3,
- ('t', '*'): 0x03c4,
- ('u', '*'): 0x03c5,
- ('f', '*'): 0x03c6,
- ('x', '*'): 0x03c7,
- ('q', '*'): 0x03c8,
- ('w', '*'): 0x03c9,
- ('j', '*'): 0x03ca,
- ('v', '*'): 0x03cb,
- ('o', '%'): 0x03cc,
- ('u', '%'): 0x03cd,
- ('w', '%'): 0x03ce,
- ('\'', 'G'): 0x03d8,
- (',', 'G'): 0x03d9,
- ('T', '3'): 0x03da,
- ('t', '3'): 0x03db,
- ('M', '3'): 0x03dc,
- ('m', '3'): 0x03dd,
- ('K', '3'): 0x03de,
- ('k', '3'): 0x03df,
- ('P', '3'): 0x03e0,
- ('p', '3'): 0x03e1,
- ('\'', '%'): 0x03f4,
- ('j', '3'): 0x03f5,
- ('I', 'O'): 0x0401,
- ('D', '%'): 0x0402,
- ('G', '%'): 0x0403,
- ('I', 'E'): 0x0404,
- ('D', 'S'): 0x0405,
- ('I', 'I'): 0x0406,
- ('Y', 'I'): 0x0407,
- ('J', '%'): 0x0408,
- ('L', 'J'): 0x0409,
- ('N', 'J'): 0x040a,
- ('T', 's'): 0x040b,
- ('K', 'J'): 0x040c,
- ('V', '%'): 0x040e,
- ('D', 'Z'): 0x040f,
- ('A', '='): 0x0410,
- ('B', '='): 0x0411,
- ('V', '='): 0x0412,
- ('G', '='): 0x0413,
- ('D', '='): 0x0414,
- ('E', '='): 0x0415,
- ('Z', '%'): 0x0416,
- ('Z', '='): 0x0417,
- ('I', '='): 0x0418,
- ('J', '='): 0x0419,
- ('K', '='): 0x041a,
- ('L', '='): 0x041b,
- ('M', '='): 0x041c,
- ('N', '='): 0x041d,
- ('O', '='): 0x041e,
- ('P', '='): 0x041f,
- ('R', '='): 0x0420,
- ('S', '='): 0x0421,
- ('T', '='): 0x0422,
- ('U', '='): 0x0423,
- ('F', '='): 0x0424,
- ('H', '='): 0x0425,
- ('C', '='): 0x0426,
- ('C', '%'): 0x0427,
- ('S', '%'): 0x0428,
- ('S', 'c'): 0x0429,
- ('=', '"'): 0x042a,
- ('Y', '='): 0x042b,
- ('%', '"'): 0x042c,
- ('J', 'E'): 0x042d,
- ('J', 'U'): 0x042e,
- ('J', 'A'): 0x042f,
- ('a', '='): 0x0430,
- ('b', '='): 0x0431,
- ('v', '='): 0x0432,
- ('g', '='): 0x0433,
- ('d', '='): 0x0434,
- ('e', '='): 0x0435,
- ('z', '%'): 0x0436,
- ('z', '='): 0x0437,
- ('i', '='): 0x0438,
- ('j', '='): 0x0439,
- ('k', '='): 0x043a,
- ('l', '='): 0x043b,
- ('m', '='): 0x043c,
- ('n', '='): 0x043d,
- ('o', '='): 0x043e,
- ('p', '='): 0x043f,
- ('r', '='): 0x0440,
- ('s', '='): 0x0441,
- ('t', '='): 0x0442,
- ('u', '='): 0x0443,
- ('f', '='): 0x0444,
- ('h', '='): 0x0445,
- ('c', '='): 0x0446,
- ('c', '%'): 0x0447,
- ('s', '%'): 0x0448,
- ('s', 'c'): 0x0449,
- ('=', '\''): 0x044a,
- ('y', '='): 0x044b,
- ('%', '\''): 0x044c,
- ('j', 'e'): 0x044d,
- ('j', 'u'): 0x044e,
- ('j', 'a'): 0x044f,
- ('i', 'o'): 0x0451,
- ('d', '%'): 0x0452,
- ('g', '%'): 0x0453,
- ('i', 'e'): 0x0454,
- ('d', 's'): 0x0455,
- ('i', 'i'): 0x0456,
- ('y', 'i'): 0x0457,
- ('j', '%'): 0x0458,
- ('l', 'j'): 0x0459,
- ('n', 'j'): 0x045a,
- ('t', 's'): 0x045b,
- ('k', 'j'): 0x045c,
- ('v', '%'): 0x045e,
- ('d', 'z'): 0x045f,
- ('Y', '3'): 0x0462,
- ('y', '3'): 0x0463,
- ('O', '3'): 0x046a,
- ('o', '3'): 0x046b,
- ('F', '3'): 0x0472,
- ('f', '3'): 0x0473,
- ('V', '3'): 0x0474,
- ('v', '3'): 0x0475,
- ('C', '3'): 0x0480,
- ('c', '3'): 0x0481,
- ('G', '3'): 0x0490,
- ('g', '3'): 0x0491,
- ('A', '+'): 0x05d0,
- ('B', '+'): 0x05d1,
- ('G', '+'): 0x05d2,
- ('D', '+'): 0x05d3,
- ('H', '+'): 0x05d4,
- ('W', '+'): 0x05d5,
- ('Z', '+'): 0x05d6,
- ('X', '+'): 0x05d7,
- ('T', 'j'): 0x05d8,
- ('J', '+'): 0x05d9,
- ('K', '%'): 0x05da,
- ('K', '+'): 0x05db,
- ('L', '+'): 0x05dc,
- ('M', '%'): 0x05dd,
- ('M', '+'): 0x05de,
- ('N', '%'): 0x05df,
- ('N', '+'): 0x05e0,
- ('S', '+'): 0x05e1,
- ('E', '+'): 0x05e2,
- ('P', '%'): 0x05e3,
- ('P', '+'): 0x05e4,
- ('Z', 'j'): 0x05e5,
- ('Z', 'J'): 0x05e6,
- ('Q', '+'): 0x05e7,
- ('R', '+'): 0x05e8,
- ('S', 'h'): 0x05e9,
- ('T', '+'): 0x05ea,
- (',', '+'): 0x060c,
- (';', '+'): 0x061b,
- ('?', '+'): 0x061f,
- ('H', '\''): 0x0621,
- ('a', 'M'): 0x0622,
- ('a', 'H'): 0x0623,
- ('w', 'H'): 0x0624,
- ('a', 'h'): 0x0625,
- ('y', 'H'): 0x0626,
- ('a', '+'): 0x0627,
- ('b', '+'): 0x0628,
- ('t', 'm'): 0x0629,
- ('t', '+'): 0x062a,
- ('t', 'k'): 0x062b,
- ('g', '+'): 0x062c,
- ('h', 'k'): 0x062d,
- ('x', '+'): 0x062e,
- ('d', '+'): 0x062f,
- ('d', 'k'): 0x0630,
- ('r', '+'): 0x0631,
- ('z', '+'): 0x0632,
- ('s', '+'): 0x0633,
- ('s', 'n'): 0x0634,
- ('c', '+'): 0x0635,
- ('d', 'd'): 0x0636,
- ('t', 'j'): 0x0637,
- ('z', 'H'): 0x0638,
- ('e', '+'): 0x0639,
- ('i', '+'): 0x063a,
- ('+', '+'): 0x0640,
- ('f', '+'): 0x0641,
- ('q', '+'): 0x0642,
- ('k', '+'): 0x0643,
- ('l', '+'): 0x0644,
- ('m', '+'): 0x0645,
- ('n', '+'): 0x0646,
- ('h', '+'): 0x0647,
- ('w', '+'): 0x0648,
- ('j', '+'): 0x0649,
- ('y', '+'): 0x064a,
- (':', '+'): 0x064b,
- ('"', '+'): 0x064c,
- ('=', '+'): 0x064d,
- ('/', '+'): 0x064e,
- ('\'', '+'): 0x064f,
- ('1', '+'): 0x0650,
- ('3', '+'): 0x0651,
- ('0', '+'): 0x0652,
- ('a', 'S'): 0x0670,
- ('p', '+'): 0x067e,
- ('v', '+'): 0x06a4,
- ('g', 'f'): 0x06af,
- ('0', 'a'): 0x06f0,
- ('1', 'a'): 0x06f1,
- ('2', 'a'): 0x06f2,
- ('3', 'a'): 0x06f3,
- ('4', 'a'): 0x06f4,
- ('5', 'a'): 0x06f5,
- ('6', 'a'): 0x06f6,
- ('7', 'a'): 0x06f7,
- ('8', 'a'): 0x06f8,
- ('9', 'a'): 0x06f9,
- ('B', '.'): 0x1e02,
- ('b', '.'): 0x1e03,
- ('B', '_'): 0x1e06,
- ('b', '_'): 0x1e07,
- ('D', '.'): 0x1e0a,
- ('d', '.'): 0x1e0b,
- ('D', '_'): 0x1e0e,
- ('d', '_'): 0x1e0f,
- ('D', ','): 0x1e10,
- ('d', ','): 0x1e11,
- ('F', '.'): 0x1e1e,
- ('f', '.'): 0x1e1f,
- ('G', '-'): 0x1e20,
- ('g', '-'): 0x1e21,
- ('H', '.'): 0x1e22,
- ('h', '.'): 0x1e23,
- ('H', ':'): 0x1e26,
- ('h', ':'): 0x1e27,
- ('H', ','): 0x1e28,
- ('h', ','): 0x1e29,
- ('K', '\''): 0x1e30,
- ('k', '\''): 0x1e31,
- ('K', '_'): 0x1e34,
- ('k', '_'): 0x1e35,
- ('L', '_'): 0x1e3a,
- ('l', '_'): 0x1e3b,
- ('M', '\''): 0x1e3e,
- ('m', '\''): 0x1e3f,
- ('M', '.'): 0x1e40,
- ('m', '.'): 0x1e41,
- ('N', '.'): 0x1e44,
- ('n', '.'): 0x1e45,
- ('N', '_'): 0x1e48,
- ('n', '_'): 0x1e49,
- ('P', '\''): 0x1e54,
- ('p', '\''): 0x1e55,
- ('P', '.'): 0x1e56,
- ('p', '.'): 0x1e57,
- ('R', '.'): 0x1e58,
- ('r', '.'): 0x1e59,
- ('R', '_'): 0x1e5e,
- ('r', '_'): 0x1e5f,
- ('S', '.'): 0x1e60,
- ('s', '.'): 0x1e61,
- ('T', '.'): 0x1e6a,
- ('t', '.'): 0x1e6b,
- ('T', '_'): 0x1e6e,
- ('t', '_'): 0x1e6f,
- ('V', '?'): 0x1e7c,
- ('v', '?'): 0x1e7d,
- ('W', '!'): 0x1e80,
- ('w', '!'): 0x1e81,
- ('W', '\''): 0x1e82,
- ('w', '\''): 0x1e83,
- ('W', ':'): 0x1e84,
- ('w', ':'): 0x1e85,
- ('W', '.'): 0x1e86,
- ('w', '.'): 0x1e87,
- ('X', '.'): 0x1e8a,
- ('x', '.'): 0x1e8b,
- ('X', ':'): 0x1e8c,
- ('x', ':'): 0x1e8d,
- ('Y', '.'): 0x1e8e,
- ('y', '.'): 0x1e8f,
- ('Z', '>'): 0x1e90,
- ('z', '>'): 0x1e91,
- ('Z', '_'): 0x1e94,
- ('z', '_'): 0x1e95,
- ('h', '_'): 0x1e96,
- ('t', ':'): 0x1e97,
- ('w', '0'): 0x1e98,
- ('y', '0'): 0x1e99,
- ('A', '2'): 0x1ea2,
- ('a', '2'): 0x1ea3,
- ('E', '2'): 0x1eba,
- ('e', '2'): 0x1ebb,
- ('E', '?'): 0x1ebc,
- ('e', '?'): 0x1ebd,
- ('I', '2'): 0x1ec8,
- ('i', '2'): 0x1ec9,
- ('O', '2'): 0x1ece,
- ('o', '2'): 0x1ecf,
- ('U', '2'): 0x1ee6,
- ('u', '2'): 0x1ee7,
- ('Y', '!'): 0x1ef2,
- ('y', '!'): 0x1ef3,
- ('Y', '2'): 0x1ef6,
- ('y', '2'): 0x1ef7,
- ('Y', '?'): 0x1ef8,
- ('y', '?'): 0x1ef9,
- (';', '\''): 0x1f00,
- (',', '\''): 0x1f01,
- (';', '!'): 0x1f02,
- (',', '!'): 0x1f03,
- ('?', ';'): 0x1f04,
- ('?', ','): 0x1f05,
- ('!', ':'): 0x1f06,
- ('?', ':'): 0x1f07,
- ('1', 'N'): 0x2002,
- ('1', 'M'): 0x2003,
- ('3', 'M'): 0x2004,
- ('4', 'M'): 0x2005,
- ('6', 'M'): 0x2006,
- ('1', 'T'): 0x2009,
- ('1', 'H'): 0x200a,
- ('-', '1'): 0x2010,
- ('-', 'N'): 0x2013,
- ('-', 'M'): 0x2014,
- ('-', '3'): 0x2015,
- ('!', '2'): 0x2016,
- ('=', '2'): 0x2017,
- ('\'', '6'): 0x2018,
- ('\'', '9'): 0x2019,
- ('.', '9'): 0x201a,
- ('9', '\''): 0x201b,
- ('"', '6'): 0x201c,
- ('"', '9'): 0x201d,
- (':', '9'): 0x201e,
- ('9', '"'): 0x201f,
- ('/', '-'): 0x2020,
- ('/', '='): 0x2021,
- ('.', '.'): 0x2025,
- ('%', '0'): 0x2030,
- ('1', '\''): 0x2032,
- ('2', '\''): 0x2033,
- ('3', '\''): 0x2034,
- ('1', '"'): 0x2035,
- ('2', '"'): 0x2036,
- ('3', '"'): 0x2037,
- ('C', 'a'): 0x2038,
- ('<', '1'): 0x2039,
- ('>', '1'): 0x203a,
- (':', 'X'): 0x203b,
- ('\'', '-'): 0x203e,
- ('/', 'f'): 0x2044,
- ('0', 'S'): 0x2070,
- ('4', 'S'): 0x2074,
- ('5', 'S'): 0x2075,
- ('6', 'S'): 0x2076,
- ('7', 'S'): 0x2077,
- ('8', 'S'): 0x2078,
- ('9', 'S'): 0x2079,
- ('+', 'S'): 0x207a,
- ('-', 'S'): 0x207b,
- ('=', 'S'): 0x207c,
- ('(', 'S'): 0x207d,
- (')', 'S'): 0x207e,
- ('n', 'S'): 0x207f,
- ('0', 's'): 0x2080,
- ('1', 's'): 0x2081,
- ('2', 's'): 0x2082,
- ('3', 's'): 0x2083,
- ('4', 's'): 0x2084,
- ('5', 's'): 0x2085,
- ('6', 's'): 0x2086,
- ('7', 's'): 0x2087,
- ('8', 's'): 0x2088,
- ('9', 's'): 0x2089,
- ('+', 's'): 0x208a,
- ('-', 's'): 0x208b,
- ('=', 's'): 0x208c,
- ('(', 's'): 0x208d,
- (')', 's'): 0x208e,
- ('L', 'i'): 0x20a4,
- ('P', 't'): 0x20a7,
- ('W', '='): 0x20a9,
- ('=', 'e'): 0x20ac, # euro
- ('E', 'u'): 0x20ac, # euro
- ('=', 'R'): 0x20bd, # rouble
- ('=', 'P'): 0x20bd, # rouble
- ('o', 'C'): 0x2103,
- ('c', 'o'): 0x2105,
- ('o', 'F'): 0x2109,
- ('N', '0'): 0x2116,
- ('P', 'O'): 0x2117,
- ('R', 'x'): 0x211e,
- ('S', 'M'): 0x2120,
- ('T', 'M'): 0x2122,
- ('O', 'm'): 0x2126,
- ('A', 'O'): 0x212b,
- ('1', '3'): 0x2153,
- ('2', '3'): 0x2154,
- ('1', '5'): 0x2155,
- ('2', '5'): 0x2156,
- ('3', '5'): 0x2157,
- ('4', '5'): 0x2158,
- ('1', '6'): 0x2159,
- ('5', '6'): 0x215a,
- ('1', '8'): 0x215b,
- ('3', '8'): 0x215c,
- ('5', '8'): 0x215d,
- ('7', '8'): 0x215e,
- ('1', 'R'): 0x2160,
- ('2', 'R'): 0x2161,
- ('3', 'R'): 0x2162,
- ('4', 'R'): 0x2163,
- ('5', 'R'): 0x2164,
- ('6', 'R'): 0x2165,
- ('7', 'R'): 0x2166,
- ('8', 'R'): 0x2167,
- ('9', 'R'): 0x2168,
- ('a', 'R'): 0x2169,
- ('b', 'R'): 0x216a,
- ('c', 'R'): 0x216b,
- ('1', 'r'): 0x2170,
- ('2', 'r'): 0x2171,
- ('3', 'r'): 0x2172,
- ('4', 'r'): 0x2173,
- ('5', 'r'): 0x2174,
- ('6', 'r'): 0x2175,
- ('7', 'r'): 0x2176,
- ('8', 'r'): 0x2177,
- ('9', 'r'): 0x2178,
- ('a', 'r'): 0x2179,
- ('b', 'r'): 0x217a,
- ('c', 'r'): 0x217b,
- ('<', '-'): 0x2190,
- ('-', '!'): 0x2191,
- ('-', '>'): 0x2192,
- ('-', 'v'): 0x2193,
- ('<', '>'): 0x2194,
- ('U', 'D'): 0x2195,
- ('<', '='): 0x21d0,
- ('=', '>'): 0x21d2,
- ('=', '='): 0x21d4,
- ('F', 'A'): 0x2200,
- ('d', 'P'): 0x2202,
- ('T', 'E'): 0x2203,
- ('/', '0'): 0x2205,
- ('D', 'E'): 0x2206,
- ('N', 'B'): 0x2207,
- ('(', '-'): 0x2208,
- ('-', ')'): 0x220b,
- ('*', 'P'): 0x220f,
- ('+', 'Z'): 0x2211,
- ('-', '2'): 0x2212,
- ('-', '+'): 0x2213,
- ('*', '-'): 0x2217,
- ('O', 'b'): 0x2218,
- ('S', 'b'): 0x2219,
- ('R', 'T'): 0x221a,
- ('0', '('): 0x221d,
- ('0', '0'): 0x221e,
- ('-', 'L'): 0x221f,
- ('-', 'V'): 0x2220,
- ('P', 'P'): 0x2225,
- ('A', 'N'): 0x2227,
- ('O', 'R'): 0x2228,
- ('(', 'U'): 0x2229,
- (')', 'U'): 0x222a,
- ('I', 'n'): 0x222b,
- ('D', 'I'): 0x222c,
- ('I', 'o'): 0x222e,
- ('.', ':'): 0x2234,
- (':', '.'): 0x2235,
- (':', 'R'): 0x2236,
- (':', ':'): 0x2237,
- ('?', '1'): 0x223c,
- ('C', 'G'): 0x223e,
- ('?', '-'): 0x2243,
- ('?', '='): 0x2245,
- ('?', '2'): 0x2248,
- ('=', '?'): 0x224c,
- ('H', 'I'): 0x2253,
- ('!', '='): 0x2260,
- ('=', '3'): 0x2261,
- ('=', '<'): 0x2264,
- ('>', '='): 0x2265,
- ('<', '*'): 0x226a,
- ('*', '>'): 0x226b,
- ('!', '<'): 0x226e,
- ('!', '>'): 0x226f,
- ('(', 'C'): 0x2282,
- (')', 'C'): 0x2283,
- ('(', '_'): 0x2286,
- (')', '_'): 0x2287,
- ('0', '.'): 0x2299,
- ('0', '2'): 0x229a,
- ('-', 'T'): 0x22a5,
- ('.', 'P'): 0x22c5,
- (':', '3'): 0x22ee,
- ('.', '3'): 0x22ef,
- ('E', 'h'): 0x2302,
- ('<', '7'): 0x2308,
- ('>', '7'): 0x2309,
- ('7', '<'): 0x230a,
- ('7', '>'): 0x230b,
- ('N', 'I'): 0x2310,
- ('(', 'A'): 0x2312,
- ('T', 'R'): 0x2315,
- ('I', 'u'): 0x2320,
- ('I', 'l'): 0x2321,
- ('<', '/'): 0x2329,
- ('/', '>'): 0x232a,
- ('V', 's'): 0x2423,
- ('1', 'h'): 0x2440,
- ('3', 'h'): 0x2441,
- ('2', 'h'): 0x2442,
- ('4', 'h'): 0x2443,
- ('1', 'j'): 0x2446,
- ('2', 'j'): 0x2447,
- ('3', 'j'): 0x2448,
- ('4', 'j'): 0x2449,
- ('1', '.'): 0x2488,
- ('2', '.'): 0x2489,
- ('3', '.'): 0x248a,
- ('4', '.'): 0x248b,
- ('5', '.'): 0x248c,
- ('6', '.'): 0x248d,
- ('7', '.'): 0x248e,
- ('8', '.'): 0x248f,
- ('9', '.'): 0x2490,
- ('h', 'h'): 0x2500,
- ('H', 'H'): 0x2501,
- ('v', 'v'): 0x2502,
- ('V', 'V'): 0x2503,
- ('3', '-'): 0x2504,
- ('3', '_'): 0x2505,
- ('3', '!'): 0x2506,
- ('3', '/'): 0x2507,
- ('4', '-'): 0x2508,
- ('4', '_'): 0x2509,
- ('4', '!'): 0x250a,
- ('4', '/'): 0x250b,
- ('d', 'r'): 0x250c,
- ('d', 'R'): 0x250d,
- ('D', 'r'): 0x250e,
- ('D', 'R'): 0x250f,
- ('d', 'l'): 0x2510,
- ('d', 'L'): 0x2511,
- ('D', 'l'): 0x2512,
- ('L', 'D'): 0x2513,
- ('u', 'r'): 0x2514,
- ('u', 'R'): 0x2515,
- ('U', 'r'): 0x2516,
- ('U', 'R'): 0x2517,
- ('u', 'l'): 0x2518,
- ('u', 'L'): 0x2519,
- ('U', 'l'): 0x251a,
- ('U', 'L'): 0x251b,
- ('v', 'r'): 0x251c,
- ('v', 'R'): 0x251d,
- ('V', 'r'): 0x2520,
- ('V', 'R'): 0x2523,
- ('v', 'l'): 0x2524,
- ('v', 'L'): 0x2525,
- ('V', 'l'): 0x2528,
- ('V', 'L'): 0x252b,
- ('d', 'h'): 0x252c,
- ('d', 'H'): 0x252f,
- ('D', 'h'): 0x2530,
- ('D', 'H'): 0x2533,
- ('u', 'h'): 0x2534,
- ('u', 'H'): 0x2537,
- ('U', 'h'): 0x2538,
- ('U', 'H'): 0x253b,
- ('v', 'h'): 0x253c,
- ('v', 'H'): 0x253f,
- ('V', 'h'): 0x2542,
- ('V', 'H'): 0x254b,
- ('F', 'D'): 0x2571,
- ('B', 'D'): 0x2572,
- ('T', 'B'): 0x2580,
- ('L', 'B'): 0x2584,
- ('F', 'B'): 0x2588,
- ('l', 'B'): 0x258c,
- ('R', 'B'): 0x2590,
- ('.', 'S'): 0x2591,
- (':', 'S'): 0x2592,
- ('?', 'S'): 0x2593,
- ('f', 'S'): 0x25a0,
- ('O', 'S'): 0x25a1,
- ('R', 'O'): 0x25a2,
- ('R', 'r'): 0x25a3,
- ('R', 'F'): 0x25a4,
- ('R', 'Y'): 0x25a5,
- ('R', 'H'): 0x25a6,
- ('R', 'Z'): 0x25a7,
- ('R', 'K'): 0x25a8,
- ('R', 'X'): 0x25a9,
- ('s', 'B'): 0x25aa,
- ('S', 'R'): 0x25ac,
- ('O', 'r'): 0x25ad,
- ('U', 'T'): 0x25b2,
- ('u', 'T'): 0x25b3,
- ('P', 'R'): 0x25b6,
- ('T', 'r'): 0x25b7,
- ('D', 't'): 0x25bc,
- ('d', 'T'): 0x25bd,
- ('P', 'L'): 0x25c0,
- ('T', 'l'): 0x25c1,
- ('D', 'b'): 0x25c6,
- ('D', 'w'): 0x25c7,
- ('L', 'Z'): 0x25ca,
- ('0', 'm'): 0x25cb,
- ('0', 'o'): 0x25ce,
- ('0', 'M'): 0x25cf,
- ('0', 'L'): 0x25d0,
- ('0', 'R'): 0x25d1,
- ('S', 'n'): 0x25d8,
- ('I', 'c'): 0x25d9,
- ('F', 'd'): 0x25e2,
- ('B', 'd'): 0x25e3,
- ('*', '2'): 0x2605,
- ('*', '1'): 0x2606,
- ('<', 'H'): 0x261c,
- ('>', 'H'): 0x261e,
- ('0', 'u'): 0x263a,
- ('0', 'U'): 0x263b,
- ('S', 'U'): 0x263c,
- ('F', 'm'): 0x2640,
- ('M', 'l'): 0x2642,
- ('c', 'S'): 0x2660,
- ('c', 'H'): 0x2661,
- ('c', 'D'): 0x2662,
- ('c', 'C'): 0x2663,
- ('M', 'd'): 0x2669,
- ('M', '8'): 0x266a,
- ('M', '2'): 0x266b,
- ('M', 'b'): 0x266d,
- ('M', 'x'): 0x266e,
- ('M', 'X'): 0x266f,
- ('O', 'K'): 0x2713,
- ('X', 'X'): 0x2717,
- ('-', 'X'): 0x2720,
- ('I', 'S'): 0x3000,
- (',', '_'): 0x3001,
- ('.', '_'): 0x3002,
- ('+', '"'): 0x3003,
- ('+', '_'): 0x3004,
- ('*', '_'): 0x3005,
- (';', '_'): 0x3006,
- ('0', '_'): 0x3007,
- ('<', '+'): 0x300a,
- ('>', '+'): 0x300b,
- ('<', '\''): 0x300c,
- ('>', '\''): 0x300d,
- ('<', '"'): 0x300e,
- ('>', '"'): 0x300f,
- ('(', '"'): 0x3010,
- (')', '"'): 0x3011,
- ('=', 'T'): 0x3012,
- ('=', '_'): 0x3013,
- ('(', '\''): 0x3014,
- (')', '\''): 0x3015,
- ('(', 'I'): 0x3016,
- (')', 'I'): 0x3017,
- ('-', '?'): 0x301c,
- ('A', '5'): 0x3041,
- ('a', '5'): 0x3042,
- ('I', '5'): 0x3043,
- ('i', '5'): 0x3044,
- ('U', '5'): 0x3045,
- ('u', '5'): 0x3046,
- ('E', '5'): 0x3047,
- ('e', '5'): 0x3048,
- ('O', '5'): 0x3049,
- ('o', '5'): 0x304a,
- ('k', 'a'): 0x304b,
- ('g', 'a'): 0x304c,
- ('k', 'i'): 0x304d,
- ('g', 'i'): 0x304e,
- ('k', 'u'): 0x304f,
- ('g', 'u'): 0x3050,
- ('k', 'e'): 0x3051,
- ('g', 'e'): 0x3052,
- ('k', 'o'): 0x3053,
- ('g', 'o'): 0x3054,
- ('s', 'a'): 0x3055,
- ('z', 'a'): 0x3056,
- ('s', 'i'): 0x3057,
- ('z', 'i'): 0x3058,
- ('s', 'u'): 0x3059,
- ('z', 'u'): 0x305a,
- ('s', 'e'): 0x305b,
- ('z', 'e'): 0x305c,
- ('s', 'o'): 0x305d,
- ('z', 'o'): 0x305e,
- ('t', 'a'): 0x305f,
- ('d', 'a'): 0x3060,
- ('t', 'i'): 0x3061,
- ('d', 'i'): 0x3062,
- ('t', 'U'): 0x3063,
- ('t', 'u'): 0x3064,
- ('d', 'u'): 0x3065,
- ('t', 'e'): 0x3066,
- ('d', 'e'): 0x3067,
- ('t', 'o'): 0x3068,
- ('d', 'o'): 0x3069,
- ('n', 'a'): 0x306a,
- ('n', 'i'): 0x306b,
- ('n', 'u'): 0x306c,
- ('n', 'e'): 0x306d,
- ('n', 'o'): 0x306e,
- ('h', 'a'): 0x306f,
- ('b', 'a'): 0x3070,
- ('p', 'a'): 0x3071,
- ('h', 'i'): 0x3072,
- ('b', 'i'): 0x3073,
- ('p', 'i'): 0x3074,
- ('h', 'u'): 0x3075,
- ('b', 'u'): 0x3076,
- ('p', 'u'): 0x3077,
- ('h', 'e'): 0x3078,
- ('b', 'e'): 0x3079,
- ('p', 'e'): 0x307a,
- ('h', 'o'): 0x307b,
- ('b', 'o'): 0x307c,
- ('p', 'o'): 0x307d,
- ('m', 'a'): 0x307e,
- ('m', 'i'): 0x307f,
- ('m', 'u'): 0x3080,
- ('m', 'e'): 0x3081,
- ('m', 'o'): 0x3082,
- ('y', 'A'): 0x3083,
- ('y', 'a'): 0x3084,
- ('y', 'U'): 0x3085,
- ('y', 'u'): 0x3086,
- ('y', 'O'): 0x3087,
- ('y', 'o'): 0x3088,
- ('r', 'a'): 0x3089,
- ('r', 'i'): 0x308a,
- ('r', 'u'): 0x308b,
- ('r', 'e'): 0x308c,
- ('r', 'o'): 0x308d,
- ('w', 'A'): 0x308e,
- ('w', 'a'): 0x308f,
- ('w', 'i'): 0x3090,
- ('w', 'e'): 0x3091,
- ('w', 'o'): 0x3092,
- ('n', '5'): 0x3093,
- ('v', 'u'): 0x3094,
- ('"', '5'): 0x309b,
- ('0', '5'): 0x309c,
- ('*', '5'): 0x309d,
- ('+', '5'): 0x309e,
- ('a', '6'): 0x30a1,
- ('A', '6'): 0x30a2,
- ('i', '6'): 0x30a3,
- ('I', '6'): 0x30a4,
- ('u', '6'): 0x30a5,
- ('U', '6'): 0x30a6,
- ('e', '6'): 0x30a7,
- ('E', '6'): 0x30a8,
- ('o', '6'): 0x30a9,
- ('O', '6'): 0x30aa,
- ('K', 'a'): 0x30ab,
- ('G', 'a'): 0x30ac,
- ('K', 'i'): 0x30ad,
- ('G', 'i'): 0x30ae,
- ('K', 'u'): 0x30af,
- ('G', 'u'): 0x30b0,
- ('K', 'e'): 0x30b1,
- ('G', 'e'): 0x30b2,
- ('K', 'o'): 0x30b3,
- ('G', 'o'): 0x30b4,
- ('S', 'a'): 0x30b5,
- ('Z', 'a'): 0x30b6,
- ('S', 'i'): 0x30b7,
- ('Z', 'i'): 0x30b8,
- ('S', 'u'): 0x30b9,
- ('Z', 'u'): 0x30ba,
- ('S', 'e'): 0x30bb,
- ('Z', 'e'): 0x30bc,
- ('S', 'o'): 0x30bd,
- ('Z', 'o'): 0x30be,
- ('T', 'a'): 0x30bf,
- ('D', 'a'): 0x30c0,
- ('T', 'i'): 0x30c1,
- ('D', 'i'): 0x30c2,
- ('T', 'U'): 0x30c3,
- ('T', 'u'): 0x30c4,
- ('D', 'u'): 0x30c5,
- ('T', 'e'): 0x30c6,
- ('D', 'e'): 0x30c7,
- ('T', 'o'): 0x30c8,
- ('D', 'o'): 0x30c9,
- ('N', 'a'): 0x30ca,
- ('N', 'i'): 0x30cb,
- ('N', 'u'): 0x30cc,
- ('N', 'e'): 0x30cd,
- ('N', 'o'): 0x30ce,
- ('H', 'a'): 0x30cf,
- ('B', 'a'): 0x30d0,
- ('P', 'a'): 0x30d1,
- ('H', 'i'): 0x30d2,
- ('B', 'i'): 0x30d3,
- ('P', 'i'): 0x30d4,
- ('H', 'u'): 0x30d5,
- ('B', 'u'): 0x30d6,
- ('P', 'u'): 0x30d7,
- ('H', 'e'): 0x30d8,
- ('B', 'e'): 0x30d9,
- ('P', 'e'): 0x30da,
- ('H', 'o'): 0x30db,
- ('B', 'o'): 0x30dc,
- ('P', 'o'): 0x30dd,
- ('M', 'a'): 0x30de,
- ('M', 'i'): 0x30df,
- ('M', 'u'): 0x30e0,
- ('M', 'e'): 0x30e1,
- ('M', 'o'): 0x30e2,
- ('Y', 'A'): 0x30e3,
- ('Y', 'a'): 0x30e4,
- ('Y', 'U'): 0x30e5,
- ('Y', 'u'): 0x30e6,
- ('Y', 'O'): 0x30e7,
- ('Y', 'o'): 0x30e8,
- ('R', 'a'): 0x30e9,
- ('R', 'i'): 0x30ea,
- ('R', 'u'): 0x30eb,
- ('R', 'e'): 0x30ec,
- ('R', 'o'): 0x30ed,
- ('W', 'A'): 0x30ee,
- ('W', 'a'): 0x30ef,
- ('W', 'i'): 0x30f0,
- ('W', 'e'): 0x30f1,
- ('W', 'o'): 0x30f2,
- ('N', '6'): 0x30f3,
- ('V', 'u'): 0x30f4,
- ('K', 'A'): 0x30f5,
- ('K', 'E'): 0x30f6,
- ('V', 'a'): 0x30f7,
- ('V', 'i'): 0x30f8,
- ('V', 'e'): 0x30f9,
- ('V', 'o'): 0x30fa,
- ('.', '6'): 0x30fb,
- ('-', '6'): 0x30fc,
- ('*', '6'): 0x30fd,
- ('+', '6'): 0x30fe,
- ('b', '4'): 0x3105,
- ('p', '4'): 0x3106,
- ('m', '4'): 0x3107,
- ('f', '4'): 0x3108,
- ('d', '4'): 0x3109,
- ('t', '4'): 0x310a,
- ('n', '4'): 0x310b,
- ('l', '4'): 0x310c,
- ('g', '4'): 0x310d,
- ('k', '4'): 0x310e,
- ('h', '4'): 0x310f,
- ('j', '4'): 0x3110,
- ('q', '4'): 0x3111,
- ('x', '4'): 0x3112,
- ('z', 'h'): 0x3113,
- ('c', 'h'): 0x3114,
- ('s', 'h'): 0x3115,
- ('r', '4'): 0x3116,
- ('z', '4'): 0x3117,
- ('c', '4'): 0x3118,
- ('s', '4'): 0x3119,
- ('a', '4'): 0x311a,
- ('o', '4'): 0x311b,
- ('e', '4'): 0x311c,
- ('a', 'i'): 0x311e,
- ('e', 'i'): 0x311f,
- ('a', 'u'): 0x3120,
- ('o', 'u'): 0x3121,
- ('a', 'n'): 0x3122,
- ('e', 'n'): 0x3123,
- ('a', 'N'): 0x3124,
- ('e', 'N'): 0x3125,
- ('e', 'r'): 0x3126,
- ('i', '4'): 0x3127,
- ('u', '4'): 0x3128,
- ('i', 'u'): 0x3129,
- ('v', '4'): 0x312a,
- ('n', 'G'): 0x312b,
- ('g', 'n'): 0x312c,
- ('1', 'c'): 0x3220,
- ('2', 'c'): 0x3221,
- ('3', 'c'): 0x3222,
- ('4', 'c'): 0x3223,
- ('5', 'c'): 0x3224,
- ('6', 'c'): 0x3225,
- ('7', 'c'): 0x3226,
- ('8', 'c'): 0x3227,
- ('9', 'c'): 0x3228,
-
- # code points 0xe000 - 0xefff excluded, they have no assigned
- # characters, only used in proposals.
- ('f', 'f'): 0xfb00,
- ('f', 'i'): 0xfb01,
- ('f', 'l'): 0xfb02,
- ('f', 't'): 0xfb05,
- ('s', 't'): 0xfb06,
-
- # Vim 5.x compatible digraphs that don't conflict with the above
- ('~', '!'): 161,
- ('c', '|'): 162,
- ('$', '$'): 163,
- ('o', 'x'): 164, # currency symbol in ISO 8859-1
- ('Y', '-'): 165,
- ('|', '|'): 166,
- ('c', 'O'): 169,
- ('-', ','): 172,
- ('-', '='): 175,
- ('~', 'o'): 176,
- ('2', '2'): 178,
- ('3', '3'): 179,
- ('p', 'p'): 182,
- ('~', '.'): 183,
- ('1', '1'): 185,
- ('~', '?'): 191,
- ('A', '`'): 192,
- ('A', '^'): 194,
- ('A', '~'): 195,
- ('A', '"'): 196,
- ('A', '@'): 197,
- ('E', '`'): 200,
- ('E', '^'): 202,
- ('E', '"'): 203,
- ('I', '`'): 204,
- ('I', '^'): 206,
- ('I', '"'): 207,
- ('N', '~'): 209,
- ('O', '`'): 210,
- ('O', '^'): 212,
- ('O', '~'): 213,
- ('/', '\\'): 215, # multiplication symbol in ISO 8859-1
- ('U', '`'): 217,
- ('U', '^'): 219,
- ('I', 'p'): 222,
- ('a', '`'): 224,
- ('a', '^'): 226,
- ('a', '~'): 227,
- ('a', '"'): 228,
- ('a', '@'): 229,
- ('e', '`'): 232,
- ('e', '^'): 234,
- ('e', '"'): 235,
- ('i', '`'): 236,
- ('i', '^'): 238,
- ('n', '~'): 241,
- ('o', '`'): 242,
- ('o', '^'): 244,
- ('o', '~'): 245,
- ('u', '`'): 249,
- ('u', '^'): 251,
- ('y', '"'): 255,
-}
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/input_processor.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/input_processor.py
deleted file mode 100644
index 51a3110827..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/input_processor.py
+++ /dev/null
@@ -1,372 +0,0 @@
-# *** encoding: utf-8 ***
-"""
-An :class:`~.InputProcessor` receives callbacks for the keystrokes parsed from
-the input in the :class:`~prompt_toolkit.inputstream.InputStream` instance.
-
-The `InputProcessor` will according to the implemented keybindings call the
-correct callbacks when new key presses are feed through `feed`.
-"""
-from __future__ import unicode_literals
-from prompt_toolkit.buffer import EditReadOnlyBuffer
-from prompt_toolkit.filters.cli import ViNavigationMode
-from prompt_toolkit.keys import Keys, Key
-from prompt_toolkit.utils import Event
-
-from .registry import BaseRegistry
-
-from collections import deque
-from six.moves import range
-import weakref
-import six
-
-__all__ = (
- 'InputProcessor',
- 'KeyPress',
-)
-
-
-class KeyPress(object):
- """
- :param key: A `Keys` instance or text (one character).
- :param data: The received string on stdin. (Often vt100 escape codes.)
- """
- def __init__(self, key, data=None):
- assert isinstance(key, (six.text_type, Key))
- assert data is None or isinstance(data, six.text_type)
-
- if data is None:
- data = key.name if isinstance(key, Key) else key
-
- self.key = key
- self.data = data
-
- def __repr__(self):
- return '%s(key=%r, data=%r)' % (
- self.__class__.__name__, self.key, self.data)
-
- def __eq__(self, other):
- return self.key == other.key and self.data == other.data
-
-
-class InputProcessor(object):
- """
- Statemachine that receives :class:`KeyPress` instances and according to the
- key bindings in the given :class:`Registry`, calls the matching handlers.
-
- ::
-
- p = InputProcessor(registry)
-
- # Send keys into the processor.
- p.feed(KeyPress(Keys.ControlX, '\x18'))
- p.feed(KeyPress(Keys.ControlC, '\x03')
-
- # Process all the keys in the queue.
- p.process_keys()
-
- # Now the ControlX-ControlC callback will be called if this sequence is
- # registered in the registry.
-
- :param registry: `BaseRegistry` instance.
- :param cli_ref: weakref to `CommandLineInterface`.
- """
- def __init__(self, registry, cli_ref):
- assert isinstance(registry, BaseRegistry)
-
- self._registry = registry
- self._cli_ref = cli_ref
-
- self.beforeKeyPress = Event(self)
- self.afterKeyPress = Event(self)
-
- # The queue of keys not yet send to our _process generator/state machine.
- self.input_queue = deque()
-
- # The key buffer that is matched in the generator state machine.
- # (This is at at most the amount of keys that make up for one key binding.)
- self.key_buffer = []
-
- # Simple macro recording. (Like readline does.)
- self.record_macro = False
- self.macro = []
-
- self.reset()
-
- def reset(self):
- self._previous_key_sequence = []
- self._previous_handler = None
-
- self._process_coroutine = self._process()
- self._process_coroutine.send(None)
-
- #: Readline argument (for repetition of commands.)
- #: https://www.gnu.org/software/bash/manual/html_node/Readline-Arguments.html
- self.arg = None
-
- def start_macro(self):
- " Start recording macro. "
- self.record_macro = True
- self.macro = []
-
- def end_macro(self):
- " End recording macro. "
- self.record_macro = False
-
- def call_macro(self):
- for k in self.macro:
- self.feed(k)
-
- def _get_matches(self, key_presses):
- """
- For a list of :class:`KeyPress` instances. Give the matching handlers
- that would handle this.
- """
- keys = tuple(k.key for k in key_presses)
- cli = self._cli_ref()
-
- # Try match, with mode flag
- return [b for b in self._registry.get_bindings_for_keys(keys) if b.filter(cli)]
-
- def _is_prefix_of_longer_match(self, key_presses):
- """
- For a list of :class:`KeyPress` instances. Return True if there is any
- handler that is bound to a suffix of this keys.
- """
- keys = tuple(k.key for k in key_presses)
- cli = self._cli_ref()
-
- # Get the filters for all the key bindings that have a longer match.
- # Note that we transform it into a `set`, because we don't care about
- # the actual bindings and executing it more than once doesn't make
- # sense. (Many key bindings share the same filter.)
- filters = set(b.filter for b in self._registry.get_bindings_starting_with_keys(keys))
-
- # When any key binding is active, return True.
- return any(f(cli) for f in filters)
-
- def _process(self):
- """
- Coroutine implementing the key match algorithm. Key strokes are sent
- into this generator, and it calls the appropriate handlers.
- """
- buffer = self.key_buffer
- retry = False
-
- while True:
- if retry:
- retry = False
- else:
- buffer.append((yield))
-
- # If we have some key presses, check for matches.
- if buffer:
- is_prefix_of_longer_match = self._is_prefix_of_longer_match(buffer)
- matches = self._get_matches(buffer)
-
- # When eager matches were found, give priority to them and also
- # ignore all the longer matches.
- eager_matches = [m for m in matches if m.eager(self._cli_ref())]
-
- if eager_matches:
- matches = eager_matches
- is_prefix_of_longer_match = False
-
- # Exact matches found, call handler.
- if not is_prefix_of_longer_match and matches:
- self._call_handler(matches[-1], key_sequence=buffer[:])
- del buffer[:] # Keep reference.
-
- # No match found.
- elif not is_prefix_of_longer_match and not matches:
- retry = True
- found = False
-
- # Loop over the input, try longest match first and shift.
- for i in range(len(buffer), 0, -1):
- matches = self._get_matches(buffer[:i])
- if matches:
- self._call_handler(matches[-1], key_sequence=buffer[:i])
- del buffer[:i]
- found = True
- break
-
- if not found:
- del buffer[:1]
-
- def feed(self, key_press):
- """
- Add a new :class:`KeyPress` to the input queue.
- (Don't forget to call `process_keys` in order to process the queue.)
- """
- assert isinstance(key_press, KeyPress)
- self.input_queue.append(key_press)
-
- def process_keys(self):
- """
- Process all the keys in the `input_queue`.
- (To be called after `feed`.)
-
- Note: because of the `feed`/`process_keys` separation, it is
- possible to call `feed` from inside a key binding.
- This function keeps looping until the queue is empty.
- """
- while self.input_queue:
- key_press = self.input_queue.popleft()
-
- if key_press.key != Keys.CPRResponse:
- self.beforeKeyPress.fire()
-
- self._process_coroutine.send(key_press)
-
- if key_press.key != Keys.CPRResponse:
- self.afterKeyPress.fire()
-
- # Invalidate user interface.
- cli = self._cli_ref()
- if cli:
- cli.invalidate()
-
- def _call_handler(self, handler, key_sequence=None):
- was_recording = self.record_macro
- arg = self.arg
- self.arg = None
-
- event = KeyPressEvent(
- weakref.ref(self), arg=arg, key_sequence=key_sequence,
- previous_key_sequence=self._previous_key_sequence,
- is_repeat=(handler == self._previous_handler))
-
- # Save the state of the current buffer.
- cli = event.cli # Can be `None` (In unit-tests only.)
-
- if handler.save_before(event) and cli:
- cli.current_buffer.save_to_undo_stack()
-
- # Call handler.
- try:
- handler.call(event)
- self._fix_vi_cursor_position(event)
-
- except EditReadOnlyBuffer:
- # When a key binding does an attempt to change a buffer which is
- # read-only, we can just silently ignore that.
- pass
-
- self._previous_key_sequence = key_sequence
- self._previous_handler = handler
-
- # Record the key sequence in our macro. (Only if we're in macro mode
- # before and after executing the key.)
- if self.record_macro and was_recording:
- self.macro.extend(key_sequence)
-
- def _fix_vi_cursor_position(self, event):
- """
- After every command, make sure that if we are in Vi navigation mode, we
- never put the cursor after the last character of a line. (Unless it's
- an empty line.)
- """
- cli = self._cli_ref()
- if cli:
- buff = cli.current_buffer
- preferred_column = buff.preferred_column
-
- if (ViNavigationMode()(event.cli) and
- buff.document.is_cursor_at_the_end_of_line and
- len(buff.document.current_line) > 0):
- buff.cursor_position -= 1
-
- # Set the preferred_column for arrow up/down again.
- # (This was cleared after changing the cursor position.)
- buff.preferred_column = preferred_column
-
-
-
-class KeyPressEvent(object):
- """
- Key press event, delivered to key bindings.
-
- :param input_processor_ref: Weak reference to the `InputProcessor`.
- :param arg: Repetition argument.
- :param key_sequence: List of `KeyPress` instances.
- :param previouskey_sequence: Previous list of `KeyPress` instances.
- :param is_repeat: True when the previous event was delivered to the same handler.
- """
- def __init__(self, input_processor_ref, arg=None, key_sequence=None,
- previous_key_sequence=None, is_repeat=False):
- self._input_processor_ref = input_processor_ref
- self.key_sequence = key_sequence
- self.previous_key_sequence = previous_key_sequence
-
- #: True when the previous key sequence was handled by the same handler.
- self.is_repeat = is_repeat
-
- self._arg = arg
-
- def __repr__(self):
- return 'KeyPressEvent(arg=%r, key_sequence=%r, is_repeat=%r)' % (
- self.arg, self.key_sequence, self.is_repeat)
-
- @property
- def data(self):
- return self.key_sequence[-1].data
-
- @property
- def input_processor(self):
- return self._input_processor_ref()
-
- @property
- def cli(self):
- """
- Command line interface.
- """
- return self.input_processor._cli_ref()
-
- @property
- def current_buffer(self):
- """
- The current buffer.
- """
- return self.cli.current_buffer
-
- @property
- def arg(self):
- """
- Repetition argument.
- """
- if self._arg == '-':
- return -1
-
- result = int(self._arg or 1)
-
- # Don't exceed a million.
- if int(result) >= 1000000:
- result = 1
-
- return result
-
- @property
- def arg_present(self):
- """
- True if repetition argument was explicitly provided.
- """
- return self._arg is not None
-
- def append_to_arg_count(self, data):
- """
- Add digit to the input argument.
-
- :param data: the typed digit as string
- """
- assert data in '-0123456789'
- current = self._arg
-
- if data == '-':
- assert current is None or current == '-'
- result = data
- elif current is None:
- result = data
- else:
- result = "%s%s" % (current, data)
-
- self.input_processor.arg = result
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/manager.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/manager.py
deleted file mode 100644
index 83612c2a5c..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/manager.py
+++ /dev/null
@@ -1,96 +0,0 @@
-"""
-DEPRECATED:
-Use `prompt_toolkit.key_binding.defaults.load_key_bindings` instead.
-
-:class:`KeyBindingManager` is a utility (or shortcut) for loading all the key
-bindings in a key binding registry, with a logic set of filters to quickly to
-quickly change from Vi to Emacs key bindings at runtime.
-
-You don't have to use this, but it's practical.
-
-Usage::
-
- manager = KeyBindingManager()
- app = Application(key_bindings_registry=manager.registry)
-"""
-from __future__ import unicode_literals
-from .defaults import load_key_bindings
-from prompt_toolkit.filters import to_cli_filter
-from prompt_toolkit.key_binding.registry import Registry, ConditionalRegistry, MergedRegistry
-
-__all__ = (
- 'KeyBindingManager',
-)
-
-
-class KeyBindingManager(object):
- """
- Utility for loading all key bindings into memory.
-
- :param registry: Optional `Registry` instance.
- :param enable_abort_and_exit_bindings: Filter to enable Ctrl-C and Ctrl-D.
- :param enable_system_bindings: Filter to enable the system bindings
- (meta-! prompt and Control-Z suspension.)
- :param enable_search: Filter to enable the search bindings.
- :param enable_open_in_editor: Filter to enable open-in-editor.
- :param enable_open_in_editor: Filter to enable open-in-editor.
- :param enable_extra_page_navigation: Filter for enabling extra page navigation.
- (Bindings for up/down scrolling through long pages, like in Emacs or Vi.)
- :param enable_auto_suggest_bindings: Filter to enable fish-style suggestions.
-
- :param enable_vi_mode: Deprecated!
- """
- def __init__(self,
- registry=None, # XXX: not used anymore.
- enable_vi_mode=None, # (`enable_vi_mode` is deprecated.)
- enable_all=True, #
- get_search_state=None,
- enable_abort_and_exit_bindings=False,
- enable_system_bindings=False,
- enable_search=False,
- enable_open_in_editor=False,
- enable_extra_page_navigation=False,
- enable_auto_suggest_bindings=False):
-
- assert registry is None or isinstance(registry, Registry)
- assert get_search_state is None or callable(get_search_state)
- enable_all = to_cli_filter(enable_all)
-
- defaults = load_key_bindings(
- get_search_state=get_search_state,
- enable_abort_and_exit_bindings=enable_abort_and_exit_bindings,
- enable_system_bindings=enable_system_bindings,
- enable_search=enable_search,
- enable_open_in_editor=enable_open_in_editor,
- enable_extra_page_navigation=enable_extra_page_navigation,
- enable_auto_suggest_bindings=enable_auto_suggest_bindings)
-
- # Note, we wrap this whole thing again in a MergedRegistry, because we
- # don't want the `enable_all` settings to apply on items that were
- # added to the registry as a whole.
- self.registry = MergedRegistry([
- ConditionalRegistry(defaults, enable_all)
- ])
-
- @classmethod
- def for_prompt(cls, **kw):
- """
- Create a ``KeyBindingManager`` with the defaults for an input prompt.
- This activates the key bindings for abort/exit (Ctrl-C/Ctrl-D),
- incremental search and auto suggestions.
-
- (Not for full screen applications.)
- """
- kw.setdefault('enable_abort_and_exit_bindings', True)
- kw.setdefault('enable_search', True)
- kw.setdefault('enable_auto_suggest_bindings', True)
-
- return cls(**kw)
-
- def reset(self, cli):
- # For backwards compatibility.
- pass
-
- def get_vi_state(self, cli):
- # Deprecated!
- return cli.vi_state
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/registry.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/registry.py
deleted file mode 100644
index 24d0e729a1..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/registry.py
+++ /dev/null
@@ -1,350 +0,0 @@
-"""
-Key bindings registry.
-
-A `Registry` object is a container that holds a list of key bindings. It has a
-very efficient internal data structure for checking which key bindings apply
-for a pressed key.
-
-Typical usage::
-
- r = Registry()
-
- @r.add_binding(Keys.ControlX, Keys.ControlC, filter=INSERT)
- def handler(event):
- # Handle ControlX-ControlC key sequence.
- pass
-
-
-It is also possible to combine multiple registries. We do this in the default
-key bindings. There are some registries that contain Emacs bindings, while
-others contain the Vi bindings. They are merged together using a
-`MergedRegistry`.
-
-We also have a `ConditionalRegistry` object that can enable/disable a group of
-key bindings at once.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-
-from prompt_toolkit.cache import SimpleCache
-from prompt_toolkit.filters import CLIFilter, to_cli_filter, Never
-from prompt_toolkit.keys import Key, Keys
-
-from six import text_type, with_metaclass
-
-__all__ = (
- 'BaseRegistry',
- 'Registry',
- 'ConditionalRegistry',
- 'MergedRegistry',
-)
-
-
-class _Binding(object):
- """
- (Immutable binding class.)
- """
- def __init__(self, keys, handler, filter=None, eager=None, save_before=None):
- assert isinstance(keys, tuple)
- assert callable(handler)
- assert isinstance(filter, CLIFilter)
- assert isinstance(eager, CLIFilter)
- assert callable(save_before)
-
- self.keys = keys
- self.handler = handler
- self.filter = filter
- self.eager = eager
- self.save_before = save_before
-
- def call(self, event):
- return self.handler(event)
-
- def __repr__(self):
- return '%s(keys=%r, handler=%r)' % (
- self.__class__.__name__, self.keys, self.handler)
-
-
-class BaseRegistry(with_metaclass(ABCMeta, object)):
- """
- Interface for a Registry.
- """
- _version = 0 # For cache invalidation.
-
- @abstractmethod
- def get_bindings_for_keys(self, keys):
- pass
-
- @abstractmethod
- def get_bindings_starting_with_keys(self, keys):
- pass
-
- # `add_binding` and `remove_binding` don't have to be part of this
- # interface.
-
-
-class Registry(BaseRegistry):
- """
- Key binding registry.
- """
- def __init__(self):
- self.key_bindings = []
- self._get_bindings_for_keys_cache = SimpleCache(maxsize=10000)
- self._get_bindings_starting_with_keys_cache = SimpleCache(maxsize=1000)
- self._version = 0 # For cache invalidation.
-
- def _clear_cache(self):
- self._version += 1
- self._get_bindings_for_keys_cache.clear()
- self._get_bindings_starting_with_keys_cache.clear()
-
- def add_binding(self, *keys, **kwargs):
- """
- Decorator for annotating key bindings.
-
- :param filter: :class:`~prompt_toolkit.filters.CLIFilter` to determine
- when this key binding is active.
- :param eager: :class:`~prompt_toolkit.filters.CLIFilter` or `bool`.
- When True, ignore potential longer matches when this key binding is
- hit. E.g. when there is an active eager key binding for Ctrl-X,
- execute the handler immediately and ignore the key binding for
- Ctrl-X Ctrl-E of which it is a prefix.
- :param save_before: Callable that takes an `Event` and returns True if
- we should save the current buffer, before handling the event.
- (That's the default.)
- """
- filter = to_cli_filter(kwargs.pop('filter', True))
- eager = to_cli_filter(kwargs.pop('eager', False))
- save_before = kwargs.pop('save_before', lambda e: True)
- to_cli_filter(kwargs.pop('invalidate_ui', True)) # Deprecated! (ignored.)
-
- assert not kwargs
- assert keys
- assert all(isinstance(k, (Key, text_type)) for k in keys), \
- 'Key bindings should consist of Key and string (unicode) instances.'
- assert callable(save_before)
-
- if isinstance(filter, Never):
- # When a filter is Never, it will always stay disabled, so in that case
- # don't bother putting it in the registry. It will slow down every key
- # press otherwise.
- def decorator(func):
- return func
- else:
- def decorator(func):
- self.key_bindings.append(
- _Binding(keys, func, filter=filter, eager=eager,
- save_before=save_before))
- self._clear_cache()
-
- return func
- return decorator
-
- def remove_binding(self, function):
- """
- Remove a key binding.
-
- This expects a function that was given to `add_binding` method as
- parameter. Raises `ValueError` when the given function was not
- registered before.
- """
- assert callable(function)
-
- for b in self.key_bindings:
- if b.handler == function:
- self.key_bindings.remove(b)
- self._clear_cache()
- return
-
- # No key binding found for this function. Raise ValueError.
- raise ValueError('Binding not found: %r' % (function, ))
-
- def get_bindings_for_keys(self, keys):
- """
- Return a list of key bindings that can handle this key.
- (This return also inactive bindings, so the `filter` still has to be
- called, for checking it.)
-
- :param keys: tuple of keys.
- """
- def get():
- result = []
- for b in self.key_bindings:
- if len(keys) == len(b.keys):
- match = True
- any_count = 0
-
- for i, j in zip(b.keys, keys):
- if i != j and i != Keys.Any:
- match = False
- break
-
- if i == Keys.Any:
- any_count += 1
-
- if match:
- result.append((any_count, b))
-
- # Place bindings that have more 'Any' occurences in them at the end.
- result = sorted(result, key=lambda item: -item[0])
-
- return [item[1] for item in result]
-
- return self._get_bindings_for_keys_cache.get(keys, get)
-
- def get_bindings_starting_with_keys(self, keys):
- """
- Return a list of key bindings that handle a key sequence starting with
- `keys`. (It does only return bindings for which the sequences are
- longer than `keys`. And like `get_bindings_for_keys`, it also includes
- inactive bindings.)
-
- :param keys: tuple of keys.
- """
- def get():
- result = []
- for b in self.key_bindings:
- if len(keys) < len(b.keys):
- match = True
- for i, j in zip(b.keys, keys):
- if i != j and i != Keys.Any:
- match = False
- break
- if match:
- result.append(b)
- return result
-
- return self._get_bindings_starting_with_keys_cache.get(keys, get)
-
-
-class _AddRemoveMixin(BaseRegistry):
- """
- Common part for ConditionalRegistry and MergedRegistry.
- """
- def __init__(self):
- # `Registry` to be synchronized with all the others.
- self._registry2 = Registry()
- self._last_version = None
-
- # The 'extra' registry. Mostly for backwards compatibility.
- self._extra_registry = Registry()
-
- def _update_cache(self):
- raise NotImplementedError
-
- # For backwards, compatibility, we allow adding bindings to both
- # ConditionalRegistry and MergedRegistry. This is however not the
- # recommended way. Better is to create a new registry and merge them
- # together using MergedRegistry.
-
- def add_binding(self, *k, **kw):
- return self._extra_registry.add_binding(*k, **kw)
-
- def remove_binding(self, *k, **kw):
- return self._extra_registry.remove_binding(*k, **kw)
-
- # Proxy methods to self._registry2.
-
- @property
- def key_bindings(self):
- self._update_cache()
- return self._registry2.key_bindings
-
- @property
- def _version(self):
- self._update_cache()
- return self._last_version
-
- def get_bindings_for_keys(self, *a, **kw):
- self._update_cache()
- return self._registry2.get_bindings_for_keys(*a, **kw)
-
- def get_bindings_starting_with_keys(self, *a, **kw):
- self._update_cache()
- return self._registry2.get_bindings_starting_with_keys(*a, **kw)
-
-
-class ConditionalRegistry(_AddRemoveMixin):
- """
- Wraps around a `Registry`. Disable/enable all the key bindings according to
- the given (additional) filter.::
-
- @Condition
- def setting_is_true(cli):
- return True # or False
-
- registy = ConditionalRegistry(registry, setting_is_true)
-
- When new key bindings are added to this object. They are also
- enable/disabled according to the given `filter`.
-
- :param registries: List of `Registry` objects.
- :param filter: `CLIFilter` object.
- """
- def __init__(self, registry=None, filter=True):
- registry = registry or Registry()
- assert isinstance(registry, BaseRegistry)
-
- _AddRemoveMixin.__init__(self)
-
- self.registry = registry
- self.filter = to_cli_filter(filter)
-
- def _update_cache(self):
- " If the original registry was changed. Update our copy version. "
- expected_version = (self.registry._version, self._extra_registry._version)
-
- if self._last_version != expected_version:
- registry2 = Registry()
-
- # Copy all bindings from `self.registry`, adding our condition.
- for reg in (self.registry, self._extra_registry):
- for b in reg.key_bindings:
- registry2.key_bindings.append(
- _Binding(
- keys=b.keys,
- handler=b.handler,
- filter=self.filter & b.filter,
- eager=b.eager,
- save_before=b.save_before))
-
- self._registry2 = registry2
- self._last_version = expected_version
-
-
-class MergedRegistry(_AddRemoveMixin):
- """
- Merge multiple registries of key bindings into one.
-
- This class acts as a proxy to multiple `Registry` objects, but behaves as
- if this is just one bigger `Registry`.
-
- :param registries: List of `Registry` objects.
- """
- def __init__(self, registries):
- assert all(isinstance(r, BaseRegistry) for r in registries)
-
- _AddRemoveMixin.__init__(self)
-
- self.registries = registries
-
- def _update_cache(self):
- """
- If one of the original registries was changed. Update our merged
- version.
- """
- expected_version = (
- tuple(r._version for r in self.registries) +
- (self._extra_registry._version, ))
-
- if self._last_version != expected_version:
- registry2 = Registry()
-
- for reg in self.registries:
- registry2.key_bindings.extend(reg.key_bindings)
-
- # Copy all bindings from `self._extra_registry`.
- registry2.key_bindings.extend(self._extra_registry.key_bindings)
-
- self._registry2 = registry2
- self._last_version = expected_version
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/vi_state.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/vi_state.py
deleted file mode 100644
index 92ce3cbd29..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/vi_state.py
+++ /dev/null
@@ -1,61 +0,0 @@
-from __future__ import unicode_literals
-
-__all__ = (
- 'InputMode',
- 'CharacterFind',
- 'ViState',
-)
-
-
-class InputMode(object):
- INSERT = 'vi-insert'
- INSERT_MULTIPLE = 'vi-insert-multiple'
- NAVIGATION = 'vi-navigation'
- REPLACE = 'vi-replace'
-
-
-class CharacterFind(object):
- def __init__(self, character, backwards=False):
- self.character = character
- self.backwards = backwards
-
-
-class ViState(object):
- """
- Mutable class to hold the state of the Vi navigation.
- """
- def __init__(self):
- #: None or CharacterFind instance. (This is used to repeat the last
- #: search in Vi mode, by pressing the 'n' or 'N' in navigation mode.)
- self.last_character_find = None
-
- # When an operator is given and we are waiting for text object,
- # -- e.g. in the case of 'dw', after the 'd' --, an operator callback
- # is set here.
- self.operator_func = None
- self.operator_arg = None
-
- #: Named registers. Maps register name (e.g. 'a') to
- #: :class:`ClipboardData` instances.
- self.named_registers = {}
-
- #: The Vi mode we're currently in to.
- self.input_mode = InputMode.INSERT
-
- #: Waiting for digraph.
- self.waiting_for_digraph = False
- self.digraph_symbol1 = None # (None or a symbol.)
-
- #: When true, make ~ act as an operator.
- self.tilde_operator = False
-
- def reset(self, mode=InputMode.INSERT):
- """
- Reset state, go back to the given mode. INSERT by default.
- """
- # Go back to insert mode.
- self.input_mode = mode
-
- self.waiting_for_digraph = False
- self.operator_func = None
- self.operator_arg = None
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/keys.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/keys.py
deleted file mode 100644
index d5df9bff41..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/keys.py
+++ /dev/null
@@ -1,129 +0,0 @@
-from __future__ import unicode_literals
-
-__all__ = (
- 'Key',
- 'Keys',
-)
-
-
-class Key(object):
- def __init__(self, name):
-
- #: Descriptive way of writing keys in configuration files. e.g. <C-A>
- #: for ``Control-A``.
- self.name = name
-
- def __repr__(self):
- return '%s(%r)' % (self.__class__.__name__, self.name)
-
-
-class Keys(object):
- Escape = Key('<Escape>')
-
- ControlA = Key('<C-A>')
- ControlB = Key('<C-B>')
- ControlC = Key('<C-C>')
- ControlD = Key('<C-D>')
- ControlE = Key('<C-E>')
- ControlF = Key('<C-F>')
- ControlG = Key('<C-G>')
- ControlH = Key('<C-H>')
- ControlI = Key('<C-I>') # Tab
- ControlJ = Key('<C-J>') # Enter
- ControlK = Key('<C-K>')
- ControlL = Key('<C-L>')
- ControlM = Key('<C-M>') # Enter
- ControlN = Key('<C-N>')
- ControlO = Key('<C-O>')
- ControlP = Key('<C-P>')
- ControlQ = Key('<C-Q>')
- ControlR = Key('<C-R>')
- ControlS = Key('<C-S>')
- ControlT = Key('<C-T>')
- ControlU = Key('<C-U>')
- ControlV = Key('<C-V>')
- ControlW = Key('<C-W>')
- ControlX = Key('<C-X>')
- ControlY = Key('<C-Y>')
- ControlZ = Key('<C-Z>')
-
- ControlSpace = Key('<C-Space>')
- ControlBackslash = Key('<C-Backslash>')
- ControlSquareClose = Key('<C-SquareClose>')
- ControlCircumflex = Key('<C-Circumflex>')
- ControlUnderscore = Key('<C-Underscore>')
- ControlLeft = Key('<C-Left>')
- ControlRight = Key('<C-Right>')
- ControlUp = Key('<C-Up>')
- ControlDown = Key('<C-Down>')
-
- Up = Key('<Up>')
- Down = Key('<Down>')
- Right = Key('<Right>')
- Left = Key('<Left>')
-
- ShiftLeft = Key('<ShiftLeft>')
- ShiftUp = Key('<ShiftUp>')
- ShiftDown = Key('<ShiftDown>')
- ShiftRight = Key('<ShiftRight>')
-
- Home = Key('<Home>')
- End = Key('<End>')
- Delete = Key('<Delete>')
- ShiftDelete = Key('<ShiftDelete>')
- ControlDelete = Key('<C-Delete>')
- PageUp = Key('<PageUp>')
- PageDown = Key('<PageDown>')
- BackTab = Key('<BackTab>') # shift + tab
- Insert = Key('<Insert>')
- Backspace = Key('<Backspace>')
-
- # Aliases.
- Tab = ControlI
- Enter = ControlJ
- # XXX: Actually Enter equals ControlM, not ControlJ,
- # However, in prompt_toolkit, we made the mistake of translating
- # \r into \n during the input, so everyone is now handling the
- # enter key by binding ControlJ.
-
- # From now on, it's better to bind `Keys.Enter` everywhere,
- # because that's future compatible, and will still work when we
- # stop replacing \r by \n.
-
- F1 = Key('<F1>')
- F2 = Key('<F2>')
- F3 = Key('<F3>')
- F4 = Key('<F4>')
- F5 = Key('<F5>')
- F6 = Key('<F6>')
- F7 = Key('<F7>')
- F8 = Key('<F8>')
- F9 = Key('<F9>')
- F10 = Key('<F10>')
- F11 = Key('<F11>')
- F12 = Key('<F12>')
- F13 = Key('<F13>')
- F14 = Key('<F14>')
- F15 = Key('<F15>')
- F16 = Key('<F16>')
- F17 = Key('<F17>')
- F18 = Key('<F18>')
- F19 = Key('<F19>')
- F20 = Key('<F20>')
- F21 = Key('<F21>')
- F22 = Key('<F22>')
- F23 = Key('<F23>')
- F24 = Key('<F24>')
-
- # Matches any key.
- Any = Key('<Any>')
-
- # Special
- CPRResponse = Key('<Cursor-Position-Response>')
- Vt100MouseEvent = Key('<Vt100-Mouse-Event>')
- WindowsMouseEvent = Key('<Windows-Mouse-Event>')
- BracketedPaste = Key('<Bracketed-Paste>')
-
- # Key which is ignored. (The key binding for this key should not do
- # anything.)
- Ignore = Key('<Ignore>')
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py
deleted file mode 100644
index 0dec5ecfaf..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py
+++ /dev/null
@@ -1,51 +0,0 @@
-"""
-Command line layout definitions
--------------------------------
-
-The layout of a command line interface is defined by a Container instance.
-There are two main groups of classes here. Containers and controls:
-
-- A container can contain other containers or controls, it can have multiple
- children and it decides about the dimensions.
-- A control is responsible for rendering the actual content to a screen.
- A control can propose some dimensions, but it's the container who decides
- about the dimensions -- or when the control consumes more space -- which part
- of the control will be visible.
-
-
-Container classes::
-
- - Container (Abstract base class)
- |- HSplit (Horizontal split)
- |- VSplit (Vertical split)
- |- FloatContainer (Container which can also contain menus and other floats)
- `- Window (Container which contains one actual control
-
-Control classes::
-
- - UIControl (Abstract base class)
- |- TokenListControl (Renders a simple list of tokens)
- |- FillControl (Fills control with one token/character.)
- `- BufferControl (Renders an input buffer.)
-
-
-Usually, you end up wrapping every control inside a `Window` object, because
-that's the only way to render it in a layout.
-
-There are some prepared toolbars which are ready to use::
-
-- SystemToolbar (Shows the 'system' input buffer, for entering system commands.)
-- ArgToolbar (Shows the input 'arg', for repetition of input commands.)
-- SearchToolbar (Shows the 'search' input buffer, for incremental search.)
-- CompletionsToolbar (Shows the completions of the current buffer.)
-- ValidationToolbar (Shows validation errors of the current buffer.)
-
-And one prepared menu:
-
-- CompletionsMenu
-
-"""
-from __future__ import unicode_literals
-
-from .containers import Float, FloatContainer, HSplit, VSplit, Window, ConditionalContainer
-from .controls import TokenListControl, FillControl, BufferControl
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py
deleted file mode 100644
index 0bdafe18e0..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py
+++ /dev/null
@@ -1,1665 +0,0 @@
-"""
-Container for the layout.
-(Containers can contain other containers or user interface controls.)
-"""
-from __future__ import unicode_literals
-
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-from six.moves import range
-
-from .controls import UIControl, TokenListControl, UIContent
-from .dimension import LayoutDimension, sum_layout_dimensions, max_layout_dimensions
-from .margins import Margin
-from .screen import Point, WritePosition, _CHAR_CACHE
-from .utils import token_list_to_text, explode_tokens
-from prompt_toolkit.cache import SimpleCache
-from prompt_toolkit.filters import to_cli_filter, ViInsertMode, EmacsInsertMode
-from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
-from prompt_toolkit.reactive import Integer
-from prompt_toolkit.token import Token
-from prompt_toolkit.utils import take_using_weights, get_cwidth
-
-__all__ = (
- 'Container',
- 'HSplit',
- 'VSplit',
- 'FloatContainer',
- 'Float',
- 'Window',
- 'WindowRenderInfo',
- 'ConditionalContainer',
- 'ScrollOffsets',
- 'ColorColumn',
-)
-
-Transparent = Token.Transparent
-
-
-class Container(with_metaclass(ABCMeta, object)):
- """
- Base class for user interface layout.
- """
- @abstractmethod
- def reset(self):
- """
- Reset the state of this container and all the children.
- (E.g. reset scroll offsets, etc...)
- """
-
- @abstractmethod
- def preferred_width(self, cli, max_available_width):
- """
- Return a :class:`~prompt_toolkit.layout.dimension.LayoutDimension` that
- represents the desired width for this container.
-
- :param cli: :class:`~prompt_toolkit.interface.CommandLineInterface`.
- """
-
- @abstractmethod
- def preferred_height(self, cli, width, max_available_height):
- """
- Return a :class:`~prompt_toolkit.layout.dimension.LayoutDimension` that
- represents the desired height for this container.
-
- :param cli: :class:`~prompt_toolkit.interface.CommandLineInterface`.
- """
-
- @abstractmethod
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- """
- Write the actual content to the screen.
-
- :param cli: :class:`~prompt_toolkit.interface.CommandLineInterface`.
- :param screen: :class:`~prompt_toolkit.layout.screen.Screen`
- :param mouse_handlers: :class:`~prompt_toolkit.layout.mouse_handlers.MouseHandlers`.
- """
-
- @abstractmethod
- def walk(self, cli):
- """
- Walk through all the layout nodes (and their children) and yield them.
- """
-
-
-def _window_too_small():
- " Create a `Window` that displays the 'Window too small' text. "
- return Window(TokenListControl.static(
- [(Token.WindowTooSmall, ' Window too small... ')]))
-
-
-class HSplit(Container):
- """
- Several layouts, one stacked above/under the other.
-
- :param children: List of child :class:`.Container` objects.
- :param window_too_small: A :class:`.Container` object that is displayed if
- there is not enough space for all the children. By default, this is a
- "Window too small" message.
- :param get_dimensions: (`None` or a callable that takes a
- `CommandLineInterface` and returns a list of `LayoutDimension`
- instances.) By default the dimensions are taken from the children and
- divided by the available space. However, when `get_dimensions` is specified,
- this is taken instead.
- :param report_dimensions_callback: When rendering, this function is called
- with the `CommandLineInterface` and the list of used dimensions. (As a
- list of integers.)
- """
- def __init__(self, children, window_too_small=None,
- get_dimensions=None, report_dimensions_callback=None):
- assert all(isinstance(c, Container) for c in children)
- assert window_too_small is None or isinstance(window_too_small, Container)
- assert get_dimensions is None or callable(get_dimensions)
- assert report_dimensions_callback is None or callable(report_dimensions_callback)
-
- self.children = children
- self.window_too_small = window_too_small or _window_too_small()
- self.get_dimensions = get_dimensions
- self.report_dimensions_callback = report_dimensions_callback
-
- def preferred_width(self, cli, max_available_width):
- if self.children:
- dimensions = [c.preferred_width(cli, max_available_width) for c in self.children]
- return max_layout_dimensions(dimensions)
- else:
- return LayoutDimension(0)
-
- def preferred_height(self, cli, width, max_available_height):
- dimensions = [c.preferred_height(cli, width, max_available_height) for c in self.children]
- return sum_layout_dimensions(dimensions)
-
- def reset(self):
- for c in self.children:
- c.reset()
-
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- """
- Render the prompt to a `Screen` instance.
-
- :param screen: The :class:`~prompt_toolkit.layout.screen.Screen` class
- to which the output has to be written.
- """
- sizes = self._divide_heigths(cli, write_position)
-
- if self.report_dimensions_callback:
- self.report_dimensions_callback(cli, sizes)
-
- if sizes is None:
- self.window_too_small.write_to_screen(
- cli, screen, mouse_handlers, write_position)
- else:
- # Draw child panes.
- ypos = write_position.ypos
- xpos = write_position.xpos
- width = write_position.width
-
- for s, c in zip(sizes, self.children):
- c.write_to_screen(cli, screen, mouse_handlers, WritePosition(xpos, ypos, width, s))
- ypos += s
-
- def _divide_heigths(self, cli, write_position):
- """
- Return the heights for all rows.
- Or None when there is not enough space.
- """
- if not self.children:
- return []
-
- # Calculate heights.
- given_dimensions = self.get_dimensions(cli) if self.get_dimensions else None
-
- def get_dimension_for_child(c, index):
- if given_dimensions and given_dimensions[index] is not None:
- return given_dimensions[index]
- else:
- return c.preferred_height(cli, write_position.width, write_position.extended_height)
-
- dimensions = [get_dimension_for_child(c, index) for index, c in enumerate(self.children)]
-
- # Sum dimensions
- sum_dimensions = sum_layout_dimensions(dimensions)
-
- # If there is not enough space for both.
- # Don't do anything.
- if sum_dimensions.min > write_position.extended_height:
- return
-
- # Find optimal sizes. (Start with minimal size, increase until we cover
- # the whole height.)
- sizes = [d.min for d in dimensions]
-
- child_generator = take_using_weights(
- items=list(range(len(dimensions))),
- weights=[d.weight for d in dimensions])
-
- i = next(child_generator)
-
- while sum(sizes) < min(write_position.extended_height, sum_dimensions.preferred):
- # Increase until we meet at least the 'preferred' size.
- if sizes[i] < dimensions[i].preferred:
- sizes[i] += 1
- i = next(child_generator)
-
- if not any([cli.is_returning, cli.is_exiting, cli.is_aborting]):
- while sum(sizes) < min(write_position.height, sum_dimensions.max):
- # Increase until we use all the available space. (or until "max")
- if sizes[i] < dimensions[i].max:
- sizes[i] += 1
- i = next(child_generator)
-
- return sizes
-
- def walk(self, cli):
- """ Walk through children. """
- yield self
- for c in self.children:
- for i in c.walk(cli):
- yield i
-
-
-class VSplit(Container):
- """
- Several layouts, one stacked left/right of the other.
-
- :param children: List of child :class:`.Container` objects.
- :param window_too_small: A :class:`.Container` object that is displayed if
- there is not enough space for all the children. By default, this is a
- "Window too small" message.
- :param get_dimensions: (`None` or a callable that takes a
- `CommandLineInterface` and returns a list of `LayoutDimension`
- instances.) By default the dimensions are taken from the children and
- divided by the available space. However, when `get_dimensions` is specified,
- this is taken instead.
- :param report_dimensions_callback: When rendering, this function is called
- with the `CommandLineInterface` and the list of used dimensions. (As a
- list of integers.)
- """
- def __init__(self, children, window_too_small=None,
- get_dimensions=None, report_dimensions_callback=None):
- assert all(isinstance(c, Container) for c in children)
- assert window_too_small is None or isinstance(window_too_small, Container)
- assert get_dimensions is None or callable(get_dimensions)
- assert report_dimensions_callback is None or callable(report_dimensions_callback)
-
- self.children = children
- self.window_too_small = window_too_small or _window_too_small()
- self.get_dimensions = get_dimensions
- self.report_dimensions_callback = report_dimensions_callback
-
- def preferred_width(self, cli, max_available_width):
- dimensions = [c.preferred_width(cli, max_available_width) for c in self.children]
- return sum_layout_dimensions(dimensions)
-
- def preferred_height(self, cli, width, max_available_height):
- sizes = self._divide_widths(cli, width)
- if sizes is None:
- return LayoutDimension()
- else:
- dimensions = [c.preferred_height(cli, s, max_available_height)
- for s, c in zip(sizes, self.children)]
- return max_layout_dimensions(dimensions)
-
- def reset(self):
- for c in self.children:
- c.reset()
-
- def _divide_widths(self, cli, width):
- """
- Return the widths for all columns.
- Or None when there is not enough space.
- """
- if not self.children:
- return []
-
- # Calculate widths.
- given_dimensions = self.get_dimensions(cli) if self.get_dimensions else None
-
- def get_dimension_for_child(c, index):
- if given_dimensions and given_dimensions[index] is not None:
- return given_dimensions[index]
- else:
- return c.preferred_width(cli, width)
-
- dimensions = [get_dimension_for_child(c, index) for index, c in enumerate(self.children)]
-
- # Sum dimensions
- sum_dimensions = sum_layout_dimensions(dimensions)
-
- # If there is not enough space for both.
- # Don't do anything.
- if sum_dimensions.min > width:
- return
-
- # Find optimal sizes. (Start with minimal size, increase until we cover
- # the whole height.)
- sizes = [d.min for d in dimensions]
-
- child_generator = take_using_weights(
- items=list(range(len(dimensions))),
- weights=[d.weight for d in dimensions])
-
- i = next(child_generator)
-
- while sum(sizes) < min(width, sum_dimensions.preferred):
- # Increase until we meet at least the 'preferred' size.
- if sizes[i] < dimensions[i].preferred:
- sizes[i] += 1
- i = next(child_generator)
-
- while sum(sizes) < min(width, sum_dimensions.max):
- # Increase until we use all the available space.
- if sizes[i] < dimensions[i].max:
- sizes[i] += 1
- i = next(child_generator)
-
- return sizes
-
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- """
- Render the prompt to a `Screen` instance.
-
- :param screen: The :class:`~prompt_toolkit.layout.screen.Screen` class
- to which the output has to be written.
- """
- if not self.children:
- return
-
- sizes = self._divide_widths(cli, write_position.width)
-
- if self.report_dimensions_callback:
- self.report_dimensions_callback(cli, sizes)
-
- # If there is not enough space.
- if sizes is None:
- self.window_too_small.write_to_screen(
- cli, screen, mouse_handlers, write_position)
- return
-
- # Calculate heights, take the largest possible, but not larger than write_position.extended_height.
- heights = [child.preferred_height(cli, width, write_position.extended_height).preferred
- for width, child in zip(sizes, self.children)]
- height = max(write_position.height, min(write_position.extended_height, max(heights)))
-
- # Draw child panes.
- ypos = write_position.ypos
- xpos = write_position.xpos
-
- for s, c in zip(sizes, self.children):
- c.write_to_screen(cli, screen, mouse_handlers, WritePosition(xpos, ypos, s, height))
- xpos += s
-
- def walk(self, cli):
- """ Walk through children. """
- yield self
- for c in self.children:
- for i in c.walk(cli):
- yield i
-
-
-class FloatContainer(Container):
- """
- Container which can contain another container for the background, as well
- as a list of floating containers on top of it.
-
- Example Usage::
-
- FloatContainer(content=Window(...),
- floats=[
- Float(xcursor=True,
- ycursor=True,
- layout=CompletionMenu(...))
- ])
- """
- def __init__(self, content, floats):
- assert isinstance(content, Container)
- assert all(isinstance(f, Float) for f in floats)
-
- self.content = content
- self.floats = floats
-
- def reset(self):
- self.content.reset()
-
- for f in self.floats:
- f.content.reset()
-
- def preferred_width(self, cli, write_position):
- return self.content.preferred_width(cli, write_position)
-
- def preferred_height(self, cli, width, max_available_height):
- """
- Return the preferred height of the float container.
- (We don't care about the height of the floats, they should always fit
- into the dimensions provided by the container.)
- """
- return self.content.preferred_height(cli, width, max_available_height)
-
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- self.content.write_to_screen(cli, screen, mouse_handlers, write_position)
-
- for fl in self.floats:
- # When a menu_position was given, use this instead of the cursor
- # position. (These cursor positions are absolute, translate again
- # relative to the write_position.)
- # Note: This should be inside the for-loop, because one float could
- # set the cursor position to be used for the next one.
- cursor_position = screen.menu_position or screen.cursor_position
- cursor_position = Point(x=cursor_position.x - write_position.xpos,
- y=cursor_position.y - write_position.ypos)
-
- fl_width = fl.get_width(cli)
- fl_height = fl.get_height(cli)
-
- # Left & width given.
- if fl.left is not None and fl_width is not None:
- xpos = fl.left
- width = fl_width
- # Left & right given -> calculate width.
- elif fl.left is not None and fl.right is not None:
- xpos = fl.left
- width = write_position.width - fl.left - fl.right
- # Width & right given -> calculate left.
- elif fl_width is not None and fl.right is not None:
- xpos = write_position.width - fl.right - fl_width
- width = fl_width
- elif fl.xcursor:
- width = fl_width
- if width is None:
- width = fl.content.preferred_width(cli, write_position.width).preferred
- width = min(write_position.width, width)
-
- xpos = cursor_position.x
- if xpos + width > write_position.width:
- xpos = max(0, write_position.width - width)
- # Only width given -> center horizontally.
- elif fl_width:
- xpos = int((write_position.width - fl_width) / 2)
- width = fl_width
- # Otherwise, take preferred width from float content.
- else:
- width = fl.content.preferred_width(cli, write_position.width).preferred
-
- if fl.left is not None:
- xpos = fl.left
- elif fl.right is not None:
- xpos = max(0, write_position.width - width - fl.right)
- else: # Center horizontally.
- xpos = max(0, int((write_position.width - width) / 2))
-
- # Trim.
- width = min(width, write_position.width - xpos)
-
- # Top & height given.
- if fl.top is not None and fl_height is not None:
- ypos = fl.top
- height = fl_height
- # Top & bottom given -> calculate height.
- elif fl.top is not None and fl.bottom is not None:
- ypos = fl.top
- height = write_position.height - fl.top - fl.bottom
- # Height & bottom given -> calculate top.
- elif fl_height is not None and fl.bottom is not None:
- ypos = write_position.height - fl_height - fl.bottom
- height = fl_height
- # Near cursor
- elif fl.ycursor:
- ypos = cursor_position.y + 1
-
- height = fl_height
- if height is None:
- height = fl.content.preferred_height(
- cli, width, write_position.extended_height).preferred
-
- # Reduce height if not enough space. (We can use the
- # extended_height when the content requires it.)
- if height > write_position.extended_height - ypos:
- if write_position.extended_height - ypos + 1 >= ypos:
- # When the space below the cursor is more than
- # the space above, just reduce the height.
- height = write_position.extended_height - ypos
- else:
- # Otherwise, fit the float above the cursor.
- height = min(height, cursor_position.y)
- ypos = cursor_position.y - height
-
- # Only height given -> center vertically.
- elif fl_width:
- ypos = int((write_position.height - fl_height) / 2)
- height = fl_height
- # Otherwise, take preferred height from content.
- else:
- height = fl.content.preferred_height(
- cli, width, write_position.extended_height).preferred
-
- if fl.top is not None:
- ypos = fl.top
- elif fl.bottom is not None:
- ypos = max(0, write_position.height - height - fl.bottom)
- else: # Center vertically.
- ypos = max(0, int((write_position.height - height) / 2))
-
- # Trim.
- height = min(height, write_position.height - ypos)
-
- # Write float.
- # (xpos and ypos can be negative: a float can be partially visible.)
- if height > 0 and width > 0:
- wp = WritePosition(xpos=xpos + write_position.xpos,
- ypos=ypos + write_position.ypos,
- width=width, height=height)
-
- if not fl.hide_when_covering_content or self._area_is_empty(screen, wp):
- fl.content.write_to_screen(cli, screen, mouse_handlers, wp)
-
- def _area_is_empty(self, screen, write_position):
- """
- Return True when the area below the write position is still empty.
- (For floats that should not hide content underneath.)
- """
- wp = write_position
- Transparent = Token.Transparent
-
- for y in range(wp.ypos, wp.ypos + wp.height):
- if y in screen.data_buffer:
- row = screen.data_buffer[y]
-
- for x in range(wp.xpos, wp.xpos + wp.width):
- c = row[x]
- if c.char != ' ' or c.token != Transparent:
- return False
-
- return True
-
- def walk(self, cli):
- """ Walk through children. """
- yield self
-
- for i in self.content.walk(cli):
- yield i
-
- for f in self.floats:
- for i in f.content.walk(cli):
- yield i
-
-
-class Float(object):
- """
- Float for use in a :class:`.FloatContainer`.
-
- :param content: :class:`.Container` instance.
- :param hide_when_covering_content: Hide the float when it covers content underneath.
- """
- def __init__(self, top=None, right=None, bottom=None, left=None,
- width=None, height=None, get_width=None, get_height=None,
- xcursor=False, ycursor=False, content=None,
- hide_when_covering_content=False):
- assert isinstance(content, Container)
- assert width is None or get_width is None
- assert height is None or get_height is None
-
- self.left = left
- self.right = right
- self.top = top
- self.bottom = bottom
-
- self._width = width
- self._height = height
-
- self._get_width = get_width
- self._get_height = get_height
-
- self.xcursor = xcursor
- self.ycursor = ycursor
-
- self.content = content
- self.hide_when_covering_content = hide_when_covering_content
-
- def get_width(self, cli):
- if self._width:
- return self._width
- if self._get_width:
- return self._get_width(cli)
-
- def get_height(self, cli):
- if self._height:
- return self._height
- if self._get_height:
- return self._get_height(cli)
-
- def __repr__(self):
- return 'Float(content=%r)' % self.content
-
-
-class WindowRenderInfo(object):
- """
- Render information, for the last render time of this control.
- It stores mapping information between the input buffers (in case of a
- :class:`~prompt_toolkit.layout.controls.BufferControl`) and the actual
- render position on the output screen.
-
- (Could be used for implementation of the Vi 'H' and 'L' key bindings as
- well as implementing mouse support.)
-
- :param ui_content: The original :class:`.UIContent` instance that contains
- the whole input, without clipping. (ui_content)
- :param horizontal_scroll: The horizontal scroll of the :class:`.Window` instance.
- :param vertical_scroll: The vertical scroll of the :class:`.Window` instance.
- :param window_width: The width of the window that displays the content,
- without the margins.
- :param window_height: The height of the window that displays the content.
- :param configured_scroll_offsets: The scroll offsets as configured for the
- :class:`Window` instance.
- :param visible_line_to_row_col: Mapping that maps the row numbers on the
- displayed screen (starting from zero for the first visible line) to
- (row, col) tuples pointing to the row and column of the :class:`.UIContent`.
- :param rowcol_to_yx: Mapping that maps (row, column) tuples representing
- coordinates of the :class:`UIContent` to (y, x) absolute coordinates at
- the rendered screen.
- """
- def __init__(self, ui_content, horizontal_scroll, vertical_scroll,
- window_width, window_height,
- configured_scroll_offsets,
- visible_line_to_row_col, rowcol_to_yx,
- x_offset, y_offset, wrap_lines):
- assert isinstance(ui_content, UIContent)
- assert isinstance(horizontal_scroll, int)
- assert isinstance(vertical_scroll, int)
- assert isinstance(window_width, int)
- assert isinstance(window_height, int)
- assert isinstance(configured_scroll_offsets, ScrollOffsets)
- assert isinstance(visible_line_to_row_col, dict)
- assert isinstance(rowcol_to_yx, dict)
- assert isinstance(x_offset, int)
- assert isinstance(y_offset, int)
- assert isinstance(wrap_lines, bool)
-
- self.ui_content = ui_content
- self.vertical_scroll = vertical_scroll
- self.window_width = window_width # Width without margins.
- self.window_height = window_height
-
- self.configured_scroll_offsets = configured_scroll_offsets
- self.visible_line_to_row_col = visible_line_to_row_col
- self.wrap_lines = wrap_lines
-
- self._rowcol_to_yx = rowcol_to_yx # row/col from input to absolute y/x
- # screen coordinates.
- self._x_offset = x_offset
- self._y_offset = y_offset
-
- @property
- def visible_line_to_input_line(self):
- return dict(
- (visible_line, rowcol[0])
- for visible_line, rowcol in self.visible_line_to_row_col.items())
-
- @property
- def cursor_position(self):
- """
- Return the cursor position coordinates, relative to the left/top corner
- of the rendered screen.
- """
- cpos = self.ui_content.cursor_position
- y, x = self._rowcol_to_yx[cpos.y, cpos.x]
- return Point(x=x - self._x_offset, y=y - self._y_offset)
-
- @property
- def applied_scroll_offsets(self):
- """
- Return a :class:`.ScrollOffsets` instance that indicates the actual
- offset. This can be less than or equal to what's configured. E.g, when
- the cursor is completely at the top, the top offset will be zero rather
- than what's configured.
- """
- if self.displayed_lines[0] == 0:
- top = 0
- else:
- # Get row where the cursor is displayed.
- y = self.input_line_to_visible_line[self.ui_content.cursor_position.y]
- top = min(y, self.configured_scroll_offsets.top)
-
- return ScrollOffsets(
- top=top,
- bottom=min(self.ui_content.line_count - self.displayed_lines[-1] - 1,
- self.configured_scroll_offsets.bottom),
-
- # For left/right, it probably doesn't make sense to return something.
- # (We would have to calculate the widths of all the lines and keep
- # double width characters in mind.)
- left=0, right=0)
-
- @property
- def displayed_lines(self):
- """
- List of all the visible rows. (Line numbers of the input buffer.)
- The last line may not be entirely visible.
- """
- return sorted(row for row, col in self.visible_line_to_row_col.values())
-
- @property
- def input_line_to_visible_line(self):
- """
- Return the dictionary mapping the line numbers of the input buffer to
- the lines of the screen. When a line spans several rows at the screen,
- the first row appears in the dictionary.
- """
- result = {}
- for k, v in self.visible_line_to_input_line.items():
- if v in result:
- result[v] = min(result[v], k)
- else:
- result[v] = k
- return result
-
- def first_visible_line(self, after_scroll_offset=False):
- """
- Return the line number (0 based) of the input document that corresponds
- with the first visible line.
- """
- if after_scroll_offset:
- return self.displayed_lines[self.applied_scroll_offsets.top]
- else:
- return self.displayed_lines[0]
-
- def last_visible_line(self, before_scroll_offset=False):
- """
- Like `first_visible_line`, but for the last visible line.
- """
- if before_scroll_offset:
- return self.displayed_lines[-1 - self.applied_scroll_offsets.bottom]
- else:
- return self.displayed_lines[-1]
-
- def center_visible_line(self, before_scroll_offset=False,
- after_scroll_offset=False):
- """
- Like `first_visible_line`, but for the center visible line.
- """
- return (self.first_visible_line(after_scroll_offset) +
- (self.last_visible_line(before_scroll_offset) -
- self.first_visible_line(after_scroll_offset)) // 2
- )
-
- @property
- def content_height(self):
- """
- The full height of the user control.
- """
- return self.ui_content.line_count
-
- @property
- def full_height_visible(self):
- """
- True when the full height is visible (There is no vertical scroll.)
- """
- return self.vertical_scroll == 0 and self.last_visible_line() == self.content_height
-
- @property
- def top_visible(self):
- """
- True when the top of the buffer is visible.
- """
- return self.vertical_scroll == 0
-
- @property
- def bottom_visible(self):
- """
- True when the bottom of the buffer is visible.
- """
- return self.last_visible_line() == self.content_height - 1
-
- @property
- def vertical_scroll_percentage(self):
- """
- Vertical scroll as a percentage. (0 means: the top is visible,
- 100 means: the bottom is visible.)
- """
- if self.bottom_visible:
- return 100
- else:
- return (100 * self.vertical_scroll // self.content_height)
-
- def get_height_for_line(self, lineno):
- """
- Return the height of the given line.
- (The height that it would take, if this line became visible.)
- """
- if self.wrap_lines:
- return self.ui_content.get_height_for_line(lineno, self.window_width)
- else:
- return 1
-
-
-class ScrollOffsets(object):
- """
- Scroll offsets for the :class:`.Window` class.
-
- Note that left/right offsets only make sense if line wrapping is disabled.
- """
- def __init__(self, top=0, bottom=0, left=0, right=0):
- assert isinstance(top, Integer)
- assert isinstance(bottom, Integer)
- assert isinstance(left, Integer)
- assert isinstance(right, Integer)
-
- self._top = top
- self._bottom = bottom
- self._left = left
- self._right = right
-
- @property
- def top(self):
- return int(self._top)
-
- @property
- def bottom(self):
- return int(self._bottom)
-
- @property
- def left(self):
- return int(self._left)
-
- @property
- def right(self):
- return int(self._right)
-
- def __repr__(self):
- return 'ScrollOffsets(top=%r, bottom=%r, left=%r, right=%r)' % (
- self.top, self.bottom, self.left, self.right)
-
-
-class ColorColumn(object):
- def __init__(self, position, token=Token.ColorColumn):
- self.position = position
- self.token = token
-
-
-_in_insert_mode = ViInsertMode() | EmacsInsertMode()
-
-
-class Window(Container):
- """
- Container that holds a control.
-
- :param content: :class:`~prompt_toolkit.layout.controls.UIControl` instance.
- :param width: :class:`~prompt_toolkit.layout.dimension.LayoutDimension` instance.
- :param height: :class:`~prompt_toolkit.layout.dimension.LayoutDimension` instance.
- :param get_width: callable which takes a `CommandLineInterface` and returns a `LayoutDimension`.
- :param get_height: callable which takes a `CommandLineInterface` and returns a `LayoutDimension`.
- :param dont_extend_width: When `True`, don't take up more width then the
- preferred width reported by the control.
- :param dont_extend_height: When `True`, don't take up more width then the
- preferred height reported by the control.
- :param left_margins: A list of :class:`~prompt_toolkit.layout.margins.Margin`
- instance to be displayed on the left. For instance:
- :class:`~prompt_toolkit.layout.margins.NumberredMargin` can be one of
- them in order to show line numbers.
- :param right_margins: Like `left_margins`, but on the other side.
- :param scroll_offsets: :class:`.ScrollOffsets` instance, representing the
- preferred amount of lines/columns to be always visible before/after the
- cursor. When both top and bottom are a very high number, the cursor
- will be centered vertically most of the time.
- :param allow_scroll_beyond_bottom: A `bool` or
- :class:`~prompt_toolkit.filters.CLIFilter` instance. When True, allow
- scrolling so far, that the top part of the content is not visible
- anymore, while there is still empty space available at the bottom of
- the window. In the Vi editor for instance, this is possible. You will
- see tildes while the top part of the body is hidden.
- :param wrap_lines: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter`
- instance. When True, don't scroll horizontally, but wrap lines instead.
- :param get_vertical_scroll: Callable that takes this window
- instance as input and returns a preferred vertical scroll.
- (When this is `None`, the scroll is only determined by the last and
- current cursor position.)
- :param get_horizontal_scroll: Callable that takes this window
- instance as input and returns a preferred vertical scroll.
- :param always_hide_cursor: A `bool` or
- :class:`~prompt_toolkit.filters.CLIFilter` instance. When True, never
- display the cursor, even when the user control specifies a cursor
- position.
- :param cursorline: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter`
- instance. When True, display a cursorline.
- :param cursorcolumn: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter`
- instance. When True, display a cursorcolumn.
- :param get_colorcolumns: A callable that takes a `CommandLineInterface` and
- returns a a list of :class:`.ColorColumn` instances that describe the
- columns to be highlighted.
- :param cursorline_token: The token to be used for highlighting the current line,
- if `cursorline` is True.
- :param cursorcolumn_token: The token to be used for highlighting the current line,
- if `cursorcolumn` is True.
- """
- def __init__(self, content, width=None, height=None, get_width=None,
- get_height=None, dont_extend_width=False, dont_extend_height=False,
- left_margins=None, right_margins=None, scroll_offsets=None,
- allow_scroll_beyond_bottom=False, wrap_lines=False,
- get_vertical_scroll=None, get_horizontal_scroll=None, always_hide_cursor=False,
- cursorline=False, cursorcolumn=False, get_colorcolumns=None,
- cursorline_token=Token.CursorLine, cursorcolumn_token=Token.CursorColumn):
- assert isinstance(content, UIControl)
- assert width is None or isinstance(width, LayoutDimension)
- assert height is None or isinstance(height, LayoutDimension)
- assert get_width is None or callable(get_width)
- assert get_height is None or callable(get_height)
- assert width is None or get_width is None
- assert height is None or get_height is None
- assert scroll_offsets is None or isinstance(scroll_offsets, ScrollOffsets)
- assert left_margins is None or all(isinstance(m, Margin) for m in left_margins)
- assert right_margins is None or all(isinstance(m, Margin) for m in right_margins)
- assert get_vertical_scroll is None or callable(get_vertical_scroll)
- assert get_horizontal_scroll is None or callable(get_horizontal_scroll)
- assert get_colorcolumns is None or callable(get_colorcolumns)
-
- self.allow_scroll_beyond_bottom = to_cli_filter(allow_scroll_beyond_bottom)
- self.always_hide_cursor = to_cli_filter(always_hide_cursor)
- self.wrap_lines = to_cli_filter(wrap_lines)
- self.cursorline = to_cli_filter(cursorline)
- self.cursorcolumn = to_cli_filter(cursorcolumn)
-
- self.content = content
- self.dont_extend_width = dont_extend_width
- self.dont_extend_height = dont_extend_height
- self.left_margins = left_margins or []
- self.right_margins = right_margins or []
- self.scroll_offsets = scroll_offsets or ScrollOffsets()
- self.get_vertical_scroll = get_vertical_scroll
- self.get_horizontal_scroll = get_horizontal_scroll
- self._width = get_width or (lambda cli: width)
- self._height = get_height or (lambda cli: height)
- self.get_colorcolumns = get_colorcolumns or (lambda cli: [])
- self.cursorline_token = cursorline_token
- self.cursorcolumn_token = cursorcolumn_token
-
- # Cache for the screens generated by the margin.
- self._ui_content_cache = SimpleCache(maxsize=8)
- self._margin_width_cache = SimpleCache(maxsize=1)
-
- self.reset()
-
- def __repr__(self):
- return 'Window(content=%r)' % self.content
-
- def reset(self):
- self.content.reset()
-
- #: Scrolling position of the main content.
- self.vertical_scroll = 0
- self.horizontal_scroll = 0
-
- # Vertical scroll 2: this is the vertical offset that a line is
- # scrolled if a single line (the one that contains the cursor) consumes
- # all of the vertical space.
- self.vertical_scroll_2 = 0
-
- #: Keep render information (mappings between buffer input and render
- #: output.)
- self.render_info = None
-
- def _get_margin_width(self, cli, margin):
- """
- Return the width for this margin.
- (Calculate only once per render time.)
- """
- # Margin.get_width, needs to have a UIContent instance.
- def get_ui_content():
- return self._get_ui_content(cli, width=0, height=0)
-
- def get_width():
- return margin.get_width(cli, get_ui_content)
-
- key = (margin, cli.render_counter)
- return self._margin_width_cache.get(key, get_width)
-
- def preferred_width(self, cli, max_available_width):
- # Calculate the width of the margin.
- total_margin_width = sum(self._get_margin_width(cli, m) for m in
- self.left_margins + self.right_margins)
-
- # Window of the content. (Can be `None`.)
- preferred_width = self.content.preferred_width(
- cli, max_available_width - total_margin_width)
-
- if preferred_width is not None:
- # Include width of the margins.
- preferred_width += total_margin_width
-
- # Merge.
- return self._merge_dimensions(
- dimension=self._width(cli),
- preferred=preferred_width,
- dont_extend=self.dont_extend_width)
-
- def preferred_height(self, cli, width, max_available_height):
- total_margin_width = sum(self._get_margin_width(cli, m) for m in
- self.left_margins + self.right_margins)
- wrap_lines = self.wrap_lines(cli)
-
- return self._merge_dimensions(
- dimension=self._height(cli),
- preferred=self.content.preferred_height(
- cli, width - total_margin_width, max_available_height, wrap_lines),
- dont_extend=self.dont_extend_height)
-
- @staticmethod
- def _merge_dimensions(dimension, preferred=None, dont_extend=False):
- """
- Take the LayoutDimension from this `Window` class and the received
- preferred size from the `UIControl` and return a `LayoutDimension` to
- report to the parent container.
- """
- dimension = dimension or LayoutDimension()
-
- # When a preferred dimension was explicitly given to the Window,
- # ignore the UIControl.
- if dimension.preferred_specified:
- preferred = dimension.preferred
-
- # When a 'preferred' dimension is given by the UIControl, make sure
- # that it stays within the bounds of the Window.
- if preferred is not None:
- if dimension.max:
- preferred = min(preferred, dimension.max)
-
- if dimension.min:
- preferred = max(preferred, dimension.min)
-
- # When a `dont_extend` flag has been given, use the preferred dimension
- # also as the max dimension.
- if dont_extend and preferred is not None:
- max_ = min(dimension.max, preferred)
- else:
- max_ = dimension.max
-
- return LayoutDimension(
- min=dimension.min, max=max_,
- preferred=preferred, weight=dimension.weight)
-
- def _get_ui_content(self, cli, width, height):
- """
- Create a `UIContent` instance.
- """
- def get_content():
- return self.content.create_content(cli, width=width, height=height)
-
- key = (cli.render_counter, width, height)
- return self._ui_content_cache.get(key, get_content)
-
- def _get_digraph_char(self, cli):
- " Return `False`, or the Digraph symbol to be used. "
- if cli.quoted_insert:
- return '^'
- if cli.vi_state.waiting_for_digraph:
- if cli.vi_state.digraph_symbol1:
- return cli.vi_state.digraph_symbol1
- return '?'
- return False
-
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- """
- Write window to screen. This renders the user control, the margins and
- copies everything over to the absolute position at the given screen.
- """
- # Calculate margin sizes.
- left_margin_widths = [self._get_margin_width(cli, m) for m in self.left_margins]
- right_margin_widths = [self._get_margin_width(cli, m) for m in self.right_margins]
- total_margin_width = sum(left_margin_widths + right_margin_widths)
-
- # Render UserControl.
- ui_content = self.content.create_content(
- cli, write_position.width - total_margin_width, write_position.height)
- assert isinstance(ui_content, UIContent)
-
- # Scroll content.
- wrap_lines = self.wrap_lines(cli)
- scroll_func = self._scroll_when_linewrapping if wrap_lines else self._scroll_without_linewrapping
-
- scroll_func(
- ui_content, write_position.width - total_margin_width, write_position.height, cli)
-
- # Write body
- visible_line_to_row_col, rowcol_to_yx = self._copy_body(
- cli, ui_content, screen, write_position,
- sum(left_margin_widths), write_position.width - total_margin_width,
- self.vertical_scroll, self.horizontal_scroll,
- has_focus=self.content.has_focus(cli),
- wrap_lines=wrap_lines, highlight_lines=True,
- vertical_scroll_2=self.vertical_scroll_2,
- always_hide_cursor=self.always_hide_cursor(cli))
-
- # Remember render info. (Set before generating the margins. They need this.)
- x_offset=write_position.xpos + sum(left_margin_widths)
- y_offset=write_position.ypos
-
- self.render_info = WindowRenderInfo(
- ui_content=ui_content,
- horizontal_scroll=self.horizontal_scroll,
- vertical_scroll=self.vertical_scroll,
- window_width=write_position.width - total_margin_width,
- window_height=write_position.height,
- configured_scroll_offsets=self.scroll_offsets,
- visible_line_to_row_col=visible_line_to_row_col,
- rowcol_to_yx=rowcol_to_yx,
- x_offset=x_offset,
- y_offset=y_offset,
- wrap_lines=wrap_lines)
-
- # Set mouse handlers.
- def mouse_handler(cli, mouse_event):
- """ Wrapper around the mouse_handler of the `UIControl` that turns
- screen coordinates into line coordinates. """
- # Find row/col position first.
- yx_to_rowcol = dict((v, k) for k, v in rowcol_to_yx.items())
- y = mouse_event.position.y
- x = mouse_event.position.x
-
- # If clicked below the content area, look for a position in the
- # last line instead.
- max_y = write_position.ypos + len(visible_line_to_row_col) - 1
- y = min(max_y, y)
-
- while x >= 0:
- try:
- row, col = yx_to_rowcol[y, x]
- except KeyError:
- # Try again. (When clicking on the right side of double
- # width characters, or on the right side of the input.)
- x -= 1
- else:
- # Found position, call handler of UIControl.
- result = self.content.mouse_handler(
- cli, MouseEvent(position=Point(x=col, y=row),
- event_type=mouse_event.event_type))
- break
- else:
- # nobreak.
- # (No x/y coordinate found for the content. This happens in
- # case of a FillControl, that only specifies a background, but
- # doesn't have a content. Report (0,0) instead.)
- result = self.content.mouse_handler(
- cli, MouseEvent(position=Point(x=0, y=0),
- event_type=mouse_event.event_type))
-
- # If it returns NotImplemented, handle it here.
- if result == NotImplemented:
- return self._mouse_handler(cli, mouse_event)
-
- return result
-
- mouse_handlers.set_mouse_handler_for_range(
- x_min=write_position.xpos + sum(left_margin_widths),
- x_max=write_position.xpos + write_position.width - total_margin_width,
- y_min=write_position.ypos,
- y_max=write_position.ypos + write_position.height,
- handler=mouse_handler)
-
- # Render and copy margins.
- move_x = 0
-
- def render_margin(m, width):
- " Render margin. Return `Screen`. "
- # Retrieve margin tokens.
- tokens = m.create_margin(cli, self.render_info, width, write_position.height)
-
- # Turn it into a UIContent object.
- # already rendered those tokens using this size.)
- return TokenListControl.static(tokens).create_content(
- cli, width + 1, write_position.height)
-
- for m, width in zip(self.left_margins, left_margin_widths):
- # Create screen for margin.
- margin_screen = render_margin(m, width)
-
- # Copy and shift X.
- self._copy_margin(cli, margin_screen, screen, write_position, move_x, width)
- move_x += width
-
- move_x = write_position.width - sum(right_margin_widths)
-
- for m, width in zip(self.right_margins, right_margin_widths):
- # Create screen for margin.
- margin_screen = render_margin(m, width)
-
- # Copy and shift X.
- self._copy_margin(cli, margin_screen, screen, write_position, move_x, width)
- move_x += width
-
- def _copy_body(self, cli, ui_content, new_screen, write_position, move_x,
- width, vertical_scroll=0, horizontal_scroll=0,
- has_focus=False, wrap_lines=False, highlight_lines=False,
- vertical_scroll_2=0, always_hide_cursor=False):
- """
- Copy the UIContent into the output screen.
- """
- xpos = write_position.xpos + move_x
- ypos = write_position.ypos
- line_count = ui_content.line_count
- new_buffer = new_screen.data_buffer
- empty_char = _CHAR_CACHE['', Token]
- ZeroWidthEscape = Token.ZeroWidthEscape
-
- # Map visible line number to (row, col) of input.
- # 'col' will always be zero if line wrapping is off.
- visible_line_to_row_col = {}
- rowcol_to_yx = {} # Maps (row, col) from the input to (y, x) screen coordinates.
-
- # Fill background with default_char first.
- default_char = ui_content.default_char
-
- if default_char:
- for y in range(ypos, ypos + write_position.height):
- new_buffer_row = new_buffer[y]
- for x in range(xpos, xpos + width):
- new_buffer_row[x] = default_char
-
- # Copy content.
- def copy():
- y = - vertical_scroll_2
- lineno = vertical_scroll
-
- while y < write_position.height and lineno < line_count:
- # Take the next line and copy it in the real screen.
- line = ui_content.get_line(lineno)
-
- col = 0
- x = -horizontal_scroll
-
- visible_line_to_row_col[y] = (lineno, horizontal_scroll)
- new_buffer_row = new_buffer[y + ypos]
-
- for token, text in line:
- # Remember raw VT escape sequences. (E.g. FinalTerm's
- # escape sequences.)
- if token == ZeroWidthEscape:
- new_screen.zero_width_escapes[y + ypos][x + xpos] += text
- continue
-
- for c in text:
- char = _CHAR_CACHE[c, token]
- char_width = char.width
-
- # Wrap when the line width is exceeded.
- if wrap_lines and x + char_width > width:
- visible_line_to_row_col[y + 1] = (
- lineno, visible_line_to_row_col[y][1] + x)
- y += 1
- x = -horizontal_scroll # This would be equal to zero.
- # (horizontal_scroll=0 when wrap_lines.)
- new_buffer_row = new_buffer[y + ypos]
-
- if y >= write_position.height:
- return y # Break out of all for loops.
-
- # Set character in screen and shift 'x'.
- if x >= 0 and y >= 0 and x < write_position.width:
- new_buffer_row[x + xpos] = char
-
- # When we print a multi width character, make sure
- # to erase the neighbous positions in the screen.
- # (The empty string if different from everything,
- # so next redraw this cell will repaint anyway.)
- if char_width > 1:
- for i in range(1, char_width):
- new_buffer_row[x + xpos + i] = empty_char
-
- # If this is a zero width characters, then it's
- # probably part of a decomposed unicode character.
- # See: https://en.wikipedia.org/wiki/Unicode_equivalence
- # Merge it in the previous cell.
- elif char_width == 0 and x - 1 >= 0:
- prev_char = new_buffer_row[x + xpos - 1]
- char2 = _CHAR_CACHE[prev_char.char + c, prev_char.token]
- new_buffer_row[x + xpos - 1] = char2
-
- # Keep track of write position for each character.
- rowcol_to_yx[lineno, col] = (y + ypos, x + xpos)
-
- col += 1
- x += char_width
-
- lineno += 1
- y += 1
- return y
-
- y = copy()
-
- def cursor_pos_to_screen_pos(row, col):
- " Translate row/col from UIContent to real Screen coordinates. "
- try:
- y, x = rowcol_to_yx[row, col]
- except KeyError:
- # Normally this should never happen. (It is a bug, if it happens.)
- # But to be sure, return (0, 0)
- return Point(y=0, x=0)
-
- # raise ValueError(
- # 'Invalid position. row=%r col=%r, vertical_scroll=%r, '
- # 'horizontal_scroll=%r, height=%r' %
- # (row, col, vertical_scroll, horizontal_scroll, write_position.height))
- else:
- return Point(y=y, x=x)
-
- # Set cursor and menu positions.
- if ui_content.cursor_position:
- screen_cursor_position = cursor_pos_to_screen_pos(
- ui_content.cursor_position.y, ui_content.cursor_position.x)
-
- if has_focus:
- new_screen.cursor_position = screen_cursor_position
-
- if always_hide_cursor:
- new_screen.show_cursor = False
- else:
- new_screen.show_cursor = ui_content.show_cursor
-
- self._highlight_digraph(cli, new_screen)
-
- if highlight_lines:
- self._highlight_cursorlines(
- cli, new_screen, screen_cursor_position, xpos, ypos, width,
- write_position.height)
-
- # Draw input characters from the input processor queue.
- if has_focus and ui_content.cursor_position:
- self._show_input_processor_key_buffer(cli, new_screen)
-
- # Set menu position.
- if not new_screen.menu_position and ui_content.menu_position:
- new_screen.menu_position = cursor_pos_to_screen_pos(
- ui_content.menu_position.y, ui_content.menu_position.x)
-
- # Update output screne height.
- new_screen.height = max(new_screen.height, ypos + write_position.height)
-
- return visible_line_to_row_col, rowcol_to_yx
-
- def _highlight_digraph(self, cli, new_screen):
- """
- When we are in Vi digraph mode, put a question mark underneath the
- cursor.
- """
- digraph_char = self._get_digraph_char(cli)
- if digraph_char:
- cpos = new_screen.cursor_position
- new_screen.data_buffer[cpos.y][cpos.x] = \
- _CHAR_CACHE[digraph_char, Token.Digraph]
-
- def _show_input_processor_key_buffer(self, cli, new_screen):
- """
- When the user is typing a key binding that consists of several keys,
- display the last pressed key if the user is in insert mode and the key
- is meaningful to be displayed.
- E.g. Some people want to bind 'jj' to escape in Vi insert mode. But the
- first 'j' needs to be displayed in order to get some feedback.
- """
- key_buffer = cli.input_processor.key_buffer
-
- if key_buffer and _in_insert_mode(cli) and not cli.is_done:
- # The textual data for the given key. (Can be a VT100 escape
- # sequence.)
- data = key_buffer[-1].data
-
- # Display only if this is a 1 cell width character.
- if get_cwidth(data) == 1:
- cpos = new_screen.cursor_position
- new_screen.data_buffer[cpos.y][cpos.x] = \
- _CHAR_CACHE[data, Token.PartialKeyBinding]
-
- def _highlight_cursorlines(self, cli, new_screen, cpos, x, y, width, height):
- """
- Highlight cursor row/column.
- """
- cursor_line_token = (':', ) + self.cursorline_token
- cursor_column_token = (':', ) + self.cursorcolumn_token
-
- data_buffer = new_screen.data_buffer
-
- # Highlight cursor line.
- if self.cursorline(cli):
- row = data_buffer[cpos.y]
- for x in range(x, x + width):
- original_char = row[x]
- row[x] = _CHAR_CACHE[
- original_char.char, original_char.token + cursor_line_token]
-
- # Highlight cursor column.
- if self.cursorcolumn(cli):
- for y2 in range(y, y + height):
- row = data_buffer[y2]
- original_char = row[cpos.x]
- row[cpos.x] = _CHAR_CACHE[
- original_char.char, original_char.token + cursor_column_token]
-
- # Highlight color columns
- for cc in self.get_colorcolumns(cli):
- assert isinstance(cc, ColorColumn)
- color_column_token = (':', ) + cc.token
- column = cc.position
-
- for y2 in range(y, y + height):
- row = data_buffer[y2]
- original_char = row[column]
- row[column] = _CHAR_CACHE[
- original_char.char, original_char.token + color_column_token]
-
- def _copy_margin(self, cli, lazy_screen, new_screen, write_position, move_x, width):
- """
- Copy characters from the margin screen to the real screen.
- """
- xpos = write_position.xpos + move_x
- ypos = write_position.ypos
-
- margin_write_position = WritePosition(xpos, ypos, width, write_position.height)
- self._copy_body(cli, lazy_screen, new_screen, margin_write_position, 0, width)
-
- def _scroll_when_linewrapping(self, ui_content, width, height, cli):
- """
- Scroll to make sure the cursor position is visible and that we maintain
- the requested scroll offset.
-
- Set `self.horizontal_scroll/vertical_scroll`.
- """
- scroll_offsets_bottom = self.scroll_offsets.bottom
- scroll_offsets_top = self.scroll_offsets.top
-
- # We don't have horizontal scrolling.
- self.horizontal_scroll = 0
-
- # If the current line consumes more than the whole window height,
- # then we have to scroll vertically inside this line. (We don't take
- # the scroll offsets into account for this.)
- # Also, ignore the scroll offsets in this case. Just set the vertical
- # scroll to this line.
- if ui_content.get_height_for_line(ui_content.cursor_position.y, width) > height - scroll_offsets_top:
- # Calculate the height of the text before the cursor, with the line
- # containing the cursor included, and the character belowe the
- # cursor included as well.
- line = explode_tokens(ui_content.get_line(ui_content.cursor_position.y))
- text_before_cursor = token_list_to_text(line[:ui_content.cursor_position.x + 1])
- text_before_height = UIContent.get_height_for_text(text_before_cursor, width)
-
- # Adjust scroll offset.
- self.vertical_scroll = ui_content.cursor_position.y
- self.vertical_scroll_2 = min(text_before_height - 1, self.vertical_scroll_2)
- self.vertical_scroll_2 = max(0, text_before_height - height, self.vertical_scroll_2)
- return
- else:
- self.vertical_scroll_2 = 0
-
- # Current line doesn't consume the whole height. Take scroll offsets into account.
- def get_min_vertical_scroll():
- # Make sure that the cursor line is not below the bottom.
- # (Calculate how many lines can be shown between the cursor and the .)
- used_height = 0
- prev_lineno = ui_content.cursor_position.y
-
- for lineno in range(ui_content.cursor_position.y, -1, -1):
- used_height += ui_content.get_height_for_line(lineno, width)
-
- if used_height > height - scroll_offsets_bottom:
- return prev_lineno
- else:
- prev_lineno = lineno
- return 0
-
- def get_max_vertical_scroll():
- # Make sure that the cursor line is not above the top.
- prev_lineno = ui_content.cursor_position.y
- used_height = 0
-
- for lineno in range(ui_content.cursor_position.y - 1, -1, -1):
- used_height += ui_content.get_height_for_line(lineno, width)
-
- if used_height > scroll_offsets_top:
- return prev_lineno
- else:
- prev_lineno = lineno
- return prev_lineno
-
- def get_topmost_visible():
- """
- Calculate the upper most line that can be visible, while the bottom
- is still visible. We should not allow scroll more than this if
- `allow_scroll_beyond_bottom` is false.
- """
- prev_lineno = ui_content.line_count - 1
- used_height = 0
- for lineno in range(ui_content.line_count - 1, -1, -1):
- used_height += ui_content.get_height_for_line(lineno, width)
- if used_height > height:
- return prev_lineno
- else:
- prev_lineno = lineno
- return prev_lineno
-
- # Scroll vertically. (Make sure that the whole line which contains the
- # cursor is visible.
- topmost_visible = get_topmost_visible()
-
- # Note: the `min(topmost_visible, ...)` is to make sure that we
- # don't require scrolling up because of the bottom scroll offset,
- # when we are at the end of the document.
- self.vertical_scroll = max(self.vertical_scroll, min(topmost_visible, get_min_vertical_scroll()))
- self.vertical_scroll = min(self.vertical_scroll, get_max_vertical_scroll())
-
- # Disallow scrolling beyond bottom?
- if not self.allow_scroll_beyond_bottom(cli):
- self.vertical_scroll = min(self.vertical_scroll, topmost_visible)
-
- def _scroll_without_linewrapping(self, ui_content, width, height, cli):
- """
- Scroll to make sure the cursor position is visible and that we maintain
- the requested scroll offset.
-
- Set `self.horizontal_scroll/vertical_scroll`.
- """
- cursor_position = ui_content.cursor_position or Point(0, 0)
-
- # Without line wrapping, we will never have to scroll vertically inside
- # a single line.
- self.vertical_scroll_2 = 0
-
- if ui_content.line_count == 0:
- self.vertical_scroll = 0
- self.horizontal_scroll = 0
- return
- else:
- current_line_text = token_list_to_text(ui_content.get_line(cursor_position.y))
-
- def do_scroll(current_scroll, scroll_offset_start, scroll_offset_end,
- cursor_pos, window_size, content_size):
- " Scrolling algorithm. Used for both horizontal and vertical scrolling. "
- # Calculate the scroll offset to apply.
- # This can obviously never be more than have the screen size. Also, when the
- # cursor appears at the top or bottom, we don't apply the offset.
- scroll_offset_start = int(min(scroll_offset_start, window_size / 2, cursor_pos))
- scroll_offset_end = int(min(scroll_offset_end, window_size / 2,
- content_size - 1 - cursor_pos))
-
- # Prevent negative scroll offsets.
- if current_scroll < 0:
- current_scroll = 0
-
- # Scroll back if we scrolled to much and there's still space to show more of the document.
- if (not self.allow_scroll_beyond_bottom(cli) and
- current_scroll > content_size - window_size):
- current_scroll = max(0, content_size - window_size)
-
- # Scroll up if cursor is before visible part.
- if current_scroll > cursor_pos - scroll_offset_start:
- current_scroll = max(0, cursor_pos - scroll_offset_start)
-
- # Scroll down if cursor is after visible part.
- if current_scroll < (cursor_pos + 1) - window_size + scroll_offset_end:
- current_scroll = (cursor_pos + 1) - window_size + scroll_offset_end
-
- return current_scroll
-
- # When a preferred scroll is given, take that first into account.
- if self.get_vertical_scroll:
- self.vertical_scroll = self.get_vertical_scroll(self)
- assert isinstance(self.vertical_scroll, int)
- if self.get_horizontal_scroll:
- self.horizontal_scroll = self.get_horizontal_scroll(self)
- assert isinstance(self.horizontal_scroll, int)
-
- # Update horizontal/vertical scroll to make sure that the cursor
- # remains visible.
- offsets = self.scroll_offsets
-
- self.vertical_scroll = do_scroll(
- current_scroll=self.vertical_scroll,
- scroll_offset_start=offsets.top,
- scroll_offset_end=offsets.bottom,
- cursor_pos=ui_content.cursor_position.y,
- window_size=height,
- content_size=ui_content.line_count)
-
- self.horizontal_scroll = do_scroll(
- current_scroll=self.horizontal_scroll,
- scroll_offset_start=offsets.left,
- scroll_offset_end=offsets.right,
- cursor_pos=get_cwidth(current_line_text[:ui_content.cursor_position.x]),
- window_size=width,
- # We can only analyse the current line. Calculating the width off
- # all the lines is too expensive.
- content_size=max(get_cwidth(current_line_text), self.horizontal_scroll + width))
-
- def _mouse_handler(self, cli, mouse_event):
- """
- Mouse handler. Called when the UI control doesn't handle this
- particular event.
- """
- if mouse_event.event_type == MouseEventType.SCROLL_DOWN:
- self._scroll_down(cli)
- elif mouse_event.event_type == MouseEventType.SCROLL_UP:
- self._scroll_up(cli)
-
- def _scroll_down(self, cli):
- " Scroll window down. "
- info = self.render_info
-
- if self.vertical_scroll < info.content_height - info.window_height:
- if info.cursor_position.y <= info.configured_scroll_offsets.top:
- self.content.move_cursor_down(cli)
-
- self.vertical_scroll += 1
-
- def _scroll_up(self, cli):
- " Scroll window up. "
- info = self.render_info
-
- if info.vertical_scroll > 0:
- # TODO: not entirely correct yet in case of line wrapping and long lines.
- if info.cursor_position.y >= info.window_height - 1 - info.configured_scroll_offsets.bottom:
- self.content.move_cursor_up(cli)
-
- self.vertical_scroll -= 1
-
- def walk(self, cli):
- # Only yield self. A window doesn't have children.
- yield self
-
-
-class ConditionalContainer(Container):
- """
- Wrapper around any other container that can change the visibility. The
- received `filter` determines whether the given container should be
- displayed or not.
-
- :param content: :class:`.Container` instance.
- :param filter: :class:`~prompt_toolkit.filters.CLIFilter` instance.
- """
- def __init__(self, content, filter):
- assert isinstance(content, Container)
-
- self.content = content
- self.filter = to_cli_filter(filter)
-
- def __repr__(self):
- return 'ConditionalContainer(%r, filter=%r)' % (self.content, self.filter)
-
- def reset(self):
- self.content.reset()
-
- def preferred_width(self, cli, max_available_width):
- if self.filter(cli):
- return self.content.preferred_width(cli, max_available_width)
- else:
- return LayoutDimension.exact(0)
-
- def preferred_height(self, cli, width, max_available_height):
- if self.filter(cli):
- return self.content.preferred_height(cli, width, max_available_height)
- else:
- return LayoutDimension.exact(0)
-
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- if self.filter(cli):
- return self.content.write_to_screen(cli, screen, mouse_handlers, write_position)
-
- def walk(self, cli):
- return self.content.walk(cli)
-
-
-# Deprecated alias for 'Container'.
-Layout = Container
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py
deleted file mode 100644
index ca74931dbc..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py
+++ /dev/null
@@ -1,730 +0,0 @@
-"""
-User interface Controls for the layout.
-"""
-from __future__ import unicode_literals
-
-from abc import ABCMeta, abstractmethod
-from collections import namedtuple
-from six import with_metaclass
-from six.moves import range
-
-from prompt_toolkit.cache import SimpleCache
-from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
-from prompt_toolkit.filters import to_cli_filter
-from prompt_toolkit.mouse_events import MouseEventType
-from prompt_toolkit.search_state import SearchState
-from prompt_toolkit.selection import SelectionType
-from prompt_toolkit.token import Token
-from prompt_toolkit.utils import get_cwidth
-
-from .lexers import Lexer, SimpleLexer
-from .processors import Processor
-from .screen import Char, Point
-from .utils import token_list_width, split_lines, token_list_to_text
-
-import six
-import time
-
-
-__all__ = (
- 'BufferControl',
- 'FillControl',
- 'TokenListControl',
- 'UIControl',
- 'UIContent',
-)
-
-
-class UIControl(with_metaclass(ABCMeta, object)):
- """
- Base class for all user interface controls.
- """
- def reset(self):
- # Default reset. (Doesn't have to be implemented.)
- pass
-
- def preferred_width(self, cli, max_available_width):
- return None
-
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
- return None
-
- def has_focus(self, cli):
- """
- Return ``True`` when this user control has the focus.
-
- If so, the cursor will be displayed according to the cursor position
- reported by :meth:`.UIControl.create_content`. If the created content
- has the property ``show_cursor=False``, the cursor will be hidden from
- the output.
- """
- return False
-
- @abstractmethod
- def create_content(self, cli, width, height):
- """
- Generate the content for this user control.
-
- Returns a :class:`.UIContent` instance.
- """
-
- def mouse_handler(self, cli, mouse_event):
- """
- Handle mouse events.
-
- When `NotImplemented` is returned, it means that the given event is not
- handled by the `UIControl` itself. The `Window` or key bindings can
- decide to handle this event as scrolling or changing focus.
-
- :param cli: `CommandLineInterface` instance.
- :param mouse_event: `MouseEvent` instance.
- """
- return NotImplemented
-
- def move_cursor_down(self, cli):
- """
- Request to move the cursor down.
- This happens when scrolling down and the cursor is completely at the
- top.
- """
-
- def move_cursor_up(self, cli):
- """
- Request to move the cursor up.
- """
-
-
-class UIContent(object):
- """
- Content generated by a user control. This content consists of a list of
- lines.
-
- :param get_line: Callable that returns the current line. This is a list of
- (Token, text) tuples.
- :param line_count: The number of lines.
- :param cursor_position: a :class:`.Point` for the cursor position.
- :param menu_position: a :class:`.Point` for the menu position.
- :param show_cursor: Make the cursor visible.
- :param default_char: The default :class:`.Char` for filling the background.
- """
- def __init__(self, get_line=None, line_count=0,
- cursor_position=None, menu_position=None, show_cursor=True,
- default_char=None):
- assert callable(get_line)
- assert isinstance(line_count, six.integer_types)
- assert cursor_position is None or isinstance(cursor_position, Point)
- assert menu_position is None or isinstance(menu_position, Point)
- assert default_char is None or isinstance(default_char, Char)
-
- self.get_line = get_line
- self.line_count = line_count
- self.cursor_position = cursor_position or Point(0, 0)
- self.menu_position = menu_position
- self.show_cursor = show_cursor
- self.default_char = default_char
-
- # Cache for line heights. Maps (lineno, width) -> height.
- self._line_heights = {}
-
- def __getitem__(self, lineno):
- " Make it iterable (iterate line by line). "
- if lineno < self.line_count:
- return self.get_line(lineno)
- else:
- raise IndexError
-
- def get_height_for_line(self, lineno, width):
- """
- Return the height that a given line would need if it is rendered in a
- space with the given width.
- """
- try:
- return self._line_heights[lineno, width]
- except KeyError:
- text = token_list_to_text(self.get_line(lineno))
- result = self.get_height_for_text(text, width)
-
- # Cache and return
- self._line_heights[lineno, width] = result
- return result
-
- @staticmethod
- def get_height_for_text(text, width):
- # Get text width for this line.
- line_width = get_cwidth(text)
-
- # Calculate height.
- try:
- quotient, remainder = divmod(line_width, width)
- except ZeroDivisionError:
- # Return something very big.
- # (This can happen, when the Window gets very small.)
- return 10 ** 10
- else:
- if remainder:
- quotient += 1 # Like math.ceil.
- return max(1, quotient)
-
-
-class TokenListControl(UIControl):
- """
- Control that displays a list of (Token, text) tuples.
- (It's mostly optimized for rather small widgets, like toolbars, menus, etc...)
-
- Mouse support:
-
- The list of tokens can also contain tuples of three items, looking like:
- (Token, text, handler). When mouse support is enabled and the user
- clicks on this token, then the given handler is called. That handler
- should accept two inputs: (CommandLineInterface, MouseEvent) and it
- should either handle the event or return `NotImplemented` in case we
- want the containing Window to handle this event.
-
- :param get_tokens: Callable that takes a `CommandLineInterface` instance
- and returns the list of (Token, text) tuples to be displayed right now.
- :param default_char: default :class:`.Char` (character and Token) to use
- for the background when there is more space available than `get_tokens`
- returns.
- :param get_default_char: Like `default_char`, but this is a callable that
- takes a :class:`prompt_toolkit.interface.CommandLineInterface` and
- returns a :class:`.Char` instance.
- :param has_focus: `bool` or `CLIFilter`, when this evaluates to `True`,
- this UI control will take the focus. The cursor will be shown in the
- upper left corner of this control, unless `get_token` returns a
- ``Token.SetCursorPosition`` token somewhere in the token list, then the
- cursor will be shown there.
- """
- def __init__(self, get_tokens, default_char=None, get_default_char=None,
- align_right=False, align_center=False, has_focus=False):
- assert callable(get_tokens)
- assert default_char is None or isinstance(default_char, Char)
- assert get_default_char is None or callable(get_default_char)
- assert not (default_char and get_default_char)
-
- self.align_right = to_cli_filter(align_right)
- self.align_center = to_cli_filter(align_center)
- self._has_focus_filter = to_cli_filter(has_focus)
-
- self.get_tokens = get_tokens
-
- # Construct `get_default_char` callable.
- if default_char:
- get_default_char = lambda _: default_char
- elif not get_default_char:
- get_default_char = lambda _: Char(' ', Token.Transparent)
-
- self.get_default_char = get_default_char
-
- #: Cache for the content.
- self._content_cache = SimpleCache(maxsize=18)
- self._token_cache = SimpleCache(maxsize=1)
- # Only cache one token list. We don't need the previous item.
-
- # Render info for the mouse support.
- self._tokens = None
-
- def reset(self):
- self._tokens = None
-
- def __repr__(self):
- return '%s(%r)' % (self.__class__.__name__, self.get_tokens)
-
- def _get_tokens_cached(self, cli):
- """
- Get tokens, but only retrieve tokens once during one render run.
- (This function is called several times during one rendering, because
- we also need those for calculating the dimensions.)
- """
- return self._token_cache.get(
- cli.render_counter, lambda: self.get_tokens(cli))
-
- def has_focus(self, cli):
- return self._has_focus_filter(cli)
-
- def preferred_width(self, cli, max_available_width):
- """
- Return the preferred width for this control.
- That is the width of the longest line.
- """
- text = token_list_to_text(self._get_tokens_cached(cli))
- line_lengths = [get_cwidth(l) for l in text.split('\n')]
- return max(line_lengths)
-
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
- content = self.create_content(cli, width, None)
- return content.line_count
-
- def create_content(self, cli, width, height):
- # Get tokens
- tokens_with_mouse_handlers = self._get_tokens_cached(cli)
-
- default_char = self.get_default_char(cli)
-
- # Wrap/align right/center parameters.
- right = self.align_right(cli)
- center = self.align_center(cli)
-
- def process_line(line):
- " Center or right align a single line. "
- used_width = token_list_width(line)
- padding = width - used_width
- if center:
- padding = int(padding / 2)
- return [(default_char.token, default_char.char * padding)] + line
-
- if right or center:
- token_lines_with_mouse_handlers = []
-
- for line in split_lines(tokens_with_mouse_handlers):
- token_lines_with_mouse_handlers.append(process_line(line))
- else:
- token_lines_with_mouse_handlers = list(split_lines(tokens_with_mouse_handlers))
-
- # Strip mouse handlers from tokens.
- token_lines = [
- [tuple(item[:2]) for item in line]
- for line in token_lines_with_mouse_handlers
- ]
-
- # Keep track of the tokens with mouse handler, for later use in
- # `mouse_handler`.
- self._tokens = tokens_with_mouse_handlers
-
- # If there is a `Token.SetCursorPosition` in the token list, set the
- # cursor position here.
- def get_cursor_position():
- SetCursorPosition = Token.SetCursorPosition
-
- for y, line in enumerate(token_lines):
- x = 0
- for token, text in line:
- if token == SetCursorPosition:
- return Point(x=x, y=y)
- x += len(text)
- return None
-
- # Create content, or take it from the cache.
- key = (default_char.char, default_char.token,
- tuple(tokens_with_mouse_handlers), width, right, center)
-
- def get_content():
- return UIContent(get_line=lambda i: token_lines[i],
- line_count=len(token_lines),
- default_char=default_char,
- cursor_position=get_cursor_position())
-
- return self._content_cache.get(key, get_content)
-
- @classmethod
- def static(cls, tokens):
- def get_static_tokens(cli):
- return tokens
- return cls(get_static_tokens)
-
- def mouse_handler(self, cli, mouse_event):
- """
- Handle mouse events.
-
- (When the token list contained mouse handlers and the user clicked on
- on any of these, the matching handler is called. This handler can still
- return `NotImplemented` in case we want the `Window` to handle this
- particular event.)
- """
- if self._tokens:
- # Read the generator.
- tokens_for_line = list(split_lines(self._tokens))
-
- try:
- tokens = tokens_for_line[mouse_event.position.y]
- except IndexError:
- return NotImplemented
- else:
- # Find position in the token list.
- xpos = mouse_event.position.x
-
- # Find mouse handler for this character.
- count = 0
- for item in tokens:
- count += len(item[1])
- if count >= xpos:
- if len(item) >= 3:
- # Handler found. Call it.
- # (Handler can return NotImplemented, so return
- # that result.)
- handler = item[2]
- return handler(cli, mouse_event)
- else:
- break
-
- # Otherwise, don't handle here.
- return NotImplemented
-
-
-class FillControl(UIControl):
- """
- Fill whole control with characters with this token.
- (Also helpful for debugging.)
-
- :param char: :class:`.Char` instance to use for filling.
- :param get_char: A callable that takes a CommandLineInterface and returns a
- :class:`.Char` object.
- """
- def __init__(self, character=None, token=Token, char=None, get_char=None): # 'character' and 'token' parameters are deprecated.
- assert char is None or isinstance(char, Char)
- assert get_char is None or callable(get_char)
- assert not (char and get_char)
-
- self.char = char
-
- if character:
- # Passing (character=' ', token=token) is deprecated.
- self.character = character
- self.token = token
-
- self.get_char = lambda cli: Char(character, token)
- elif get_char:
- # When 'get_char' is given.
- self.get_char = get_char
- else:
- # When 'char' is given.
- self.char = self.char or Char()
- self.get_char = lambda cli: self.char
- self.char = char
-
- def __repr__(self):
- if self.char:
- return '%s(char=%r)' % (self.__class__.__name__, self.char)
- else:
- return '%s(get_char=%r)' % (self.__class__.__name__, self.get_char)
-
- def reset(self):
- pass
-
- def has_focus(self, cli):
- return False
-
- def create_content(self, cli, width, height):
- def get_line(i):
- return []
-
- return UIContent(
- get_line=get_line,
- line_count=100 ** 100, # Something very big.
- default_char=self.get_char(cli))
-
-
-_ProcessedLine = namedtuple('_ProcessedLine', 'tokens source_to_display display_to_source')
-
-
-class BufferControl(UIControl):
- """
- Control for visualising the content of a `Buffer`.
-
- :param input_processors: list of :class:`~prompt_toolkit.layout.processors.Processor`.
- :param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` instance for syntax highlighting.
- :param preview_search: `bool` or `CLIFilter`: Show search while typing.
- :param get_search_state: Callable that takes a CommandLineInterface and
- returns the SearchState to be used. (If not CommandLineInterface.search_state.)
- :param buffer_name: String representing the name of the buffer to display.
- :param default_char: :class:`.Char` instance to use to fill the background. This is
- transparent by default.
- :param focus_on_click: Focus this buffer when it's click, but not yet focussed.
- """
- def __init__(self,
- buffer_name=DEFAULT_BUFFER,
- input_processors=None,
- lexer=None,
- preview_search=False,
- search_buffer_name=SEARCH_BUFFER,
- get_search_state=None,
- menu_position=None,
- default_char=None,
- focus_on_click=False):
- assert input_processors is None or all(isinstance(i, Processor) for i in input_processors)
- assert menu_position is None or callable(menu_position)
- assert lexer is None or isinstance(lexer, Lexer)
- assert get_search_state is None or callable(get_search_state)
- assert default_char is None or isinstance(default_char, Char)
-
- self.preview_search = to_cli_filter(preview_search)
- self.get_search_state = get_search_state
- self.focus_on_click = to_cli_filter(focus_on_click)
-
- self.input_processors = input_processors or []
- self.buffer_name = buffer_name
- self.menu_position = menu_position
- self.lexer = lexer or SimpleLexer()
- self.default_char = default_char or Char(token=Token.Transparent)
- self.search_buffer_name = search_buffer_name
-
- #: Cache for the lexer.
- #: Often, due to cursor movement, undo/redo and window resizing
- #: operations, it happens that a short time, the same document has to be
- #: lexed. This is a faily easy way to cache such an expensive operation.
- self._token_cache = SimpleCache(maxsize=8)
-
- self._xy_to_cursor_position = None
- self._last_click_timestamp = None
- self._last_get_processed_line = None
-
- def _buffer(self, cli):
- """
- The buffer object that contains the 'main' content.
- """
- return cli.buffers[self.buffer_name]
-
- def has_focus(self, cli):
- # This control gets the focussed if the actual `Buffer` instance has the
- # focus or when any of the `InputProcessor` classes tells us that it
- # wants the focus. (E.g. in case of a reverse-search, where the actual
- # search buffer may not be displayed, but the "reverse-i-search" text
- # should get the focus.)
- return cli.current_buffer_name == self.buffer_name or \
- any(i.has_focus(cli) for i in self.input_processors)
-
- def preferred_width(self, cli, max_available_width):
- """
- This should return the preferred width.
-
- Note: We don't specify a preferred width according to the content,
- because it would be too expensive. Calculating the preferred
- width can be done by calculating the longest line, but this would
- require applying all the processors to each line. This is
- unfeasible for a larger document, and doing it for small
- documents only would result in inconsistent behaviour.
- """
- return None
-
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
- # Calculate the content height, if it was drawn on a screen with the
- # given width.
- height = 0
- content = self.create_content(cli, width, None)
-
- # When line wrapping is off, the height should be equal to the amount
- # of lines.
- if not wrap_lines:
- return content.line_count
-
- # When the number of lines exceeds the max_available_height, just
- # return max_available_height. No need to calculate anything.
- if content.line_count >= max_available_height:
- return max_available_height
-
- for i in range(content.line_count):
- height += content.get_height_for_line(i, width)
-
- if height >= max_available_height:
- return max_available_height
-
- return height
-
- def _get_tokens_for_line_func(self, cli, document):
- """
- Create a function that returns the tokens for a given line.
- """
- # Cache using `document.text`.
- def get_tokens_for_line():
- return self.lexer.lex_document(cli, document)
-
- return self._token_cache.get(document.text, get_tokens_for_line)
-
- def _create_get_processed_line_func(self, cli, document):
- """
- Create a function that takes a line number of the current document and
- returns a _ProcessedLine(processed_tokens, source_to_display, display_to_source)
- tuple.
- """
- def transform(lineno, tokens):
- " Transform the tokens for a given line number. "
- source_to_display_functions = []
- display_to_source_functions = []
-
- # Get cursor position at this line.
- if document.cursor_position_row == lineno:
- cursor_column = document.cursor_position_col
- else:
- cursor_column = None
-
- def source_to_display(i):
- """ Translate x position from the buffer to the x position in the
- processed token list. """
- for f in source_to_display_functions:
- i = f(i)
- return i
-
- # Apply each processor.
- for p in self.input_processors:
- transformation = p.apply_transformation(
- cli, document, lineno, source_to_display, tokens)
- tokens = transformation.tokens
-
- if cursor_column:
- cursor_column = transformation.source_to_display(cursor_column)
-
- display_to_source_functions.append(transformation.display_to_source)
- source_to_display_functions.append(transformation.source_to_display)
-
- def display_to_source(i):
- for f in reversed(display_to_source_functions):
- i = f(i)
- return i
-
- return _ProcessedLine(tokens, source_to_display, display_to_source)
-
- def create_func():
- get_line = self._get_tokens_for_line_func(cli, document)
- cache = {}
-
- def get_processed_line(i):
- try:
- return cache[i]
- except KeyError:
- processed_line = transform(i, get_line(i))
- cache[i] = processed_line
- return processed_line
- return get_processed_line
-
- return create_func()
-
- def create_content(self, cli, width, height):
- """
- Create a UIContent.
- """
- buffer = self._buffer(cli)
-
- # Get the document to be shown. If we are currently searching (the
- # search buffer has focus, and the preview_search filter is enabled),
- # then use the search document, which has possibly a different
- # text/cursor position.)
- def preview_now():
- """ True when we should preview a search. """
- return bool(self.preview_search(cli) and
- cli.buffers[self.search_buffer_name].text)
-
- if preview_now():
- if self.get_search_state:
- ss = self.get_search_state(cli)
- else:
- ss = cli.search_state
-
- document = buffer.document_for_search(SearchState(
- text=cli.current_buffer.text,
- direction=ss.direction,
- ignore_case=ss.ignore_case))
- else:
- document = buffer.document
-
- get_processed_line = self._create_get_processed_line_func(cli, document)
- self._last_get_processed_line = get_processed_line
-
- def translate_rowcol(row, col):
- " Return the content column for this coordinate. "
- return Point(y=row, x=get_processed_line(row).source_to_display(col))
-
- def get_line(i):
- " Return the tokens for a given line number. "
- tokens = get_processed_line(i).tokens
-
- # Add a space at the end, because that is a possible cursor
- # position. (When inserting after the input.) We should do this on
- # all the lines, not just the line containing the cursor. (Because
- # otherwise, line wrapping/scrolling could change when moving the
- # cursor around.)
- tokens = tokens + [(self.default_char.token, ' ')]
- return tokens
-
- content = UIContent(
- get_line=get_line,
- line_count=document.line_count,
- cursor_position=translate_rowcol(document.cursor_position_row,
- document.cursor_position_col),
- default_char=self.default_char)
-
- # If there is an auto completion going on, use that start point for a
- # pop-up menu position. (But only when this buffer has the focus --
- # there is only one place for a menu, determined by the focussed buffer.)
- if cli.current_buffer_name == self.buffer_name:
- menu_position = self.menu_position(cli) if self.menu_position else None
- if menu_position is not None:
- assert isinstance(menu_position, int)
- menu_row, menu_col = buffer.document.translate_index_to_position(menu_position)
- content.menu_position = translate_rowcol(menu_row, menu_col)
- elif buffer.complete_state:
- # Position for completion menu.
- # Note: We use 'min', because the original cursor position could be
- # behind the input string when the actual completion is for
- # some reason shorter than the text we had before. (A completion
- # can change and shorten the input.)
- menu_row, menu_col = buffer.document.translate_index_to_position(
- min(buffer.cursor_position,
- buffer.complete_state.original_document.cursor_position))
- content.menu_position = translate_rowcol(menu_row, menu_col)
- else:
- content.menu_position = None
-
- return content
-
- def mouse_handler(self, cli, mouse_event):
- """
- Mouse handler for this control.
- """
- buffer = self._buffer(cli)
- position = mouse_event.position
-
- # Focus buffer when clicked.
- if self.has_focus(cli):
- if self._last_get_processed_line:
- processed_line = self._last_get_processed_line(position.y)
-
- # Translate coordinates back to the cursor position of the
- # original input.
- xpos = processed_line.display_to_source(position.x)
- index = buffer.document.translate_row_col_to_index(position.y, xpos)
-
- # Set the cursor position.
- if mouse_event.event_type == MouseEventType.MOUSE_DOWN:
- buffer.exit_selection()
- buffer.cursor_position = index
-
- elif mouse_event.event_type == MouseEventType.MOUSE_UP:
- # When the cursor was moved to another place, select the text.
- # (The >1 is actually a small but acceptable workaround for
- # selecting text in Vi navigation mode. In navigation mode,
- # the cursor can never be after the text, so the cursor
- # will be repositioned automatically.)
- if abs(buffer.cursor_position - index) > 1:
- buffer.start_selection(selection_type=SelectionType.CHARACTERS)
- buffer.cursor_position = index
-
- # Select word around cursor on double click.
- # Two MOUSE_UP events in a short timespan are considered a double click.
- double_click = self._last_click_timestamp and time.time() - self._last_click_timestamp < .3
- self._last_click_timestamp = time.time()
-
- if double_click:
- start, end = buffer.document.find_boundaries_of_current_word()
- buffer.cursor_position += start
- buffer.start_selection(selection_type=SelectionType.CHARACTERS)
- buffer.cursor_position += end - start
- else:
- # Don't handle scroll events here.
- return NotImplemented
-
- # Not focussed, but focussing on click events.
- else:
- if self.focus_on_click(cli) and mouse_event.event_type == MouseEventType.MOUSE_UP:
- # Focus happens on mouseup. (If we did this on mousedown, the
- # up event will be received at the point where this widget is
- # focussed and be handled anyway.)
- cli.focus(self.buffer_name)
- else:
- return NotImplemented
-
- def move_cursor_down(self, cli):
- b = self._buffer(cli)
- b.cursor_position += b.document.get_cursor_down_position()
-
- def move_cursor_up(self, cli):
- b = self._buffer(cli)
- b.cursor_position += b.document.get_cursor_up_position()
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/dimension.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/dimension.py
deleted file mode 100644
index 717ad7a81f..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/dimension.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""
-Layout dimensions are used to give the minimum, maximum and preferred
-dimensions for containers and controls.
-"""
-from __future__ import unicode_literals
-
-__all__ = (
- 'LayoutDimension',
- 'sum_layout_dimensions',
- 'max_layout_dimensions',
-)
-
-
-class LayoutDimension(object):
- """
- Specified dimension (width/height) of a user control or window.
-
- The layout engine tries to honor the preferred size. If that is not
- possible, because the terminal is larger or smaller, it tries to keep in
- between min and max.
-
- :param min: Minimum size.
- :param max: Maximum size.
- :param weight: For a VSplit/HSplit, the actual size will be determined
- by taking the proportion of weights from all the children.
- E.g. When there are two children, one width a weight of 1,
- and the other with a weight of 2. The second will always be
- twice as big as the first, if the min/max values allow it.
- :param preferred: Preferred size.
- """
- def __init__(self, min=None, max=None, weight=1, preferred=None):
- assert isinstance(weight, int) and weight > 0 # Cannot be a float.
-
- self.min_specified = min is not None
- self.max_specified = max is not None
- self.preferred_specified = preferred is not None
-
- if min is None:
- min = 0 # Smallest possible value.
- if max is None: # 0-values are allowed, so use "is None"
- max = 1000 ** 10 # Something huge.
- if preferred is None:
- preferred = min
-
- self.min = min
- self.max = max
- self.preferred = preferred
- self.weight = weight
-
- # Make sure that the 'preferred' size is always in the min..max range.
- if self.preferred < self.min:
- self.preferred = self.min
-
- if self.preferred > self.max:
- self.preferred = self.max
-
- @classmethod
- def exact(cls, amount):
- """
- Return a :class:`.LayoutDimension` with an exact size. (min, max and
- preferred set to ``amount``).
- """
- return cls(min=amount, max=amount, preferred=amount)
-
- def __repr__(self):
- return 'LayoutDimension(min=%r, max=%r, preferred=%r, weight=%r)' % (
- self.min, self.max, self.preferred, self.weight)
-
- def __add__(self, other):
- return sum_layout_dimensions([self, other])
-
-
-def sum_layout_dimensions(dimensions):
- """
- Sum a list of :class:`.LayoutDimension` instances.
- """
- min = sum([d.min for d in dimensions if d.min is not None])
- max = sum([d.max for d in dimensions if d.max is not None])
- preferred = sum([d.preferred for d in dimensions])
-
- return LayoutDimension(min=min, max=max, preferred=preferred)
-
-
-def max_layout_dimensions(dimensions):
- """
- Take the maximum of a list of :class:`.LayoutDimension` instances.
- """
- min_ = max([d.min for d in dimensions if d.min is not None])
- max_ = max([d.max for d in dimensions if d.max is not None])
- preferred = max([d.preferred for d in dimensions])
-
- return LayoutDimension(min=min_, max=max_, preferred=preferred)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py
deleted file mode 100644
index a928fd8226..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py
+++ /dev/null
@@ -1,320 +0,0 @@
-"""
-Lexer interface and implementation.
-Used for syntax highlighting.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-from six.moves import range
-
-from prompt_toolkit.token import Token
-from prompt_toolkit.filters import to_cli_filter
-from .utils import split_lines
-
-import re
-import six
-
-__all__ = (
- 'Lexer',
- 'SimpleLexer',
- 'PygmentsLexer',
- 'SyntaxSync',
- 'SyncFromStart',
- 'RegexSync',
-)
-
-
-class Lexer(with_metaclass(ABCMeta, object)):
- """
- Base class for all lexers.
- """
- @abstractmethod
- def lex_document(self, cli, document):
- """
- Takes a :class:`~prompt_toolkit.document.Document` and returns a
- callable that takes a line number and returns the tokens for that line.
- """
-
-
-class SimpleLexer(Lexer):
- """
- Lexer that doesn't do any tokenizing and returns the whole input as one token.
-
- :param token: The `Token` for this lexer.
- """
- # `default_token` parameter is deprecated!
- def __init__(self, token=Token, default_token=None):
- self.token = token
-
- if default_token is not None:
- self.token = default_token
-
- def lex_document(self, cli, document):
- lines = document.lines
-
- def get_line(lineno):
- " Return the tokens for the given line. "
- try:
- return [(self.token, lines[lineno])]
- except IndexError:
- return []
- return get_line
-
-
-class SyntaxSync(with_metaclass(ABCMeta, object)):
- """
- Syntax synchroniser. This is a tool that finds a start position for the
- lexer. This is especially important when editing big documents; we don't
- want to start the highlighting by running the lexer from the beginning of
- the file. That is very slow when editing.
- """
- @abstractmethod
- def get_sync_start_position(self, document, lineno):
- """
- Return the position from where we can start lexing as a (row, column)
- tuple.
-
- :param document: `Document` instance that contains all the lines.
- :param lineno: The line that we want to highlight. (We need to return
- this line, or an earlier position.)
- """
-
-class SyncFromStart(SyntaxSync):
- """
- Always start the syntax highlighting from the beginning.
- """
- def get_sync_start_position(self, document, lineno):
- return 0, 0
-
-
-class RegexSync(SyntaxSync):
- """
- Synchronize by starting at a line that matches the given regex pattern.
- """
- # Never go more than this amount of lines backwards for synchronisation.
- # That would be too CPU intensive.
- MAX_BACKWARDS = 500
-
- # Start lexing at the start, if we are in the first 'n' lines and no
- # synchronisation position was found.
- FROM_START_IF_NO_SYNC_POS_FOUND = 100
-
- def __init__(self, pattern):
- assert isinstance(pattern, six.text_type)
- self._compiled_pattern = re.compile(pattern)
-
- def get_sync_start_position(self, document, lineno):
- " Scan backwards, and find a possible position to start. "
- pattern = self._compiled_pattern
- lines = document.lines
-
- # Scan upwards, until we find a point where we can start the syntax
- # synchronisation.
- for i in range(lineno, max(-1, lineno - self.MAX_BACKWARDS), -1):
- match = pattern.match(lines[i])
- if match:
- return i, match.start()
-
- # No synchronisation point found. If we aren't that far from the
- # beginning, start at the very beginning, otherwise, just try to start
- # at the current line.
- if lineno < self.FROM_START_IF_NO_SYNC_POS_FOUND:
- return 0, 0
- else:
- return lineno, 0
-
- @classmethod
- def from_pygments_lexer_cls(cls, lexer_cls):
- """
- Create a :class:`.RegexSync` instance for this Pygments lexer class.
- """
- patterns = {
- # For Python, start highlighting at any class/def block.
- 'Python': r'^\s*(class|def)\s+',
- 'Python 3': r'^\s*(class|def)\s+',
-
- # For HTML, start at any open/close tag definition.
- 'HTML': r'<[/a-zA-Z]',
-
- # For javascript, start at a function.
- 'JavaScript': r'\bfunction\b'
-
- # TODO: Add definitions for other languages.
- # By default, we start at every possible line.
- }
- p = patterns.get(lexer_cls.name, '^')
- return cls(p)
-
-
-class PygmentsLexer(Lexer):
- """
- Lexer that calls a pygments lexer.
-
- Example::
-
- from pygments.lexers import HtmlLexer
- lexer = PygmentsLexer(HtmlLexer)
-
- Note: Don't forget to also load a Pygments compatible style. E.g.::
-
- from prompt_toolkit.styles.from_pygments import style_from_pygments
- from pygments.styles import get_style_by_name
- style = style_from_pygments(get_style_by_name('monokai'))
-
- :param pygments_lexer_cls: A `Lexer` from Pygments.
- :param sync_from_start: Start lexing at the start of the document. This
- will always give the best results, but it will be slow for bigger
- documents. (When the last part of the document is display, then the
- whole document will be lexed by Pygments on every key stroke.) It is
- recommended to disable this for inputs that are expected to be more
- than 1,000 lines.
- :param syntax_sync: `SyntaxSync` object.
- """
- # Minimum amount of lines to go backwards when starting the parser.
- # This is important when the lines are retrieved in reverse order, or when
- # scrolling upwards. (Due to the complexity of calculating the vertical
- # scroll offset in the `Window` class, lines are not always retrieved in
- # order.)
- MIN_LINES_BACKWARDS = 50
-
- # When a parser was started this amount of lines back, read the parser
- # until we get the current line. Otherwise, start a new parser.
- # (This should probably be bigger than MIN_LINES_BACKWARDS.)
- REUSE_GENERATOR_MAX_DISTANCE = 100
-
- def __init__(self, pygments_lexer_cls, sync_from_start=True, syntax_sync=None):
- assert syntax_sync is None or isinstance(syntax_sync, SyntaxSync)
-
- self.pygments_lexer_cls = pygments_lexer_cls
- self.sync_from_start = to_cli_filter(sync_from_start)
-
- # Instantiate the Pygments lexer.
- self.pygments_lexer = pygments_lexer_cls(
- stripnl=False,
- stripall=False,
- ensurenl=False)
-
- # Create syntax sync instance.
- self.syntax_sync = syntax_sync or RegexSync.from_pygments_lexer_cls(pygments_lexer_cls)
-
- @classmethod
- def from_filename(cls, filename, sync_from_start=True):
- """
- Create a `Lexer` from a filename.
- """
- # Inline imports: the Pygments dependency is optional!
- from pygments.util import ClassNotFound
- from pygments.lexers import get_lexer_for_filename
-
- try:
- pygments_lexer = get_lexer_for_filename(filename)
- except ClassNotFound:
- return SimpleLexer()
- else:
- return cls(pygments_lexer.__class__, sync_from_start=sync_from_start)
-
- def lex_document(self, cli, document):
- """
- Create a lexer function that takes a line number and returns the list
- of (Token, text) tuples as the Pygments lexer returns for that line.
- """
- # Cache of already lexed lines.
- cache = {}
-
- # Pygments generators that are currently lexing.
- line_generators = {} # Map lexer generator to the line number.
-
- def get_syntax_sync():
- " The Syntax synchronisation objcet that we currently use. "
- if self.sync_from_start(cli):
- return SyncFromStart()
- else:
- return self.syntax_sync
-
- def find_closest_generator(i):
- " Return a generator close to line 'i', or None if none was fonud. "
- for generator, lineno in line_generators.items():
- if lineno < i and i - lineno < self.REUSE_GENERATOR_MAX_DISTANCE:
- return generator
-
- def create_line_generator(start_lineno, column=0):
- """
- Create a generator that yields the lexed lines.
- Each iteration it yields a (line_number, [(token, text), ...]) tuple.
- """
- def get_tokens():
- text = '\n'.join(document.lines[start_lineno:])[column:]
-
- # We call `get_tokens_unprocessed`, because `get_tokens` will
- # still replace \r\n and \r by \n. (We don't want that,
- # Pygments should return exactly the same amount of text, as we
- # have given as input.)
- for _, t, v in self.pygments_lexer.get_tokens_unprocessed(text):
- yield t, v
-
- return enumerate(split_lines(get_tokens()), start_lineno)
-
- def get_generator(i):
- """
- Find an already started generator that is close, or create a new one.
- """
- # Find closest line generator.
- generator = find_closest_generator(i)
- if generator:
- return generator
-
- # No generator found. Determine starting point for the syntax
- # synchronisation first.
-
- # Go at least x lines back. (Make scrolling upwards more
- # efficient.)
- i = max(0, i - self.MIN_LINES_BACKWARDS)
-
- if i == 0:
- row = 0
- column = 0
- else:
- row, column = get_syntax_sync().get_sync_start_position(document, i)
-
- # Find generator close to this point, or otherwise create a new one.
- generator = find_closest_generator(i)
- if generator:
- return generator
- else:
- generator = create_line_generator(row, column)
-
- # If the column is not 0, ignore the first line. (Which is
- # incomplete. This happens when the synchronisation algorithm tells
- # us to start parsing in the middle of a line.)
- if column:
- next(generator)
- row += 1
-
- line_generators[generator] = row
- return generator
-
- def get_line(i):
- " Return the tokens for a given line number. "
- try:
- return cache[i]
- except KeyError:
- generator = get_generator(i)
-
- # Exhaust the generator, until we find the requested line.
- for num, line in generator:
- cache[num] = line
- if num == i:
- line_generators[generator] = i
-
- # Remove the next item from the cache.
- # (It could happen that it's already there, because of
- # another generator that started filling these lines,
- # but we want to synchronise these lines with the
- # current lexer's state.)
- if num + 1 in cache:
- del cache[num + 1]
-
- return cache[num]
- return []
-
- return get_line
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py
deleted file mode 100644
index 2934dfc9a7..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py
+++ /dev/null
@@ -1,253 +0,0 @@
-"""
-Margin implementations for a :class:`~prompt_toolkit.layout.containers.Window`.
-"""
-from __future__ import unicode_literals
-
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-from six.moves import range
-
-from prompt_toolkit.filters import to_cli_filter
-from prompt_toolkit.token import Token
-from prompt_toolkit.utils import get_cwidth
-from .utils import token_list_to_text
-
-__all__ = (
- 'Margin',
- 'NumberredMargin',
- 'ScrollbarMargin',
- 'ConditionalMargin',
- 'PromptMargin',
-)
-
-
-class Margin(with_metaclass(ABCMeta, object)):
- """
- Base interface for a margin.
- """
- @abstractmethod
- def get_width(self, cli, get_ui_content):
- """
- Return the width that this margin is going to consume.
-
- :param cli: :class:`.CommandLineInterface` instance.
- :param get_ui_content: Callable that asks the user control to create
- a :class:`.UIContent` instance. This can be used for instance to
- obtain the number of lines.
- """
- return 0
-
- @abstractmethod
- def create_margin(self, cli, window_render_info, width, height):
- """
- Creates a margin.
- This should return a list of (Token, text) tuples.
-
- :param cli: :class:`.CommandLineInterface` instance.
- :param window_render_info:
- :class:`~prompt_toolkit.layout.containers.WindowRenderInfo`
- instance, generated after rendering and copying the visible part of
- the :class:`~prompt_toolkit.layout.controls.UIControl` into the
- :class:`~prompt_toolkit.layout.containers.Window`.
- :param width: The width that's available for this margin. (As reported
- by :meth:`.get_width`.)
- :param height: The height that's available for this margin. (The height
- of the :class:`~prompt_toolkit.layout.containers.Window`.)
- """
- return []
-
-
-class NumberredMargin(Margin):
- """
- Margin that displays the line numbers.
-
- :param relative: Number relative to the cursor position. Similar to the Vi
- 'relativenumber' option.
- :param display_tildes: Display tildes after the end of the document, just
- like Vi does.
- """
- def __init__(self, relative=False, display_tildes=False):
- self.relative = to_cli_filter(relative)
- self.display_tildes = to_cli_filter(display_tildes)
-
- def get_width(self, cli, get_ui_content):
- line_count = get_ui_content().line_count
- return max(3, len('%s' % line_count) + 1)
-
- def create_margin(self, cli, window_render_info, width, height):
- relative = self.relative(cli)
-
- token = Token.LineNumber
- token_current = Token.LineNumber.Current
-
- # Get current line number.
- current_lineno = window_render_info.ui_content.cursor_position.y
-
- # Construct margin.
- result = []
- last_lineno = None
-
- for y, lineno in enumerate(window_render_info.displayed_lines):
- # Only display line number if this line is not a continuation of the previous line.
- if lineno != last_lineno:
- if lineno is None:
- pass
- elif lineno == current_lineno:
- # Current line.
- if relative:
- # Left align current number in relative mode.
- result.append((token_current, '%i' % (lineno + 1)))
- else:
- result.append((token_current, ('%i ' % (lineno + 1)).rjust(width)))
- else:
- # Other lines.
- if relative:
- lineno = abs(lineno - current_lineno) - 1
-
- result.append((token, ('%i ' % (lineno + 1)).rjust(width)))
-
- last_lineno = lineno
- result.append((Token, '\n'))
-
- # Fill with tildes.
- if self.display_tildes(cli):
- while y < window_render_info.window_height:
- result.append((Token.Tilde, '~\n'))
- y += 1
-
- return result
-
-
-class ConditionalMargin(Margin):
- """
- Wrapper around other :class:`.Margin` classes to show/hide them.
- """
- def __init__(self, margin, filter):
- assert isinstance(margin, Margin)
-
- self.margin = margin
- self.filter = to_cli_filter(filter)
-
- def get_width(self, cli, ui_content):
- if self.filter(cli):
- return self.margin.get_width(cli, ui_content)
- else:
- return 0
-
- def create_margin(self, cli, window_render_info, width, height):
- if width and self.filter(cli):
- return self.margin.create_margin(cli, window_render_info, width, height)
- else:
- return []
-
-
-class ScrollbarMargin(Margin):
- """
- Margin displaying a scrollbar.
-
- :param display_arrows: Display scroll up/down arrows.
- """
- def __init__(self, display_arrows=False):
- self.display_arrows = to_cli_filter(display_arrows)
-
- def get_width(self, cli, ui_content):
- return 1
-
- def create_margin(self, cli, window_render_info, width, height):
- total_height = window_render_info.content_height
- display_arrows = self.display_arrows(cli)
-
- window_height = window_render_info.window_height
- if display_arrows:
- window_height -= 2
-
- try:
- items_per_row = float(total_height) / min(total_height, window_height)
- except ZeroDivisionError:
- return []
- else:
- def is_scroll_button(row):
- " True if we should display a button on this row. "
- current_row_middle = int((row + .5) * items_per_row)
- return current_row_middle in window_render_info.displayed_lines
-
- # Up arrow.
- result = []
- if display_arrows:
- result.extend([
- (Token.Scrollbar.Arrow, '^'),
- (Token.Scrollbar, '\n')
- ])
-
- # Scrollbar body.
- for i in range(window_height):
- if is_scroll_button(i):
- result.append((Token.Scrollbar.Button, ' '))
- else:
- result.append((Token.Scrollbar, ' '))
- result.append((Token, '\n'))
-
- # Down arrow
- if display_arrows:
- result.append((Token.Scrollbar.Arrow, 'v'))
-
- return result
-
-
-class PromptMargin(Margin):
- """
- Create margin that displays a prompt.
- This can display one prompt at the first line, and a continuation prompt
- (e.g, just dots) on all the following lines.
-
- :param get_prompt_tokens: Callable that takes a CommandLineInterface as
- input and returns a list of (Token, type) tuples to be shown as the
- prompt at the first line.
- :param get_continuation_tokens: Callable that takes a CommandLineInterface
- and a width as input and returns a list of (Token, type) tuples for the
- next lines of the input.
- :param show_numbers: (bool or :class:`~prompt_toolkit.filters.CLIFilter`)
- Display line numbers instead of the continuation prompt.
- """
- def __init__(self, get_prompt_tokens, get_continuation_tokens=None,
- show_numbers=False):
- assert callable(get_prompt_tokens)
- assert get_continuation_tokens is None or callable(get_continuation_tokens)
- show_numbers = to_cli_filter(show_numbers)
-
- self.get_prompt_tokens = get_prompt_tokens
- self.get_continuation_tokens = get_continuation_tokens
- self.show_numbers = show_numbers
-
- def get_width(self, cli, ui_content):
- " Width to report to the `Window`. "
- # Take the width from the first line.
- text = token_list_to_text(self.get_prompt_tokens(cli))
- return get_cwidth(text)
-
- def create_margin(self, cli, window_render_info, width, height):
- # First line.
- tokens = self.get_prompt_tokens(cli)[:]
-
- # Next lines. (Show line numbering when numbering is enabled.)
- if self.get_continuation_tokens:
- # Note: we turn this into a list, to make sure that we fail early
- # in case `get_continuation_tokens` returns something else,
- # like `None`.
- tokens2 = list(self.get_continuation_tokens(cli, width))
- else:
- tokens2 = []
-
- show_numbers = self.show_numbers(cli)
- last_y = None
-
- for y in window_render_info.displayed_lines[1:]:
- tokens.append((Token, '\n'))
- if show_numbers:
- if y != last_y:
- tokens.append((Token.LineNumber, ('%i ' % (y + 1)).rjust(width)))
- else:
- tokens.extend(tokens2)
- last_y = y
-
- return tokens
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py
deleted file mode 100644
index a916846e45..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py
+++ /dev/null
@@ -1,496 +0,0 @@
-from __future__ import unicode_literals
-
-from six.moves import zip_longest, range
-from prompt_toolkit.filters import HasCompletions, IsDone, Condition, to_cli_filter
-from prompt_toolkit.mouse_events import MouseEventType
-from prompt_toolkit.token import Token
-from prompt_toolkit.utils import get_cwidth
-
-from .containers import Window, HSplit, ConditionalContainer, ScrollOffsets
-from .controls import UIControl, UIContent
-from .dimension import LayoutDimension
-from .margins import ScrollbarMargin
-from .screen import Point, Char
-
-import math
-
-__all__ = (
- 'CompletionsMenu',
- 'MultiColumnCompletionsMenu',
-)
-
-
-class CompletionsMenuControl(UIControl):
- """
- Helper for drawing the complete menu to the screen.
-
- :param scroll_offset: Number (integer) representing the preferred amount of
- completions to be displayed before and after the current one. When this
- is a very high number, the current completion will be shown in the
- middle most of the time.
- """
- # Preferred minimum size of the menu control.
- # The CompletionsMenu class defines a width of 8, and there is a scrollbar
- # of 1.)
- MIN_WIDTH = 7
-
- def __init__(self):
- self.token = Token.Menu.Completions
-
- def has_focus(self, cli):
- return False
-
- def preferred_width(self, cli, max_available_width):
- complete_state = cli.current_buffer.complete_state
- if complete_state:
- menu_width = self._get_menu_width(500, complete_state)
- menu_meta_width = self._get_menu_meta_width(500, complete_state)
-
- return menu_width + menu_meta_width
- else:
- return 0
-
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
- complete_state = cli.current_buffer.complete_state
- if complete_state:
- return len(complete_state.current_completions)
- else:
- return 0
-
- def create_content(self, cli, width, height):
- """
- Create a UIContent object for this control.
- """
- complete_state = cli.current_buffer.complete_state
- if complete_state:
- completions = complete_state.current_completions
- index = complete_state.complete_index # Can be None!
-
- # Calculate width of completions menu.
- menu_width = self._get_menu_width(width, complete_state)
- menu_meta_width = self._get_menu_meta_width(width - menu_width, complete_state)
- show_meta = self._show_meta(complete_state)
-
- def get_line(i):
- c = completions[i]
- is_current_completion = (i == index)
- result = self._get_menu_item_tokens(c, is_current_completion, menu_width)
-
- if show_meta:
- result += self._get_menu_item_meta_tokens(c, is_current_completion, menu_meta_width)
- return result
-
- return UIContent(get_line=get_line,
- cursor_position=Point(x=0, y=index or 0),
- line_count=len(completions),
- default_char=Char(' ', self.token))
-
- return UIContent()
-
- def _show_meta(self, complete_state):
- """
- Return ``True`` if we need to show a column with meta information.
- """
- return any(c.display_meta for c in complete_state.current_completions)
-
- def _get_menu_width(self, max_width, complete_state):
- """
- Return the width of the main column.
- """
- return min(max_width, max(self.MIN_WIDTH, max(get_cwidth(c.display)
- for c in complete_state.current_completions) + 2))
-
- def _get_menu_meta_width(self, max_width, complete_state):
- """
- Return the width of the meta column.
- """
- if self._show_meta(complete_state):
- return min(max_width, max(get_cwidth(c.display_meta)
- for c in complete_state.current_completions) + 2)
- else:
- return 0
-
- def _get_menu_item_tokens(self, completion, is_current_completion, width):
- if is_current_completion:
- token = self.token.Completion.Current
- else:
- token = self.token.Completion
-
- text, tw = _trim_text(completion.display, width - 2)
- padding = ' ' * (width - 2 - tw)
- return [(token, ' %s%s ' % (text, padding))]
-
- def _get_menu_item_meta_tokens(self, completion, is_current_completion, width):
- if is_current_completion:
- token = self.token.Meta.Current
- else:
- token = self.token.Meta
-
- text, tw = _trim_text(completion.display_meta, width - 2)
- padding = ' ' * (width - 2 - tw)
- return [(token, ' %s%s ' % (text, padding))]
-
- def mouse_handler(self, cli, mouse_event):
- """
- Handle mouse events: clicking and scrolling.
- """
- b = cli.current_buffer
-
- if mouse_event.event_type == MouseEventType.MOUSE_UP:
- # Select completion.
- b.go_to_completion(mouse_event.position.y)
- b.complete_state = None
-
- elif mouse_event.event_type == MouseEventType.SCROLL_DOWN:
- # Scroll up.
- b.complete_next(count=3, disable_wrap_around=True)
-
- elif mouse_event.event_type == MouseEventType.SCROLL_UP:
- # Scroll down.
- b.complete_previous(count=3, disable_wrap_around=True)
-
-
-def _trim_text(text, max_width):
- """
- Trim the text to `max_width`, append dots when the text is too long.
- Returns (text, width) tuple.
- """
- width = get_cwidth(text)
-
- # When the text is too wide, trim it.
- if width > max_width:
- # When there are no double width characters, just use slice operation.
- if len(text) == width:
- trimmed_text = (text[:max(1, max_width-3)] + '...')[:max_width]
- return trimmed_text, len(trimmed_text)
-
- # Otherwise, loop until we have the desired width. (Rather
- # inefficient, but ok for now.)
- else:
- trimmed_text = ''
- for c in text:
- if get_cwidth(trimmed_text + c) <= max_width - 3:
- trimmed_text += c
- trimmed_text += '...'
-
- return (trimmed_text, get_cwidth(trimmed_text))
- else:
- return text, width
-
-
-class CompletionsMenu(ConditionalContainer):
- def __init__(self, max_height=None, scroll_offset=0, extra_filter=True, display_arrows=False):
- extra_filter = to_cli_filter(extra_filter)
- display_arrows = to_cli_filter(display_arrows)
-
- super(CompletionsMenu, self).__init__(
- content=Window(
- content=CompletionsMenuControl(),
- width=LayoutDimension(min=8),
- height=LayoutDimension(min=1, max=max_height),
- scroll_offsets=ScrollOffsets(top=scroll_offset, bottom=scroll_offset),
- right_margins=[ScrollbarMargin(display_arrows=display_arrows)],
- dont_extend_width=True,
- ),
- # Show when there are completions but not at the point we are
- # returning the input.
- filter=HasCompletions() & ~IsDone() & extra_filter)
-
-
-class MultiColumnCompletionMenuControl(UIControl):
- """
- Completion menu that displays all the completions in several columns.
- When there are more completions than space for them to be displayed, an
- arrow is shown on the left or right side.
-
- `min_rows` indicates how many rows will be available in any possible case.
- When this is langer than one, in will try to use less columns and more
- rows until this value is reached.
- Be careful passing in a too big value, if less than the given amount of
- rows are available, more columns would have been required, but
- `preferred_width` doesn't know about that and reports a too small value.
- This results in less completions displayed and additional scrolling.
- (It's a limitation of how the layout engine currently works: first the
- widths are calculated, then the heights.)
-
- :param suggested_max_column_width: The suggested max width of a column.
- The column can still be bigger than this, but if there is place for two
- columns of this width, we will display two columns. This to avoid that
- if there is one very wide completion, that it doesn't significantly
- reduce the amount of columns.
- """
- _required_margin = 3 # One extra padding on the right + space for arrows.
-
- def __init__(self, min_rows=3, suggested_max_column_width=30):
- assert isinstance(min_rows, int) and min_rows >= 1
-
- self.min_rows = min_rows
- self.suggested_max_column_width = suggested_max_column_width
- self.token = Token.Menu.Completions
- self.scroll = 0
-
- # Info of last rendering.
- self._rendered_rows = 0
- self._rendered_columns = 0
- self._total_columns = 0
- self._render_pos_to_completion = {}
- self._render_left_arrow = False
- self._render_right_arrow = False
- self._render_width = 0
-
- def reset(self):
- self.scroll = 0
-
- def has_focus(self, cli):
- return False
-
- def preferred_width(self, cli, max_available_width):
- """
- Preferred width: prefer to use at least min_rows, but otherwise as much
- as possible horizontally.
- """
- complete_state = cli.current_buffer.complete_state
- column_width = self._get_column_width(complete_state)
- result = int(column_width * math.ceil(len(complete_state.current_completions) / float(self.min_rows)))
-
- # When the desired width is still more than the maximum available,
- # reduce by removing columns until we are less than the available
- # width.
- while result > column_width and result > max_available_width - self._required_margin:
- result -= column_width
- return result + self._required_margin
-
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
- """
- Preferred height: as much as needed in order to display all the completions.
- """
- complete_state = cli.current_buffer.complete_state
- column_width = self._get_column_width(complete_state)
- column_count = max(1, (width - self._required_margin) // column_width)
-
- return int(math.ceil(len(complete_state.current_completions) / float(column_count)))
-
- def create_content(self, cli, width, height):
- """
- Create a UIContent object for this menu.
- """
- complete_state = cli.current_buffer.complete_state
- column_width = self._get_column_width(complete_state)
- self._render_pos_to_completion = {}
-
- def grouper(n, iterable, fillvalue=None):
- " grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx "
- args = [iter(iterable)] * n
- return zip_longest(fillvalue=fillvalue, *args)
-
- def is_current_completion(completion):
- " Returns True when this completion is the currently selected one. "
- return complete_state.complete_index is not None and c == complete_state.current_completion
-
- # Space required outside of the regular columns, for displaying the
- # left and right arrow.
- HORIZONTAL_MARGIN_REQUIRED = 3
-
- if complete_state:
- # There should be at least one column, but it cannot be wider than
- # the available width.
- column_width = min(width - HORIZONTAL_MARGIN_REQUIRED, column_width)
-
- # However, when the columns tend to be very wide, because there are
- # some very wide entries, shrink it anyway.
- if column_width > self.suggested_max_column_width:
- # `column_width` can still be bigger that `suggested_max_column_width`,
- # but if there is place for two columns, we divide by two.
- column_width //= (column_width // self.suggested_max_column_width)
-
- visible_columns = max(1, (width - self._required_margin) // column_width)
-
- columns_ = list(grouper(height, complete_state.current_completions))
- rows_ = list(zip(*columns_))
-
- # Make sure the current completion is always visible: update scroll offset.
- selected_column = (complete_state.complete_index or 0) // height
- self.scroll = min(selected_column, max(self.scroll, selected_column - visible_columns + 1))
-
- render_left_arrow = self.scroll > 0
- render_right_arrow = self.scroll < len(rows_[0]) - visible_columns
-
- # Write completions to screen.
- tokens_for_line = []
-
- for row_index, row in enumerate(rows_):
- tokens = []
- middle_row = row_index == len(rows_) // 2
-
- # Draw left arrow if we have hidden completions on the left.
- if render_left_arrow:
- tokens += [(Token.Scrollbar, '<' if middle_row else ' ')]
-
- # Draw row content.
- for column_index, c in enumerate(row[self.scroll:][:visible_columns]):
- if c is not None:
- tokens += self._get_menu_item_tokens(c, is_current_completion(c), column_width)
-
- # Remember render position for mouse click handler.
- for x in range(column_width):
- self._render_pos_to_completion[(column_index * column_width + x, row_index)] = c
- else:
- tokens += [(self.token.Completion, ' ' * column_width)]
-
- # Draw trailing padding. (_get_menu_item_tokens only returns padding on the left.)
- tokens += [(self.token.Completion, ' ')]
-
- # Draw right arrow if we have hidden completions on the right.
- if render_right_arrow:
- tokens += [(Token.Scrollbar, '>' if middle_row else ' ')]
-
- # Newline.
- tokens_for_line.append(tokens)
-
- else:
- tokens = []
-
- self._rendered_rows = height
- self._rendered_columns = visible_columns
- self._total_columns = len(columns_)
- self._render_left_arrow = render_left_arrow
- self._render_right_arrow = render_right_arrow
- self._render_width = column_width * visible_columns + render_left_arrow + render_right_arrow + 1
-
- def get_line(i):
- return tokens_for_line[i]
-
- return UIContent(get_line=get_line, line_count=len(rows_))
-
- def _get_column_width(self, complete_state):
- """
- Return the width of each column.
- """
- return max(get_cwidth(c.display) for c in complete_state.current_completions) + 1
-
- def _get_menu_item_tokens(self, completion, is_current_completion, width):
- if is_current_completion:
- token = self.token.Completion.Current
- else:
- token = self.token.Completion
-
- text, tw = _trim_text(completion.display, width)
- padding = ' ' * (width - tw - 1)
-
- return [(token, ' %s%s' % (text, padding))]
-
- def mouse_handler(self, cli, mouse_event):
- """
- Handle scoll and click events.
- """
- b = cli.current_buffer
-
- def scroll_left():
- b.complete_previous(count=self._rendered_rows, disable_wrap_around=True)
- self.scroll = max(0, self.scroll - 1)
-
- def scroll_right():
- b.complete_next(count=self._rendered_rows, disable_wrap_around=True)
- self.scroll = min(self._total_columns - self._rendered_columns, self.scroll + 1)
-
- if mouse_event.event_type == MouseEventType.SCROLL_DOWN:
- scroll_right()
-
- elif mouse_event.event_type == MouseEventType.SCROLL_UP:
- scroll_left()
-
- elif mouse_event.event_type == MouseEventType.MOUSE_UP:
- x = mouse_event.position.x
- y = mouse_event.position.y
-
- # Mouse click on left arrow.
- if x == 0:
- if self._render_left_arrow:
- scroll_left()
-
- # Mouse click on right arrow.
- elif x == self._render_width - 1:
- if self._render_right_arrow:
- scroll_right()
-
- # Mouse click on completion.
- else:
- completion = self._render_pos_to_completion.get((x, y))
- if completion:
- b.apply_completion(completion)
-
-
-class MultiColumnCompletionsMenu(HSplit):
- """
- Container that displays the completions in several columns.
- When `show_meta` (a :class:`~prompt_toolkit.filters.CLIFilter`) evaluates
- to True, it shows the meta information at the bottom.
- """
- def __init__(self, min_rows=3, suggested_max_column_width=30, show_meta=True, extra_filter=True):
- show_meta = to_cli_filter(show_meta)
- extra_filter = to_cli_filter(extra_filter)
-
- # Display filter: show when there are completions but not at the point
- # we are returning the input.
- full_filter = HasCompletions() & ~IsDone() & extra_filter
-
- any_completion_has_meta = Condition(lambda cli:
- any(c.display_meta for c in cli.current_buffer.complete_state.current_completions))
-
- # Create child windows.
- completions_window = ConditionalContainer(
- content=Window(
- content=MultiColumnCompletionMenuControl(
- min_rows=min_rows, suggested_max_column_width=suggested_max_column_width),
- width=LayoutDimension(min=8),
- height=LayoutDimension(min=1)),
- filter=full_filter)
-
- meta_window = ConditionalContainer(
- content=Window(content=_SelectedCompletionMetaControl()),
- filter=show_meta & full_filter & any_completion_has_meta)
-
- # Initialise split.
- super(MultiColumnCompletionsMenu, self).__init__([
- completions_window,
- meta_window
- ])
-
-
-class _SelectedCompletionMetaControl(UIControl):
- """
- Control that shows the meta information of the selected token.
- """
- def preferred_width(self, cli, max_available_width):
- """
- Report the width of the longest meta text as the preferred width of this control.
-
- It could be that we use less width, but this way, we're sure that the
- layout doesn't change when we select another completion (E.g. that
- completions are suddenly shown in more or fewer columns.)
- """
- if cli.current_buffer.complete_state:
- state = cli.current_buffer.complete_state
- return 2 + max(get_cwidth(c.display_meta) for c in state.current_completions)
- else:
- return 0
-
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
- return 1
-
- def create_content(self, cli, width, height):
- tokens = self._get_tokens(cli)
-
- def get_line(i):
- return tokens
-
- return UIContent(get_line=get_line, line_count=1 if tokens else 0)
-
- def _get_tokens(self, cli):
- token = Token.Menu.Completions.MultiColumnMeta
- state = cli.current_buffer.complete_state
-
- if state and state.current_completion and state.current_completion.display_meta:
- return [(token, ' %s ' % state.current_completion.display_meta)]
-
- return []
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/mouse_handlers.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/mouse_handlers.py
deleted file mode 100644
index d443bf8315..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/mouse_handlers.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-
-from itertools import product
-from collections import defaultdict
-
-__all__ = (
- 'MouseHandlers',
-)
-
-
-class MouseHandlers(object):
- """
- Two dimentional raster of callbacks for mouse events.
- """
- def __init__(self):
- def dummy_callback(cli, mouse_event):
- """
- :param mouse_event: `MouseEvent` instance.
- """
-
- # Map (x,y) tuples to handlers.
- self.mouse_handlers = defaultdict(lambda: dummy_callback)
-
- def set_mouse_handler_for_range(self, x_min, x_max, y_min, y_max, handler=None):
- """
- Set mouse handler for a region.
- """
- for x, y in product(range(x_min, x_max), range(y_min, y_max)):
- self.mouse_handlers[x,y] = handler
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py
deleted file mode 100644
index 0b8bc9c223..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py
+++ /dev/null
@@ -1,605 +0,0 @@
-"""
-Processors are little transformation blocks that transform the token list from
-a buffer before the BufferControl will render it to the screen.
-
-They can insert tokens before or after, or highlight fragments by replacing the
-token types.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-from six.moves import range
-
-from prompt_toolkit.cache import SimpleCache
-from prompt_toolkit.document import Document
-from prompt_toolkit.enums import SEARCH_BUFFER
-from prompt_toolkit.filters import to_cli_filter, ViInsertMultipleMode
-from prompt_toolkit.layout.utils import token_list_to_text
-from prompt_toolkit.reactive import Integer
-from prompt_toolkit.token import Token
-
-from .utils import token_list_len, explode_tokens
-
-import re
-
-__all__ = (
- 'Processor',
- 'Transformation',
-
- 'HighlightSearchProcessor',
- 'HighlightSelectionProcessor',
- 'PasswordProcessor',
- 'HighlightMatchingBracketProcessor',
- 'DisplayMultipleCursors',
- 'BeforeInput',
- 'AfterInput',
- 'AppendAutoSuggestion',
- 'ConditionalProcessor',
- 'ShowLeadingWhiteSpaceProcessor',
- 'ShowTrailingWhiteSpaceProcessor',
- 'TabsProcessor',
-)
-
-
-class Processor(with_metaclass(ABCMeta, object)):
- """
- Manipulate the tokens for a given line in a
- :class:`~prompt_toolkit.layout.controls.BufferControl`.
- """
- @abstractmethod
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- """
- Apply transformation. Returns a :class:`.Transformation` instance.
-
- :param cli: :class:`.CommandLineInterface` instance.
- :param lineno: The number of the line to which we apply the processor.
- :param source_to_display: A function that returns the position in the
- `tokens` for any position in the source string. (This takes
- previous processors into account.)
- :param tokens: List of tokens that we can transform. (Received from the
- previous processor.)
- """
- return Transformation(tokens)
-
- def has_focus(self, cli):
- """
- Processors can override the focus.
- (Used for the reverse-i-search prefix in DefaultPrompt.)
- """
- return False
-
-
-class Transformation(object):
- """
- Transformation result, as returned by :meth:`.Processor.apply_transformation`.
-
- Important: Always make sure that the length of `document.text` is equal to
- the length of all the text in `tokens`!
-
- :param tokens: The transformed tokens. To be displayed, or to pass to the
- next processor.
- :param source_to_display: Cursor position transformation from original string to
- transformed string.
- :param display_to_source: Cursor position transformed from source string to
- original string.
- """
- def __init__(self, tokens, source_to_display=None, display_to_source=None):
- self.tokens = tokens
- self.source_to_display = source_to_display or (lambda i: i)
- self.display_to_source = display_to_source or (lambda i: i)
-
-
-class HighlightSearchProcessor(Processor):
- """
- Processor that highlights search matches in the document.
- Note that this doesn't support multiline search matches yet.
-
- :param preview_search: A Filter; when active it indicates that we take
- the search text in real time while the user is typing, instead of the
- last active search state.
- """
- def __init__(self, preview_search=False, search_buffer_name=SEARCH_BUFFER,
- get_search_state=None):
- self.preview_search = to_cli_filter(preview_search)
- self.search_buffer_name = search_buffer_name
- self.get_search_state = get_search_state or (lambda cli: cli.search_state)
-
- def _get_search_text(self, cli):
- """
- The text we are searching for.
- """
- # When the search buffer has focus, take that text.
- if self.preview_search(cli) and cli.buffers[self.search_buffer_name].text:
- return cli.buffers[self.search_buffer_name].text
- # Otherwise, take the text of the last active search.
- else:
- return self.get_search_state(cli).text
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- search_text = self._get_search_text(cli)
- searchmatch_current_token = (':', ) + Token.SearchMatch.Current
- searchmatch_token = (':', ) + Token.SearchMatch
-
- if search_text and not cli.is_returning:
- # For each search match, replace the Token.
- line_text = token_list_to_text(tokens)
- tokens = explode_tokens(tokens)
-
- flags = re.IGNORECASE if cli.is_ignoring_case else 0
-
- # Get cursor column.
- if document.cursor_position_row == lineno:
- cursor_column = source_to_display(document.cursor_position_col)
- else:
- cursor_column = None
-
- for match in re.finditer(re.escape(search_text), line_text, flags=flags):
- if cursor_column is not None:
- on_cursor = match.start() <= cursor_column < match.end()
- else:
- on_cursor = False
-
- for i in range(match.start(), match.end()):
- old_token, text = tokens[i]
- if on_cursor:
- tokens[i] = (old_token + searchmatch_current_token, tokens[i][1])
- else:
- tokens[i] = (old_token + searchmatch_token, tokens[i][1])
-
- return Transformation(tokens)
-
-
-class HighlightSelectionProcessor(Processor):
- """
- Processor that highlights the selection in the document.
- """
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- selected_token = (':', ) + Token.SelectedText
-
- # In case of selection, highlight all matches.
- selection_at_line = document.selection_range_at_line(lineno)
-
- if selection_at_line:
- from_, to = selection_at_line
- from_ = source_to_display(from_)
- to = source_to_display(to)
-
- tokens = explode_tokens(tokens)
-
- if from_ == 0 and to == 0 and len(tokens) == 0:
- # When this is an empty line, insert a space in order to
- # visualiase the selection.
- return Transformation([(Token.SelectedText, ' ')])
- else:
- for i in range(from_, to + 1):
- if i < len(tokens):
- old_token, old_text = tokens[i]
- tokens[i] = (old_token + selected_token, old_text)
-
- return Transformation(tokens)
-
-
-class PasswordProcessor(Processor):
- """
- Processor that turns masks the input. (For passwords.)
-
- :param char: (string) Character to be used. "*" by default.
- """
- def __init__(self, char='*'):
- self.char = char
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- tokens = [(token, self.char * len(text)) for token, text in tokens]
- return Transformation(tokens)
-
-
-class HighlightMatchingBracketProcessor(Processor):
- """
- When the cursor is on or right after a bracket, it highlights the matching
- bracket.
-
- :param max_cursor_distance: Only highlight matching brackets when the
- cursor is within this distance. (From inside a `Processor`, we can't
- know which lines will be visible on the screen. But we also don't want
- to scan the whole document for matching brackets on each key press, so
- we limit to this value.)
- """
- _closing_braces = '])}>'
-
- def __init__(self, chars='[](){}<>', max_cursor_distance=1000):
- self.chars = chars
- self.max_cursor_distance = max_cursor_distance
-
- self._positions_cache = SimpleCache(maxsize=8)
-
- def _get_positions_to_highlight(self, document):
- """
- Return a list of (row, col) tuples that need to be highlighted.
- """
- # Try for the character under the cursor.
- if document.current_char and document.current_char in self.chars:
- pos = document.find_matching_bracket_position(
- start_pos=document.cursor_position - self.max_cursor_distance,
- end_pos=document.cursor_position + self.max_cursor_distance)
-
- # Try for the character before the cursor.
- elif (document.char_before_cursor and document.char_before_cursor in
- self._closing_braces and document.char_before_cursor in self.chars):
- document = Document(document.text, document.cursor_position - 1)
-
- pos = document.find_matching_bracket_position(
- start_pos=document.cursor_position - self.max_cursor_distance,
- end_pos=document.cursor_position + self.max_cursor_distance)
- else:
- pos = None
-
- # Return a list of (row, col) tuples that need to be highlighted.
- if pos:
- pos += document.cursor_position # pos is relative.
- row, col = document.translate_index_to_position(pos)
- return [(row, col), (document.cursor_position_row, document.cursor_position_col)]
- else:
- return []
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- # Get the highlight positions.
- key = (cli.render_counter, document.text, document.cursor_position)
- positions = self._positions_cache.get(
- key, lambda: self._get_positions_to_highlight(document))
-
- # Apply if positions were found at this line.
- if positions:
- for row, col in positions:
- if row == lineno:
- col = source_to_display(col)
- tokens = explode_tokens(tokens)
- token, text = tokens[col]
-
- if col == document.cursor_position_col:
- token += (':', ) + Token.MatchingBracket.Cursor
- else:
- token += (':', ) + Token.MatchingBracket.Other
-
- tokens[col] = (token, text)
-
- return Transformation(tokens)
-
-
-class DisplayMultipleCursors(Processor):
- """
- When we're in Vi block insert mode, display all the cursors.
- """
- _insert_multiple = ViInsertMultipleMode()
-
- def __init__(self, buffer_name):
- self.buffer_name = buffer_name
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- buff = cli.buffers[self.buffer_name]
-
- if self._insert_multiple(cli):
- positions = buff.multiple_cursor_positions
- tokens = explode_tokens(tokens)
-
- # If any cursor appears on the current line, highlight that.
- start_pos = document.translate_row_col_to_index(lineno, 0)
- end_pos = start_pos + len(document.lines[lineno])
-
- token_suffix = (':', ) + Token.MultipleCursors.Cursor
-
- for p in positions:
- if start_pos <= p < end_pos:
- column = source_to_display(p - start_pos)
-
- # Replace token.
- token, text = tokens[column]
- token += token_suffix
- tokens[column] = (token, text)
- elif p == end_pos:
- tokens.append((token_suffix, ' '))
-
- return Transformation(tokens)
- else:
- return Transformation(tokens)
-
-
-class BeforeInput(Processor):
- """
- Insert tokens before the input.
-
- :param get_tokens: Callable that takes a
- :class:`~prompt_toolkit.interface.CommandLineInterface` and returns the
- list of tokens to be inserted.
- """
- def __init__(self, get_tokens):
- assert callable(get_tokens)
- self.get_tokens = get_tokens
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- if lineno == 0:
- tokens_before = self.get_tokens(cli)
- tokens = tokens_before + tokens
-
- shift_position = token_list_len(tokens_before)
- source_to_display = lambda i: i + shift_position
- display_to_source = lambda i: i - shift_position
- else:
- source_to_display = None
- display_to_source = None
-
- return Transformation(tokens, source_to_display=source_to_display,
- display_to_source=display_to_source)
-
- @classmethod
- def static(cls, text, token=Token):
- """
- Create a :class:`.BeforeInput` instance that always inserts the same
- text.
- """
- def get_static_tokens(cli):
- return [(token, text)]
- return cls(get_static_tokens)
-
- def __repr__(self):
- return '%s(get_tokens=%r)' % (
- self.__class__.__name__, self.get_tokens)
-
-
-class AfterInput(Processor):
- """
- Insert tokens after the input.
-
- :param get_tokens: Callable that takes a
- :class:`~prompt_toolkit.interface.CommandLineInterface` and returns the
- list of tokens to be appended.
- """
- def __init__(self, get_tokens):
- assert callable(get_tokens)
- self.get_tokens = get_tokens
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- # Insert tokens after the last line.
- if lineno == document.line_count - 1:
- return Transformation(tokens=tokens + self.get_tokens(cli))
- else:
- return Transformation(tokens=tokens)
-
- @classmethod
- def static(cls, text, token=Token):
- """
- Create a :class:`.AfterInput` instance that always inserts the same
- text.
- """
- def get_static_tokens(cli):
- return [(token, text)]
- return cls(get_static_tokens)
-
- def __repr__(self):
- return '%s(get_tokens=%r)' % (
- self.__class__.__name__, self.get_tokens)
-
-
-class AppendAutoSuggestion(Processor):
- """
- Append the auto suggestion to the input.
- (The user can then press the right arrow the insert the suggestion.)
-
- :param buffer_name: The name of the buffer from where we should take the
- auto suggestion. If not given, we take the current buffer.
- """
- def __init__(self, buffer_name=None, token=Token.AutoSuggestion):
- self.buffer_name = buffer_name
- self.token = token
-
- def _get_buffer(self, cli):
- if self.buffer_name:
- return cli.buffers[self.buffer_name]
- else:
- return cli.current_buffer
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- # Insert tokens after the last line.
- if lineno == document.line_count - 1:
- buffer = self._get_buffer(cli)
-
- if buffer.suggestion and buffer.document.is_cursor_at_the_end:
- suggestion = buffer.suggestion.text
- else:
- suggestion = ''
-
- return Transformation(tokens=tokens + [(self.token, suggestion)])
- else:
- return Transformation(tokens=tokens)
-
-
-class ShowLeadingWhiteSpaceProcessor(Processor):
- """
- Make leading whitespace visible.
-
- :param get_char: Callable that takes a :class:`CommandLineInterface`
- instance and returns one character.
- :param token: Token to be used.
- """
- def __init__(self, get_char=None, token=Token.LeadingWhiteSpace):
- assert get_char is None or callable(get_char)
-
- if get_char is None:
- def get_char(cli):
- if '\xb7'.encode(cli.output.encoding(), 'replace') == b'?':
- return '.'
- else:
- return '\xb7'
-
- self.token = token
- self.get_char = get_char
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- # Walk through all te tokens.
- if tokens and token_list_to_text(tokens).startswith(' '):
- t = (self.token, self.get_char(cli))
- tokens = explode_tokens(tokens)
-
- for i in range(len(tokens)):
- if tokens[i][1] == ' ':
- tokens[i] = t
- else:
- break
-
- return Transformation(tokens)
-
-
-class ShowTrailingWhiteSpaceProcessor(Processor):
- """
- Make trailing whitespace visible.
-
- :param get_char: Callable that takes a :class:`CommandLineInterface`
- instance and returns one character.
- :param token: Token to be used.
- """
- def __init__(self, get_char=None, token=Token.TrailingWhiteSpace):
- assert get_char is None or callable(get_char)
-
- if get_char is None:
- def get_char(cli):
- if '\xb7'.encode(cli.output.encoding(), 'replace') == b'?':
- return '.'
- else:
- return '\xb7'
-
- self.token = token
- self.get_char = get_char
-
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- if tokens and tokens[-1][1].endswith(' '):
- t = (self.token, self.get_char(cli))
- tokens = explode_tokens(tokens)
-
- # Walk backwards through all te tokens and replace whitespace.
- for i in range(len(tokens) - 1, -1, -1):
- char = tokens[i][1]
- if char == ' ':
- tokens[i] = t
- else:
- break
-
- return Transformation(tokens)
-
-
-class TabsProcessor(Processor):
- """
- Render tabs as spaces (instead of ^I) or make them visible (for instance,
- by replacing them with dots.)
-
- :param tabstop: (Integer) Horizontal space taken by a tab.
- :param get_char1: Callable that takes a `CommandLineInterface` and return a
- character (text of length one). This one is used for the first space
- taken by the tab.
- :param get_char2: Like `get_char1`, but for the rest of the space.
- """
- def __init__(self, tabstop=4, get_char1=None, get_char2=None, token=Token.Tab):
- assert isinstance(tabstop, Integer)
- assert get_char1 is None or callable(get_char1)
- assert get_char2 is None or callable(get_char2)
-
- self.get_char1 = get_char1 or get_char2 or (lambda cli: '|')
- self.get_char2 = get_char2 or get_char1 or (lambda cli: '\u2508')
- self.tabstop = tabstop
- self.token = token
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- tabstop = int(self.tabstop)
- token = self.token
-
- # Create separator for tabs.
- separator1 = self.get_char1(cli)
- separator2 = self.get_char2(cli)
-
- # Transform tokens.
- tokens = explode_tokens(tokens)
-
- position_mappings = {}
- result_tokens = []
- pos = 0
-
- for i, token_and_text in enumerate(tokens):
- position_mappings[i] = pos
-
- if token_and_text[1] == '\t':
- # Calculate how many characters we have to insert.
- count = tabstop - (pos % tabstop)
- if count == 0:
- count = tabstop
-
- # Insert tab.
- result_tokens.append((token, separator1))
- result_tokens.append((token, separator2 * (count - 1)))
- pos += count
- else:
- result_tokens.append(token_and_text)
- pos += 1
-
- position_mappings[len(tokens)] = pos
-
- def source_to_display(from_position):
- " Maps original cursor position to the new one. "
- return position_mappings[from_position]
-
- def display_to_source(display_pos):
- " Maps display cursor position to the original one. "
- position_mappings_reversed = dict((v, k) for k, v in position_mappings.items())
-
- while display_pos >= 0:
- try:
- return position_mappings_reversed[display_pos]
- except KeyError:
- display_pos -= 1
- return 0
-
- return Transformation(
- result_tokens,
- source_to_display=source_to_display,
- display_to_source=display_to_source)
-
-
-class ConditionalProcessor(Processor):
- """
- Processor that applies another processor, according to a certain condition.
- Example::
-
- # Create a function that returns whether or not the processor should
- # currently be applied.
- def highlight_enabled(cli):
- return true_or_false
-
- # Wrapt it in a `ConditionalProcessor` for usage in a `BufferControl`.
- BufferControl(input_processors=[
- ConditionalProcessor(HighlightSearchProcessor(),
- Condition(highlight_enabled))])
-
- :param processor: :class:`.Processor` instance.
- :param filter: :class:`~prompt_toolkit.filters.CLIFilter` instance.
- """
- def __init__(self, processor, filter):
- assert isinstance(processor, Processor)
-
- self.processor = processor
- self.filter = to_cli_filter(filter)
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- # Run processor when enabled.
- if self.filter(cli):
- return self.processor.apply_transformation(
- cli, document, lineno, source_to_display, tokens)
- else:
- return Transformation(tokens)
-
- def has_focus(self, cli):
- if self.filter(cli):
- return self.processor.has_focus(cli)
- else:
- return False
-
- def __repr__(self):
- return '%s(processor=%r, filter=%r)' % (
- self.__class__.__name__, self.processor, self.filter)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py
deleted file mode 100644
index 7d00ec513e..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py
+++ /dev/null
@@ -1,111 +0,0 @@
-from __future__ import unicode_literals
-
-from six import text_type
-
-from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER
-from prompt_toolkit.token import Token
-
-from .utils import token_list_len
-from .processors import Processor, Transformation
-
-__all__ = (
- 'DefaultPrompt',
-)
-
-
-class DefaultPrompt(Processor):
- """
- Default prompt. This one shows the 'arg' and reverse search like
- Bash/readline normally do.
-
- There are two ways to instantiate a ``DefaultPrompt``. For a prompt
- with a static message, do for instance::
-
- prompt = DefaultPrompt.from_message('prompt> ')
-
- For a dynamic prompt, generated from a token list function::
-
- def get_tokens(cli):
- return [(Token.A, 'text'), (Token.B, 'text2')]
-
- prompt = DefaultPrompt(get_tokens)
- """
- def __init__(self, get_tokens):
- assert callable(get_tokens)
- self.get_tokens = get_tokens
-
- @classmethod
- def from_message(cls, message='> '):
- """
- Create a default prompt with a static message text.
- """
- assert isinstance(message, text_type)
-
- def get_message_tokens(cli):
- return [(Token.Prompt, message)]
- return cls(get_message_tokens)
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- # Get text before cursor.
- if cli.is_searching:
- before = _get_isearch_tokens(cli)
-
- elif cli.input_processor.arg is not None:
- before = _get_arg_tokens(cli)
-
- else:
- before = self.get_tokens(cli)
-
- # Insert before buffer text.
- shift_position = token_list_len(before)
-
- # Only show the prompt before the first line. For the following lines,
- # only indent using spaces.
- if lineno != 0:
- before = [(Token.Prompt, ' ' * shift_position)]
-
- return Transformation(
- tokens=before + tokens,
- source_to_display=lambda i: i + shift_position,
- display_to_source=lambda i: i - shift_position)
-
- def has_focus(self, cli):
- # Obtain focus when the CLI is searching.
-
- # Usually, when using this `DefaultPrompt`, we don't have a
- # `BufferControl` instance that displays the content of the search
- # buffer. Instead the search text is displayed before the current text.
- # So, we can still show the cursor here, while it's actually not this
- # buffer that's focussed.
- return cli.is_searching
-
-
-def _get_isearch_tokens(cli):
- def before():
- if cli.search_state.direction == IncrementalSearchDirection.BACKWARD:
- text = 'reverse-i-search'
- else:
- text = 'i-search'
-
- return [(Token.Prompt.Search, '(%s)`' % text)]
-
- def text():
- return [(Token.Prompt.Search.Text, cli.buffers[SEARCH_BUFFER].text)]
-
- def after():
- return [(Token.Prompt.Search, '`: ')]
-
- return before() + text() + after()
-
-
-def _get_arg_tokens(cli):
- """
- Tokens for the arg-prompt.
- """
- arg = cli.input_processor.arg
-
- return [
- (Token.Prompt.Arg, '(arg: '),
- (Token.Prompt.Arg.Text, str(arg)),
- (Token.Prompt.Arg, ') '),
- ]
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py
deleted file mode 100644
index 95561f5de7..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py
+++ /dev/null
@@ -1,151 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.cache import FastDictCache
-from prompt_toolkit.token import Token
-from prompt_toolkit.utils import get_cwidth
-
-from collections import defaultdict, namedtuple
-
-__all__ = (
- 'Point',
- 'Size',
- 'Screen',
- 'Char',
-)
-
-
-Point = namedtuple('Point', 'y x')
-Size = namedtuple('Size', 'rows columns')
-
-
-class Char(object):
- """
- Represent a single character in a :class:`.Screen`.
-
- This should be considered immutable.
- """
- __slots__ = ('char', 'token', 'width')
-
- # If we end up having one of these special control sequences in the input string,
- # we should display them as follows:
- # Usually this happens after a "quoted insert".
- display_mappings = {
- '\x00': '^@', # Control space
- '\x01': '^A',
- '\x02': '^B',
- '\x03': '^C',
- '\x04': '^D',
- '\x05': '^E',
- '\x06': '^F',
- '\x07': '^G',
- '\x08': '^H',
- '\x09': '^I',
- '\x0a': '^J',
- '\x0b': '^K',
- '\x0c': '^L',
- '\x0d': '^M',
- '\x0e': '^N',
- '\x0f': '^O',
- '\x10': '^P',
- '\x11': '^Q',
- '\x12': '^R',
- '\x13': '^S',
- '\x14': '^T',
- '\x15': '^U',
- '\x16': '^V',
- '\x17': '^W',
- '\x18': '^X',
- '\x19': '^Y',
- '\x1a': '^Z',
- '\x1b': '^[', # Escape
- '\x1c': '^\\',
- '\x1d': '^]',
- '\x1f': '^_',
- '\x7f': '^?', # Backspace
- }
-
- def __init__(self, char=' ', token=Token):
- # If this character has to be displayed otherwise, take that one.
- char = self.display_mappings.get(char, char)
-
- self.char = char
- self.token = token
-
- # Calculate width. (We always need this, so better to store it directly
- # as a member for performance.)
- self.width = get_cwidth(char)
-
- def __eq__(self, other):
- return self.char == other.char and self.token == other.token
-
- def __ne__(self, other):
- # Not equal: We don't do `not char.__eq__` here, because of the
- # performance of calling yet another function.
- return self.char != other.char or self.token != other.token
-
- def __repr__(self):
- return '%s(%r, %r)' % (self.__class__.__name__, self.char, self.token)
-
-
-_CHAR_CACHE = FastDictCache(Char, size=1000 * 1000)
-Transparent = Token.Transparent
-
-
-class Screen(object):
- """
- Two dimentional buffer of :class:`.Char` instances.
- """
- def __init__(self, default_char=None, initial_width=0, initial_height=0):
- if default_char is None:
- default_char = _CHAR_CACHE[' ', Transparent]
-
- self.data_buffer = defaultdict(lambda: defaultdict(lambda: default_char))
-
- #: Escape sequences to be injected.
- self.zero_width_escapes = defaultdict(lambda: defaultdict(lambda: ''))
-
- #: Position of the cursor.
- self.cursor_position = Point(y=0, x=0)
-
- #: Visibility of the cursor.
- self.show_cursor = True
-
- #: (Optional) Where to position the menu. E.g. at the start of a completion.
- #: (We can't use the cursor position, because we don't want the
- #: completion menu to change its position when we browse through all the
- #: completions.)
- self.menu_position = None
-
- #: Currently used width/height of the screen. This will increase when
- #: data is written to the screen.
- self.width = initial_width or 0
- self.height = initial_height or 0
-
- def replace_all_tokens(self, token):
- """
- For all the characters in the screen. Set the token to the given `token`.
- """
- b = self.data_buffer
-
- for y, row in b.items():
- for x, char in row.items():
- b[y][x] = _CHAR_CACHE[char.char, token]
-
-
-class WritePosition(object):
- def __init__(self, xpos, ypos, width, height, extended_height=None):
- assert height >= 0
- assert extended_height is None or extended_height >= 0
- assert width >= 0
- # xpos and ypos can be negative. (A float can be partially visible.)
-
- self.xpos = xpos
- self.ypos = ypos
- self.width = width
- self.height = height
- self.extended_height = extended_height or height
-
- def __repr__(self):
- return '%s(%r, %r, %r, %r, %r)' % (
- self.__class__.__name__,
- self.xpos, self.ypos, self.width, self.height, self.extended_height)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py
deleted file mode 100644
index 2e77c2fa16..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py
+++ /dev/null
@@ -1,209 +0,0 @@
-from __future__ import unicode_literals
-
-from ..enums import IncrementalSearchDirection
-
-from .processors import BeforeInput
-
-from .lexers import SimpleLexer
-from .dimension import LayoutDimension
-from .controls import BufferControl, TokenListControl, UIControl, UIContent
-from .containers import Window, ConditionalContainer
-from .screen import Char
-from .utils import token_list_len
-from prompt_toolkit.enums import SEARCH_BUFFER, SYSTEM_BUFFER
-from prompt_toolkit.filters import HasFocus, HasArg, HasCompletions, HasValidationError, HasSearch, Always, IsDone
-from prompt_toolkit.token import Token
-
-__all__ = (
- 'TokenListToolbar',
- 'ArgToolbar',
- 'CompletionsToolbar',
- 'SearchToolbar',
- 'SystemToolbar',
- 'ValidationToolbar',
-)
-
-
-class TokenListToolbar(ConditionalContainer):
- def __init__(self, get_tokens, filter=Always(), **kw):
- super(TokenListToolbar, self).__init__(
- content=Window(
- TokenListControl(get_tokens, **kw),
- height=LayoutDimension.exact(1)),
- filter=filter)
-
-
-class SystemToolbarControl(BufferControl):
- def __init__(self):
- token = Token.Toolbar.System
-
- super(SystemToolbarControl, self).__init__(
- buffer_name=SYSTEM_BUFFER,
- default_char=Char(token=token),
- lexer=SimpleLexer(token=token.Text),
- input_processors=[BeforeInput.static('Shell command: ', token)],)
-
-
-class SystemToolbar(ConditionalContainer):
- def __init__(self):
- super(SystemToolbar, self).__init__(
- content=Window(
- SystemToolbarControl(),
- height=LayoutDimension.exact(1)),
- filter=HasFocus(SYSTEM_BUFFER) & ~IsDone())
-
-
-class ArgToolbarControl(TokenListControl):
- def __init__(self):
- def get_tokens(cli):
- arg = cli.input_processor.arg
- if arg == '-':
- arg = '-1'
-
- return [
- (Token.Toolbar.Arg, 'Repeat: '),
- (Token.Toolbar.Arg.Text, arg),
- ]
-
- super(ArgToolbarControl, self).__init__(get_tokens)
-
-
-class ArgToolbar(ConditionalContainer):
- def __init__(self):
- super(ArgToolbar, self).__init__(
- content=Window(
- ArgToolbarControl(),
- height=LayoutDimension.exact(1)),
- filter=HasArg())
-
-
-class SearchToolbarControl(BufferControl):
- """
- :param vi_mode: Display '/' and '?' instead of I-search.
- """
- def __init__(self, vi_mode=False):
- token = Token.Toolbar.Search
-
- def get_before_input(cli):
- if not cli.is_searching:
- text = ''
- elif cli.search_state.direction == IncrementalSearchDirection.BACKWARD:
- text = ('?' if vi_mode else 'I-search backward: ')
- else:
- text = ('/' if vi_mode else 'I-search: ')
-
- return [(token, text)]
-
- super(SearchToolbarControl, self).__init__(
- buffer_name=SEARCH_BUFFER,
- input_processors=[BeforeInput(get_before_input)],
- default_char=Char(token=token),
- lexer=SimpleLexer(token=token.Text))
-
-
-class SearchToolbar(ConditionalContainer):
- def __init__(self, vi_mode=False):
- super(SearchToolbar, self).__init__(
- content=Window(
- SearchToolbarControl(vi_mode=vi_mode),
- height=LayoutDimension.exact(1)),
- filter=HasSearch() & ~IsDone())
-
-
-class CompletionsToolbarControl(UIControl):
- token = Token.Toolbar.Completions
-
- def create_content(self, cli, width, height):
- complete_state = cli.current_buffer.complete_state
- if complete_state:
- completions = complete_state.current_completions
- index = complete_state.complete_index # Can be None!
-
- # Width of the completions without the left/right arrows in the margins.
- content_width = width - 6
-
- # Booleans indicating whether we stripped from the left/right
- cut_left = False
- cut_right = False
-
- # Create Menu content.
- tokens = []
-
- for i, c in enumerate(completions):
- # When there is no more place for the next completion
- if token_list_len(tokens) + len(c.display) >= content_width:
- # If the current one was not yet displayed, page to the next sequence.
- if i <= (index or 0):
- tokens = []
- cut_left = True
- # If the current one is visible, stop here.
- else:
- cut_right = True
- break
-
- tokens.append((self.token.Completion.Current if i == index else self.token.Completion, c.display))
- tokens.append((self.token, ' '))
-
- # Extend/strip until the content width.
- tokens.append((self.token, ' ' * (content_width - token_list_len(tokens))))
- tokens = tokens[:content_width]
-
- # Return tokens
- all_tokens = [
- (self.token, ' '),
- (self.token.Arrow, '<' if cut_left else ' '),
- (self.token, ' '),
- ] + tokens + [
- (self.token, ' '),
- (self.token.Arrow, '>' if cut_right else ' '),
- (self.token, ' '),
- ]
- else:
- all_tokens = []
-
- def get_line(i):
- return all_tokens
-
- return UIContent(get_line=get_line, line_count=1)
-
-
-class CompletionsToolbar(ConditionalContainer):
- def __init__(self, extra_filter=Always()):
- super(CompletionsToolbar, self).__init__(
- content=Window(
- CompletionsToolbarControl(),
- height=LayoutDimension.exact(1)),
- filter=HasCompletions() & ~IsDone() & extra_filter)
-
-
-class ValidationToolbarControl(TokenListControl):
- def __init__(self, show_position=False):
- token = Token.Toolbar.Validation
-
- def get_tokens(cli):
- buffer = cli.current_buffer
-
- if buffer.validation_error:
- row, column = buffer.document.translate_index_to_position(
- buffer.validation_error.cursor_position)
-
- if show_position:
- text = '%s (line=%s column=%s)' % (
- buffer.validation_error.message, row + 1, column + 1)
- else:
- text = buffer.validation_error.message
-
- return [(token, text)]
- else:
- return []
-
- super(ValidationToolbarControl, self).__init__(get_tokens)
-
-
-class ValidationToolbar(ConditionalContainer):
- def __init__(self, show_position=False):
- super(ValidationToolbar, self).__init__(
- content=Window(
- ValidationToolbarControl(show_position=show_position),
- height=LayoutDimension.exact(1)),
- filter=HasValidationError() & ~IsDone())
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py
deleted file mode 100644
index a4fb7ed0f5..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py
+++ /dev/null
@@ -1,181 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.utils import get_cwidth
-from prompt_toolkit.token import Token
-
-__all__ = (
- 'token_list_len',
- 'token_list_width',
- 'token_list_to_text',
- 'explode_tokens',
- 'split_lines',
- 'find_window_for_buffer_name',
-)
-
-
-def token_list_len(tokenlist):
- """
- Return the amount of characters in this token list.
-
- :param tokenlist: List of (token, text) or (token, text, mouse_handler)
- tuples.
- """
- ZeroWidthEscape = Token.ZeroWidthEscape
- return sum(len(item[1]) for item in tokenlist if item[0] != ZeroWidthEscape)
-
-
-def token_list_width(tokenlist):
- """
- Return the character width of this token list.
- (Take double width characters into account.)
-
- :param tokenlist: List of (token, text) or (token, text, mouse_handler)
- tuples.
- """
- ZeroWidthEscape = Token.ZeroWidthEscape
- return sum(get_cwidth(c) for item in tokenlist for c in item[1] if item[0] != ZeroWidthEscape)
-
-
-def token_list_to_text(tokenlist):
- """
- Concatenate all the text parts again.
- """
- ZeroWidthEscape = Token.ZeroWidthEscape
- return ''.join(item[1] for item in tokenlist if item[0] != ZeroWidthEscape)
-
-
-def iter_token_lines(tokenlist):
- """
- Iterator that yields tokenlists for each line.
- """
- line = []
- for token, c in explode_tokens(tokenlist):
- line.append((token, c))
-
- if c == '\n':
- yield line
- line = []
-
- yield line
-
-
-def split_lines(tokenlist):
- """
- Take a single list of (Token, text) tuples and yield one such list for each
- line. Just like str.split, this will yield at least one item.
-
- :param tokenlist: List of (token, text) or (token, text, mouse_handler)
- tuples.
- """
- line = []
-
- for item in tokenlist:
- # For (token, text) tuples.
- if len(item) == 2:
- token, string = item
- parts = string.split('\n')
-
- for part in parts[:-1]:
- if part:
- line.append((token, part))
- yield line
- line = []
-
- line.append((token, parts[-1]))
- # Note that parts[-1] can be empty, and that's fine. It happens
- # in the case of [(Token.SetCursorPosition, '')].
-
- # For (token, text, mouse_handler) tuples.
- # I know, partly copy/paste, but understandable and more efficient
- # than many tests.
- else:
- token, string, mouse_handler = item
- parts = string.split('\n')
-
- for part in parts[:-1]:
- if part:
- line.append((token, part, mouse_handler))
- yield line
- line = []
-
- line.append((token, parts[-1], mouse_handler))
-
- # Always yield the last line, even when this is an empty line. This ensures
- # that when `tokenlist` ends with a newline character, an additional empty
- # line is yielded. (Otherwise, there's no way to differentiate between the
- # cases where `tokenlist` does and doesn't end with a newline.)
- yield line
-
-
-class _ExplodedList(list):
- """
- Wrapper around a list, that marks it as 'exploded'.
-
- As soon as items are added or the list is extended, the new items are
- automatically exploded as well.
- """
- def __init__(self, *a, **kw):
- super(_ExplodedList, self).__init__(*a, **kw)
- self.exploded = True
-
- def append(self, item):
- self.extend([item])
-
- def extend(self, lst):
- super(_ExplodedList, self).extend(explode_tokens(lst))
-
- def insert(self, index, item):
- raise NotImplementedError # TODO
-
- # TODO: When creating a copy() or [:], return also an _ExplodedList.
-
- def __setitem__(self, index, value):
- """
- Ensure that when `(Token, 'long string')` is set, the string will be
- exploded.
- """
- if not isinstance(index, slice):
- index = slice(index, index + 1)
- value = explode_tokens([value])
- super(_ExplodedList, self).__setitem__(index, value)
-
-
-def explode_tokens(tokenlist):
- """
- Turn a list of (token, text) tuples into another list where each string is
- exactly one character.
-
- It should be fine to call this function several times. Calling this on a
- list that is already exploded, is a null operation.
-
- :param tokenlist: List of (token, text) tuples.
- """
- # When the tokenlist is already exploded, don't explode again.
- if getattr(tokenlist, 'exploded', False):
- return tokenlist
-
- result = []
-
- for token, string in tokenlist:
- for c in string:
- result.append((token, c))
-
- return _ExplodedList(result)
-
-
-def find_window_for_buffer_name(cli, buffer_name):
- """
- Look for a :class:`~prompt_toolkit.layout.containers.Window` in the Layout
- that contains the :class:`~prompt_toolkit.layout.controls.BufferControl`
- for the given buffer and return it. If no such Window is found, return None.
- """
- from prompt_toolkit.interface import CommandLineInterface
- assert isinstance(cli, CommandLineInterface)
-
- from .containers import Window
- from .controls import BufferControl
-
- for l in cli.layout.walk(cli):
- if isinstance(l, Window) and isinstance(l.content, BufferControl):
- if l.content.buffer_name == buffer_name:
- return l
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/mouse_events.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/mouse_events.py
deleted file mode 100644
index f42276ce9f..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/mouse_events.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""
-Mouse events.
-
-
-How it works
-------------
-
-The renderer has a 2 dimensional grid of mouse event handlers.
-(`prompt_toolkit.layout.MouseHandlers`.) When the layout is rendered, the
-`Window` class will make sure that this grid will also be filled with
-callbacks. For vt100 terminals, mouse events are received through stdin, just
-like any other key press. There is a handler among the key bindings that
-catches these events and forwards them to such a mouse event handler. It passes
-through the `Window` class where the coordinates are translated from absolute
-coordinates to coordinates relative to the user control, and there
-`UIControl.mouse_handler` is called.
-"""
-from __future__ import unicode_literals
-
-__all__ = (
- 'MouseEventType',
- 'MouseEvent'
-)
-
-
-class MouseEventType:
- MOUSE_UP = 'MOUSE_UP'
- MOUSE_DOWN = 'MOUSE_DOWN'
- SCROLL_UP = 'SCROLL_UP'
- SCROLL_DOWN = 'SCROLL_DOWN'
-
-
-MouseEventTypes = MouseEventType # Deprecated: plural for backwards compatibility.
-
-
-class MouseEvent(object):
- """
- Mouse event, sent to `UIControl.mouse_handler`.
-
- :param position: `Point` instance.
- :param event_type: `MouseEventType`.
- """
- def __init__(self, position, event_type):
- self.position = position
- self.event_type = event_type
-
- def __repr__(self):
- return 'MouseEvent(%r, %r)' % (self.position, self.event_type)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/output.py
deleted file mode 100644
index 072fb0677f..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/output.py
+++ /dev/null
@@ -1,192 +0,0 @@
-"""
-Interface for an output.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-from prompt_toolkit.layout.screen import Size
-
-__all__ = (
- 'Output',
-)
-
-
-class Output(with_metaclass(ABCMeta, object)):
- """
- Base class defining the output interface for a
- :class:`~prompt_toolkit.renderer.Renderer`.
-
- Actual implementations are
- :class:`~prompt_toolkit.terminal.vt100_output.Vt100_Output` and
- :class:`~prompt_toolkit.terminal.win32_output.Win32Output`.
- """
- @abstractmethod
- def fileno(self):
- " Return the file descriptor to which we can write for the output. "
-
- @abstractmethod
- def encoding(self):
- """
- Return the encoding for this output, e.g. 'utf-8'.
- (This is used mainly to know which characters are supported by the
- output the data, so that the UI can provide alternatives, when
- required.)
- """
-
- @abstractmethod
- def write(self, data):
- " Write text (Terminal escape sequences will be removed/escaped.) "
-
- @abstractmethod
- def write_raw(self, data):
- " Write text. "
-
- @abstractmethod
- def set_title(self, title):
- " Set terminal title. "
-
- @abstractmethod
- def clear_title(self):
- " Clear title again. (or restore previous title.) "
-
- @abstractmethod
- def flush(self):
- " Write to output stream and flush. "
-
- @abstractmethod
- def erase_screen(self):
- """
- Erases the screen with the background colour and moves the cursor to
- home.
- """
-
- @abstractmethod
- def enter_alternate_screen(self):
- " Go to the alternate screen buffer. (For full screen applications). "
-
- @abstractmethod
- def quit_alternate_screen(self):
- " Leave the alternate screen buffer. "
-
- @abstractmethod
- def enable_mouse_support(self):
- " Enable mouse. "
-
- @abstractmethod
- def disable_mouse_support(self):
- " Disable mouse. "
-
- @abstractmethod
- def erase_end_of_line(self):
- """
- Erases from the current cursor position to the end of the current line.
- """
-
- @abstractmethod
- def erase_down(self):
- """
- Erases the screen from the current line down to the bottom of the
- screen.
- """
-
- @abstractmethod
- def reset_attributes(self):
- " Reset color and styling attributes. "
-
- @abstractmethod
- def set_attributes(self, attrs):
- " Set new color and styling attributes. "
-
- @abstractmethod
- def disable_autowrap(self):
- " Disable auto line wrapping. "
-
- @abstractmethod
- def enable_autowrap(self):
- " Enable auto line wrapping. "
-
- @abstractmethod
- def cursor_goto(self, row=0, column=0):
- " Move cursor position. "
-
- @abstractmethod
- def cursor_up(self, amount):
- " Move cursor `amount` place up. "
-
- @abstractmethod
- def cursor_down(self, amount):
- " Move cursor `amount` place down. "
-
- @abstractmethod
- def cursor_forward(self, amount):
- " Move cursor `amount` place forward. "
-
- @abstractmethod
- def cursor_backward(self, amount):
- " Move cursor `amount` place backward. "
-
- @abstractmethod
- def hide_cursor(self):
- " Hide cursor. "
-
- @abstractmethod
- def show_cursor(self):
- " Show cursor. "
-
- def ask_for_cpr(self):
- """
- Asks for a cursor position report (CPR).
- (VT100 only.)
- """
-
- def bell(self):
- " Sound bell. "
-
- def enable_bracketed_paste(self):
- " For vt100 only. "
-
- def disable_bracketed_paste(self):
- " For vt100 only. "
-
-
-class DummyOutput(Output):
- """
- For testing. An output class that doesn't render anything.
- """
- def fileno(self):
- " There is no sensible default for fileno(). "
- raise NotImplementedError
-
- def encoding(self):
- return 'utf-8'
-
- def write(self, data): pass
- def write_raw(self, data): pass
- def set_title(self, title): pass
- def clear_title(self): pass
- def flush(self): pass
- def erase_screen(self): pass
- def enter_alternate_screen(self): pass
- def quit_alternate_screen(self): pass
- def enable_mouse_support(self): pass
- def disable_mouse_support(self): pass
- def erase_end_of_line(self): pass
- def erase_down(self): pass
- def reset_attributes(self): pass
- def set_attributes(self, attrs): pass
- def disable_autowrap(self): pass
- def enable_autowrap(self): pass
- def cursor_goto(self, row=0, column=0): pass
- def cursor_up(self, amount): pass
- def cursor_down(self, amount): pass
- def cursor_forward(self, amount): pass
- def cursor_backward(self, amount): pass
- def hide_cursor(self): pass
- def show_cursor(self): pass
- def ask_for_cpr(self): pass
- def bell(self): pass
- def enable_bracketed_paste(self): pass
- def disable_bracketed_paste(self): pass
-
- def get_size(self):
- return Size(rows=40, columns=80)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/reactive.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/reactive.py
deleted file mode 100644
index ec3aa06712..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/reactive.py
+++ /dev/null
@@ -1,56 +0,0 @@
-"""
-Prompt_toolkit is designed a way that the amount of changing state is reduced
-to a minimum. Where possible, code is written in a pure functional way. In
-general, this results in code where the flow is very easy to follow: the value
-of a variable can be deducted from its first assignment.
-
-However, often, practicality and performance beat purity and some classes still
-have a changing state. In order to not having to care too much about
-transferring states between several components we use some reactive
-programming. Actually some kind of data binding.
-
-We introduce two types:
-
-- Filter: for binding a boolean state. They can be chained using & and |
- operators. Have a look in the ``filters`` module. Resolving the actual value
- of a filter happens by calling it.
-
-- Integer: for binding integer values. Reactive operations (like addition and
- substraction) are not suppported. Resolving the actual value happens by
- casting it to int, like ``int(integer)``. This way, it is possible to use
- normal integers as well for static values.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-
-
-class Integer(with_metaclass(ABCMeta, object)):
- """
- Reactive integer -- anything that can be resolved to an ``int``.
- """
- @abstractmethod
- def __int__(self):
- return 0
-
- @classmethod
- def from_callable(cls, func):
- """
- Create an Integer-like object that calls the given function when it is
- resolved to an int.
- """
- return _IntegerFromCallable(func)
-
-
-Integer.register(int)
-
-
-class _IntegerFromCallable(Integer):
- def __init__(self, func=0):
- self.func = func
-
- def __repr__(self):
- return 'Integer.from_callable(%r)' % self.func
-
- def __int__(self):
- return int(self.func())
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py
deleted file mode 100644
index 7a8fde55b3..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py
+++ /dev/null
@@ -1,535 +0,0 @@
-"""
-Renders the command line on the console.
-(Redraws parts of the input line that were changed.)
-"""
-from __future__ import unicode_literals
-
-from prompt_toolkit.filters import to_cli_filter
-from prompt_toolkit.layout.mouse_handlers import MouseHandlers
-from prompt_toolkit.layout.screen import Point, Screen, WritePosition
-from prompt_toolkit.output import Output
-from prompt_toolkit.styles import Style
-from prompt_toolkit.token import Token
-from prompt_toolkit.utils import is_windows
-
-from six.moves import range
-
-__all__ = (
- 'Renderer',
- 'print_tokens',
-)
-
-
-def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_token=None,
- is_done=False, use_alternate_screen=False, attrs_for_token=None, size=None,
- previous_width=0): # XXX: drop is_done
- """
- Render the diff between this screen and the previous screen.
-
- This takes two `Screen` instances. The one that represents the output like
- it was during the last rendering and one that represents the current
- output raster. Looking at these two `Screen` instances, this function will
- render the difference by calling the appropriate methods of the `Output`
- object that only paint the changes to the terminal.
-
- This is some performance-critical code which is heavily optimized.
- Don't change things without profiling first.
-
- :param current_pos: Current cursor position.
- :param last_token: `Token` instance that represents the output attributes of
- the last drawn character. (Color/attributes.)
- :param attrs_for_token: :class:`._TokenToAttrsCache` instance.
- :param width: The width of the terminal.
- :param prevous_width: The width of the terminal during the last rendering.
- """
- width, height = size.columns, size.rows
-
- #: Remember the last printed character.
- last_token = [last_token] # nonlocal
-
- #: Variable for capturing the output.
- write = output.write
- write_raw = output.write_raw
-
- # Create locals for the most used output methods.
- # (Save expensive attribute lookups.)
- _output_set_attributes = output.set_attributes
- _output_reset_attributes = output.reset_attributes
- _output_cursor_forward = output.cursor_forward
- _output_cursor_up = output.cursor_up
- _output_cursor_backward = output.cursor_backward
-
- # Hide cursor before rendering. (Avoid flickering.)
- output.hide_cursor()
-
- def reset_attributes():
- " Wrapper around Output.reset_attributes. "
- _output_reset_attributes()
- last_token[0] = None # Forget last char after resetting attributes.
-
- def move_cursor(new):
- " Move cursor to this `new` point. Returns the given Point. "
- current_x, current_y = current_pos.x, current_pos.y
-
- if new.y > current_y:
- # Use newlines instead of CURSOR_DOWN, because this meight add new lines.
- # CURSOR_DOWN will never create new lines at the bottom.
- # Also reset attributes, otherwise the newline could draw a
- # background color.
- reset_attributes()
- write('\r\n' * (new.y - current_y))
- current_x = 0
- _output_cursor_forward(new.x)
- return new
- elif new.y < current_y:
- _output_cursor_up(current_y - new.y)
-
- if current_x >= width - 1:
- write('\r')
- _output_cursor_forward(new.x)
- elif new.x < current_x or current_x >= width - 1:
- _output_cursor_backward(current_x - new.x)
- elif new.x > current_x:
- _output_cursor_forward(new.x - current_x)
-
- return new
-
- def output_char(char):
- """
- Write the output of this character.
- """
- # If the last printed character has the same token, it also has the
- # same style, so we don't output it.
- the_last_token = last_token[0]
-
- if the_last_token and the_last_token == char.token:
- write(char.char)
- else:
- _output_set_attributes(attrs_for_token[char.token])
- write(char.char)
- last_token[0] = char.token
-
- # Render for the first time: reset styling.
- if not previous_screen:
- reset_attributes()
-
- # Disable autowrap. (When entering a the alternate screen, or anytime when
- # we have a prompt. - In the case of a REPL, like IPython, people can have
- # background threads, and it's hard for debugging if their output is not
- # wrapped.)
- if not previous_screen or not use_alternate_screen:
- output.disable_autowrap()
-
- # When the previous screen has a different size, redraw everything anyway.
- # Also when we are done. (We meight take up less rows, so clearing is important.)
- if is_done or not previous_screen or previous_width != width: # XXX: also consider height??
- current_pos = move_cursor(Point(0, 0))
- reset_attributes()
- output.erase_down()
-
- previous_screen = Screen()
-
- # Get height of the screen.
- # (height changes as we loop over data_buffer, so remember the current value.)
- # (Also make sure to clip the height to the size of the output.)
- current_height = min(screen.height, height)
-
- # Loop over the rows.
- row_count = min(max(screen.height, previous_screen.height), height)
- c = 0 # Column counter.
-
- for y in range(row_count):
- new_row = screen.data_buffer[y]
- previous_row = previous_screen.data_buffer[y]
- zero_width_escapes_row = screen.zero_width_escapes[y]
-
- new_max_line_len = min(width - 1, max(new_row.keys()) if new_row else 0)
- previous_max_line_len = min(width - 1, max(previous_row.keys()) if previous_row else 0)
-
- # Loop over the columns.
- c = 0
- while c < new_max_line_len + 1:
- new_char = new_row[c]
- old_char = previous_row[c]
- char_width = (new_char.width or 1)
-
- # When the old and new character at this position are different,
- # draw the output. (Because of the performance, we don't call
- # `Char.__ne__`, but inline the same expression.)
- if new_char.char != old_char.char or new_char.token != old_char.token:
- current_pos = move_cursor(Point(y=y, x=c))
-
- # Send injected escape sequences to output.
- if c in zero_width_escapes_row:
- write_raw(zero_width_escapes_row[c])
-
- output_char(new_char)
- current_pos = current_pos._replace(x=current_pos.x + char_width)
-
- c += char_width
-
- # If the new line is shorter, trim it.
- if previous_screen and new_max_line_len < previous_max_line_len:
- current_pos = move_cursor(Point(y=y, x=new_max_line_len+1))
- reset_attributes()
- output.erase_end_of_line()
-
- # Correctly reserve vertical space as required by the layout.
- # When this is a new screen (drawn for the first time), or for some reason
- # higher than the previous one. Move the cursor once to the bottom of the
- # output. That way, we're sure that the terminal scrolls up, even when the
- # lower lines of the canvas just contain whitespace.
-
- # The most obvious reason that we actually want this behaviour is the avoid
- # the artifact of the input scrolling when the completion menu is shown.
- # (If the scrolling is actually wanted, the layout can still be build in a
- # way to behave that way by setting a dynamic height.)
- if current_height > previous_screen.height:
- current_pos = move_cursor(Point(y=current_height - 1, x=0))
-
- # Move cursor:
- if is_done:
- current_pos = move_cursor(Point(y=current_height, x=0))
- output.erase_down()
- else:
- current_pos = move_cursor(screen.cursor_position)
-
- if is_done or not use_alternate_screen:
- output.enable_autowrap()
-
- # Always reset the color attributes. This is important because a background
- # thread could print data to stdout and we want that to be displayed in the
- # default colors. (Also, if a background color has been set, many terminals
- # give weird artifacs on resize events.)
- reset_attributes()
-
- if screen.show_cursor or is_done:
- output.show_cursor()
-
- return current_pos, last_token[0]
-
-
-class HeightIsUnknownError(Exception):
- " Information unavailable. Did not yet receive the CPR response. "
-
-
-class _TokenToAttrsCache(dict):
- """
- A cache structure that maps Pygments Tokens to :class:`.Attr`.
- (This is an important speed up.)
- """
- def __init__(self, get_style_for_token):
- self.get_style_for_token = get_style_for_token
-
- def __missing__(self, token):
- try:
- result = self.get_style_for_token(token)
- except KeyError:
- result = None
-
- self[token] = result
- return result
-
-
-class Renderer(object):
- """
- Typical usage:
-
- ::
-
- output = Vt100_Output.from_pty(sys.stdout)
- r = Renderer(style, output)
- r.render(cli, layout=...)
- """
- def __init__(self, style, output, use_alternate_screen=False, mouse_support=False):
- assert isinstance(style, Style)
- assert isinstance(output, Output)
-
- self.style = style
- self.output = output
- self.use_alternate_screen = use_alternate_screen
- self.mouse_support = to_cli_filter(mouse_support)
-
- self._in_alternate_screen = False
- self._mouse_support_enabled = False
- self._bracketed_paste_enabled = False
-
- # Waiting for CPR flag. True when we send the request, but didn't got a
- # response.
- self.waiting_for_cpr = False
-
- self.reset(_scroll=True)
-
- def reset(self, _scroll=False, leave_alternate_screen=True):
- # Reset position
- self._cursor_pos = Point(x=0, y=0)
-
- # Remember the last screen instance between renderers. This way,
- # we can create a `diff` between two screens and only output the
- # difference. It's also to remember the last height. (To show for
- # instance a toolbar at the bottom position.)
- self._last_screen = None
- self._last_size = None
- self._last_token = None
-
- # When the style hash changes, we have to do a full redraw as well as
- # clear the `_attrs_for_token` dictionary.
- self._last_style_hash = None
- self._attrs_for_token = None
-
- # Default MouseHandlers. (Just empty.)
- self.mouse_handlers = MouseHandlers()
-
- # Remember the last title. Only set the title when it changes.
- self._last_title = None
-
- #: Space from the top of the layout, until the bottom of the terminal.
- #: We don't know this until a `report_absolute_cursor_row` call.
- self._min_available_height = 0
-
- # In case of Windown, also make sure to scroll to the current cursor
- # position. (Only when rendering the first time.)
- if is_windows() and _scroll:
- self.output.scroll_buffer_to_prompt()
-
- # Quit alternate screen.
- if self._in_alternate_screen and leave_alternate_screen:
- self.output.quit_alternate_screen()
- self._in_alternate_screen = False
-
- # Disable mouse support.
- if self._mouse_support_enabled:
- self.output.disable_mouse_support()
- self._mouse_support_enabled = False
-
- # Disable bracketed paste.
- if self._bracketed_paste_enabled:
- self.output.disable_bracketed_paste()
- self._bracketed_paste_enabled = False
-
- # Flush output. `disable_mouse_support` needs to write to stdout.
- self.output.flush()
-
- @property
- def height_is_known(self):
- """
- True when the height from the cursor until the bottom of the terminal
- is known. (It's often nicer to draw bottom toolbars only if the height
- is known, in order to avoid flickering when the CPR response arrives.)
- """
- return self.use_alternate_screen or self._min_available_height > 0 or \
- is_windows() # On Windows, we don't have to wait for a CPR.
-
- @property
- def rows_above_layout(self):
- """
- Return the number of rows visible in the terminal above the layout.
- """
- if self._in_alternate_screen:
- return 0
- elif self._min_available_height > 0:
- total_rows = self.output.get_size().rows
- last_screen_height = self._last_screen.height if self._last_screen else 0
- return total_rows - max(self._min_available_height, last_screen_height)
- else:
- raise HeightIsUnknownError('Rows above layout is unknown.')
-
- def request_absolute_cursor_position(self):
- """
- Get current cursor position.
- For vt100: Do CPR request. (answer will arrive later.)
- For win32: Do API call. (Answer comes immediately.)
- """
- # Only do this request when the cursor is at the top row. (after a
- # clear or reset). We will rely on that in `report_absolute_cursor_row`.
- assert self._cursor_pos.y == 0
-
- # For Win32, we have an API call to get the number of rows below the
- # cursor.
- if is_windows():
- self._min_available_height = self.output.get_rows_below_cursor_position()
- else:
- if self.use_alternate_screen:
- self._min_available_height = self.output.get_size().rows
- else:
- # Asks for a cursor position report (CPR).
- self.waiting_for_cpr = True
- self.output.ask_for_cpr()
-
- def report_absolute_cursor_row(self, row):
- """
- To be called when we know the absolute cursor position.
- (As an answer of a "Cursor Position Request" response.)
- """
- # Calculate the amount of rows from the cursor position until the
- # bottom of the terminal.
- total_rows = self.output.get_size().rows
- rows_below_cursor = total_rows - row + 1
-
- # Set the
- self._min_available_height = rows_below_cursor
-
- self.waiting_for_cpr = False
-
- def render(self, cli, layout, is_done=False):
- """
- Render the current interface to the output.
-
- :param is_done: When True, put the cursor at the end of the interface. We
- won't print any changes to this part.
- """
- output = self.output
-
- # Enter alternate screen.
- if self.use_alternate_screen and not self._in_alternate_screen:
- self._in_alternate_screen = True
- output.enter_alternate_screen()
-
- # Enable bracketed paste.
- if not self._bracketed_paste_enabled:
- self.output.enable_bracketed_paste()
- self._bracketed_paste_enabled = True
-
- # Enable/disable mouse support.
- needs_mouse_support = self.mouse_support(cli)
-
- if needs_mouse_support and not self._mouse_support_enabled:
- output.enable_mouse_support()
- self._mouse_support_enabled = True
-
- elif not needs_mouse_support and self._mouse_support_enabled:
- output.disable_mouse_support()
- self._mouse_support_enabled = False
-
- # Create screen and write layout to it.
- size = output.get_size()
- screen = Screen()
- screen.show_cursor = False # Hide cursor by default, unless one of the
- # containers decides to display it.
- mouse_handlers = MouseHandlers()
-
- if is_done:
- height = 0 # When we are done, we don't necessary want to fill up until the bottom.
- else:
- height = self._last_screen.height if self._last_screen else 0
- height = max(self._min_available_height, height)
-
- # When te size changes, don't consider the previous screen.
- if self._last_size != size:
- self._last_screen = None
-
- # When we render using another style, do a full repaint. (Forget about
- # the previous rendered screen.)
- # (But note that we still use _last_screen to calculate the height.)
- if self.style.invalidation_hash() != self._last_style_hash:
- self._last_screen = None
- self._attrs_for_token = None
- if self._attrs_for_token is None:
- self._attrs_for_token = _TokenToAttrsCache(self.style.get_attrs_for_token)
- self._last_style_hash = self.style.invalidation_hash()
-
- layout.write_to_screen(cli, screen, mouse_handlers, WritePosition(
- xpos=0,
- ypos=0,
- width=size.columns,
- height=(size.rows if self.use_alternate_screen else height),
- extended_height=size.rows,
- ))
-
- # When grayed. Replace all tokens in the new screen.
- if cli.is_aborting or cli.is_exiting:
- screen.replace_all_tokens(Token.Aborted)
-
- # Process diff and write to output.
- self._cursor_pos, self._last_token = _output_screen_diff(
- output, screen, self._cursor_pos,
- self._last_screen, self._last_token, is_done,
- use_alternate_screen=self.use_alternate_screen,
- attrs_for_token=self._attrs_for_token,
- size=size,
- previous_width=(self._last_size.columns if self._last_size else 0))
- self._last_screen = screen
- self._last_size = size
- self.mouse_handlers = mouse_handlers
-
- # Write title if it changed.
- new_title = cli.terminal_title
-
- if new_title != self._last_title:
- if new_title is None:
- self.output.clear_title()
- else:
- self.output.set_title(new_title)
- self._last_title = new_title
-
- output.flush()
-
- def erase(self, leave_alternate_screen=True, erase_title=True):
- """
- Hide all output and put the cursor back at the first line. This is for
- instance used for running a system command (while hiding the CLI) and
- later resuming the same CLI.)
-
- :param leave_alternate_screen: When True, and when inside an alternate
- screen buffer, quit the alternate screen.
- :param erase_title: When True, clear the title from the title bar.
- """
- output = self.output
-
- output.cursor_backward(self._cursor_pos.x)
- output.cursor_up(self._cursor_pos.y)
- output.erase_down()
- output.reset_attributes()
- output.enable_autowrap()
- output.flush()
-
- # Erase title.
- if self._last_title and erase_title:
- output.clear_title()
-
- self.reset(leave_alternate_screen=leave_alternate_screen)
-
- def clear(self):
- """
- Clear screen and go to 0,0
- """
- # Erase current output first.
- self.erase()
-
- # Send "Erase Screen" command and go to (0, 0).
- output = self.output
-
- output.erase_screen()
- output.cursor_goto(0, 0)
- output.flush()
-
- self.request_absolute_cursor_position()
-
-
-def print_tokens(output, tokens, style):
- """
- Print a list of (Token, text) tuples in the given style to the output.
- """
- assert isinstance(output, Output)
- assert isinstance(style, Style)
-
- # Reset first.
- output.reset_attributes()
- output.enable_autowrap()
-
- # Print all (token, text) tuples.
- attrs_for_token = _TokenToAttrsCache(style.get_attrs_for_token)
-
- for token, text in tokens:
- attrs = attrs_for_token[token]
-
- if attrs:
- output.set_attributes(attrs)
- else:
- output.reset_attributes()
-
- output.write(text)
-
- # Reset again.
- output.reset_attributes()
- output.flush()
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/search_state.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/search_state.py
deleted file mode 100644
index 3c494ea1a9..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/search_state.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from .enums import IncrementalSearchDirection
-from .filters import to_simple_filter
-
-__all__ = (
- 'SearchState',
-)
-
-
-class SearchState(object):
- """
- A search 'query'.
- """
- __slots__ = ('text', 'direction', 'ignore_case')
-
- def __init__(self, text='', direction=IncrementalSearchDirection.FORWARD, ignore_case=False):
- ignore_case = to_simple_filter(ignore_case)
-
- self.text = text
- self.direction = direction
- self.ignore_case = ignore_case
-
- def __repr__(self):
- return '%s(%r, direction=%r, ignore_case=%r)' % (
- self.__class__.__name__, self.text, self.direction, self.ignore_case)
-
- def __invert__(self):
- """
- Create a new SearchState where backwards becomes forwards and the other
- way around.
- """
- if self.direction == IncrementalSearchDirection.BACKWARD:
- direction = IncrementalSearchDirection.FORWARD
- else:
- direction = IncrementalSearchDirection.BACKWARD
-
- return SearchState(text=self.text, direction=direction, ignore_case=self.ignore_case)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py
deleted file mode 100644
index 6582921222..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py
+++ /dev/null
@@ -1,47 +0,0 @@
-"""
-Data structures for the selection.
-"""
-from __future__ import unicode_literals
-
-__all__ = (
- 'SelectionType',
- 'PasteMode',
- 'SelectionState',
-)
-
-
-class SelectionType(object):
- """
- Type of selection.
- """
- #: Characters. (Visual in Vi.)
- CHARACTERS = 'CHARACTERS'
-
- #: Whole lines. (Visual-Line in Vi.)
- LINES = 'LINES'
-
- #: A block selection. (Visual-Block in Vi.)
- BLOCK = 'BLOCK'
-
-
-class PasteMode(object):
- EMACS = 'EMACS' # Yank like emacs.
- VI_AFTER = 'VI_AFTER' # When pressing 'p' in Vi.
- VI_BEFORE = 'VI_BEFORE' # When pressing 'P' in Vi.
-
-
-class SelectionState(object):
- """
- State of the current selection.
-
- :param original_cursor_position: int
- :param type: :class:`~.SelectionType`
- """
- def __init__(self, original_cursor_position=0, type=SelectionType.CHARACTERS):
- self.original_cursor_position = original_cursor_position
- self.type = type
-
- def __repr__(self):
- return '%s(original_cursor_position=%r, type=%r)' % (
- self.__class__.__name__,
- self.original_cursor_position, self.type)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py
deleted file mode 100644
index 9893624c6e..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py
+++ /dev/null
@@ -1,717 +0,0 @@
-"""
-Shortcuts for retrieving input from the user.
-
-If you are using this library for retrieving some input from the user (as a
-pure Python replacement for GNU readline), probably for 90% of the use cases,
-the :func:`.prompt` function is all you need. It's the easiest shortcut which
-does a lot of the underlying work like creating a
-:class:`~prompt_toolkit.interface.CommandLineInterface` instance for you.
-
-When is this not sufficient:
- - When you want to have more complicated layouts (maybe with sidebars or
- multiple toolbars. Or visibility of certain user interface controls
- according to some conditions.)
- - When you wish to have multiple input buffers. (If you would create an
- editor like a Vi clone.)
- - Something else that requires more customization than what is possible
- with the parameters of `prompt`.
-
-In that case, study the code in this file and build your own
-`CommandLineInterface` instance. It's not too complicated.
-"""
-from __future__ import unicode_literals
-
-from .buffer import Buffer, AcceptAction
-from .document import Document
-from .enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode
-from .filters import IsDone, HasFocus, RendererHeightIsKnown, to_simple_filter, to_cli_filter, Condition
-from .history import InMemoryHistory
-from .interface import CommandLineInterface, Application, AbortAction
-from .key_binding.defaults import load_key_bindings_for_prompt
-from .key_binding.registry import Registry
-from .keys import Keys
-from .layout import Window, HSplit, FloatContainer, Float
-from .layout.containers import ConditionalContainer
-from .layout.controls import BufferControl, TokenListControl
-from .layout.dimension import LayoutDimension
-from .layout.lexers import PygmentsLexer
-from .layout.margins import PromptMargin, ConditionalMargin
-from .layout.menus import CompletionsMenu, MultiColumnCompletionsMenu
-from .layout.processors import PasswordProcessor, ConditionalProcessor, AppendAutoSuggestion, HighlightSearchProcessor, HighlightSelectionProcessor, DisplayMultipleCursors
-from .layout.prompt import DefaultPrompt
-from .layout.screen import Char
-from .layout.toolbars import ValidationToolbar, SystemToolbar, ArgToolbar, SearchToolbar
-from .layout.utils import explode_tokens
-from .renderer import print_tokens as renderer_print_tokens
-from .styles import DEFAULT_STYLE, Style, style_from_dict
-from .token import Token
-from .utils import is_conemu_ansi, is_windows, DummyContext
-
-from six import text_type, exec_, PY2
-
-import os
-import sys
-import textwrap
-import threading
-import time
-
-try:
- from pygments.lexer import Lexer as pygments_Lexer
- from pygments.style import Style as pygments_Style
-except ImportError:
- pygments_Lexer = None
- pygments_Style = None
-
-if is_windows():
- from .terminal.win32_output import Win32Output
- from .terminal.conemu_output import ConEmuOutput
-else:
- from .terminal.vt100_output import Vt100_Output
-
-
-__all__ = (
- 'create_eventloop',
- 'create_output',
- 'create_prompt_layout',
- 'create_prompt_application',
- 'prompt',
- 'prompt_async',
- 'create_confirm_application',
- 'run_application',
- 'confirm',
- 'print_tokens',
- 'clear',
-)
-
-
-def create_eventloop(inputhook=None, recognize_win32_paste=True):
- """
- Create and return an
- :class:`~prompt_toolkit.eventloop.base.EventLoop` instance for a
- :class:`~prompt_toolkit.interface.CommandLineInterface`.
- """
- if is_windows():
- from prompt_toolkit.eventloop.win32 import Win32EventLoop as Loop
- return Loop(inputhook=inputhook, recognize_paste=recognize_win32_paste)
- else:
- from prompt_toolkit.eventloop.posix import PosixEventLoop as Loop
- return Loop(inputhook=inputhook)
-
-
-def create_output(stdout=None, true_color=False, ansi_colors_only=None):
- """
- Return an :class:`~prompt_toolkit.output.Output` instance for the command
- line.
-
- :param true_color: When True, use 24bit colors instead of 256 colors.
- (`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.)
- :param ansi_colors_only: When True, restrict to 16 ANSI colors only.
- (`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.)
- """
- stdout = stdout or sys.__stdout__
- true_color = to_simple_filter(true_color)
-
- if is_windows():
- if is_conemu_ansi():
- return ConEmuOutput(stdout)
- else:
- return Win32Output(stdout)
- else:
- term = os.environ.get('TERM', '')
- if PY2:
- term = term.decode('utf-8')
-
- return Vt100_Output.from_pty(
- stdout, true_color=true_color,
- ansi_colors_only=ansi_colors_only, term=term)
-
-
-def create_asyncio_eventloop(loop=None):
- """
- Returns an asyncio :class:`~prompt_toolkit.eventloop.EventLoop` instance
- for usage in a :class:`~prompt_toolkit.interface.CommandLineInterface`. It
- is a wrapper around an asyncio loop.
-
- :param loop: The asyncio eventloop (or `None` if the default asyncioloop
- should be used.)
- """
- # Inline import, to make sure the rest doesn't break on Python 2. (Where
- # asyncio is not available.)
- if is_windows():
- from prompt_toolkit.eventloop.asyncio_win32 import Win32AsyncioEventLoop as AsyncioEventLoop
- else:
- from prompt_toolkit.eventloop.asyncio_posix import PosixAsyncioEventLoop as AsyncioEventLoop
-
- return AsyncioEventLoop(loop)
-
-
-def _split_multiline_prompt(get_prompt_tokens):
- """
- Take a `get_prompt_tokens` function and return three new functions instead.
- One that tells whether this prompt consists of multiple lines; one that
- returns the tokens to be shown on the lines above the input; and another
- one with the tokens to be shown at the first line of the input.
- """
- def has_before_tokens(cli):
- for token, char in get_prompt_tokens(cli):
- if '\n' in char:
- return True
- return False
-
- def before(cli):
- result = []
- found_nl = False
- for token, char in reversed(explode_tokens(get_prompt_tokens(cli))):
- if found_nl:
- result.insert(0, (token, char))
- elif char == '\n':
- found_nl = True
- return result
-
- def first_input_line(cli):
- result = []
- for token, char in reversed(explode_tokens(get_prompt_tokens(cli))):
- if char == '\n':
- break
- else:
- result.insert(0, (token, char))
- return result
-
- return has_before_tokens, before, first_input_line
-
-
-class _RPrompt(Window):
- " The prompt that is displayed on the right side of the Window. "
- def __init__(self, get_tokens=None):
- get_tokens = get_tokens or (lambda cli: [])
-
- super(_RPrompt, self).__init__(
- TokenListControl(get_tokens, align_right=True))
-
-
-def create_prompt_layout(message='', lexer=None, is_password=False,
- reserve_space_for_menu=8,
- get_prompt_tokens=None, get_continuation_tokens=None,
- get_rprompt_tokens=None,
- get_bottom_toolbar_tokens=None,
- display_completions_in_columns=False,
- extra_input_processors=None, multiline=False,
- wrap_lines=True):
- """
- Create a :class:`.Container` instance for a prompt.
-
- :param message: Text to be used as prompt.
- :param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` to be used for
- the highlighting.
- :param is_password: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
- When True, display input as '*'.
- :param reserve_space_for_menu: Space to be reserved for the menu. When >0,
- make sure that a minimal height is allocated in the terminal, in order
- to display the completion menu.
- :param get_prompt_tokens: An optional callable that returns the tokens to be
- shown in the menu. (To be used instead of a `message`.)
- :param get_continuation_tokens: An optional callable that takes a
- CommandLineInterface and width as input and returns a list of (Token,
- text) tuples to be used for the continuation.
- :param get_bottom_toolbar_tokens: An optional callable that returns the
- tokens for a toolbar at the bottom.
- :param display_completions_in_columns: `bool` or
- :class:`~prompt_toolkit.filters.CLIFilter`. Display the completions in
- multiple columns.
- :param multiline: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
- When True, prefer a layout that is more adapted for multiline input.
- Text after newlines is automatically indented, and search/arg input is
- shown below the input, instead of replacing the prompt.
- :param wrap_lines: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
- When True (the default), automatically wrap long lines instead of
- scrolling horizontally.
- """
- assert isinstance(message, text_type), 'Please provide a unicode string.'
- assert get_bottom_toolbar_tokens is None or callable(get_bottom_toolbar_tokens)
- assert get_prompt_tokens is None or callable(get_prompt_tokens)
- assert get_rprompt_tokens is None or callable(get_rprompt_tokens)
- assert not (message and get_prompt_tokens)
-
- display_completions_in_columns = to_cli_filter(display_completions_in_columns)
- multiline = to_cli_filter(multiline)
-
- if get_prompt_tokens is None:
- get_prompt_tokens = lambda _: [(Token.Prompt, message)]
-
- has_before_tokens, get_prompt_tokens_1, get_prompt_tokens_2 = \
- _split_multiline_prompt(get_prompt_tokens)
-
- # `lexer` is supposed to be a `Lexer` instance. But if a Pygments lexer
- # class is given, turn it into a PygmentsLexer. (Important for
- # backwards-compatibility.)
- try:
- if pygments_Lexer and issubclass(lexer, pygments_Lexer):
- lexer = PygmentsLexer(lexer, sync_from_start=True)
- except TypeError: # Happens when lexer is `None` or an instance of something else.
- pass
-
- # Create processors list.
- input_processors = [
- ConditionalProcessor(
- # By default, only highlight search when the search
- # input has the focus. (Note that this doesn't mean
- # there is no search: the Vi 'n' binding for instance
- # still allows to jump to the next match in
- # navigation mode.)
- HighlightSearchProcessor(preview_search=True),
- HasFocus(SEARCH_BUFFER)),
- HighlightSelectionProcessor(),
- ConditionalProcessor(AppendAutoSuggestion(), HasFocus(DEFAULT_BUFFER) & ~IsDone()),
- ConditionalProcessor(PasswordProcessor(), is_password),
- DisplayMultipleCursors(DEFAULT_BUFFER),
- ]
-
- if extra_input_processors:
- input_processors.extend(extra_input_processors)
-
- # Show the prompt before the input (using the DefaultPrompt processor.
- # This also replaces it with reverse-i-search and 'arg' when required.
- # (Only for single line mode.)
- # (DefaultPrompt should always be at the end of the processors.)
- input_processors.append(ConditionalProcessor(
- DefaultPrompt(get_prompt_tokens_2), ~multiline))
-
- # Create bottom toolbar.
- if get_bottom_toolbar_tokens:
- toolbars = [ConditionalContainer(
- Window(TokenListControl(get_bottom_toolbar_tokens,
- default_char=Char(' ', Token.Toolbar)),
- height=LayoutDimension.exact(1)),
- filter=~IsDone() & RendererHeightIsKnown())]
- else:
- toolbars = []
-
- def get_height(cli):
- # If there is an autocompletion menu to be shown, make sure that our
- # layout has at least a minimal height in order to display it.
- if reserve_space_for_menu and not cli.is_done:
- buff = cli.current_buffer
-
- # Reserve the space, either when there are completions, or when
- # `complete_while_typing` is true and we expect completions very
- # soon.
- if buff.complete_while_typing() or buff.complete_state is not None:
- return LayoutDimension(min=reserve_space_for_menu)
-
- return LayoutDimension()
-
- # Create and return Container instance.
- return HSplit([
- # The main input, with completion menus floating on top of it.
- FloatContainer(
- HSplit([
- ConditionalContainer(
- Window(
- TokenListControl(get_prompt_tokens_1),
- dont_extend_height=True),
- Condition(has_before_tokens)
- ),
- Window(
- BufferControl(
- input_processors=input_processors,
- lexer=lexer,
- # Enable preview_search, we want to have immediate feedback
- # in reverse-i-search mode.
- preview_search=True),
- get_height=get_height,
- left_margins=[
- # In multiline mode, use the window margin to display
- # the prompt and continuation tokens.
- ConditionalMargin(
- PromptMargin(get_prompt_tokens_2, get_continuation_tokens),
- filter=multiline
- )
- ],
- wrap_lines=wrap_lines,
- ),
- ]),
- [
- # Completion menus.
- Float(xcursor=True,
- ycursor=True,
- content=CompletionsMenu(
- max_height=16,
- scroll_offset=1,
- extra_filter=HasFocus(DEFAULT_BUFFER) &
- ~display_completions_in_columns)),
- Float(xcursor=True,
- ycursor=True,
- content=MultiColumnCompletionsMenu(
- extra_filter=HasFocus(DEFAULT_BUFFER) &
- display_completions_in_columns,
- show_meta=True)),
-
- # The right prompt.
- Float(right=0, top=0, hide_when_covering_content=True,
- content=_RPrompt(get_rprompt_tokens)),
- ]
- ),
- ValidationToolbar(),
- SystemToolbar(),
-
- # In multiline mode, we use two toolbars for 'arg' and 'search'.
- ConditionalContainer(ArgToolbar(), multiline),
- ConditionalContainer(SearchToolbar(), multiline),
- ] + toolbars)
-
-
-def create_prompt_application(
- message='',
- multiline=False,
- wrap_lines=True,
- is_password=False,
- vi_mode=False,
- editing_mode=EditingMode.EMACS,
- complete_while_typing=True,
- enable_history_search=False,
- lexer=None,
- enable_system_bindings=False,
- enable_open_in_editor=False,
- validator=None,
- completer=None,
- reserve_space_for_menu=8,
- auto_suggest=None,
- style=None,
- history=None,
- clipboard=None,
- get_prompt_tokens=None,
- get_continuation_tokens=None,
- get_rprompt_tokens=None,
- get_bottom_toolbar_tokens=None,
- display_completions_in_columns=False,
- get_title=None,
- mouse_support=False,
- extra_input_processors=None,
- key_bindings_registry=None,
- on_abort=AbortAction.RAISE_EXCEPTION,
- on_exit=AbortAction.RAISE_EXCEPTION,
- accept_action=AcceptAction.RETURN_DOCUMENT,
- erase_when_done=False,
- default=''):
- """
- Create an :class:`~Application` instance for a prompt.
-
- (It is meant to cover 90% of the prompt use cases, where no extreme
- customization is required. For more complex input, it is required to create
- a custom :class:`~Application` instance.)
-
- :param message: Text to be shown before the prompt.
- :param mulitiline: Allow multiline input. Pressing enter will insert a
- newline. (This requires Meta+Enter to accept the input.)
- :param wrap_lines: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`.
- When True (the default), automatically wrap long lines instead of
- scrolling horizontally.
- :param is_password: Show asterisks instead of the actual typed characters.
- :param editing_mode: ``EditingMode.VI`` or ``EditingMode.EMACS``.
- :param vi_mode: `bool`, if True, Identical to ``editing_mode=EditingMode.VI``.
- :param complete_while_typing: `bool` or
- :class:`~prompt_toolkit.filters.SimpleFilter`. Enable autocompletion
- while typing.
- :param enable_history_search: `bool` or
- :class:`~prompt_toolkit.filters.SimpleFilter`. Enable up-arrow parting
- string matching.
- :param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` to be used for
- the syntax highlighting.
- :param validator: :class:`~prompt_toolkit.validation.Validator` instance
- for input validation.
- :param completer: :class:`~prompt_toolkit.completion.Completer` instance
- for input completion.
- :param reserve_space_for_menu: Space to be reserved for displaying the menu.
- (0 means that no space needs to be reserved.)
- :param auto_suggest: :class:`~prompt_toolkit.auto_suggest.AutoSuggest`
- instance for input suggestions.
- :param style: :class:`.Style` instance for the color scheme.
- :param enable_system_bindings: `bool` or
- :class:`~prompt_toolkit.filters.CLIFilter`. Pressing Meta+'!' will show
- a system prompt.
- :param enable_open_in_editor: `bool` or
- :class:`~prompt_toolkit.filters.CLIFilter`. Pressing 'v' in Vi mode or
- C-X C-E in emacs mode will open an external editor.
- :param history: :class:`~prompt_toolkit.history.History` instance.
- :param clipboard: :class:`~prompt_toolkit.clipboard.base.Clipboard` instance.
- (e.g. :class:`~prompt_toolkit.clipboard.in_memory.InMemoryClipboard`)
- :param get_bottom_toolbar_tokens: Optional callable which takes a
- :class:`~prompt_toolkit.interface.CommandLineInterface` and returns a
- list of tokens for the bottom toolbar.
- :param display_completions_in_columns: `bool` or
- :class:`~prompt_toolkit.filters.CLIFilter`. Display the completions in
- multiple columns.
- :param get_title: Callable that returns the title to be displayed in the
- terminal.
- :param mouse_support: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`
- to enable mouse support.
- :param default: The default text to be shown in the input buffer. (This can
- be edited by the user.)
- """
- if key_bindings_registry is None:
- key_bindings_registry = load_key_bindings_for_prompt(
- enable_system_bindings=enable_system_bindings,
- enable_open_in_editor=enable_open_in_editor)
-
- # Ensure backwards-compatibility, when `vi_mode` is passed.
- if vi_mode:
- editing_mode = EditingMode.VI
-
- # Make sure that complete_while_typing is disabled when enable_history_search
- # is enabled. (First convert to SimpleFilter, to avoid doing bitwise operations
- # on bool objects.)
- complete_while_typing = to_simple_filter(complete_while_typing)
- enable_history_search = to_simple_filter(enable_history_search)
- multiline = to_simple_filter(multiline)
-
- complete_while_typing = complete_while_typing & ~enable_history_search
-
- # Accept Pygments styles as well for backwards compatibility.
- try:
- if pygments_Style and issubclass(style, pygments_Style):
- style = style_from_dict(style.styles)
- except TypeError: # Happens when style is `None` or an instance of something else.
- pass
-
- # Create application
- return Application(
- layout=create_prompt_layout(
- message=message,
- lexer=lexer,
- is_password=is_password,
- reserve_space_for_menu=(reserve_space_for_menu if completer is not None else 0),
- multiline=Condition(lambda cli: multiline()),
- get_prompt_tokens=get_prompt_tokens,
- get_continuation_tokens=get_continuation_tokens,
- get_rprompt_tokens=get_rprompt_tokens,
- get_bottom_toolbar_tokens=get_bottom_toolbar_tokens,
- display_completions_in_columns=display_completions_in_columns,
- extra_input_processors=extra_input_processors,
- wrap_lines=wrap_lines),
- buffer=Buffer(
- enable_history_search=enable_history_search,
- complete_while_typing=complete_while_typing,
- is_multiline=multiline,
- history=(history or InMemoryHistory()),
- validator=validator,
- completer=completer,
- auto_suggest=auto_suggest,
- accept_action=accept_action,
- initial_document=Document(default),
- ),
- style=style or DEFAULT_STYLE,
- clipboard=clipboard,
- key_bindings_registry=key_bindings_registry,
- get_title=get_title,
- mouse_support=mouse_support,
- editing_mode=editing_mode,
- erase_when_done=erase_when_done,
- reverse_vi_search_direction=True,
- on_abort=on_abort,
- on_exit=on_exit)
-
-
-def prompt(message='', **kwargs):
- """
- Get input from the user and return it.
-
- This is a wrapper around a lot of ``prompt_toolkit`` functionality and can
- be a replacement for `raw_input`. (or GNU readline.)
-
- If you want to keep your history across several calls, create one
- :class:`~prompt_toolkit.history.History` instance and pass it every time.
-
- This function accepts many keyword arguments. Except for the following,
- they are a proxy to the arguments of :func:`.create_prompt_application`.
-
- :param patch_stdout: Replace ``sys.stdout`` by a proxy that ensures that
- print statements from other threads won't destroy the prompt. (They
- will be printed above the prompt instead.)
- :param return_asyncio_coroutine: When True, return a asyncio coroutine. (Python >3.3)
- :param true_color: When True, use 24bit colors instead of 256 colors.
- :param refresh_interval: (number; in seconds) When given, refresh the UI
- every so many seconds.
- """
- patch_stdout = kwargs.pop('patch_stdout', False)
- return_asyncio_coroutine = kwargs.pop('return_asyncio_coroutine', False)
- true_color = kwargs.pop('true_color', False)
- refresh_interval = kwargs.pop('refresh_interval', 0)
- eventloop = kwargs.pop('eventloop', None)
-
- application = create_prompt_application(message, **kwargs)
-
- return run_application(application,
- patch_stdout=patch_stdout,
- return_asyncio_coroutine=return_asyncio_coroutine,
- true_color=true_color,
- refresh_interval=refresh_interval,
- eventloop=eventloop)
-
-
-def run_application(
- application, patch_stdout=False, return_asyncio_coroutine=False,
- true_color=False, refresh_interval=0, eventloop=None):
- """
- Run a prompt toolkit application.
-
- :param patch_stdout: Replace ``sys.stdout`` by a proxy that ensures that
- print statements from other threads won't destroy the prompt. (They
- will be printed above the prompt instead.)
- :param return_asyncio_coroutine: When True, return a asyncio coroutine. (Python >3.3)
- :param true_color: When True, use 24bit colors instead of 256 colors.
- :param refresh_interval: (number; in seconds) When given, refresh the UI
- every so many seconds.
- """
- assert isinstance(application, Application)
-
- if return_asyncio_coroutine:
- eventloop = create_asyncio_eventloop()
- else:
- eventloop = eventloop or create_eventloop()
-
- # Create CommandLineInterface.
- cli = CommandLineInterface(
- application=application,
- eventloop=eventloop,
- output=create_output(true_color=true_color))
-
- # Set up refresh interval.
- if refresh_interval:
- done = [False]
- def start_refresh_loop(cli):
- def run():
- while not done[0]:
- time.sleep(refresh_interval)
- cli.request_redraw()
- t = threading.Thread(target=run)
- t.daemon = True
- t.start()
-
- def stop_refresh_loop(cli):
- done[0] = True
-
- cli.on_start += start_refresh_loop
- cli.on_stop += stop_refresh_loop
-
- # Replace stdout.
- patch_context = cli.patch_stdout_context(raw=True) if patch_stdout else DummyContext()
-
- # Read input and return it.
- if return_asyncio_coroutine:
- # Create an asyncio coroutine and call it.
- exec_context = {'patch_context': patch_context, 'cli': cli,
- 'Document': Document}
- exec_(textwrap.dedent('''
- def prompt_coro():
- # Inline import, because it slows down startup when asyncio is not
- # needed.
- import asyncio
-
- @asyncio.coroutine
- def run():
- with patch_context:
- result = yield from cli.run_async()
-
- if isinstance(result, Document): # Backwards-compatibility.
- return result.text
- return result
- return run()
- '''), exec_context)
-
- return exec_context['prompt_coro']()
- else:
- try:
- with patch_context:
- result = cli.run()
-
- if isinstance(result, Document): # Backwards-compatibility.
- return result.text
- return result
- finally:
- eventloop.close()
-
-
-def prompt_async(message='', **kwargs):
- """
- Similar to :func:`.prompt`, but return an asyncio coroutine instead.
- """
- kwargs['return_asyncio_coroutine'] = True
- return prompt(message, **kwargs)
-
-
-def create_confirm_application(message):
- """
- Create a confirmation `Application` that returns True/False.
- """
- registry = Registry()
-
- @registry.add_binding('y')
- @registry.add_binding('Y')
- def _(event):
- event.cli.buffers[DEFAULT_BUFFER].text = 'y'
- event.cli.set_return_value(True)
-
- @registry.add_binding('n')
- @registry.add_binding('N')
- @registry.add_binding(Keys.ControlC)
- def _(event):
- event.cli.buffers[DEFAULT_BUFFER].text = 'n'
- event.cli.set_return_value(False)
-
- return create_prompt_application(message, key_bindings_registry=registry)
-
-
-def confirm(message='Confirm (y or n) '):
- """
- Display a confirmation prompt.
- """
- assert isinstance(message, text_type)
-
- app = create_confirm_application(message)
- return run_application(app)
-
-
-def print_tokens(tokens, style=None, true_color=False, file=None):
- """
- Print a list of (Token, text) tuples in the given style to the output.
- E.g.::
-
- style = style_from_dict({
- Token.Hello: '#ff0066',
- Token.World: '#884444 italic',
- })
- tokens = [
- (Token.Hello, 'Hello'),
- (Token.World, 'World'),
- ]
- print_tokens(tokens, style=style)
-
- :param tokens: List of ``(Token, text)`` tuples.
- :param style: :class:`.Style` instance for the color scheme.
- :param true_color: When True, use 24bit colors instead of 256 colors.
- :param file: The output file. This can be `sys.stdout` or `sys.stderr`.
- """
- if style is None:
- style = DEFAULT_STYLE
- assert isinstance(style, Style)
-
- output = create_output(true_color=true_color, stdout=file)
- renderer_print_tokens(output, tokens, style)
-
-
-def clear():
- """
- Clear the screen.
- """
- out = create_output()
- out.erase_screen()
- out.cursor_goto(0, 0)
- out.flush()
-
-
-# Deprecated alias for `prompt`.
-get_input = prompt
-# Deprecated alias for create_prompt_layout
-create_default_layout = create_prompt_layout
-# Deprecated alias for create_prompt_application
-create_default_application = create_prompt_application
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/__init__.py
deleted file mode 100644
index 9d641f0447..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""
-Styling for prompt_toolkit applications.
-"""
-from __future__ import unicode_literals
-
-from .base import *
-from .defaults import *
-from .from_dict import *
-from .from_pygments import *
-from .utils import *
-
-
-#: The default built-in style.
-#: (For backwards compatibility, when Pygments is installed, this includes the
-#: default Pygments style.)
-try:
- import pygments
-except ImportError:
- DEFAULT_STYLE = style_from_dict(DEFAULT_STYLE_EXTENSIONS)
-else:
- DEFAULT_STYLE = style_from_pygments()
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/base.py
deleted file mode 100644
index e9ddaa524d..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/base.py
+++ /dev/null
@@ -1,86 +0,0 @@
-"""
-The base classes for the styling.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from collections import namedtuple
-from six import with_metaclass
-
-__all__ = (
- 'Attrs',
- 'DEFAULT_ATTRS',
- 'ANSI_COLOR_NAMES',
- 'Style',
- 'DynamicStyle',
-)
-
-
-#: Style attributes.
-Attrs = namedtuple('Attrs', 'color bgcolor bold underline italic blink reverse')
-"""
-:param color: Hexadecimal string. E.g. '000000' or Ansi color name: e.g. 'ansiblue'
-:param bgcolor: Hexadecimal string. E.g. 'ffffff' or Ansi color name: e.g. 'ansired'
-:param bold: Boolean
-:param underline: Boolean
-:param italic: Boolean
-:param blink: Boolean
-:param reverse: Boolean
-"""
-
-#: The default `Attrs`.
-DEFAULT_ATTRS = Attrs(color=None, bgcolor=None, bold=False, underline=False,
- italic=False, blink=False, reverse=False)
-
-
-#: ``Attrs.bgcolor/fgcolor`` can be in either 'ffffff' format, or can be any of
-#: the following in case we want to take colors from the 8/16 color palette.
-#: Usually, in that case, the terminal application allows to configure the RGB
-#: values for these names.
-ANSI_COLOR_NAMES = [
- 'ansiblack', 'ansiwhite', 'ansidefault',
-
- # Low intensity.
- 'ansired', 'ansigreen', 'ansiyellow', 'ansiblue', 'ansifuchsia', 'ansiturquoise', 'ansilightgray',
-
- # High intensity. (Not supported everywhere.)
- 'ansidarkgray', 'ansidarkred', 'ansidarkgreen', 'ansibrown', 'ansidarkblue',
- 'ansipurple', 'ansiteal',
-]
-
-
-class Style(with_metaclass(ABCMeta, object)):
- """
- Abstract base class for prompt_toolkit styles.
- """
- @abstractmethod
- def get_attrs_for_token(self, token):
- """
- Return :class:`.Attrs` for the given token.
- """
-
- @abstractmethod
- def invalidation_hash(self):
- """
- Invalidation hash for the style. When this changes over time, the
- renderer knows that something in the style changed, and that everything
- has to be redrawn.
- """
-
-
-class DynamicStyle(Style):
- """
- Style class that can dynamically returns an other Style.
-
- :param get_style: Callable that returns a :class:`.Style` instance.
- """
- def __init__(self, get_style):
- self.get_style = get_style
-
- def get_attrs_for_token(self, token):
- style = self.get_style()
- assert isinstance(style, Style)
-
- return style.get_attrs_for_token(token)
-
- def invalidation_hash(self):
- return self.get_style().invalidation_hash()
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/defaults.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/defaults.py
deleted file mode 100644
index 5357eaa111..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/defaults.py
+++ /dev/null
@@ -1,95 +0,0 @@
-"""
-The default styling.
-"""
-from __future__ import unicode_literals
-
-from prompt_toolkit.token import Token
-
-__all__ = (
- 'DEFAULT_STYLE_EXTENSIONS',
- 'default_style_extensions',
-)
-
-
-#: Styling of prompt-toolkit specific tokens, that are not know by the default
-#: Pygments style.
-DEFAULT_STYLE_EXTENSIONS = {
- # Highlighting of search matches in document.
- Token.SearchMatch: 'noinherit reverse',
- Token.SearchMatch.Current: 'noinherit #ffffff bg:#448844 underline',
-
- # Highlighting of select text in document.
- Token.SelectedText: 'reverse',
-
- Token.CursorColumn: 'bg:#dddddd',
- Token.CursorLine: 'underline',
- Token.ColorColumn: 'bg:#ccaacc',
-
- # Highlighting of matching brackets.
- Token.MatchingBracket: '',
- Token.MatchingBracket.Other: '#000000 bg:#aacccc',
- Token.MatchingBracket.Cursor: '#ff8888 bg:#880000',
-
- Token.MultipleCursors.Cursor: '#000000 bg:#ccccaa',
-
- # Line numbers.
- Token.LineNumber: '#888888',
- Token.LineNumber.Current: 'bold',
- Token.Tilde: '#8888ff',
-
- # Default prompt.
- Token.Prompt: '',
- Token.Prompt.Arg: 'noinherit',
- Token.Prompt.Search: 'noinherit',
- Token.Prompt.Search.Text: '',
-
- # Search toolbar.
- Token.Toolbar.Search: 'bold',
- Token.Toolbar.Search.Text: 'nobold',
-
- # System toolbar
- Token.Toolbar.System: 'bold',
- Token.Toolbar.System.Text: 'nobold',
-
- # "arg" toolbar.
- Token.Toolbar.Arg: 'bold',
- Token.Toolbar.Arg.Text: 'nobold',
-
- # Validation toolbar.
- Token.Toolbar.Validation: 'bg:#550000 #ffffff',
- Token.WindowTooSmall: 'bg:#550000 #ffffff',
-
- # Completions toolbar.
- Token.Toolbar.Completions: 'bg:#bbbbbb #000000',
- Token.Toolbar.Completions.Arrow: 'bg:#bbbbbb #000000 bold',
- Token.Toolbar.Completions.Completion: 'bg:#bbbbbb #000000',
- Token.Toolbar.Completions.Completion.Current: 'bg:#444444 #ffffff',
-
- # Completions menu.
- Token.Menu.Completions: 'bg:#bbbbbb #000000',
- Token.Menu.Completions.Completion: '',
- Token.Menu.Completions.Completion.Current: 'bg:#888888 #ffffff',
- Token.Menu.Completions.Meta: 'bg:#999999 #000000',
- Token.Menu.Completions.Meta.Current: 'bg:#aaaaaa #000000',
- Token.Menu.Completions.MultiColumnMeta: 'bg:#aaaaaa #000000',
-
- # Scrollbars.
- Token.Scrollbar: 'bg:#888888',
- Token.Scrollbar.Button: 'bg:#444444',
- Token.Scrollbar.Arrow: 'bg:#222222 #888888 bold',
-
- # Auto suggestion text.
- Token.AutoSuggestion: '#666666',
-
- # Trailing whitespace and tabs.
- Token.TrailingWhiteSpace: '#999999',
- Token.Tab: '#999999',
-
- # When Control-C has been pressed. Grayed.
- Token.Aborted: '#888888',
-
- # Entering a Vi digraph.
- Token.Digraph: '#4444ff',
-}
-
-default_style_extensions = DEFAULT_STYLE_EXTENSIONS # Old name.
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_dict.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_dict.py
deleted file mode 100644
index b50325710f..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_dict.py
+++ /dev/null
@@ -1,151 +0,0 @@
-"""
-Tool for creating styles from a dictionary.
-
-This is very similar to the Pygments style dictionary, with some additions:
-- Support for reverse and blink.
-- Support for ANSI color names. (These will map directly to the 16 terminal
- colors.)
-"""
-try:
- from collections.abc import Mapping
-except ImportError:
- from collections import Mapping
-
-from .base import Style, DEFAULT_ATTRS, ANSI_COLOR_NAMES
-from .defaults import DEFAULT_STYLE_EXTENSIONS
-from .utils import merge_attrs, split_token_in_parts
-from six.moves import range
-
-__all__ = (
- 'style_from_dict',
-)
-
-
-def _colorformat(text):
- """
- Parse/validate color format.
-
- Like in Pygments, but also support the ANSI color names.
- (These will map to the colors of the 16 color palette.)
- """
- if text[0:1] == '#':
- col = text[1:]
- if col in ANSI_COLOR_NAMES:
- return col
- elif len(col) == 6:
- return col
- elif len(col) == 3:
- return col[0]*2 + col[1]*2 + col[2]*2
- elif text == '':
- return text
-
- raise ValueError('Wrong color format %r' % text)
-
-
-def style_from_dict(style_dict, include_defaults=True):
- """
- Create a ``Style`` instance from a dictionary or other mapping.
-
- The dictionary is equivalent to the ``Style.styles`` dictionary from
- pygments, with a few additions: it supports 'reverse' and 'blink'.
-
- Usage::
-
- style_from_dict({
- Token: '#ff0000 bold underline',
- Token.Title: 'blink',
- Token.SomethingElse: 'reverse',
- })
-
- :param include_defaults: Include the defaults (built-in) styling for
- selected text, etc...)
- """
- assert isinstance(style_dict, Mapping)
-
- if include_defaults:
- s2 = {}
- s2.update(DEFAULT_STYLE_EXTENSIONS)
- s2.update(style_dict)
- style_dict = s2
-
- # Expand token inheritance and turn style description into Attrs.
- token_to_attrs = {}
-
- # (Loop through the tokens in order. Sorting makes sure that
- # we process the parent first.)
- for ttype, styledef in sorted(style_dict.items()):
- # Start from parent Attrs or default Attrs.
- attrs = DEFAULT_ATTRS
-
- if 'noinherit' not in styledef:
- for i in range(1, len(ttype) + 1):
- try:
- attrs = token_to_attrs[ttype[:-i]]
- except KeyError:
- pass
- else:
- break
-
- # Now update with the given attributes.
- for part in styledef.split():
- if part == 'noinherit':
- pass
- elif part == 'bold':
- attrs = attrs._replace(bold=True)
- elif part == 'nobold':
- attrs = attrs._replace(bold=False)
- elif part == 'italic':
- attrs = attrs._replace(italic=True)
- elif part == 'noitalic':
- attrs = attrs._replace(italic=False)
- elif part == 'underline':
- attrs = attrs._replace(underline=True)
- elif part == 'nounderline':
- attrs = attrs._replace(underline=False)
-
- # prompt_toolkit extensions. Not in Pygments.
- elif part == 'blink':
- attrs = attrs._replace(blink=True)
- elif part == 'noblink':
- attrs = attrs._replace(blink=False)
- elif part == 'reverse':
- attrs = attrs._replace(reverse=True)
- elif part == 'noreverse':
- attrs = attrs._replace(reverse=False)
-
- # Pygments properties that we ignore.
- elif part in ('roman', 'sans', 'mono'):
- pass
- elif part.startswith('border:'):
- pass
-
- # Colors.
-
- elif part.startswith('bg:'):
- attrs = attrs._replace(bgcolor=_colorformat(part[3:]))
- else:
- attrs = attrs._replace(color=_colorformat(part))
-
- token_to_attrs[ttype] = attrs
-
- return _StyleFromDict(token_to_attrs)
-
-
-class _StyleFromDict(Style):
- """
- Turn a dictionary that maps `Token` to `Attrs` into a style class.
-
- :param token_to_attrs: Dictionary that maps `Token` to `Attrs`.
- """
- def __init__(self, token_to_attrs):
- self.token_to_attrs = token_to_attrs
-
- def get_attrs_for_token(self, token):
- # Split Token.
- list_of_attrs = []
- for token in split_token_in_parts(token):
- list_of_attrs.append(self.token_to_attrs.get(token, DEFAULT_ATTRS))
- return merge_attrs(list_of_attrs)
-
- def invalidation_hash(self):
- return id(self.token_to_attrs)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_pygments.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_pygments.py
deleted file mode 100644
index 0af8c53cf2..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_pygments.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""
-Adaptor for building prompt_toolkit styles, starting from a Pygments style.
-
-Usage::
-
- from pygments.styles.tango import TangoStyle
- style = style_from_pygments(pygments_style_cls=TangoStyle)
-"""
-from __future__ import unicode_literals
-
-from .base import Style
-from .from_dict import style_from_dict
-
-__all__ = (
- 'PygmentsStyle',
- 'style_from_pygments',
-)
-
-
-# Following imports are only needed when a ``PygmentsStyle`` class is used.
-try:
- from pygments.style import Style as pygments_Style
- from pygments.styles.default import DefaultStyle as pygments_DefaultStyle
-except ImportError:
- pygments_Style = None
- pygments_DefaultStyle = None
-
-
-def style_from_pygments(style_cls=pygments_DefaultStyle,
- style_dict=None,
- include_defaults=True):
- """
- Shortcut to create a :class:`.Style` instance from a Pygments style class
- and a style dictionary.
-
- Example::
-
- from prompt_toolkit.styles.from_pygments import style_from_pygments
- from pygments.styles import get_style_by_name
- style = style_from_pygments(get_style_by_name('monokai'))
-
- :param style_cls: Pygments style class to start from.
- :param style_dict: Dictionary for this style. `{Token: style}`.
- :param include_defaults: (`bool`) Include prompt_toolkit extensions.
- """
- assert style_dict is None or isinstance(style_dict, dict)
- assert style_cls is None or issubclass(style_cls, pygments_Style)
-
- styles_dict = {}
-
- if style_cls is not None:
- styles_dict.update(style_cls.styles)
-
- if style_dict is not None:
- styles_dict.update(style_dict)
-
- return style_from_dict(styles_dict, include_defaults=include_defaults)
-
-
-class PygmentsStyle(Style):
- " Deprecated. "
- def __new__(cls, pygments_style_cls):
- assert issubclass(pygments_style_cls, pygments_Style)
- return style_from_dict(pygments_style_cls.styles)
-
- def invalidation_hash(self):
- pass
-
- @classmethod
- def from_defaults(cls, style_dict=None,
- pygments_style_cls=pygments_DefaultStyle,
- include_extensions=True):
- " Deprecated. "
- return style_from_pygments(
- style_cls=pygments_style_cls,
- style_dict=style_dict,
- include_defaults=include_extensions)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/utils.py
deleted file mode 100644
index 6087e76abe..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/utils.py
+++ /dev/null
@@ -1,45 +0,0 @@
-from __future__ import unicode_literals
-from .base import DEFAULT_ATTRS, Attrs
-
-__all__ = (
- 'split_token_in_parts',
- 'merge_attrs',
-)
-
-
-def split_token_in_parts(token):
- """
- Take a Token, and turn it in a list of tokens, by splitting
- it on ':' (taking that as a separator.)
- """
- result = []
- current = []
- for part in token + (':', ):
- if part == ':':
- if current:
- result.append(tuple(current))
- current = []
- else:
- current.append(part)
-
- return result
-
-
-def merge_attrs(list_of_attrs):
- """
- Take a list of :class:`.Attrs` instances and merge them into one.
- Every `Attr` in the list can override the styling of the previous one.
- """
- result = DEFAULT_ATTRS
-
- for attr in list_of_attrs:
- result = Attrs(
- color=attr.color or result.color,
- bgcolor=attr.bgcolor or result.bgcolor,
- bold=attr.bold or result.bold,
- underline=attr.underline or result.underline,
- italic=attr.italic or result.italic,
- blink=attr.blink or result.blink,
- reverse=attr.reverse or result.reverse)
-
- return result
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/__init__.py
+++ /dev/null
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py
deleted file mode 100644
index 16b7bde8f3..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.renderer import Output
-
-from .win32_output import Win32Output
-from .vt100_output import Vt100_Output
-
-__all__ = (
- 'ConEmuOutput',
-)
-
-
-class ConEmuOutput(object):
- """
- ConEmu (Windows) output abstraction.
-
- ConEmu is a Windows console application, but it also supports ANSI escape
- sequences. This output class is actually a proxy to both `Win32Output` and
- `Vt100_Output`. It uses `Win32Output` for console sizing and scrolling, but
- all cursor movements and scrolling happens through the `Vt100_Output`.
-
- This way, we can have 256 colors in ConEmu and Cmder. Rendering will be
- even a little faster as well.
-
- http://conemu.github.io/
- http://gooseberrycreative.com/cmder/
- """
- def __init__(self, stdout):
- self.win32_output = Win32Output(stdout)
- self.vt100_output = Vt100_Output(stdout, lambda: None)
-
- def __getattr__(self, name):
- if name in ('get_size', 'get_rows_below_cursor_position',
- 'enable_mouse_support', 'disable_mouse_support',
- 'scroll_buffer_to_prompt', 'get_win32_screen_buffer_info',
- 'enable_bracketed_paste', 'disable_bracketed_paste'):
- return getattr(self.win32_output, name)
- else:
- return getattr(self.vt100_output, name)
-
-
-Output.register(ConEmuOutput)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py
deleted file mode 100644
index 74841312fa..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py
+++ /dev/null
@@ -1,520 +0,0 @@
-"""
-Parser for VT100 input stream.
-"""
-from __future__ import unicode_literals
-
-import os
-import re
-import six
-import termios
-import tty
-
-from six.moves import range
-
-from ..keys import Keys
-from ..key_binding.input_processor import KeyPress
-
-__all__ = (
- 'InputStream',
- 'raw_mode',
- 'cooked_mode',
-)
-
-_DEBUG_RENDERER_INPUT = False
-_DEBUG_RENDERER_INPUT_FILENAME = 'prompt-toolkit-render-input.log'
-
-
-# Regex matching any CPR response
-# (Note that we use '\Z' instead of '$', because '$' could include a trailing
-# newline.)
-_cpr_response_re = re.compile('^' + re.escape('\x1b[') + r'\d+;\d+R\Z')
-
-# Mouse events:
-# Typical: "Esc[MaB*" Urxvt: "Esc[96;14;13M" and for Xterm SGR: "Esc[<64;85;12M"
-_mouse_event_re = re.compile('^' + re.escape('\x1b[') + r'(<?[\d;]+[mM]|M...)\Z')
-
-# Regex matching any valid prefix of a CPR response.
-# (Note that it doesn't contain the last character, the 'R'. The prefix has to
-# be shorter.)
-_cpr_response_prefix_re = re.compile('^' + re.escape('\x1b[') + r'[\d;]*\Z')
-
-_mouse_event_prefix_re = re.compile('^' + re.escape('\x1b[') + r'(<?[\d;]*|M.{0,2})\Z')
-
-
-class _Flush(object):
- """ Helper object to indicate flush operation to the parser. """
- pass
-
-
-# Mapping of vt100 escape codes to Keys.
-ANSI_SEQUENCES = {
- '\x1b': Keys.Escape,
-
- '\x00': Keys.ControlSpace, # Control-Space (Also for Ctrl-@)
- '\x01': Keys.ControlA, # Control-A (home)
- '\x02': Keys.ControlB, # Control-B (emacs cursor left)
- '\x03': Keys.ControlC, # Control-C (interrupt)
- '\x04': Keys.ControlD, # Control-D (exit)
- '\x05': Keys.ControlE, # Contrel-E (end)
- '\x06': Keys.ControlF, # Control-F (cursor forward)
- '\x07': Keys.ControlG, # Control-G
- '\x08': Keys.ControlH, # Control-H (8) (Identical to '\b')
- '\x09': Keys.ControlI, # Control-I (9) (Identical to '\t')
- '\x0a': Keys.ControlJ, # Control-J (10) (Identical to '\n')
- '\x0b': Keys.ControlK, # Control-K (delete until end of line; vertical tab)
- '\x0c': Keys.ControlL, # Control-L (clear; form feed)
- '\x0d': Keys.ControlM, # Control-M (13) (Identical to '\r')
- '\x0e': Keys.ControlN, # Control-N (14) (history forward)
- '\x0f': Keys.ControlO, # Control-O (15)
- '\x10': Keys.ControlP, # Control-P (16) (history back)
- '\x11': Keys.ControlQ, # Control-Q
- '\x12': Keys.ControlR, # Control-R (18) (reverse search)
- '\x13': Keys.ControlS, # Control-S (19) (forward search)
- '\x14': Keys.ControlT, # Control-T
- '\x15': Keys.ControlU, # Control-U
- '\x16': Keys.ControlV, # Control-V
- '\x17': Keys.ControlW, # Control-W
- '\x18': Keys.ControlX, # Control-X
- '\x19': Keys.ControlY, # Control-Y (25)
- '\x1a': Keys.ControlZ, # Control-Z
-
- '\x1c': Keys.ControlBackslash, # Both Control-\ and Ctrl-|
- '\x1d': Keys.ControlSquareClose, # Control-]
- '\x1e': Keys.ControlCircumflex, # Control-^
- '\x1f': Keys.ControlUnderscore, # Control-underscore (Also for Ctrl-hypen.)
- '\x7f': Keys.Backspace, # (127) Backspace
- '\x1b[A': Keys.Up,
- '\x1b[B': Keys.Down,
- '\x1b[C': Keys.Right,
- '\x1b[D': Keys.Left,
- '\x1b[H': Keys.Home,
- '\x1bOH': Keys.Home,
- '\x1b[F': Keys.End,
- '\x1bOF': Keys.End,
- '\x1b[3~': Keys.Delete,
- '\x1b[3;2~': Keys.ShiftDelete, # xterm, gnome-terminal.
- '\x1b[3;5~': Keys.ControlDelete, # xterm, gnome-terminal.
- '\x1b[1~': Keys.Home, # tmux
- '\x1b[4~': Keys.End, # tmux
- '\x1b[5~': Keys.PageUp,
- '\x1b[6~': Keys.PageDown,
- '\x1b[7~': Keys.Home, # xrvt
- '\x1b[8~': Keys.End, # xrvt
- '\x1b[Z': Keys.BackTab, # shift + tab
- '\x1b[2~': Keys.Insert,
-
- '\x1bOP': Keys.F1,
- '\x1bOQ': Keys.F2,
- '\x1bOR': Keys.F3,
- '\x1bOS': Keys.F4,
- '\x1b[[A': Keys.F1, # Linux console.
- '\x1b[[B': Keys.F2, # Linux console.
- '\x1b[[C': Keys.F3, # Linux console.
- '\x1b[[D': Keys.F4, # Linux console.
- '\x1b[[E': Keys.F5, # Linux console.
- '\x1b[11~': Keys.F1, # rxvt-unicode
- '\x1b[12~': Keys.F2, # rxvt-unicode
- '\x1b[13~': Keys.F3, # rxvt-unicode
- '\x1b[14~': Keys.F4, # rxvt-unicode
- '\x1b[15~': Keys.F5,
- '\x1b[17~': Keys.F6,
- '\x1b[18~': Keys.F7,
- '\x1b[19~': Keys.F8,
- '\x1b[20~': Keys.F9,
- '\x1b[21~': Keys.F10,
- '\x1b[23~': Keys.F11,
- '\x1b[24~': Keys.F12,
- '\x1b[25~': Keys.F13,
- '\x1b[26~': Keys.F14,
- '\x1b[28~': Keys.F15,
- '\x1b[29~': Keys.F16,
- '\x1b[31~': Keys.F17,
- '\x1b[32~': Keys.F18,
- '\x1b[33~': Keys.F19,
- '\x1b[34~': Keys.F20,
-
- # Xterm
- '\x1b[1;2P': Keys.F13,
- '\x1b[1;2Q': Keys.F14,
- # '\x1b[1;2R': Keys.F15, # Conflicts with CPR response.
- '\x1b[1;2S': Keys.F16,
- '\x1b[15;2~': Keys.F17,
- '\x1b[17;2~': Keys.F18,
- '\x1b[18;2~': Keys.F19,
- '\x1b[19;2~': Keys.F20,
- '\x1b[20;2~': Keys.F21,
- '\x1b[21;2~': Keys.F22,
- '\x1b[23;2~': Keys.F23,
- '\x1b[24;2~': Keys.F24,
-
- '\x1b[1;5A': Keys.ControlUp, # Cursor Mode
- '\x1b[1;5B': Keys.ControlDown, # Cursor Mode
- '\x1b[1;5C': Keys.ControlRight, # Cursor Mode
- '\x1b[1;5D': Keys.ControlLeft, # Cursor Mode
-
- '\x1b[1;2A': Keys.ShiftUp,
- '\x1b[1;2B': Keys.ShiftDown,
- '\x1b[1;2C': Keys.ShiftRight,
- '\x1b[1;2D': Keys.ShiftLeft,
-
- # Tmux sends following keystrokes when control+arrow is pressed, but for
- # Emacs ansi-term sends the same sequences for normal arrow keys. Consider
- # it a normal arrow press, because that's more important.
- '\x1bOA': Keys.Up,
- '\x1bOB': Keys.Down,
- '\x1bOC': Keys.Right,
- '\x1bOD': Keys.Left,
-
- '\x1b[5A': Keys.ControlUp,
- '\x1b[5B': Keys.ControlDown,
- '\x1b[5C': Keys.ControlRight,
- '\x1b[5D': Keys.ControlLeft,
-
- '\x1bOc': Keys.ControlRight, # rxvt
- '\x1bOd': Keys.ControlLeft, # rxvt
-
- '\x1b[200~': Keys.BracketedPaste, # Start of bracketed paste.
-
- # Meta + arrow keys. Several terminals handle this differently.
- # The following sequences are for xterm and gnome-terminal.
- # (Iterm sends ESC followed by the normal arrow_up/down/left/right
- # sequences, and the OSX Terminal sends ESCb and ESCf for "alt
- # arrow_left" and "alt arrow_right." We don't handle these
- # explicitely, in here, because would could not distinguesh between
- # pressing ESC (to go to Vi navigation mode), followed by just the
- # 'b' or 'f' key. These combinations are handled in
- # the input processor.)
- '\x1b[1;3D': (Keys.Escape, Keys.Left),
- '\x1b[1;3C': (Keys.Escape, Keys.Right),
- '\x1b[1;3A': (Keys.Escape, Keys.Up),
- '\x1b[1;3B': (Keys.Escape, Keys.Down),
-
- # Sequences generated by numpad 5. Not sure what it means. (It doesn't
- # appear in 'infocmp'. Just ignore.
- '\x1b[E': Keys.Ignore, # Xterm.
- '\x1b[G': Keys.Ignore, # Linux console.
-}
-
-
-class _IsPrefixOfLongerMatchCache(dict):
- """
- Dictiory that maps input sequences to a boolean indicating whether there is
- any key that start with this characters.
- """
- def __missing__(self, prefix):
- # (hard coded) If this could be a prefix of a CPR response, return
- # True.
- if (_cpr_response_prefix_re.match(prefix) or _mouse_event_prefix_re.match(prefix)):
- result = True
- else:
- # If this could be a prefix of anything else, also return True.
- result = any(v for k, v in ANSI_SEQUENCES.items() if k.startswith(prefix) and k != prefix)
-
- self[prefix] = result
- return result
-
-
-_IS_PREFIX_OF_LONGER_MATCH_CACHE = _IsPrefixOfLongerMatchCache()
-
-
-class InputStream(object):
- """
- Parser for VT100 input stream.
-
- Feed the data through the `feed` method and the correct callbacks of the
- `input_processor` will be called.
-
- ::
-
- def callback(key):
- pass
- i = InputStream(callback)
- i.feed('data\x01...')
-
- :attr input_processor: :class:`~prompt_toolkit.key_binding.InputProcessor` instance.
- """
- # Lookup table of ANSI escape sequences for a VT100 terminal
- # Hint: in order to know what sequences your terminal writes to stdin, run
- # "od -c" and start typing.
- def __init__(self, feed_key_callback):
- assert callable(feed_key_callback)
-
- self.feed_key_callback = feed_key_callback
- self.reset()
-
- if _DEBUG_RENDERER_INPUT:
- self.LOG = open(_DEBUG_RENDERER_INPUT_FILENAME, 'ab')
-
- def reset(self, request=False):
- self._in_bracketed_paste = False
- self._start_parser()
-
- def _start_parser(self):
- """
- Start the parser coroutine.
- """
- self._input_parser = self._input_parser_generator()
- self._input_parser.send(None)
-
- def _get_match(self, prefix):
- """
- Return the key that maps to this prefix.
- """
- # (hard coded) If we match a CPR response, return Keys.CPRResponse.
- # (This one doesn't fit in the ANSI_SEQUENCES, because it contains
- # integer variables.)
- if _cpr_response_re.match(prefix):
- return Keys.CPRResponse
-
- elif _mouse_event_re.match(prefix):
- return Keys.Vt100MouseEvent
-
- # Otherwise, use the mappings.
- try:
- return ANSI_SEQUENCES[prefix]
- except KeyError:
- return None
-
- def _input_parser_generator(self):
- """
- Coroutine (state machine) for the input parser.
- """
- prefix = ''
- retry = False
- flush = False
-
- while True:
- flush = False
-
- if retry:
- retry = False
- else:
- # Get next character.
- c = yield
-
- if c == _Flush:
- flush = True
- else:
- prefix += c
-
- # If we have some data, check for matches.
- if prefix:
- is_prefix_of_longer_match = _IS_PREFIX_OF_LONGER_MATCH_CACHE[prefix]
- match = self._get_match(prefix)
-
- # Exact matches found, call handlers..
- if (flush or not is_prefix_of_longer_match) and match:
- self._call_handler(match, prefix)
- prefix = ''
-
- # No exact match found.
- elif (flush or not is_prefix_of_longer_match) and not match:
- found = False
- retry = True
-
- # Loop over the input, try the longest match first and
- # shift.
- for i in range(len(prefix), 0, -1):
- match= self._get_match(prefix[:i])
- if match:
- self._call_handler(match, prefix[:i])
- prefix = prefix[i:]
- found = True
-
- if not found:
- self._call_handler(prefix[0], prefix[0])
- prefix = prefix[1:]
-
- def _call_handler(self, key, insert_text):
- """
- Callback to handler.
- """
- if isinstance(key, tuple):
- for k in key:
- self._call_handler(k, insert_text)
- else:
- if key == Keys.BracketedPaste:
- self._in_bracketed_paste = True
- self._paste_buffer = ''
- else:
- self.feed_key_callback(KeyPress(key, insert_text))
-
- def feed(self, data):
- """
- Feed the input stream.
-
- :param data: Input string (unicode).
- """
- assert isinstance(data, six.text_type)
-
- if _DEBUG_RENDERER_INPUT:
- self.LOG.write(repr(data).encode('utf-8') + b'\n')
- self.LOG.flush()
-
- # Handle bracketed paste. (We bypass the parser that matches all other
- # key presses and keep reading input until we see the end mark.)
- # This is much faster then parsing character by character.
- if self._in_bracketed_paste:
- self._paste_buffer += data
- end_mark = '\x1b[201~'
-
- if end_mark in self._paste_buffer:
- end_index = self._paste_buffer.index(end_mark)
-
- # Feed content to key bindings.
- paste_content = self._paste_buffer[:end_index]
- self.feed_key_callback(KeyPress(Keys.BracketedPaste, paste_content))
-
- # Quit bracketed paste mode and handle remaining input.
- self._in_bracketed_paste = False
- remaining = self._paste_buffer[end_index + len(end_mark):]
- self._paste_buffer = ''
-
- self.feed(remaining)
-
- # Handle normal input character by character.
- else:
- for i, c in enumerate(data):
- if self._in_bracketed_paste:
- # Quit loop and process from this position when the parser
- # entered bracketed paste.
- self.feed(data[i:])
- break
- else:
- # Replace \r by \n. (Some clients send \r instead of \n
- # when enter is pressed. E.g. telnet and some other
- # terminals.)
-
- # XXX: We should remove this in a future version. It *is*
- # now possible to recognise the difference.
- # (We remove ICRNL/INLCR/IGNCR below.)
- # However, this breaks IPython and maybe other applications,
- # because they bind ControlJ (\n) for handling the Enter key.
-
- # When this is removed, replace Enter=ControlJ by
- # Enter=ControlM in keys.py.
- if c == '\r':
- c = '\n'
- self._input_parser.send(c)
-
- def flush(self):
- """
- Flush the buffer of the input stream.
-
- This will allow us to handle the escape key (or maybe meta) sooner.
- The input received by the escape key is actually the same as the first
- characters of e.g. Arrow-Up, so without knowing what follows the escape
- sequence, we don't know whether escape has been pressed, or whether
- it's something else. This flush function should be called after a
- timeout, and processes everything that's still in the buffer as-is, so
- without assuming any characters will folow.
- """
- self._input_parser.send(_Flush)
-
- def feed_and_flush(self, data):
- """
- Wrapper around ``feed`` and ``flush``.
- """
- self.feed(data)
- self.flush()
-
-
-class raw_mode(object):
- """
- ::
-
- with raw_mode(stdin):
- ''' the pseudo-terminal stdin is now used in raw mode '''
-
- We ignore errors when executing `tcgetattr` fails.
- """
- # There are several reasons for ignoring errors:
- # 1. To avoid the "Inappropriate ioctl for device" crash if somebody would
- # execute this code (In a Python REPL, for instance):
- #
- # import os; f = open(os.devnull); os.dup2(f.fileno(), 0)
- #
- # The result is that the eventloop will stop correctly, because it has
- # to logic to quit when stdin is closed. However, we should not fail at
- # this point. See:
- # https://github.com/jonathanslenders/python-prompt-toolkit/pull/393
- # https://github.com/jonathanslenders/python-prompt-toolkit/issues/392
-
- # 2. Related, when stdin is an SSH pipe, and no full terminal was allocated.
- # See: https://github.com/jonathanslenders/python-prompt-toolkit/pull/165
- def __init__(self, fileno):
- self.fileno = fileno
- try:
- self.attrs_before = termios.tcgetattr(fileno)
- except termios.error:
- # Ignore attribute errors.
- self.attrs_before = None
-
- def __enter__(self):
- # NOTE: On os X systems, using pty.setraw() fails. Therefor we are using this:
- try:
- newattr = termios.tcgetattr(self.fileno)
- except termios.error:
- pass
- else:
- newattr[tty.LFLAG] = self._patch_lflag(newattr[tty.LFLAG])
- newattr[tty.IFLAG] = self._patch_iflag(newattr[tty.IFLAG])
-
- # VMIN defines the number of characters read at a time in
- # non-canonical mode. It seems to default to 1 on Linux, but on
- # Solaris and derived operating systems it defaults to 4. (This is
- # because the VMIN slot is the same as the VEOF slot, which
- # defaults to ASCII EOT = Ctrl-D = 4.)
- newattr[tty.CC][termios.VMIN] = 1
-
- termios.tcsetattr(self.fileno, termios.TCSANOW, newattr)
-
- # Put the terminal in cursor mode. (Instead of application mode.)
- os.write(self.fileno, b'\x1b[?1l')
-
- @classmethod
- def _patch_lflag(cls, attrs):
- return attrs & ~(termios.ECHO | termios.ICANON | termios.IEXTEN | termios.ISIG)
-
- @classmethod
- def _patch_iflag(cls, attrs):
- return attrs & ~(
- # Disable XON/XOFF flow control on output and input.
- # (Don't capture Ctrl-S and Ctrl-Q.)
- # Like executing: "stty -ixon."
- termios.IXON | termios.IXOFF |
-
- # Don't translate carriage return into newline on input.
- termios.ICRNL | termios.INLCR | termios.IGNCR
- )
-
- def __exit__(self, *a, **kw):
- if self.attrs_before is not None:
- try:
- termios.tcsetattr(self.fileno, termios.TCSANOW, self.attrs_before)
- except termios.error:
- pass
-
- # # Put the terminal in application mode.
- # self._stdout.write('\x1b[?1h')
-
-
-class cooked_mode(raw_mode):
- """
- The opposide of ``raw_mode``, used when we need cooked mode inside a
- `raw_mode` block. Used in `CommandLineInterface.run_in_terminal`.::
-
- with cooked_mode(stdin):
- ''' the pseudo-terminal stdin is now used in cooked mode. '''
- """
- @classmethod
- def _patch_lflag(cls, attrs):
- return attrs | (termios.ECHO | termios.ICANON | termios.IEXTEN | termios.ISIG)
-
- @classmethod
- def _patch_iflag(cls, attrs):
- # Turn the ICRNL flag back on. (Without this, calling `input()` in
- # run_in_terminal doesn't work and displays ^M instead. Ptpython
- # evaluates commands using `run_in_terminal`, so it's important that
- # they translate ^M back into ^J.)
- return attrs | termios.ICRNL
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py
deleted file mode 100644
index b800aaacec..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py
+++ /dev/null
@@ -1,632 +0,0 @@
-"""
-Output for vt100 terminals.
-
-A lot of thanks, regarding outputting of colors, goes to the Pygments project:
-(We don't rely on Pygments anymore, because many things are very custom, and
-everything has been highly optimized.)
-http://pygments.org/
-"""
-from __future__ import unicode_literals
-
-from prompt_toolkit.filters import to_simple_filter, Condition
-from prompt_toolkit.layout.screen import Size
-from prompt_toolkit.renderer import Output
-from prompt_toolkit.styles import ANSI_COLOR_NAMES
-
-from six.moves import range
-import array
-import errno
-import os
-import six
-
-__all__ = (
- 'Vt100_Output',
-)
-
-
-FG_ANSI_COLORS = {
- 'ansidefault': 39,
-
- # Low intensity.
- 'ansiblack': 30,
- 'ansidarkred': 31,
- 'ansidarkgreen': 32,
- 'ansibrown': 33,
- 'ansidarkblue': 34,
- 'ansipurple': 35,
- 'ansiteal': 36,
- 'ansilightgray': 37,
-
- # High intensity.
- 'ansidarkgray': 90,
- 'ansired': 91,
- 'ansigreen': 92,
- 'ansiyellow': 93,
- 'ansiblue': 94,
- 'ansifuchsia': 95,
- 'ansiturquoise': 96,
- 'ansiwhite': 97,
-}
-
-BG_ANSI_COLORS = {
- 'ansidefault': 49,
-
- # Low intensity.
- 'ansiblack': 40,
- 'ansidarkred': 41,
- 'ansidarkgreen': 42,
- 'ansibrown': 43,
- 'ansidarkblue': 44,
- 'ansipurple': 45,
- 'ansiteal': 46,
- 'ansilightgray': 47,
-
- # High intensity.
- 'ansidarkgray': 100,
- 'ansired': 101,
- 'ansigreen': 102,
- 'ansiyellow': 103,
- 'ansiblue': 104,
- 'ansifuchsia': 105,
- 'ansiturquoise': 106,
- 'ansiwhite': 107,
-}
-
-
-ANSI_COLORS_TO_RGB = {
- 'ansidefault': (0x00, 0x00, 0x00), # Don't use, 'default' doesn't really have a value.
- 'ansiblack': (0x00, 0x00, 0x00),
- 'ansidarkgray': (0x7f, 0x7f, 0x7f),
- 'ansiwhite': (0xff, 0xff, 0xff),
- 'ansilightgray': (0xe5, 0xe5, 0xe5),
-
- # Low intensity.
- 'ansidarkred': (0xcd, 0x00, 0x00),
- 'ansidarkgreen': (0x00, 0xcd, 0x00),
- 'ansibrown': (0xcd, 0xcd, 0x00),
- 'ansidarkblue': (0x00, 0x00, 0xcd),
- 'ansipurple': (0xcd, 0x00, 0xcd),
- 'ansiteal': (0x00, 0xcd, 0xcd),
-
- # High intensity.
- 'ansired': (0xff, 0x00, 0x00),
- 'ansigreen': (0x00, 0xff, 0x00),
- 'ansiyellow': (0xff, 0xff, 0x00),
- 'ansiblue': (0x00, 0x00, 0xff),
- 'ansifuchsia': (0xff, 0x00, 0xff),
- 'ansiturquoise': (0x00, 0xff, 0xff),
-}
-
-
-assert set(FG_ANSI_COLORS) == set(ANSI_COLOR_NAMES)
-assert set(BG_ANSI_COLORS) == set(ANSI_COLOR_NAMES)
-assert set(ANSI_COLORS_TO_RGB) == set(ANSI_COLOR_NAMES)
-
-
-def _get_closest_ansi_color(r, g, b, exclude=()):
- """
- Find closest ANSI color. Return it by name.
-
- :param r: Red (Between 0 and 255.)
- :param g: Green (Between 0 and 255.)
- :param b: Blue (Between 0 and 255.)
- :param exclude: A tuple of color names to exclude. (E.g. ``('ansired', )``.)
- """
- assert isinstance(exclude, tuple)
-
- # When we have a bit of saturation, avoid the gray-like colors, otherwise,
- # too often the distance to the gray color is less.
- saturation = abs(r - g) + abs(g - b) + abs(b - r) # Between 0..510
-
- if saturation > 30:
- exclude += ('ansilightgray', 'ansidarkgray', 'ansiwhite', 'ansiblack')
-
- # Take the closest color.
- # (Thanks to Pygments for this part.)
- distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff)
- match = 'ansidefault'
-
- for name, (r2, g2, b2) in ANSI_COLORS_TO_RGB.items():
- if name != 'ansidefault' and name not in exclude:
- d = (r - r2) ** 2 + (g - g2) ** 2 + (b - b2) ** 2
-
- if d < distance:
- match = name
- distance = d
-
- return match
-
-
-class _16ColorCache(dict):
- """
- Cache which maps (r, g, b) tuples to 16 ansi colors.
-
- :param bg: Cache for background colors, instead of foreground.
- """
- def __init__(self, bg=False):
- assert isinstance(bg, bool)
- self.bg = bg
-
- def get_code(self, value, exclude=()):
- """
- Return a (ansi_code, ansi_name) tuple. (E.g. ``(44, 'ansiblue')``.) for
- a given (r,g,b) value.
- """
- key = (value, exclude)
- if key not in self:
- self[key] = self._get(value, exclude)
- return self[key]
-
- def _get(self, value, exclude=()):
- r, g, b = value
- match = _get_closest_ansi_color(r, g, b, exclude=exclude)
-
- # Turn color name into code.
- if self.bg:
- code = BG_ANSI_COLORS[match]
- else:
- code = FG_ANSI_COLORS[match]
-
- self[value] = code
- return code, match
-
-
-class _256ColorCache(dict):
- """
- Cach which maps (r, g, b) tuples to 256 colors.
- """
- def __init__(self):
- # Build color table.
- colors = []
-
- # colors 0..15: 16 basic colors
- colors.append((0x00, 0x00, 0x00)) # 0
- colors.append((0xcd, 0x00, 0x00)) # 1
- colors.append((0x00, 0xcd, 0x00)) # 2
- colors.append((0xcd, 0xcd, 0x00)) # 3
- colors.append((0x00, 0x00, 0xee)) # 4
- colors.append((0xcd, 0x00, 0xcd)) # 5
- colors.append((0x00, 0xcd, 0xcd)) # 6
- colors.append((0xe5, 0xe5, 0xe5)) # 7
- colors.append((0x7f, 0x7f, 0x7f)) # 8
- colors.append((0xff, 0x00, 0x00)) # 9
- colors.append((0x00, 0xff, 0x00)) # 10
- colors.append((0xff, 0xff, 0x00)) # 11
- colors.append((0x5c, 0x5c, 0xff)) # 12
- colors.append((0xff, 0x00, 0xff)) # 13
- colors.append((0x00, 0xff, 0xff)) # 14
- colors.append((0xff, 0xff, 0xff)) # 15
-
- # colors 16..232: the 6x6x6 color cube
- valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff)
-
- for i in range(217):
- r = valuerange[(i // 36) % 6]
- g = valuerange[(i // 6) % 6]
- b = valuerange[i % 6]
- colors.append((r, g, b))
-
- # colors 233..253: grayscale
- for i in range(1, 22):
- v = 8 + i * 10
- colors.append((v, v, v))
-
- self.colors = colors
-
- def __missing__(self, value):
- r, g, b = value
-
- # Find closest color.
- # (Thanks to Pygments for this!)
- distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff)
- match = 0
-
- for i, (r2, g2, b2) in enumerate(self.colors):
- d = (r - r2) ** 2 + (g - g2) ** 2 + (b - b2) ** 2
-
- if d < distance:
- match = i
- distance = d
-
- # Turn color name into code.
- self[value] = match
- return match
-
-
-_16_fg_colors = _16ColorCache(bg=False)
-_16_bg_colors = _16ColorCache(bg=True)
-_256_colors = _256ColorCache()
-
-
-class _EscapeCodeCache(dict):
- """
- Cache for VT100 escape codes. It maps
- (fgcolor, bgcolor, bold, underline, reverse) tuples to VT100 escape sequences.
-
- :param true_color: When True, use 24bit colors instead of 256 colors.
- """
- def __init__(self, true_color=False, ansi_colors_only=False):
- assert isinstance(true_color, bool)
- self.true_color = true_color
- self.ansi_colors_only = to_simple_filter(ansi_colors_only)
-
- def __missing__(self, attrs):
- fgcolor, bgcolor, bold, underline, italic, blink, reverse = attrs
- parts = []
-
- parts.extend(self._colors_to_code(fgcolor, bgcolor))
-
- if bold:
- parts.append('1')
- if italic:
- parts.append('3')
- if blink:
- parts.append('5')
- if underline:
- parts.append('4')
- if reverse:
- parts.append('7')
-
- if parts:
- result = '\x1b[0;' + ';'.join(parts) + 'm'
- else:
- result = '\x1b[0m'
-
- self[attrs] = result
- return result
-
- def _color_name_to_rgb(self, color):
- " Turn 'ffffff', into (0xff, 0xff, 0xff). "
- try:
- rgb = int(color, 16)
- except ValueError:
- raise
- else:
- r = (rgb >> 16) & 0xff
- g = (rgb >> 8) & 0xff
- b = rgb & 0xff
- return r, g, b
-
- def _colors_to_code(self, fg_color, bg_color):
- " Return a tuple with the vt100 values that represent this color. "
- # When requesting ANSI colors only, and both fg/bg color were converted
- # to ANSI, ensure that the foreground and background color are not the
- # same. (Unless they were explicitely defined to be the same color.)
- fg_ansi = [()]
-
- def get(color, bg):
- table = BG_ANSI_COLORS if bg else FG_ANSI_COLORS
-
- if color is None:
- return ()
-
- # 16 ANSI colors. (Given by name.)
- elif color in table:
- return (table[color], )
-
- # RGB colors. (Defined as 'ffffff'.)
- else:
- try:
- rgb = self._color_name_to_rgb(color)
- except ValueError:
- return ()
-
- # When only 16 colors are supported, use that.
- if self.ansi_colors_only():
- if bg: # Background.
- if fg_color != bg_color:
- exclude = (fg_ansi[0], )
- else:
- exclude = ()
- code, name = _16_bg_colors.get_code(rgb, exclude=exclude)
- return (code, )
- else: # Foreground.
- code, name = _16_fg_colors.get_code(rgb)
- fg_ansi[0] = name
- return (code, )
-
- # True colors. (Only when this feature is enabled.)
- elif self.true_color:
- r, g, b = rgb
- return (48 if bg else 38, 2, r, g, b)
-
- # 256 RGB colors.
- else:
- return (48 if bg else 38, 5, _256_colors[rgb])
-
- result = []
- result.extend(get(fg_color, False))
- result.extend(get(bg_color, True))
-
- return map(six.text_type, result)
-
-
-def _get_size(fileno):
- # Thanks to fabric (fabfile.org), and
- # http://sqizit.bartletts.id.au/2011/02/14/pseudo-terminals-in-python/
- """
- Get the size of this pseudo terminal.
-
- :param fileno: stdout.fileno()
- :returns: A (rows, cols) tuple.
- """
- # Inline imports, because these modules are not available on Windows.
- # (This file is used by ConEmuOutput, which is used on Windows.)
- import fcntl
- import termios
-
- # Buffer for the C call
- buf = array.array(b'h' if six.PY2 else u'h', [0, 0, 0, 0])
-
- # Do TIOCGWINSZ (Get)
- # Note: We should not pass 'True' as a fourth parameter to 'ioctl'. (True
- # is the default.) This causes segmentation faults on some systems.
- # See: https://github.com/jonathanslenders/python-prompt-toolkit/pull/364
- fcntl.ioctl(fileno, termios.TIOCGWINSZ, buf)
-
- # Return rows, cols
- return buf[0], buf[1]
-
-
-class Vt100_Output(Output):
- """
- :param get_size: A callable which returns the `Size` of the output terminal.
- :param stdout: Any object with has a `write` and `flush` method + an 'encoding' property.
- :param true_color: Use 24bit color instead of 256 colors. (Can be a :class:`SimpleFilter`.)
- When `ansi_colors_only` is set, only 16 colors are used.
- :param ansi_colors_only: Restrict to 16 ANSI colors only.
- :param term: The terminal environment variable. (xterm, xterm-256color, linux, ...)
- :param write_binary: Encode the output before writing it. If `True` (the
- default), the `stdout` object is supposed to expose an `encoding` attribute.
- """
- def __init__(self, stdout, get_size, true_color=False,
- ansi_colors_only=None, term=None, write_binary=True):
- assert callable(get_size)
- assert term is None or isinstance(term, six.text_type)
- assert all(hasattr(stdout, a) for a in ('write', 'flush'))
-
- if write_binary:
- assert hasattr(stdout, 'encoding')
-
- self._buffer = []
- self.stdout = stdout
- self.write_binary = write_binary
- self.get_size = get_size
- self.true_color = to_simple_filter(true_color)
- self.term = term or 'xterm'
-
- # ANSI colors only?
- if ansi_colors_only is None:
- # When not given, use the following default.
- ANSI_COLORS_ONLY = bool(os.environ.get(
- 'PROMPT_TOOLKIT_ANSI_COLORS_ONLY', False))
-
- @Condition
- def ansi_colors_only():
- return ANSI_COLORS_ONLY or term in ('linux', 'eterm-color')
- else:
- ansi_colors_only = to_simple_filter(ansi_colors_only)
-
- self.ansi_colors_only = ansi_colors_only
-
- # Cache for escape codes.
- self._escape_code_cache = _EscapeCodeCache(ansi_colors_only=ansi_colors_only)
- self._escape_code_cache_true_color = _EscapeCodeCache(
- true_color=True, ansi_colors_only=ansi_colors_only)
-
- @classmethod
- def from_pty(cls, stdout, true_color=False, ansi_colors_only=None, term=None):
- """
- Create an Output class from a pseudo terminal.
- (This will take the dimensions by reading the pseudo
- terminal attributes.)
- """
- assert stdout.isatty()
- def get_size():
- rows, columns = _get_size(stdout.fileno())
- # If terminal (incorrectly) reports its size as 0, pick a reasonable default.
- # See https://github.com/ipython/ipython/issues/10071
- return Size(rows=(rows or 24), columns=(columns or 80))
-
- return cls(stdout, get_size, true_color=true_color,
- ansi_colors_only=ansi_colors_only, term=term)
-
- def fileno(self):
- " Return file descriptor. "
- return self.stdout.fileno()
-
- def encoding(self):
- " Return encoding used for stdout. "
- return self.stdout.encoding
-
- def write_raw(self, data):
- """
- Write raw data to output.
- """
- self._buffer.append(data)
-
- def write(self, data):
- """
- Write text to output.
- (Removes vt100 escape codes. -- used for safely writing text.)
- """
- self._buffer.append(data.replace('\x1b', '?'))
-
- def set_title(self, title):
- """
- Set terminal title.
- """
- if self.term not in ('linux', 'eterm-color'): # Not supported by the Linux console.
- self.write_raw('\x1b]2;%s\x07' % title.replace('\x1b', '').replace('\x07', ''))
-
- def clear_title(self):
- self.set_title('')
-
- def erase_screen(self):
- """
- Erases the screen with the background colour and moves the cursor to
- home.
- """
- self.write_raw('\x1b[2J')
-
- def enter_alternate_screen(self):
- self.write_raw('\x1b[?1049h\x1b[H')
-
- def quit_alternate_screen(self):
- self.write_raw('\x1b[?1049l')
-
- def enable_mouse_support(self):
- self.write_raw('\x1b[?1000h')
-
- # Enable urxvt Mouse mode. (For terminals that understand this.)
- self.write_raw('\x1b[?1015h')
-
- # Also enable Xterm SGR mouse mode. (For terminals that understand this.)
- self.write_raw('\x1b[?1006h')
-
- # Note: E.g. lxterminal understands 1000h, but not the urxvt or sgr
- # extensions.
-
- def disable_mouse_support(self):
- self.write_raw('\x1b[?1000l')
- self.write_raw('\x1b[?1015l')
- self.write_raw('\x1b[?1006l')
-
- def erase_end_of_line(self):
- """
- Erases from the current cursor position to the end of the current line.
- """
- self.write_raw('\x1b[K')
-
- def erase_down(self):
- """
- Erases the screen from the current line down to the bottom of the
- screen.
- """
- self.write_raw('\x1b[J')
-
- def reset_attributes(self):
- self.write_raw('\x1b[0m')
-
- def set_attributes(self, attrs):
- """
- Create new style and output.
-
- :param attrs: `Attrs` instance.
- """
- if self.true_color() and not self.ansi_colors_only():
- self.write_raw(self._escape_code_cache_true_color[attrs])
- else:
- self.write_raw(self._escape_code_cache[attrs])
-
- def disable_autowrap(self):
- self.write_raw('\x1b[?7l')
-
- def enable_autowrap(self):
- self.write_raw('\x1b[?7h')
-
- def enable_bracketed_paste(self):
- self.write_raw('\x1b[?2004h')
-
- def disable_bracketed_paste(self):
- self.write_raw('\x1b[?2004l')
-
- def cursor_goto(self, row=0, column=0):
- """ Move cursor position. """
- self.write_raw('\x1b[%i;%iH' % (row, column))
-
- def cursor_up(self, amount):
- if amount == 0:
- pass
- elif amount == 1:
- self.write_raw('\x1b[A')
- else:
- self.write_raw('\x1b[%iA' % amount)
-
- def cursor_down(self, amount):
- if amount == 0:
- pass
- elif amount == 1:
- # Note: Not the same as '\n', '\n' can cause the window content to
- # scroll.
- self.write_raw('\x1b[B')
- else:
- self.write_raw('\x1b[%iB' % amount)
-
- def cursor_forward(self, amount):
- if amount == 0:
- pass
- elif amount == 1:
- self.write_raw('\x1b[C')
- else:
- self.write_raw('\x1b[%iC' % amount)
-
- def cursor_backward(self, amount):
- if amount == 0:
- pass
- elif amount == 1:
- self.write_raw('\b') # '\x1b[D'
- else:
- self.write_raw('\x1b[%iD' % amount)
-
- def hide_cursor(self):
- self.write_raw('\x1b[?25l')
-
- def show_cursor(self):
- self.write_raw('\x1b[?12l\x1b[?25h') # Stop blinking cursor and show.
-
- def flush(self):
- """
- Write to output stream and flush.
- """
- if not self._buffer:
- return
-
- data = ''.join(self._buffer)
-
- try:
- # (We try to encode ourself, because that way we can replace
- # characters that don't exist in the character set, avoiding
- # UnicodeEncodeError crashes. E.g. u'\xb7' does not appear in 'ascii'.)
- # My Arch Linux installation of july 2015 reported 'ANSI_X3.4-1968'
- # for sys.stdout.encoding in xterm.
- if self.write_binary:
- if hasattr(self.stdout, 'buffer'):
- out = self.stdout.buffer # Py3.
- else:
- out = self.stdout
- out.write(data.encode(self.stdout.encoding or 'utf-8', 'replace'))
- else:
- self.stdout.write(data)
-
- self.stdout.flush()
- except IOError as e:
- if e.args and e.args[0] == errno.EINTR:
- # Interrupted system call. Can happpen in case of a window
- # resize signal. (Just ignore. The resize handler will render
- # again anyway.)
- pass
- elif e.args and e.args[0] == 0:
- # This can happen when there is a lot of output and the user
- # sends a KeyboardInterrupt by pressing Control-C. E.g. in
- # a Python REPL when we execute "while True: print('test')".
- # (The `ptpython` REPL uses this `Output` class instead of
- # `stdout` directly -- in order to be network transparent.)
- # So, just ignore.
- pass
- else:
- raise
-
- self._buffer = []
-
- def ask_for_cpr(self):
- """
- Asks for a cursor position report (CPR).
- """
- self.write_raw('\x1b[6n')
- self.flush()
-
- def bell(self):
- " Sound bell. "
- self.write_raw('\a')
- self.flush()
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py
deleted file mode 100644
index 410e5fa517..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py
+++ /dev/null
@@ -1,364 +0,0 @@
-from __future__ import unicode_literals
-from ctypes import windll, pointer
-from ctypes.wintypes import DWORD, HANDLE
-from six.moves import range
-
-from prompt_toolkit.key_binding.input_processor import KeyPress
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.mouse_events import MouseEventType
-from prompt_toolkit.win32_types import EventTypes, KEY_EVENT_RECORD, MOUSE_EVENT_RECORD, INPUT_RECORD, STD_INPUT_HANDLE
-
-import msvcrt
-import os
-import sys
-import six
-
-__all__ = (
- 'ConsoleInputReader',
- 'raw_mode',
- 'cooked_mode'
-)
-
-
-class ConsoleInputReader(object):
- """
- :param recognize_paste: When True, try to discover paste actions and turn
- the event into a BracketedPaste.
- """
- # Keys with character data.
- mappings = {
- b'\x1b': Keys.Escape,
-
- b'\x00': Keys.ControlSpace, # Control-Space (Also for Ctrl-@)
- b'\x01': Keys.ControlA, # Control-A (home)
- b'\x02': Keys.ControlB, # Control-B (emacs cursor left)
- b'\x03': Keys.ControlC, # Control-C (interrupt)
- b'\x04': Keys.ControlD, # Control-D (exit)
- b'\x05': Keys.ControlE, # Contrel-E (end)
- b'\x06': Keys.ControlF, # Control-F (cursor forward)
- b'\x07': Keys.ControlG, # Control-G
- b'\x08': Keys.ControlH, # Control-H (8) (Identical to '\b')
- b'\x09': Keys.ControlI, # Control-I (9) (Identical to '\t')
- b'\x0a': Keys.ControlJ, # Control-J (10) (Identical to '\n')
- b'\x0b': Keys.ControlK, # Control-K (delete until end of line; vertical tab)
- b'\x0c': Keys.ControlL, # Control-L (clear; form feed)
- b'\x0d': Keys.ControlJ, # Control-J NOTE: Windows sends \r instead of
- # \n when pressing enter. We turn it into \n
- # to be compatible with other platforms.
- b'\x0e': Keys.ControlN, # Control-N (14) (history forward)
- b'\x0f': Keys.ControlO, # Control-O (15)
- b'\x10': Keys.ControlP, # Control-P (16) (history back)
- b'\x11': Keys.ControlQ, # Control-Q
- b'\x12': Keys.ControlR, # Control-R (18) (reverse search)
- b'\x13': Keys.ControlS, # Control-S (19) (forward search)
- b'\x14': Keys.ControlT, # Control-T
- b'\x15': Keys.ControlU, # Control-U
- b'\x16': Keys.ControlV, # Control-V
- b'\x17': Keys.ControlW, # Control-W
- b'\x18': Keys.ControlX, # Control-X
- b'\x19': Keys.ControlY, # Control-Y (25)
- b'\x1a': Keys.ControlZ, # Control-Z
-
- b'\x1c': Keys.ControlBackslash, # Both Control-\ and Ctrl-|
- b'\x1d': Keys.ControlSquareClose, # Control-]
- b'\x1e': Keys.ControlCircumflex, # Control-^
- b'\x1f': Keys.ControlUnderscore, # Control-underscore (Also for Ctrl-hypen.)
- b'\x7f': Keys.Backspace, # (127) Backspace
- }
-
- # Keys that don't carry character data.
- keycodes = {
- # Home/End
- 33: Keys.PageUp,
- 34: Keys.PageDown,
- 35: Keys.End,
- 36: Keys.Home,
-
- # Arrows
- 37: Keys.Left,
- 38: Keys.Up,
- 39: Keys.Right,
- 40: Keys.Down,
-
- 45: Keys.Insert,
- 46: Keys.Delete,
-
- # F-keys.
- 112: Keys.F1,
- 113: Keys.F2,
- 114: Keys.F3,
- 115: Keys.F4,
- 116: Keys.F5,
- 117: Keys.F6,
- 118: Keys.F7,
- 119: Keys.F8,
- 120: Keys.F9,
- 121: Keys.F10,
- 122: Keys.F11,
- 123: Keys.F12,
- }
-
- LEFT_ALT_PRESSED = 0x0002
- RIGHT_ALT_PRESSED = 0x0001
- SHIFT_PRESSED = 0x0010
- LEFT_CTRL_PRESSED = 0x0008
- RIGHT_CTRL_PRESSED = 0x0004
-
- def __init__(self, recognize_paste=True):
- self._fdcon = None
- self.recognize_paste = recognize_paste
-
- # When stdin is a tty, use that handle, otherwise, create a handle from
- # CONIN$.
- if sys.stdin.isatty():
- self.handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE))
- else:
- self._fdcon = os.open('CONIN$', os.O_RDWR | os.O_BINARY)
- self.handle = HANDLE(msvcrt.get_osfhandle(self._fdcon))
-
- def close(self):
- " Close fdcon. "
- if self._fdcon is not None:
- os.close(self._fdcon)
-
- def read(self):
- """
- Return a list of `KeyPress` instances. It won't return anything when
- there was nothing to read. (This function doesn't block.)
-
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx
- """
- max_count = 2048 # Max events to read at the same time.
-
- read = DWORD(0)
- arrtype = INPUT_RECORD * max_count
- input_records = arrtype()
-
- # Get next batch of input event.
- windll.kernel32.ReadConsoleInputW(
- self.handle, pointer(input_records), max_count, pointer(read))
-
- # First, get all the keys from the input buffer, in order to determine
- # whether we should consider this a paste event or not.
- all_keys = list(self._get_keys(read, input_records))
-
- if self.recognize_paste and self._is_paste(all_keys):
- gen = iter(all_keys)
- for k in gen:
- # Pasting: if the current key consists of text or \n, turn it
- # into a BracketedPaste.
- data = []
- while k and (isinstance(k.key, six.text_type) or
- k.key == Keys.ControlJ):
- data.append(k.data)
- try:
- k = next(gen)
- except StopIteration:
- k = None
-
- if data:
- yield KeyPress(Keys.BracketedPaste, ''.join(data))
- if k is not None:
- yield k
- else:
- for k in all_keys:
- yield k
-
- def _get_keys(self, read, input_records):
- """
- Generator that yields `KeyPress` objects from the input records.
- """
- for i in range(read.value):
- ir = input_records[i]
-
- # Get the right EventType from the EVENT_RECORD.
- # (For some reason the Windows console application 'cmder'
- # [http://gooseberrycreative.com/cmder/] can return '0' for
- # ir.EventType. -- Just ignore that.)
- if ir.EventType in EventTypes:
- ev = getattr(ir.Event, EventTypes[ir.EventType])
-
- # Process if this is a key event. (We also have mouse, menu and
- # focus events.)
- if type(ev) == KEY_EVENT_RECORD and ev.KeyDown:
- for key_press in self._event_to_key_presses(ev):
- yield key_press
-
- elif type(ev) == MOUSE_EVENT_RECORD:
- for key_press in self._handle_mouse(ev):
- yield key_press
-
- @staticmethod
- def _is_paste(keys):
- """
- Return `True` when we should consider this list of keys as a paste
- event. Pasted text on windows will be turned into a
- `Keys.BracketedPaste` event. (It's not 100% correct, but it is probably
- the best possible way to detect pasting of text and handle that
- correctly.)
- """
- # Consider paste when it contains at least one newline and at least one
- # other character.
- text_count = 0
- newline_count = 0
-
- for k in keys:
- if isinstance(k.key, six.text_type):
- text_count += 1
- if k.key == Keys.ControlJ:
- newline_count += 1
-
- return newline_count >= 1 and text_count > 1
-
- def _event_to_key_presses(self, ev):
- """
- For this `KEY_EVENT_RECORD`, return a list of `KeyPress` instances.
- """
- assert type(ev) == KEY_EVENT_RECORD and ev.KeyDown
-
- result = None
-
- u_char = ev.uChar.UnicodeChar
- ascii_char = u_char.encode('utf-8')
-
- # NOTE: We don't use `ev.uChar.AsciiChar`. That appears to be latin-1
- # encoded. See also:
- # https://github.com/ipython/ipython/issues/10004
- # https://github.com/jonathanslenders/python-prompt-toolkit/issues/389
-
- if u_char == '\x00':
- if ev.VirtualKeyCode in self.keycodes:
- result = KeyPress(self.keycodes[ev.VirtualKeyCode], '')
- else:
- if ascii_char in self.mappings:
- if self.mappings[ascii_char] == Keys.ControlJ:
- u_char = '\n' # Windows sends \n, turn into \r for unix compatibility.
- result = KeyPress(self.mappings[ascii_char], u_char)
- else:
- result = KeyPress(u_char, u_char)
-
- # Correctly handle Control-Arrow keys.
- if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
- ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result:
- if result.key == Keys.Left:
- result.key = Keys.ControlLeft
-
- if result.key == Keys.Right:
- result.key = Keys.ControlRight
-
- if result.key == Keys.Up:
- result.key = Keys.ControlUp
-
- if result.key == Keys.Down:
- result.key = Keys.ControlDown
-
- # Turn 'Tab' into 'BackTab' when shift was pressed.
- if ev.ControlKeyState & self.SHIFT_PRESSED and result:
- if result.key == Keys.Tab:
- result.key = Keys.BackTab
-
- # Turn 'Space' into 'ControlSpace' when control was pressed.
- if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
- ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result and result.data == ' ':
- result = KeyPress(Keys.ControlSpace, ' ')
-
- # Turn Control-Enter into META-Enter. (On a vt100 terminal, we cannot
- # detect this combination. But it's really practical on Windows.)
- if (ev.ControlKeyState & self.LEFT_CTRL_PRESSED or
- ev.ControlKeyState & self.RIGHT_CTRL_PRESSED) and result and \
- result.key == Keys.ControlJ:
- return [KeyPress(Keys.Escape, ''), result]
-
- # Return result. If alt was pressed, prefix the result with an
- # 'Escape' key, just like unix VT100 terminals do.
-
- # NOTE: Only replace the left alt with escape. The right alt key often
- # acts as altgr and is used in many non US keyboard layouts for
- # typing some special characters, like a backslash. We don't want
- # all backslashes to be prefixed with escape. (Esc-\ has a
- # meaning in E-macs, for instance.)
- if result:
- meta_pressed = ev.ControlKeyState & self.LEFT_ALT_PRESSED
-
- if meta_pressed:
- return [KeyPress(Keys.Escape, ''), result]
- else:
- return [result]
-
- else:
- return []
-
- def _handle_mouse(self, ev):
- """
- Handle mouse events. Return a list of KeyPress instances.
- """
- FROM_LEFT_1ST_BUTTON_PRESSED = 0x1
-
- result = []
-
- # Check event type.
- if ev.ButtonState == FROM_LEFT_1ST_BUTTON_PRESSED:
- # On a key press, generate both the mouse down and up event.
- for event_type in [MouseEventType.MOUSE_DOWN, MouseEventType.MOUSE_UP]:
- data = ';'.join([
- event_type,
- str(ev.MousePosition.X),
- str(ev.MousePosition.Y)
- ])
- result.append(KeyPress(Keys.WindowsMouseEvent, data))
-
- return result
-
-
-class raw_mode(object):
- """
- ::
-
- with raw_mode(stdin):
- ''' the windows terminal is now in 'raw' mode. '''
-
- The ``fileno`` attribute is ignored. This is to be compatble with the
- `raw_input` method of `.vt100_input`.
- """
- def __init__(self, fileno=None):
- self.handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE))
-
- def __enter__(self):
- # Remember original mode.
- original_mode = DWORD()
- windll.kernel32.GetConsoleMode(self.handle, pointer(original_mode))
- self.original_mode = original_mode
-
- self._patch()
-
- def _patch(self):
- # Set raw
- ENABLE_ECHO_INPUT = 0x0004
- ENABLE_LINE_INPUT = 0x0002
- ENABLE_PROCESSED_INPUT = 0x0001
-
- windll.kernel32.SetConsoleMode(
- self.handle, self.original_mode.value &
- ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT))
-
- def __exit__(self, *a, **kw):
- # Restore original mode
- windll.kernel32.SetConsoleMode(self.handle, self.original_mode)
-
-
-class cooked_mode(raw_mode):
- """
- ::
-
- with cooked_mode(stdin):
- ''' the pseudo-terminal stdin is now used in raw mode '''
- """
- def _patch(self):
- # Set cooked.
- ENABLE_ECHO_INPUT = 0x0004
- ENABLE_LINE_INPUT = 0x0002
- ENABLE_PROCESSED_INPUT = 0x0001
-
- windll.kernel32.SetConsoleMode(
- self.handle, self.original_mode.value |
- (ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT))
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py
deleted file mode 100644
index d4dddbab42..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py
+++ /dev/null
@@ -1,556 +0,0 @@
-from __future__ import unicode_literals
-
-from ctypes import windll, byref, ArgumentError, c_char, c_long, c_ulong, c_uint, pointer
-from ctypes.wintypes import DWORD, HANDLE
-
-from prompt_toolkit.renderer import Output
-from prompt_toolkit.styles import ANSI_COLOR_NAMES
-from prompt_toolkit.win32_types import CONSOLE_SCREEN_BUFFER_INFO, STD_OUTPUT_HANDLE, STD_INPUT_HANDLE, COORD, SMALL_RECT
-
-import os
-import six
-
-__all__ = (
- 'Win32Output',
-)
-
-
-def _coord_byval(coord):
- """
- Turns a COORD object into a c_long.
- This will cause it to be passed by value instead of by reference. (That is what I think at least.)
-
- When runing ``ptipython`` is run (only with IPython), we often got the following error::
-
- Error in 'SetConsoleCursorPosition'.
- ArgumentError("argument 2: <class 'TypeError'>: wrong type",)
- argument 2: <class 'TypeError'>: wrong type
-
- It was solved by turning ``COORD`` parameters into a ``c_long`` like this.
-
- More info: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx
- """
- return c_long(coord.Y * 0x10000 | coord.X & 0xFFFF)
-
-
-#: If True: write the output of the renderer also to the following file. This
-#: is very useful for debugging. (e.g.: to see that we don't write more bytes
-#: than required.)
-_DEBUG_RENDER_OUTPUT = False
-_DEBUG_RENDER_OUTPUT_FILENAME = r'prompt-toolkit-windows-output.log'
-
-
-class NoConsoleScreenBufferError(Exception):
- """
- Raised when the application is not running inside a Windows Console, but
- the user tries to instantiate Win32Output.
- """
- def __init__(self):
- # Are we running in 'xterm' on Windows, like git-bash for instance?
- xterm = 'xterm' in os.environ.get('TERM', '')
-
- if xterm:
- message = ('Found %s, while expecting a Windows console. '
- 'Maybe try to run this program using "winpty" '
- 'or run it in cmd.exe instead. Or otherwise, '
- 'in case of Cygwin, use the Python executable '
- 'that is compiled for Cygwin.' % os.environ['TERM'])
- else:
- message = 'No Windows console found. Are you running cmd.exe?'
- super(NoConsoleScreenBufferError, self).__init__(message)
-
-
-class Win32Output(Output):
- """
- I/O abstraction for rendering to Windows consoles.
- (cmd.exe and similar.)
- """
- def __init__(self, stdout, use_complete_width=False):
- self.use_complete_width = use_complete_width
-
- self._buffer = []
- self.stdout = stdout
- self.hconsole = HANDLE(windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE))
-
- self._in_alternate_screen = False
-
- self.color_lookup_table = ColorLookupTable()
-
- # Remember the default console colors.
- info = self.get_win32_screen_buffer_info()
- self.default_attrs = info.wAttributes if info else 15
-
- if _DEBUG_RENDER_OUTPUT:
- self.LOG = open(_DEBUG_RENDER_OUTPUT_FILENAME, 'ab')
-
- def fileno(self):
- " Return file descriptor. "
- return self.stdout.fileno()
-
- def encoding(self):
- " Return encoding used for stdout. "
- return self.stdout.encoding
-
- def write(self, data):
- self._buffer.append(data)
-
- def write_raw(self, data):
- " For win32, there is no difference between write and write_raw. "
- self.write(data)
-
- def get_size(self):
- from prompt_toolkit.layout.screen import Size
- info = self.get_win32_screen_buffer_info()
-
- # We take the width of the *visible* region as the size. Not the width
- # of the complete screen buffer. (Unless use_complete_width has been
- # set.)
- if self.use_complete_width:
- width = info.dwSize.X
- else:
- width = info.srWindow.Right - info.srWindow.Left
-
- height = info.srWindow.Bottom - info.srWindow.Top + 1
-
- # We avoid the right margin, windows will wrap otherwise.
- maxwidth = info.dwSize.X - 1
- width = min(maxwidth, width)
-
- # Create `Size` object.
- return Size(rows=height, columns=width)
-
- def _winapi(self, func, *a, **kw):
- """
- Flush and call win API function.
- """
- self.flush()
-
- if _DEBUG_RENDER_OUTPUT:
- self.LOG.write(('%r' % func.__name__).encode('utf-8') + b'\n')
- self.LOG.write(b' ' + ', '.join(['%r' % i for i in a]).encode('utf-8') + b'\n')
- self.LOG.write(b' ' + ', '.join(['%r' % type(i) for i in a]).encode('utf-8') + b'\n')
- self.LOG.flush()
-
- try:
- return func(*a, **kw)
- except ArgumentError as e:
- if _DEBUG_RENDER_OUTPUT:
- self.LOG.write((' Error in %r %r %s\n' % (func.__name__, e, e)).encode('utf-8'))
-
- def get_win32_screen_buffer_info(self):
- """
- Return Screen buffer info.
- """
- # NOTE: We don't call the `GetConsoleScreenBufferInfo` API through
- # `self._winapi`. Doing so causes Python to crash on certain 64bit
- # Python versions. (Reproduced with 64bit Python 2.7.6, on Windows
- # 10). It is not clear why. Possibly, it has to do with passing
- # these objects as an argument, or through *args.
-
- # The Python documentation contains the following - possibly related - warning:
- # ctypes does not support passing unions or structures with
- # bit-fields to functions by value. While this may work on 32-bit
- # x86, it's not guaranteed by the library to work in the general
- # case. Unions and structures with bit-fields should always be
- # passed to functions by pointer.
-
- # Also see:
- # - https://github.com/ipython/ipython/issues/10070
- # - https://github.com/jonathanslenders/python-prompt-toolkit/issues/406
- # - https://github.com/jonathanslenders/python-prompt-toolkit/issues/86
-
- self.flush()
- sbinfo = CONSOLE_SCREEN_BUFFER_INFO()
- success = windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(sbinfo))
-
- # success = self._winapi(windll.kernel32.GetConsoleScreenBufferInfo,
- # self.hconsole, byref(sbinfo))
-
- if success:
- return sbinfo
- else:
- raise NoConsoleScreenBufferError
-
- def set_title(self, title):
- """
- Set terminal title.
- """
- assert isinstance(title, six.text_type)
- self._winapi(windll.kernel32.SetConsoleTitleW, title)
-
- def clear_title(self):
- self._winapi(windll.kernel32.SetConsoleTitleW, '')
-
- def erase_screen(self):
- start = COORD(0, 0)
- sbinfo = self.get_win32_screen_buffer_info()
- length = sbinfo.dwSize.X * sbinfo.dwSize.Y
-
- self.cursor_goto(row=0, column=0)
- self._erase(start, length)
-
- def erase_down(self):
- sbinfo = self.get_win32_screen_buffer_info()
- size = sbinfo.dwSize
-
- start = sbinfo.dwCursorPosition
- length = ((size.X - size.X) + size.X * (size.Y - sbinfo.dwCursorPosition.Y))
-
- self._erase(start, length)
-
- def erase_end_of_line(self):
- """
- """
- sbinfo = self.get_win32_screen_buffer_info()
- start = sbinfo.dwCursorPosition
- length = sbinfo.dwSize.X - sbinfo.dwCursorPosition.X
-
- self._erase(start, length)
-
- def _erase(self, start, length):
- chars_written = c_ulong()
-
- self._winapi(windll.kernel32.FillConsoleOutputCharacterA,
- self.hconsole, c_char(b' '), DWORD(length), _coord_byval(start),
- byref(chars_written))
-
- # Reset attributes.
- sbinfo = self.get_win32_screen_buffer_info()
- self._winapi(windll.kernel32.FillConsoleOutputAttribute,
- self.hconsole, sbinfo.wAttributes, length, _coord_byval(start),
- byref(chars_written))
-
- def reset_attributes(self):
- " Reset the console foreground/background color. "
- self._winapi(windll.kernel32.SetConsoleTextAttribute, self.hconsole,
- self.default_attrs)
-
- def set_attributes(self, attrs):
- fgcolor, bgcolor, bold, underline, italic, blink, reverse = attrs
-
- # Start from the default attributes.
- attrs = self.default_attrs
-
- # Override the last four bits: foreground color.
- if fgcolor is not None:
- attrs = attrs & ~0xf
- attrs |= self.color_lookup_table.lookup_fg_color(fgcolor)
-
- # Override the next four bits: background color.
- if bgcolor is not None:
- attrs = attrs & ~0xf0
- attrs |= self.color_lookup_table.lookup_bg_color(bgcolor)
-
- # Reverse: swap these four bits groups.
- if reverse:
- attrs = (attrs & ~0xff) | ((attrs & 0xf) << 4) | ((attrs & 0xf0) >> 4)
-
- self._winapi(windll.kernel32.SetConsoleTextAttribute, self.hconsole, attrs)
-
- def disable_autowrap(self):
- # Not supported by Windows.
- pass
-
- def enable_autowrap(self):
- # Not supported by Windows.
- pass
-
- def cursor_goto(self, row=0, column=0):
- pos = COORD(x=column, y=row)
- self._winapi(windll.kernel32.SetConsoleCursorPosition, self.hconsole, _coord_byval(pos))
-
- def cursor_up(self, amount):
- sr = self.get_win32_screen_buffer_info().dwCursorPosition
- pos = COORD(sr.X, sr.Y - amount)
- self._winapi(windll.kernel32.SetConsoleCursorPosition, self.hconsole, _coord_byval(pos))
-
- def cursor_down(self, amount):
- self.cursor_up(-amount)
-
- def cursor_forward(self, amount):
- sr = self.get_win32_screen_buffer_info().dwCursorPosition
-# assert sr.X + amount >= 0, 'Negative cursor position: x=%r amount=%r' % (sr.X, amount)
-
- pos = COORD(max(0, sr.X + amount), sr.Y)
- self._winapi(windll.kernel32.SetConsoleCursorPosition, self.hconsole, _coord_byval(pos))
-
- def cursor_backward(self, amount):
- self.cursor_forward(-amount)
-
- def flush(self):
- """
- Write to output stream and flush.
- """
- if not self._buffer:
- # Only flush stdout buffer. (It could be that Python still has
- # something in its buffer. -- We want to be sure to print that in
- # the correct color.)
- self.stdout.flush()
- return
-
- data = ''.join(self._buffer)
-
- if _DEBUG_RENDER_OUTPUT:
- self.LOG.write(('%r' % data).encode('utf-8') + b'\n')
- self.LOG.flush()
-
- # Print characters one by one. This appears to be the best soluton
- # in oder to avoid traces of vertical lines when the completion
- # menu disappears.
- for b in data:
- written = DWORD()
-
- retval = windll.kernel32.WriteConsoleW(self.hconsole, b, 1, byref(written), None)
- assert retval != 0
-
- self._buffer = []
-
- def get_rows_below_cursor_position(self):
- info = self.get_win32_screen_buffer_info()
- return info.srWindow.Bottom - info.dwCursorPosition.Y + 1
-
- def scroll_buffer_to_prompt(self):
- """
- To be called before drawing the prompt. This should scroll the console
- to left, with the cursor at the bottom (if possible).
- """
- # Get current window size
- info = self.get_win32_screen_buffer_info()
- sr = info.srWindow
- cursor_pos = info.dwCursorPosition
-
- result = SMALL_RECT()
-
- # Scroll to the left.
- result.Left = 0
- result.Right = sr.Right - sr.Left
-
- # Scroll vertical
- win_height = sr.Bottom - sr.Top
- if 0 < sr.Bottom - cursor_pos.Y < win_height - 1:
- # no vertical scroll if cursor already on the screen
- result.Bottom = sr.Bottom
- else:
- result.Bottom = max(win_height, cursor_pos.Y)
- result.Top = result.Bottom - win_height
-
- # Scroll API
- self._winapi(windll.kernel32.SetConsoleWindowInfo, self.hconsole, True, byref(result))
-
- def enter_alternate_screen(self):
- """
- Go to alternate screen buffer.
- """
- if not self._in_alternate_screen:
- GENERIC_READ = 0x80000000
- GENERIC_WRITE = 0x40000000
-
- # Create a new console buffer and activate that one.
- handle = HANDLE(self._winapi(windll.kernel32.CreateConsoleScreenBuffer, GENERIC_READ|GENERIC_WRITE,
- DWORD(0), None, DWORD(1), None))
-
- self._winapi(windll.kernel32.SetConsoleActiveScreenBuffer, handle)
- self.hconsole = handle
- self._in_alternate_screen = True
-
- def quit_alternate_screen(self):
- """
- Make stdout again the active buffer.
- """
- if self._in_alternate_screen:
- stdout = HANDLE(self._winapi(windll.kernel32.GetStdHandle, STD_OUTPUT_HANDLE))
- self._winapi(windll.kernel32.SetConsoleActiveScreenBuffer, stdout)
- self._winapi(windll.kernel32.CloseHandle, self.hconsole)
- self.hconsole = stdout
- self._in_alternate_screen = False
-
- def enable_mouse_support(self):
- ENABLE_MOUSE_INPUT = 0x10
- handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE))
-
- original_mode = DWORD()
- self._winapi(windll.kernel32.GetConsoleMode, handle, pointer(original_mode))
- self._winapi(windll.kernel32.SetConsoleMode, handle, original_mode.value | ENABLE_MOUSE_INPUT)
-
- def disable_mouse_support(self):
- ENABLE_MOUSE_INPUT = 0x10
- handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE))
-
- original_mode = DWORD()
- self._winapi(windll.kernel32.GetConsoleMode, handle, pointer(original_mode))
- self._winapi(windll.kernel32.SetConsoleMode, handle, original_mode.value & ~ ENABLE_MOUSE_INPUT)
-
- def hide_cursor(self):
- pass
-
- def show_cursor(self):
- pass
-
- @classmethod
- def win32_refresh_window(cls):
- """
- Call win32 API to refresh the whole Window.
-
- This is sometimes necessary when the application paints background
- for completion menus. When the menu disappears, it leaves traces due
- to a bug in the Windows Console. Sending a repaint request solves it.
- """
- # Get console handle
- handle = HANDLE(windll.kernel32.GetConsoleWindow())
-
- RDW_INVALIDATE = 0x0001
- windll.user32.RedrawWindow(handle, None, None, c_uint(RDW_INVALIDATE))
-
-
-class FOREGROUND_COLOR:
- BLACK = 0x0000
- BLUE = 0x0001
- GREEN = 0x0002
- CYAN = 0x0003
- RED = 0x0004
- MAGENTA = 0x0005
- YELLOW = 0x0006
- GRAY = 0x0007
- INTENSITY = 0x0008 # Foreground color is intensified.
-
-
-class BACKROUND_COLOR:
- BLACK = 0x0000
- BLUE = 0x0010
- GREEN = 0x0020
- CYAN = 0x0030
- RED = 0x0040
- MAGENTA = 0x0050
- YELLOW = 0x0060
- GRAY = 0x0070
- INTENSITY = 0x0080 # Background color is intensified.
-
-
-def _create_ansi_color_dict(color_cls):
- " Create a table that maps the 16 named ansi colors to their Windows code. "
- return {
- 'ansidefault': color_cls.BLACK,
- 'ansiblack': color_cls.BLACK,
- 'ansidarkgray': color_cls.BLACK | color_cls.INTENSITY,
- 'ansilightgray': color_cls.GRAY,
- 'ansiwhite': color_cls.GRAY | color_cls.INTENSITY,
-
- # Low intensity.
- 'ansidarkred': color_cls.RED,
- 'ansidarkgreen': color_cls.GREEN,
- 'ansibrown': color_cls.YELLOW,
- 'ansidarkblue': color_cls.BLUE,
- 'ansipurple': color_cls.MAGENTA,
- 'ansiteal': color_cls.CYAN,
-
- # High intensity.
- 'ansired': color_cls.RED | color_cls.INTENSITY,
- 'ansigreen': color_cls.GREEN | color_cls.INTENSITY,
- 'ansiyellow': color_cls.YELLOW | color_cls.INTENSITY,
- 'ansiblue': color_cls.BLUE | color_cls.INTENSITY,
- 'ansifuchsia': color_cls.MAGENTA | color_cls.INTENSITY,
- 'ansiturquoise': color_cls.CYAN | color_cls.INTENSITY,
- }
-
-FG_ANSI_COLORS = _create_ansi_color_dict(FOREGROUND_COLOR)
-BG_ANSI_COLORS = _create_ansi_color_dict(BACKROUND_COLOR)
-
-assert set(FG_ANSI_COLORS) == set(ANSI_COLOR_NAMES)
-assert set(BG_ANSI_COLORS) == set(ANSI_COLOR_NAMES)
-
-
-class ColorLookupTable(object):
- """
- Inspired by pygments/formatters/terminal256.py
- """
- def __init__(self):
- self._win32_colors = self._build_color_table()
- self.best_match = {} # Cache
-
- @staticmethod
- def _build_color_table():
- """
- Build an RGB-to-256 color conversion table
- """
- FG = FOREGROUND_COLOR
- BG = BACKROUND_COLOR
-
- return [
- (0x00, 0x00, 0x00, FG.BLACK, BG.BLACK),
- (0x00, 0x00, 0xaa, FG.BLUE, BG.BLUE),
- (0x00, 0xaa, 0x00, FG.GREEN, BG.GREEN),
- (0x00, 0xaa, 0xaa, FG.CYAN, BG.CYAN),
- (0xaa, 0x00, 0x00, FG.RED, BG.RED),
- (0xaa, 0x00, 0xaa, FG.MAGENTA, BG.MAGENTA),
- (0xaa, 0xaa, 0x00, FG.YELLOW, BG.YELLOW),
- (0x88, 0x88, 0x88, FG.GRAY, BG.GRAY),
-
- (0x44, 0x44, 0xff, FG.BLUE | FG.INTENSITY, BG.BLUE | BG.INTENSITY),
- (0x44, 0xff, 0x44, FG.GREEN | FG.INTENSITY, BG.GREEN | BG.INTENSITY),
- (0x44, 0xff, 0xff, FG.CYAN | FG.INTENSITY, BG.CYAN | BG.INTENSITY),
- (0xff, 0x44, 0x44, FG.RED | FG.INTENSITY, BG.RED | BG.INTENSITY),
- (0xff, 0x44, 0xff, FG.MAGENTA | FG.INTENSITY, BG.MAGENTA | BG.INTENSITY),
- (0xff, 0xff, 0x44, FG.YELLOW | FG.INTENSITY, BG.YELLOW | BG.INTENSITY),
-
- (0x44, 0x44, 0x44, FG.BLACK | FG.INTENSITY, BG.BLACK | BG.INTENSITY),
- (0xff, 0xff, 0xff, FG.GRAY | FG.INTENSITY, BG.GRAY | BG.INTENSITY),
- ]
-
- def _closest_color(self, r, g, b):
- distance = 257 * 257 * 3 # "infinity" (>distance from #000000 to #ffffff)
- fg_match = 0
- bg_match = 0
-
- for r_, g_, b_, fg_, bg_ in self._win32_colors:
- rd = r - r_
- gd = g - g_
- bd = b - b_
-
- d = rd * rd + gd * gd + bd * bd
-
- if d < distance:
- fg_match = fg_
- bg_match = bg_
- distance = d
- return fg_match, bg_match
-
- def _color_indexes(self, color):
- indexes = self.best_match.get(color, None)
- if indexes is None:
- try:
- rgb = int(str(color), 16)
- except ValueError:
- rgb = 0
-
- r = (rgb >> 16) & 0xff
- g = (rgb >> 8) & 0xff
- b = rgb & 0xff
- indexes = self._closest_color(r, g, b)
- self.best_match[color] = indexes
- return indexes
-
- def lookup_fg_color(self, fg_color):
- """
- Return the color for use in the
- `windll.kernel32.SetConsoleTextAttribute` API call.
-
- :param fg_color: Foreground as text. E.g. 'ffffff' or 'red'
- """
- # Foreground.
- if fg_color in FG_ANSI_COLORS:
- return FG_ANSI_COLORS[fg_color]
- else:
- return self._color_indexes(fg_color)[0]
-
- def lookup_bg_color(self, bg_color):
- """
- Return the color for use in the
- `windll.kernel32.SetConsoleTextAttribute` API call.
-
- :param bg_color: Background as text. E.g. 'ffffff' or 'red'
- """
- # Background.
- if bg_color in BG_ANSI_COLORS:
- return BG_ANSI_COLORS[bg_color]
- else:
- return self._color_indexes(bg_color)[1]
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/token.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/token.py
deleted file mode 100644
index 5170daf38a..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/token.py
+++ /dev/null
@@ -1,47 +0,0 @@
-"""
-The Token class, interchangeable with ``pygments.token``.
-
-A `Token` has some semantics for a piece of text that is given a style through
-a :class:`~prompt_toolkit.styles.Style` class. A pygments lexer for instance,
-returns a list of (Token, text) tuples. Each fragment of text has a token
-assigned, which when combined with a style sheet, will determine the fine
-style.
-"""
-
-# If we don't need any lexers or style classes from Pygments, we don't want
-# Pygments to be installed for only the following 10 lines of code. So, there
-# is some duplication, but this should stay compatible with Pygments.
-
-__all__ = (
- 'Token',
- 'ZeroWidthEscape',
-)
-
-
-class _TokenType(tuple):
- def __getattr__(self, val):
- if not val or not val[0].isupper():
- return tuple.__getattribute__(self, val)
-
- new = _TokenType(self + (val,))
- setattr(self, val, new)
- return new
-
- def __repr__(self):
- return 'Token' + (self and '.' or '') + '.'.join(self)
-
-
-# Prefer the Token class from Pygments. If Pygments is not installed, use our
-# minimalistic Token class.
-try:
- from pygments.token import Token
-except ImportError:
- Token = _TokenType()
-
-
-# Built-in tokens:
-
-#: `ZeroWidthEscape` can be used for raw VT escape sequences that don't
-#: cause the cursor position to move. (E.g. FinalTerm's escape sequences
-#: for shell integration.)
-ZeroWidthEscape = Token.ZeroWidthEscape
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/utils.py
deleted file mode 100644
index 3cd931883c..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/utils.py
+++ /dev/null
@@ -1,240 +0,0 @@
-from __future__ import unicode_literals
-import inspect
-import os
-import signal
-import sys
-import threading
-import weakref
-
-from wcwidth import wcwidth
-from six.moves import range
-
-
-__all__ = (
- 'Event',
- 'DummyContext',
- 'get_cwidth',
- 'suspend_to_background_supported',
- 'is_conemu_ansi',
- 'is_windows',
- 'in_main_thread',
- 'take_using_weights',
- 'test_callable_args',
-)
-
-
-class Event(object):
- """
- Simple event to which event handlers can be attached. For instance::
-
- class Cls:
- def __init__(self):
- # Define event. The first parameter is the sender.
- self.event = Event(self)
-
- obj = Cls()
-
- def handler(sender):
- pass
-
- # Add event handler by using the += operator.
- obj.event += handler
-
- # Fire event.
- obj.event()
- """
- def __init__(self, sender, handler=None):
- self.sender = sender
- self._handlers = []
-
- if handler is not None:
- self += handler
-
- def __call__(self):
- " Fire event. "
- for handler in self._handlers:
- handler(self.sender)
-
- def fire(self):
- " Alias for just calling the event. "
- self()
-
- def __iadd__(self, handler):
- """
- Add another handler to this callback.
- (Handler should be a callable that takes exactly one parameter: the
- sender object.)
- """
- # Test handler.
- assert callable(handler)
- if not test_callable_args(handler, [None]):
- raise TypeError("%r doesn't take exactly one argument." % handler)
-
- # Add to list of event handlers.
- self._handlers.append(handler)
- return self
-
- def __isub__(self, handler):
- """
- Remove a handler from this callback.
- """
- self._handlers.remove(handler)
- return self
-
-
-# Cache of signatures. Improves the performance of `test_callable_args`.
-_signatures_cache = weakref.WeakKeyDictionary()
-
-
-def test_callable_args(func, args):
- """
- Return True when this function can be called with the given arguments.
- """
- assert isinstance(args, (list, tuple))
- signature = getattr(inspect, 'signature', None)
-
- if signature is not None:
- # For Python 3, use inspect.signature.
- try:
- sig = _signatures_cache[func]
- except KeyError:
- sig = signature(func)
- _signatures_cache[func] = sig
-
- try:
- sig.bind(*args)
- except TypeError:
- return False
- else:
- return True
- else:
- # For older Python versions, fall back to using getargspec.
- spec = inspect.getargspec(func)
-
- # Drop the 'self'
- def drop_self(spec):
- args, varargs, varkw, defaults = spec
- if args[0:1] == ['self']:
- args = args[1:]
- return inspect.ArgSpec(args, varargs, varkw, defaults)
-
- spec = drop_self(spec)
-
- # When taking *args, always return True.
- if spec.varargs is not None:
- return True
-
- # Test whether the given amount of args is between the min and max
- # accepted argument counts.
- return len(spec.args) - len(spec.defaults or []) <= len(args) <= len(spec.args)
-
-
-class DummyContext(object):
- """
- (contextlib.nested is not available on Py3)
- """
- def __enter__(self):
- pass
-
- def __exit__(self, *a):
- pass
-
-
-class _CharSizesCache(dict):
- """
- Cache for wcwidth sizes.
- """
- def __missing__(self, string):
- # Note: We use the `max(0, ...` because some non printable control
- # characters, like e.g. Ctrl-underscore get a -1 wcwidth value.
- # It can be possible that these characters end up in the input
- # text.
- if len(string) == 1:
- result = max(0, wcwidth(string))
- else:
- result = sum(max(0, wcwidth(c)) for c in string)
-
- # Cache for short strings.
- # (It's hard to tell what we can consider short...)
- if len(string) < 256:
- self[string] = result
-
- return result
-
-
-_CHAR_SIZES_CACHE = _CharSizesCache()
-
-
-def get_cwidth(string):
- """
- Return width of a string. Wrapper around ``wcwidth``.
- """
- return _CHAR_SIZES_CACHE[string]
-
-
-def suspend_to_background_supported():
- """
- Returns `True` when the Python implementation supports
- suspend-to-background. This is typically `False' on Windows systems.
- """
- return hasattr(signal, 'SIGTSTP')
-
-
-def is_windows():
- """
- True when we are using Windows.
- """
- return sys.platform.startswith('win') # E.g. 'win32', not 'darwin' or 'linux2'
-
-
-def is_conemu_ansi():
- """
- True when the ConEmu Windows console is used.
- """
- return is_windows() and os.environ.get('ConEmuANSI', 'OFF') == 'ON'
-
-
-def in_main_thread():
- """
- True when the current thread is the main thread.
- """
- return threading.current_thread().__class__.__name__ == '_MainThread'
-
-
-def take_using_weights(items, weights):
- """
- Generator that keeps yielding items from the items list, in proportion to
- their weight. For instance::
-
- # Getting the first 70 items from this generator should have yielded 10
- # times A, 20 times B and 40 times C, all distributed equally..
- take_using_weights(['A', 'B', 'C'], [5, 10, 20])
-
- :param items: List of items to take from.
- :param weights: Integers representing the weight. (Numbers have to be
- integers, not floats.)
- """
- assert isinstance(items, list)
- assert isinstance(weights, list)
- assert all(isinstance(i, int) for i in weights)
- assert len(items) == len(weights)
- assert len(items) > 0
-
- already_taken = [0 for i in items]
- item_count = len(items)
- max_weight = max(weights)
-
- i = 0
- while True:
- # Each iteration of this loop, we fill up until by (total_weight/max_weight).
- adding = True
- while adding:
- adding = False
-
- for item_i, item, weight in zip(range(item_count), items, weights):
- if already_taken[item_i] < i * weight / float(max_weight):
- yield item
- already_taken[item_i] += 1
- adding = True
-
- i += 1
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/validation.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/validation.py
deleted file mode 100644
index 0027873f88..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/validation.py
+++ /dev/null
@@ -1,64 +0,0 @@
-"""
-Input validation for a `Buffer`.
-(Validators will be called before accepting input.)
-"""
-from __future__ import unicode_literals
-from .filters import to_simple_filter
-
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
-
-__all__ = (
- 'ConditionalValidator',
- 'ValidationError',
- 'Validator',
-)
-
-
-class ValidationError(Exception):
- """
- Error raised by :meth:`.Validator.validate`.
-
- :param cursor_position: The cursor position where the error occured.
- :param message: Text.
- """
- def __init__(self, cursor_position=0, message=''):
- super(ValidationError, self).__init__(message)
- self.cursor_position = cursor_position
- self.message = message
-
- def __repr__(self):
- return '%s(cursor_position=%r, message=%r)' % (
- self.__class__.__name__, self.cursor_position, self.message)
-
-
-class Validator(with_metaclass(ABCMeta, object)):
- """
- Abstract base class for an input validator.
- """
- @abstractmethod
- def validate(self, document):
- """
- Validate the input.
- If invalid, this should raise a :class:`.ValidationError`.
-
- :param document: :class:`~prompt_toolkit.document.Document` instance.
- """
- pass
-
-
-class ConditionalValidator(Validator):
- """
- Validator that can be switched on/off according to
- a filter. (This wraps around another validator.)
- """
- def __init__(self, validator, filter):
- assert isinstance(validator, Validator)
-
- self.validator = validator
- self.filter = to_simple_filter(filter)
-
- def validate(self, document):
- # Call the validator only if the filter is active.
- if self.filter():
- self.validator.validate(document)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/win32_types.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/win32_types.py
deleted file mode 100644
index ba2d90df8e..0000000000
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/win32_types.py
+++ /dev/null
@@ -1,155 +0,0 @@
-from ctypes import Union, Structure, c_char, c_short, c_long, c_ulong
-from ctypes.wintypes import DWORD, BOOL, LPVOID, WORD, WCHAR
-
-
-# Input/Output standard device numbers. Note that these are not handle objects.
-# It's the `windll.kernel32.GetStdHandle` system call that turns them into a
-# real handle object.
-STD_INPUT_HANDLE = c_ulong(-10)
-STD_OUTPUT_HANDLE = c_ulong(-11)
-STD_ERROR_HANDLE = c_ulong(-12)
-
-
-class COORD(Structure):
- """
- Struct in wincon.h
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119(v=vs.85).aspx
- """
- _fields_ = [
- ('X', c_short), # Short
- ('Y', c_short), # Short
- ]
-
- def __repr__(self):
- return '%s(X=%r, Y=%r, type_x=%r, type_y=%r)' % (
- self.__class__.__name__, self.X, self.Y, type(self.X), type(self.Y))
-
-
-class UNICODE_OR_ASCII(Union):
- _fields_ = [
- ('AsciiChar', c_char),
- ('UnicodeChar', WCHAR),
- ]
-
-
-class KEY_EVENT_RECORD(Structure):
- """
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms684166(v=vs.85).aspx
- """
- _fields_ = [
- ('KeyDown', c_long), # bool
- ('RepeatCount', c_short), # word
- ('VirtualKeyCode', c_short), # word
- ('VirtualScanCode', c_short), # word
- ('uChar', UNICODE_OR_ASCII), # Unicode or ASCII.
- ('ControlKeyState', c_long) # double word
- ]
-
-
-class MOUSE_EVENT_RECORD(Structure):
- """
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms684239(v=vs.85).aspx
- """
- _fields_ = [
- ('MousePosition', COORD),
- ('ButtonState', c_long), # dword
- ('ControlKeyState', c_long), # dword
- ('EventFlags', c_long) # dword
- ]
-
-
-class WINDOW_BUFFER_SIZE_RECORD(Structure):
- """
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms687093(v=vs.85).aspx
- """
- _fields_ = [
- ('Size', COORD)
- ]
-
-
-class MENU_EVENT_RECORD(Structure):
- """
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms684213(v=vs.85).aspx
- """
- _fields_ = [
- ('CommandId', c_long) # uint
- ]
-
-
-class FOCUS_EVENT_RECORD(Structure):
- """
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms683149(v=vs.85).aspx
- """
- _fields_ = [
- ('SetFocus', c_long) # bool
- ]
-
-
-class EVENT_RECORD(Union):
- _fields_ = [
- ('KeyEvent', KEY_EVENT_RECORD),
- ('MouseEvent', MOUSE_EVENT_RECORD),
- ('WindowBufferSizeEvent', WINDOW_BUFFER_SIZE_RECORD),
- ('MenuEvent', MENU_EVENT_RECORD),
- ('FocusEvent', FOCUS_EVENT_RECORD)
- ]
-
-
-class INPUT_RECORD(Structure):
- """
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx
- """
- _fields_ = [
- ('EventType', c_short), # word
- ('Event', EVENT_RECORD) # Union.
- ]
-
-
-EventTypes = {
- 1: 'KeyEvent',
- 2: 'MouseEvent',
- 4: 'WindowBufferSizeEvent',
- 8: 'MenuEvent',
- 16: 'FocusEvent'
-}
-
-
-class SMALL_RECT(Structure):
- """struct in wincon.h."""
- _fields_ = [
- ("Left", c_short),
- ("Top", c_short),
- ("Right", c_short),
- ("Bottom", c_short),
- ]
-
-
-class CONSOLE_SCREEN_BUFFER_INFO(Structure):
- """struct in wincon.h."""
- _fields_ = [
- ("dwSize", COORD),
- ("dwCursorPosition", COORD),
- ("wAttributes", WORD),
- ("srWindow", SMALL_RECT),
- ("dwMaximumWindowSize", COORD),
- ]
-
- def __str__(self):
- return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
- self.dwSize.Y, self.dwSize.X,
- self.dwCursorPosition.Y, self.dwCursorPosition.X,
- self.wAttributes,
- self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right,
- self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X,
- )
-
-
-class SECURITY_ATTRIBUTES(Structure):
- """
- http://msdn.microsoft.com/en-us/library/windows/desktop/aa379560(v=vs.85).aspx
- """
- _fields_ = [
- ('nLength', DWORD),
- ('lpSecurityDescriptor', LPVOID),
- ('bInheritHandle', BOOL),
- ]
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_buffer.py b/contrib/python/prompt-toolkit/py2/tests/test_buffer.py
deleted file mode 100644
index a9cff19024..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_buffer.py
+++ /dev/null
@@ -1,111 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.buffer import Buffer
-
-import pytest
-
-
-@pytest.fixture
-def _buffer():
- return Buffer()
-
-
-def test_initial(_buffer):
- assert _buffer.text == ''
- assert _buffer.cursor_position == 0
-
-
-def test_insert_text(_buffer):
- _buffer.insert_text('some_text')
- assert _buffer.text == 'some_text'
- assert _buffer.cursor_position == len('some_text')
-
-
-def test_cursor_movement(_buffer):
- _buffer.insert_text('some_text')
- _buffer.cursor_left()
- _buffer.cursor_left()
- _buffer.cursor_left()
- _buffer.cursor_right()
- _buffer.insert_text('A')
-
- assert _buffer.text == 'some_teAxt'
- assert _buffer.cursor_position == len('some_teA')
-
-
-def test_backspace(_buffer):
- _buffer.insert_text('some_text')
- _buffer.cursor_left()
- _buffer.cursor_left()
- _buffer.delete_before_cursor()
-
- assert _buffer.text == 'some_txt'
- assert _buffer.cursor_position == len('some_t')
-
-
-def test_cursor_up(_buffer):
- # Cursor up to a line thats longer.
- _buffer.insert_text('long line1\nline2')
- _buffer.cursor_up()
-
- assert _buffer.document.cursor_position == 5
-
- # Going up when already at the top.
- _buffer.cursor_up()
- assert _buffer.document.cursor_position == 5
-
- # Going up to a line that's shorter.
- _buffer.reset()
- _buffer.insert_text('line1\nlong line2')
-
- _buffer.cursor_up()
- assert _buffer.document.cursor_position == 5
-
-
-def test_cursor_down(_buffer):
- _buffer.insert_text('line1\nline2')
- _buffer.cursor_position = 3
-
- # Normally going down
- _buffer.cursor_down()
- assert _buffer.document.cursor_position == len('line1\nlin')
-
- # Going down to a line that's storter.
- _buffer.reset()
- _buffer.insert_text('long line1\na\nb')
- _buffer.cursor_position = 3
-
- _buffer.cursor_down()
- assert _buffer.document.cursor_position == len('long line1\na')
-
-
-def test_join_next_line(_buffer):
- _buffer.insert_text('line1\nline2\nline3')
- _buffer.cursor_up()
- _buffer.join_next_line()
-
- assert _buffer.text == 'line1\nline2 line3'
-
- # Test when there is no '\n' in the text
- _buffer.reset()
- _buffer.insert_text('line1')
- _buffer.cursor_position = 0
- _buffer.join_next_line()
-
- assert _buffer.text == 'line1'
-
-
-def test_newline(_buffer):
- _buffer.insert_text('hello world')
- _buffer.newline()
-
- assert _buffer.text == 'hello world\n'
-
-
-def test_swap_characters_before_cursor(_buffer):
- _buffer.insert_text('hello world')
- _buffer.cursor_left()
- _buffer.cursor_left()
- _buffer.swap_characters_before_cursor()
-
- assert _buffer.text == 'hello wrold'
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_cli.py b/contrib/python/prompt-toolkit/py2/tests/test_cli.py
deleted file mode 100644
index 68ca3d03f0..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_cli.py
+++ /dev/null
@@ -1,629 +0,0 @@
-# encoding: utf-8
-"""
-These are almost end-to-end tests. They create a CommandLineInterface
-instance, feed it with some input and check the result.
-"""
-from __future__ import unicode_literals
-from prompt_toolkit.application import Application
-from prompt_toolkit.buffer import Buffer, AcceptAction
-from prompt_toolkit.clipboard import InMemoryClipboard, ClipboardData
-from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
-from prompt_toolkit.eventloop.posix import PosixEventLoop
-from prompt_toolkit.history import InMemoryHistory
-from prompt_toolkit.input import PipeInput
-from prompt_toolkit.interface import CommandLineInterface
-from prompt_toolkit.key_binding.manager import KeyBindingManager
-from prompt_toolkit.output import DummyOutput
-from prompt_toolkit.terminal.vt100_input import ANSI_SEQUENCES
-from functools import partial
-import pytest
-
-
-def _history():
- h = InMemoryHistory()
- h.append('line1 first input')
- h.append('line2 second input')
- h.append('line3 third input')
- return h
-
-
-def _feed_cli_with_input(text, editing_mode=EditingMode.EMACS, clipboard=None,
- history=None, multiline=False, check_line_ending=True,
- pre_run_callback=None):
- """
- Create a CommandLineInterface, feed it with the given user input and return
- the CLI object.
-
- This returns a (result, CLI) tuple.
- """
- # If the given text doesn't end with a newline, the interface won't finish.
- if check_line_ending:
- assert text.endswith('\n')
-
- loop = PosixEventLoop()
- try:
- inp = PipeInput()
- inp.send_text(text)
- cli = CommandLineInterface(
- application=Application(
- buffer=Buffer(accept_action=AcceptAction.RETURN_DOCUMENT,
- history=history, is_multiline=multiline),
- editing_mode=editing_mode,
- clipboard=clipboard or InMemoryClipboard(),
- key_bindings_registry=KeyBindingManager.for_prompt().registry,
- ),
- eventloop=loop,
- input=inp,
- output=DummyOutput())
-
- if pre_run_callback:
- pre_run_callback(cli)
-
- result = cli.run()
- return result, cli
- finally:
- loop.close()
- inp.close()
-
-
-def test_simple_text_input():
- # Simple text input, followed by enter.
- result, cli = _feed_cli_with_input('hello\n')
- assert result.text == 'hello'
- assert cli.buffers[DEFAULT_BUFFER].text == 'hello'
-
-
-def test_emacs_cursor_movements():
- """
- Test cursor movements with Emacs key bindings.
- """
- # ControlA (beginning-of-line)
- result, cli = _feed_cli_with_input('hello\x01X\n')
- assert result.text == 'Xhello'
-
- # ControlE (end-of-line)
- result, cli = _feed_cli_with_input('hello\x01X\x05Y\n')
- assert result.text == 'XhelloY'
-
- # ControlH or \b
- result, cli = _feed_cli_with_input('hello\x08X\n')
- assert result.text == 'hellX'
-
- # Delete. (Left, left, delete)
- result, cli = _feed_cli_with_input('hello\x1b[D\x1b[D\x1b[3~\n')
- assert result.text == 'helo'
-
- # Left.
- result, cli = _feed_cli_with_input('hello\x1b[DX\n')
- assert result.text == 'hellXo'
-
- # ControlA, right
- result, cli = _feed_cli_with_input('hello\x01\x1b[CX\n')
- assert result.text == 'hXello'
-
- # ControlA, right
- result, cli = _feed_cli_with_input('hello\x01\x1b[CX\n')
- assert result.text == 'hXello'
-
- # ControlB (backward-char)
- result, cli = _feed_cli_with_input('hello\x02X\n')
- assert result.text == 'hellXo'
-
- # ControlF (forward-char)
- result, cli = _feed_cli_with_input('hello\x01\x06X\n')
- assert result.text == 'hXello'
-
- # ControlC: raise KeyboardInterrupt.
- with pytest.raises(KeyboardInterrupt):
- result, cli = _feed_cli_with_input('hello\x03\n')
- assert result.text == 'hello'
-
- # ControlD without any input: raises EOFError.
- with pytest.raises(EOFError):
- result, cli = _feed_cli_with_input('\x04\n')
- assert result.text == 'hello'
-
- # ControlD: delete after cursor.
- result, cli = _feed_cli_with_input('hello\x01\x04\n')
- assert result.text == 'ello'
-
- # ControlD at the end of the input ssshould not do anything.
- result, cli = _feed_cli_with_input('hello\x04\n')
- assert result.text == 'hello'
-
- # Left, Left, ControlK (kill-line)
- result, cli = _feed_cli_with_input('hello\x1b[D\x1b[D\x0b\n')
- assert result.text == 'hel'
-
- # Left, Left Esc- ControlK (kill-line, but negative)
- result, cli = _feed_cli_with_input('hello\x1b[D\x1b[D\x1b-\x0b\n')
- assert result.text == 'lo'
-
- # ControlL: should not influence the result.
- result, cli = _feed_cli_with_input('hello\x0c\n')
- assert result.text == 'hello'
-
- # ControlRight (forward-word)
- result, cli = _feed_cli_with_input('hello world\x01X\x1b[1;5CY\n')
- assert result.text == 'XhelloY world'
-
- # ContrlolLeft (backward-word)
- result, cli = _feed_cli_with_input('hello world\x1b[1;5DY\n')
- assert result.text == 'hello Yworld'
-
- # <esc>-f with argument. (forward-word)
- result, cli = _feed_cli_with_input('hello world abc def\x01\x1b3\x1bfX\n')
- assert result.text == 'hello world abcX def'
-
- # <esc>-f with negative argument. (forward-word)
- result, cli = _feed_cli_with_input('hello world abc def\x1b-\x1b3\x1bfX\n')
- assert result.text == 'hello Xworld abc def'
-
- # <esc>-b with argument. (backward-word)
- result, cli = _feed_cli_with_input('hello world abc def\x1b3\x1bbX\n')
- assert result.text == 'hello Xworld abc def'
-
- # <esc>-b with negative argument. (backward-word)
- result, cli = _feed_cli_with_input('hello world abc def\x01\x1b-\x1b3\x1bbX\n')
- assert result.text == 'hello world abc Xdef'
-
- # ControlW (kill-word / unix-word-rubout)
- result, cli = _feed_cli_with_input('hello world\x17\n')
- assert result.text == 'hello '
- assert cli.clipboard.get_data().text == 'world'
-
- result, cli = _feed_cli_with_input('test hello world\x1b2\x17\n')
- assert result.text == 'test '
-
- # Escape Backspace (unix-word-rubout)
- result, cli = _feed_cli_with_input('hello world\x1b\x7f\n')
- assert result.text == 'hello '
- assert cli.clipboard.get_data().text == 'world'
-
- result, cli = _feed_cli_with_input('hello world\x1b\x08\n')
- assert result.text == 'hello '
- assert cli.clipboard.get_data().text == 'world'
-
- # Backspace (backward-delete-char)
- result, cli = _feed_cli_with_input('hello world\x7f\n')
- assert result.text == 'hello worl'
- assert result.cursor_position == len('hello worl')
-
- result, cli = _feed_cli_with_input('hello world\x08\n')
- assert result.text == 'hello worl'
- assert result.cursor_position == len('hello worl')
-
- # Delete (delete-char)
- result, cli = _feed_cli_with_input('hello world\x01\x1b[3~\n')
- assert result.text == 'ello world'
- assert result.cursor_position == 0
-
- # Escape-\\ (delete-horizontal-space)
- result, cli = _feed_cli_with_input('hello world\x1b8\x02\x1b\\\n')
- assert result.text == 'helloworld'
- assert result.cursor_position == len('hello')
-
-
-def test_emacs_yank():
- # ControlY (yank)
- c = InMemoryClipboard(ClipboardData('XYZ'))
- result, cli = _feed_cli_with_input('hello\x02\x19\n', clipboard=c)
- assert result.text == 'hellXYZo'
- assert result.cursor_position == len('hellXYZ')
-
-
-def test_quoted_insert():
- # ControlQ - ControlB (quoted-insert)
- result, cli = _feed_cli_with_input('hello\x11\x02\n')
- assert result.text == 'hello\x02'
-
-
-def test_transformations():
- # Meta-c (capitalize-word)
- result, cli = _feed_cli_with_input('hello world\01\x1bc\n')
- assert result.text == 'Hello world'
- assert result.cursor_position == len('Hello')
-
- # Meta-u (uppercase-word)
- result, cli = _feed_cli_with_input('hello world\01\x1bu\n')
- assert result.text == 'HELLO world'
- assert result.cursor_position == len('Hello')
-
- # Meta-u (downcase-word)
- result, cli = _feed_cli_with_input('HELLO WORLD\01\x1bl\n')
- assert result.text == 'hello WORLD'
- assert result.cursor_position == len('Hello')
-
- # ControlT (transpose-chars)
- result, cli = _feed_cli_with_input('hello\x14\n')
- assert result.text == 'helol'
- assert result.cursor_position == len('hello')
-
- # Left, Left, Control-T (transpose-chars)
- result, cli = _feed_cli_with_input('abcde\x1b[D\x1b[D\x14\n')
- assert result.text == 'abdce'
- assert result.cursor_position == len('abcd')
-
-
-def test_emacs_other_bindings():
- # Transpose characters.
- result, cli = _feed_cli_with_input('abcde\x14X\n') # Ctrl-T
- assert result.text == 'abcedX'
-
- # Left, Left, Transpose. (This is slightly different.)
- result, cli = _feed_cli_with_input('abcde\x1b[D\x1b[D\x14X\n')
- assert result.text == 'abdcXe'
-
- # Clear before cursor.
- result, cli = _feed_cli_with_input('hello\x1b[D\x1b[D\x15X\n')
- assert result.text == 'Xlo'
-
- # unix-word-rubout: delete word before the cursor.
- # (ControlW).
- result, cli = _feed_cli_with_input('hello world test\x17X\n')
- assert result.text == 'hello world X'
-
- result, cli = _feed_cli_with_input('hello world /some/very/long/path\x17X\n')
- assert result.text == 'hello world X'
-
- # (with argument.)
- result, cli = _feed_cli_with_input('hello world test\x1b2\x17X\n')
- assert result.text == 'hello X'
-
- result, cli = _feed_cli_with_input('hello world /some/very/long/path\x1b2\x17X\n')
- assert result.text == 'hello X'
-
- # backward-kill-word: delete word before the cursor.
- # (Esc-ControlH).
- result, cli = _feed_cli_with_input('hello world /some/very/long/path\x1b\x08X\n')
- assert result.text == 'hello world /some/very/long/X'
-
- # (with arguments.)
- result, cli = _feed_cli_with_input('hello world /some/very/long/path\x1b3\x1b\x08X\n')
- assert result.text == 'hello world /some/very/X'
-
-
-def test_controlx_controlx():
- # At the end: go to the start of the line.
- result, cli = _feed_cli_with_input('hello world\x18\x18X\n')
- assert result.text == 'Xhello world'
- assert result.cursor_position == 1
-
- # At the start: go to the end of the line.
- result, cli = _feed_cli_with_input('hello world\x01\x18\x18X\n')
- assert result.text == 'hello worldX'
-
- # Left, Left Control-X Control-X: go to the end of the line.
- result, cli = _feed_cli_with_input('hello world\x1b[D\x1b[D\x18\x18X\n')
- assert result.text == 'hello worldX'
-
-
-def test_emacs_history_bindings():
- # Adding a new item to the history.
- history = _history()
- result, cli = _feed_cli_with_input('new input\n', history=history)
- assert result.text == 'new input'
- history.strings[-1] == 'new input'
-
- # Go up in history, and accept the last item.
- result, cli = _feed_cli_with_input('hello\x1b[A\n', history=history)
- assert result.text == 'new input'
-
- # Esc< (beginning-of-history)
- result, cli = _feed_cli_with_input('hello\x1b<\n', history=history)
- assert result.text == 'line1 first input'
-
- # Esc> (end-of-history)
- result, cli = _feed_cli_with_input('another item\x1b[A\x1b[a\x1b>\n', history=history)
- assert result.text == 'another item'
-
- # ControlUp (previous-history)
- result, cli = _feed_cli_with_input('\x1b[1;5A\n', history=history)
- assert result.text == 'another item'
-
- # Esc< ControlDown (beginning-of-history, next-history)
- result, cli = _feed_cli_with_input('\x1b<\x1b[1;5B\n', history=history)
- assert result.text == 'line2 second input'
-
-
-def test_emacs_reverse_search():
- history = _history()
-
- # ControlR (reverse-search-history)
- result, cli = _feed_cli_with_input('\x12input\n\n', history=history)
- assert result.text == 'line3 third input'
-
- # Hitting ControlR twice.
- result, cli = _feed_cli_with_input('\x12input\x12\n\n', history=history)
- assert result.text == 'line2 second input'
-
-
-def test_emacs_arguments():
- """
- Test various combinations of arguments in Emacs mode.
- """
- # esc 4
- result, cli = _feed_cli_with_input('\x1b4x\n')
- assert result.text == 'xxxx'
-
- # esc 4 4
- result, cli = _feed_cli_with_input('\x1b44x\n')
- assert result.text == 'x' * 44
-
- # esc 4 esc 4
- result, cli = _feed_cli_with_input('\x1b4\x1b4x\n')
- assert result.text == 'x' * 44
-
- # esc - right (-1 position to the right, equals 1 to the left.)
- result, cli = _feed_cli_with_input('aaaa\x1b-\x1b[Cbbbb\n')
- assert result.text == 'aaabbbba'
-
- # esc - 3 right
- result, cli = _feed_cli_with_input('aaaa\x1b-3\x1b[Cbbbb\n')
- assert result.text == 'abbbbaaa'
-
- # esc - - - 3 right
- result, cli = _feed_cli_with_input('aaaa\x1b---3\x1b[Cbbbb\n')
- assert result.text == 'abbbbaaa'
-
-
-def test_emacs_arguments_for_all_commands():
- """
- Test all Emacs commands with Meta-[0-9] arguments (both positive and
- negative). No one should crash.
- """
- for key in ANSI_SEQUENCES:
- # Ignore BracketedPaste. This would hang forever, because it waits for
- # the end sequence.
- if key != '\x1b[200~':
- try:
- # Note: we add an 'X' after the key, because Ctrl-Q (quoted-insert)
- # expects something to follow. We add an additional \n, because
- # Ctrl-R and Ctrl-S (reverse-search) expect that.
- result, cli = _feed_cli_with_input(
- 'hello\x1b4' + key + 'X\n\n')
-
- result, cli = _feed_cli_with_input(
- 'hello\x1b-' + key + 'X\n\n')
- except KeyboardInterrupt:
- # This exception should only be raised for Ctrl-C
- assert key == '\x03'
-
-
-def test_emacs_kill_ring():
- operations = (
- # abc ControlA ControlK
- 'abc\x01\x0b'
-
- # def ControlA ControlK
- 'def\x01\x0b'
-
- # ghi ControlA ControlK
- 'ghi\x01\x0b'
-
- # ControlY (yank)
- '\x19'
- )
-
- result, cli = _feed_cli_with_input(operations + '\n')
- assert result.text == 'ghi'
-
- result, cli = _feed_cli_with_input(operations + '\x1by\n')
- assert result.text == 'def'
-
- result, cli = _feed_cli_with_input(operations + '\x1by\x1by\n')
- assert result.text == 'abc'
-
- result, cli = _feed_cli_with_input(operations + '\x1by\x1by\x1by\n')
- assert result.text == 'ghi'
-
-
-def test_emacs_insert_comment():
- # Test insert-comment (M-#) binding.
- result, cli = _feed_cli_with_input('hello\x1b#', check_line_ending=False)
- assert result.text == '#hello'
-
- result, cli = _feed_cli_with_input(
- 'hello\nworld\x1b#', check_line_ending=False, multiline=True)
- assert result.text == '#hello\n#world'
-
-
-def test_emacs_record_macro():
- operations = (
- ' '
- '\x18(' # Start recording macro. C-X(
- 'hello'
- '\x18)' # Stop recording macro.
- ' '
- '\x18e' # Execute macro.
- '\x18e' # Execute macro.
- '\n'
- )
-
- result, cli = _feed_cli_with_input(operations)
- assert result.text == ' hello hellohello'
-
-
-def test_prefix_meta():
- # Test the prefix-meta command.
- def setup_keybindings(cli):
- from prompt_toolkit.key_binding.bindings.named_commands import prefix_meta
- from prompt_toolkit.filters import ViInsertMode
- cli.application.key_bindings_registry.add_binding('j', 'j', filter=ViInsertMode())(prefix_meta)
-
- result, cli = _feed_cli_with_input(
- 'hellojjIX\n', pre_run_callback=setup_keybindings, editing_mode=EditingMode.VI)
- assert result.text == 'Xhello'
-
-
-def test_bracketed_paste():
- result, cli = _feed_cli_with_input('\x1b[200~hello world\x1b[201~\n')
- assert result.text == 'hello world'
-
- result, cli = _feed_cli_with_input('\x1b[200~hello\nworld\x1b[201~\x1b\n')
- assert result.text == 'hello\nworld'
-
- # With \r\n endings.
- result, cli = _feed_cli_with_input('\x1b[200~hello\r\nworld\x1b[201~\x1b\n')
- assert result.text == 'hello\nworld'
-
- # With \r endings.
- result, cli = _feed_cli_with_input('\x1b[200~hello\rworld\x1b[201~\x1b\n')
- assert result.text == 'hello\nworld'
-
-
-def test_vi_cursor_movements():
- """
- Test cursor movements with Vi key bindings.
- """
- feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI)
-
- result, cli = feed('\x1b\n')
- assert result.text == ''
- assert cli.editing_mode == EditingMode.VI
-
- # Esc h a X
- result, cli = feed('hello\x1bhaX\n')
- assert result.text == 'hellXo'
-
- # Esc I X
- result, cli = feed('hello\x1bIX\n')
- assert result.text == 'Xhello'
-
- # Esc I X
- result, cli = feed('hello\x1bIX\n')
- assert result.text == 'Xhello'
-
- # Esc 2hiX
- result, cli = feed('hello\x1b2hiX\n')
- assert result.text == 'heXllo'
-
- # Esc 2h2liX
- result, cli = feed('hello\x1b2h2liX\n')
- assert result.text == 'hellXo'
-
- # Esc \b\b
- result, cli = feed('hello\b\b\n')
- assert result.text == 'hel'
-
- # Esc \b\b
- result, cli = feed('hello\b\b\n')
- assert result.text == 'hel'
-
- # Esc 2h D
- result, cli = feed('hello\x1b2hD\n')
- assert result.text == 'he'
-
- # Esc 2h rX \n
- result, cli = feed('hello\x1b2hrX\n')
- assert result.text == 'heXlo'
-
-
-def test_vi_operators():
- feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI)
-
- # Esc g~0
- result, cli = feed('hello\x1bg~0\n')
- assert result.text == 'HELLo'
-
- # Esc gU0
- result, cli = feed('hello\x1bgU0\n')
- assert result.text == 'HELLo'
-
- # Esc d0
- result, cli = feed('hello\x1bd0\n')
- assert result.text == 'o'
-
-
-def test_vi_text_objects():
- feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI)
-
- # Esc gUgg
- result, cli = feed('hello\x1bgUgg\n')
- assert result.text == 'HELLO'
-
- # Esc gUU
- result, cli = feed('hello\x1bgUU\n')
- assert result.text == 'HELLO'
-
- # Esc di(
- result, cli = feed('before(inside)after\x1b8hdi(\n')
- assert result.text == 'before()after'
-
- # Esc di[
- result, cli = feed('before[inside]after\x1b8hdi[\n')
- assert result.text == 'before[]after'
-
- # Esc da(
- result, cli = feed('before(inside)after\x1b8hda(\n')
- assert result.text == 'beforeafter'
-
-
-def test_vi_digraphs():
- feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI)
-
- # C-K o/
- result, cli = feed('hello\x0bo/\n')
- assert result.text == 'helloø'
-
- # C-K /o (reversed input.)
- result, cli = feed('hello\x0b/o\n')
- assert result.text == 'helloø'
-
- # C-K e:
- result, cli = feed('hello\x0be:\n')
- assert result.text == 'helloë'
-
- # C-K xxy (Unknown digraph.)
- result, cli = feed('hello\x0bxxy\n')
- assert result.text == 'helloy'
-
-
-def test_vi_block_editing():
- " Test Vi Control-V style block insertion. "
- feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI,
- multiline=True)
-
- operations = (
- # Three lines of text.
- '-line1\n-line2\n-line3\n-line4\n-line5\n-line6'
- # Go to the second character of the second line.
- '\x1bkkkkkkkj0l'
- # Enter Visual block mode.
- '\x16'
- # Go down two more lines.
- 'jj'
- # Go 3 characters to the right.
- 'lll'
- # Go to insert mode.
- 'insert' # (Will be replaced.)
- # Insert stars.
- '***'
- # Escape again.
- '\x1b\n')
-
- # Control-I
- result, cli = feed(operations.replace('insert', 'I'))
-
- assert (result.text ==
- '-line1\n-***line2\n-***line3\n-***line4\n-line5\n-line6')
-
- # Control-A
- result, cli = feed(operations.replace('insert', 'A'))
-
- assert (result.text ==
- '-line1\n-line***2\n-line***3\n-line***4\n-line5\n-line6')
-
-
-def test_vi_character_paste():
- feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI)
-
- # Test 'p' character paste.
- result, cli = feed('abcde\x1bhhxp\n')
- assert result.text == 'abdce'
- assert result.cursor_position == 3
-
- # Test 'P' character paste.
- result, cli = feed('abcde\x1bhhxP\n')
- assert result.text == 'abcde'
- assert result.cursor_position == 2
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_contrib.py b/contrib/python/prompt-toolkit/py2/tests/test_contrib.py
deleted file mode 100644
index 64765d3f1a..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_contrib.py
+++ /dev/null
@@ -1,254 +0,0 @@
-from __future__ import unicode_literals, absolute_import, print_function
-
-import os
-import shutil
-import tempfile
-
-from contextlib import contextmanager
-
-from six import text_type
-
-from prompt_toolkit.completion import CompleteEvent
-from prompt_toolkit.document import Document
-from prompt_toolkit.contrib.completers.filesystem import PathCompleter
-
-
-@contextmanager
-def chdir(directory):
- """Context manager for current working directory temporary change."""
- orig_dir = os.getcwd()
- os.chdir(directory)
-
- try:
- yield
- finally:
- os.chdir(orig_dir)
-
-
-def write_test_files(test_dir, names=None):
- """Write test files in test_dir using the names list."""
- names = names or range(10)
- for i in names:
- with open(os.path.join(test_dir, str(i)), 'wb') as out:
- out.write(''.encode('UTF-8'))
-
-
-def test_pathcompleter_completes_in_current_directory():
- completer = PathCompleter()
- doc_text = ''
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- assert len(completions) > 0
-
-
-def test_pathcompleter_completes_files_in_current_directory():
- # setup: create a test dir with 10 files
- test_dir = tempfile.mkdtemp()
- write_test_files(test_dir)
-
- expected = sorted([str(i) for i in range(10)])
-
- if not test_dir.endswith(os.path.sep):
- test_dir += os.path.sep
-
- with chdir(test_dir):
- completer = PathCompleter()
- # this should complete on the cwd
- doc_text = ''
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- result = sorted(c.text for c in completions)
- assert expected == result
-
- # cleanup
- shutil.rmtree(test_dir)
-
-
-def test_pathcompleter_completes_files_in_absolute_directory():
- # setup: create a test dir with 10 files
- test_dir = tempfile.mkdtemp()
- write_test_files(test_dir)
-
- expected = sorted([str(i) for i in range(10)])
-
- test_dir = os.path.abspath(test_dir)
- if not test_dir.endswith(os.path.sep):
- test_dir += os.path.sep
-
- completer = PathCompleter()
- # force unicode
- doc_text = text_type(test_dir)
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- result = sorted([c.text for c in completions])
- assert expected == result
-
- # cleanup
- shutil.rmtree(test_dir)
-
-
-def test_pathcompleter_completes_directories_with_only_directories():
- # setup: create a test dir with 10 files
- test_dir = tempfile.mkdtemp()
- write_test_files(test_dir)
-
- # create a sub directory there
- os.mkdir(os.path.join(test_dir, 'subdir'))
-
- if not test_dir.endswith(os.path.sep):
- test_dir += os.path.sep
-
- with chdir(test_dir):
- completer = PathCompleter(only_directories=True)
- doc_text = ''
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- result = [c.text for c in completions]
- assert ['subdir'] == result
-
- # check that there is no completion when passing a file
- with chdir(test_dir):
- completer = PathCompleter(only_directories=True)
- doc_text = '1'
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- assert [] == completions
-
- # cleanup
- shutil.rmtree(test_dir)
-
-
-def test_pathcompleter_respects_completions_under_min_input_len():
- # setup: create a test dir with 10 files
- test_dir = tempfile.mkdtemp()
- write_test_files(test_dir)
-
- # min len:1 and no text
- with chdir(test_dir):
- completer = PathCompleter(min_input_len=1)
- doc_text = ''
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- assert [] == completions
-
- # min len:1 and text of len 1
- with chdir(test_dir):
- completer = PathCompleter(min_input_len=1)
- doc_text = '1'
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- result = [c.text for c in completions]
- assert [''] == result
-
- # min len:0 and text of len 2
- with chdir(test_dir):
- completer = PathCompleter(min_input_len=0)
- doc_text = '1'
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- result = [c.text for c in completions]
- assert [''] == result
-
- # create 10 files with a 2 char long name
- for i in range(10):
- with open(os.path.join(test_dir, str(i) * 2), 'wb') as out:
- out.write(b'')
-
- # min len:1 and text of len 1
- with chdir(test_dir):
- completer = PathCompleter(min_input_len=1)
- doc_text = '2'
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- result = sorted(c.text for c in completions)
- assert ['', '2'] == result
-
- # min len:2 and text of len 1
- with chdir(test_dir):
- completer = PathCompleter(min_input_len=2)
- doc_text = '2'
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- assert [] == completions
-
- # cleanup
- shutil.rmtree(test_dir)
-
-
-def test_pathcompleter_does_not_expanduser_by_default():
- completer = PathCompleter()
- doc_text = '~'
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- assert [] == completions
-
-
-def test_pathcompleter_can_expanduser(monkeypatch):
- monkeypatch.setenv('HOME', '/tmp')
- completer = PathCompleter(expanduser=True)
- doc_text = '~'
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- assert len(completions) > 0
-
-
-def test_pathcompleter_can_apply_file_filter():
- # setup: create a test dir with 10 files
- test_dir = tempfile.mkdtemp()
- write_test_files(test_dir)
-
- # add a .csv file
- with open(os.path.join(test_dir, 'my.csv'), 'wb') as out:
- out.write(b'')
-
- file_filter = lambda f: f and f.endswith('.csv')
-
- with chdir(test_dir):
- completer = PathCompleter(file_filter=file_filter)
- doc_text = ''
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- result = [c.text for c in completions]
- assert ['my.csv'] == result
-
- # cleanup
- shutil.rmtree(test_dir)
-
-
-def test_pathcompleter_get_paths_constrains_path():
- # setup: create a test dir with 10 files
- test_dir = tempfile.mkdtemp()
- write_test_files(test_dir)
-
- # add a subdir with 10 other files with different names
- subdir = os.path.join(test_dir, 'subdir')
- os.mkdir(subdir)
- write_test_files(subdir, 'abcdefghij')
-
- get_paths = lambda: ['subdir']
-
- with chdir(test_dir):
- completer = PathCompleter(get_paths=get_paths)
- doc_text = ''
- doc = Document(doc_text, len(doc_text))
- event = CompleteEvent()
- completions = list(completer.get_completions(doc, event))
- result = [c.text for c in completions]
- expected = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
- assert expected == result
-
- # cleanup
- shutil.rmtree(test_dir)
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_document.py b/contrib/python/prompt-toolkit/py2/tests/test_document.py
deleted file mode 100644
index 8c0cf5704c..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_document.py
+++ /dev/null
@@ -1,74 +0,0 @@
-from __future__ import unicode_literals
-
-import pytest
-
-from prompt_toolkit.document import Document
-
-
-@pytest.fixture
-def document():
- return Document(
- 'line 1\n' +
- 'line 2\n' +
- 'line 3\n' +
- 'line 4\n',
- len('line 1\n' + 'lin')
- )
-
-
-def test_current_char(document):
- assert document.current_char == 'e'
-
-
-def test_text_before_cursor(document):
- assert document.text_before_cursor == 'line 1\nlin'
-
-
-def test_text_after_cursor(document):
- assert document.text_after_cursor == 'e 2\n' + \
- 'line 3\n' + \
- 'line 4\n'
-
-
-def test_lines(document):
- assert document.lines == [
- 'line 1',
- 'line 2',
- 'line 3',
- 'line 4', '']
-
-
-def test_line_count(document):
- assert document.line_count == 5
-
-
-def test_current_line_before_cursor(document):
- assert document.current_line_before_cursor == 'lin'
-
-
-def test_current_line_after_cursor(document):
- assert document.current_line_after_cursor == 'e 2'
-
-
-def test_current_line(document):
- assert document.current_line == 'line 2'
-
-
-def test_cursor_position(document):
- assert document.cursor_position_row == 1
- assert document.cursor_position_col == 3
-
- d = Document('', 0)
- assert d.cursor_position_row == 0
- assert d.cursor_position_col == 0
-
-
-def test_translate_index_to_position(document):
- pos = document.translate_index_to_position(
- len('line 1\nline 2\nlin'))
-
- assert pos[0] == 2
- assert pos[1] == 3
-
- pos = document.translate_index_to_position(0)
- assert pos == (0, 0)
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_filter.py b/contrib/python/prompt-toolkit/py2/tests/test_filter.py
deleted file mode 100644
index 5aee62a9a9..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_filter.py
+++ /dev/null
@@ -1,168 +0,0 @@
-from __future__ import unicode_literals
-from prompt_toolkit.filters import Condition, Never, Always, Filter
-from prompt_toolkit.filters.types import CLIFilter, SimpleFilter
-from prompt_toolkit.filters.utils import to_cli_filter, to_simple_filter
-from prompt_toolkit.filters.cli import HasArg, HasFocus, HasSelection
-
-import pytest
-
-
-def test_condition_filter_args():
- c = Condition(lambda a, b, c: True)
- assert c.test_args('a', 'b', 'c')
- assert not c.test_args()
- assert not c.test_args('a')
- assert not c.test_args('a', 'b')
- assert not c.test_args('a', 'b', 'c', 'd')
-
- c2 = Condition(lambda a, b=1: True)
- assert c2.test_args('a')
- assert c2.test_args('a', 'b')
- assert not c2.test_args('a', 'b', 'c')
- assert not c2.test_args()
-
- c3 = Condition(lambda *a: True)
- assert c3.test_args()
- assert c3.test_args('a')
- assert c3.test_args('a', 'b')
-
-
-def test_and_arg():
- c1 = Condition(lambda a: True)
- c2 = Condition(lambda a: True)
- c3 = c1 & c2
-
- assert c3.test_args('a')
- assert not c3.test_args()
- assert not c3.test_args('a', 'b')
-
-
-def test_or_arg():
- c1 = Condition(lambda a: True)
- c2 = Condition(lambda a: True)
- c3 = c1 | c2
-
- assert c3.test_args('a')
- assert not c3.test_args()
- assert not c3.test_args('a', 'b')
-
-
-def test_condition():
- c = Condition(lambda a: a % 2 == 0)
- assert c(4)
- assert c(6)
- assert not c(5)
- assert not c(3)
-
-
-def test_never():
- assert not Never()()
-
-
-def test_always():
- assert Always()()
-
-
-def test_invert():
- assert not (~Always())()
- assert (~Never()())
-
- c = ~Condition(lambda: False)
- assert c()
-
-
-def test_or():
- for a in (True, False):
- for b in (True, False):
- c1 = Condition(lambda: a)
- c2 = Condition(lambda: b)
- c3 = c1 | c2
-
- assert isinstance(c3, Filter)
- assert c3() == a or b
-
-
-def test_and():
- for a in (True, False):
- for b in (True, False):
- c1 = Condition(lambda: a)
- c2 = Condition(lambda: b)
- c3 = c1 & c2
-
- assert isinstance(c3, Filter)
- assert c3() == (a and b)
-
-
-def test_cli_filter():
- c1 = Condition(lambda cli: True)
- assert isinstance(c1, CLIFilter)
- assert not isinstance(c1, SimpleFilter)
-
- c2 = Condition(lambda: True)
- assert not isinstance(c2, CLIFilter)
- assert isinstance(c2, SimpleFilter)
-
- c3 = c1 | c2
- assert not isinstance(c3, CLIFilter)
- assert not isinstance(c3, SimpleFilter)
-
- c4 = Condition(lambda cli: True)
- c5 = Condition(lambda cli: True)
- c6 = c4 & c5
- c7 = c4 | c5
- assert isinstance(c6, CLIFilter)
- assert isinstance(c7, CLIFilter)
- assert not isinstance(c6, SimpleFilter)
- assert not isinstance(c7, SimpleFilter)
-
- c8 = Condition(lambda *args: True)
- assert isinstance(c8, CLIFilter)
- assert isinstance(c8, SimpleFilter)
-
-
-def test_to_cli_filter():
- f1 = to_cli_filter(True)
- f2 = to_cli_filter(False)
- f3 = to_cli_filter(Condition(lambda cli: True))
- f4 = to_cli_filter(Condition(lambda cli: False))
-
- assert isinstance(f1, CLIFilter)
- assert isinstance(f2, CLIFilter)
- assert isinstance(f3, CLIFilter)
- assert isinstance(f4, CLIFilter)
- assert f1(None)
- assert not f2(None)
- assert f3(None)
- assert not f4(None)
-
- with pytest.raises(TypeError):
- to_cli_filter(4)
- with pytest.raises(TypeError):
- to_cli_filter(Condition(lambda: True))
-
-
-def test_to_simple_filter():
- f1 = to_simple_filter(True)
- f2 = to_simple_filter(False)
- f3 = to_simple_filter(Condition(lambda: True))
- f4 = to_simple_filter(Condition(lambda: False))
-
- assert isinstance(f1, SimpleFilter)
- assert isinstance(f2, SimpleFilter)
- assert isinstance(f3, SimpleFilter)
- assert isinstance(f4, SimpleFilter)
- assert f1()
- assert not f2()
- assert f3()
- assert not f4()
-
- with pytest.raises(TypeError):
- to_simple_filter(4)
- with pytest.raises(TypeError):
- to_simple_filter(Condition(lambda cli: True))
-
-
-def test_cli_filters():
- assert isinstance(HasArg(), CLIFilter)
- assert isinstance(HasFocus('BUFFER_NAME'), CLIFilter)
- assert isinstance(HasSelection(), CLIFilter)
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_inputstream.py b/contrib/python/prompt-toolkit/py2/tests/test_inputstream.py
deleted file mode 100644
index de10c0f9a9..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_inputstream.py
+++ /dev/null
@@ -1,142 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.terminal.vt100_input import InputStream
-from prompt_toolkit.keys import Keys
-
-import pytest
-
-
-class _ProcessorMock(object):
-
- def __init__(self):
- self.keys = []
-
- def feed_key(self, key_press):
- self.keys.append(key_press)
-
-
-@pytest.fixture
-def processor():
- return _ProcessorMock()
-
-
-@pytest.fixture
-def stream(processor):
- return InputStream(processor.feed_key)
-
-
-def test_control_keys(processor, stream):
- stream.feed('\x01\x02\x10')
-
- assert len(processor.keys) == 3
- assert processor.keys[0].key == Keys.ControlA
- assert processor.keys[1].key == Keys.ControlB
- assert processor.keys[2].key == Keys.ControlP
- assert processor.keys[0].data == '\x01'
- assert processor.keys[1].data == '\x02'
- assert processor.keys[2].data == '\x10'
-
-
-def test_arrows(processor, stream):
- stream.feed('\x1b[A\x1b[B\x1b[C\x1b[D')
-
- assert len(processor.keys) == 4
- assert processor.keys[0].key == Keys.Up
- assert processor.keys[1].key == Keys.Down
- assert processor.keys[2].key == Keys.Right
- assert processor.keys[3].key == Keys.Left
- assert processor.keys[0].data == '\x1b[A'
- assert processor.keys[1].data == '\x1b[B'
- assert processor.keys[2].data == '\x1b[C'
- assert processor.keys[3].data == '\x1b[D'
-
-
-def test_escape(processor, stream):
- stream.feed('\x1bhello')
-
- assert len(processor.keys) == 1 + len('hello')
- assert processor.keys[0].key == Keys.Escape
- assert processor.keys[1].key == 'h'
- assert processor.keys[0].data == '\x1b'
- assert processor.keys[1].data == 'h'
-
-
-def test_special_double_keys(processor, stream):
- stream.feed('\x1b[1;3D') # Should both send escape and left.
-
- assert len(processor.keys) == 2
- assert processor.keys[0].key == Keys.Escape
- assert processor.keys[1].key == Keys.Left
- assert processor.keys[0].data == '\x1b[1;3D'
- assert processor.keys[1].data == '\x1b[1;3D'
-
-
-def test_flush_1(processor, stream):
- # Send left key in two parts without flush.
- stream.feed('\x1b')
- stream.feed('[D')
-
- assert len(processor.keys) == 1
- assert processor.keys[0].key == Keys.Left
- assert processor.keys[0].data == '\x1b[D'
-
-
-def test_flush_2(processor, stream):
- # Send left key with a 'Flush' in between.
- # The flush should make sure that we process evenything before as-is,
- # with makes the first part just an escape character instead.
- stream.feed('\x1b')
- stream.flush()
- stream.feed('[D')
-
- assert len(processor.keys) == 3
- assert processor.keys[0].key == Keys.Escape
- assert processor.keys[1].key == '['
- assert processor.keys[2].key == 'D'
-
- assert processor.keys[0].data == '\x1b'
- assert processor.keys[1].data == '['
- assert processor.keys[2].data == 'D'
-
-
-def test_meta_arrows(processor, stream):
- stream.feed('\x1b\x1b[D')
-
- assert len(processor.keys) == 2
- assert processor.keys[0].key == Keys.Escape
- assert processor.keys[1].key == Keys.Left
-
-
-def test_control_square_close(processor, stream):
- stream.feed('\x1dC')
-
- assert len(processor.keys) == 2
- assert processor.keys[0].key == Keys.ControlSquareClose
- assert processor.keys[1].key == 'C'
-
-
-def test_invalid(processor, stream):
- # Invalid sequence that has at two characters in common with other
- # sequences.
- stream.feed('\x1b[*')
-
- assert len(processor.keys) == 3
- assert processor.keys[0].key == Keys.Escape
- assert processor.keys[1].key == '['
- assert processor.keys[2].key == '*'
-
-
-def test_cpr_response(processor, stream):
- stream.feed('a\x1b[40;10Rb')
- assert len(processor.keys) == 3
- assert processor.keys[0].key == 'a'
- assert processor.keys[1].key == Keys.CPRResponse
- assert processor.keys[2].key == 'b'
-
-
-def test_cpr_response_2(processor, stream):
- # Make sure that the newline is not included in the CPR response.
- stream.feed('\x1b[40;1R\n')
- assert len(processor.keys) == 2
- assert processor.keys[0].key == Keys.CPRResponse
- assert processor.keys[1].key == Keys.ControlJ
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_key_binding.py b/contrib/python/prompt-toolkit/py2/tests/test_key_binding.py
deleted file mode 100644
index d706c4443b..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_key_binding.py
+++ /dev/null
@@ -1,140 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.key_binding.input_processor import InputProcessor, KeyPress
-from prompt_toolkit.key_binding.registry import Registry
-from prompt_toolkit.keys import Keys
-
-import pytest
-
-
-class Handlers(object):
-
- def __init__(self):
- self.called = []
-
- def __getattr__(self, name):
- def func(event):
- self.called.append(name)
- return func
-
-
-@pytest.fixture
-def handlers():
- return Handlers()
-
-
-@pytest.fixture
-def registry(handlers):
- registry = Registry()
- registry.add_binding(
- Keys.ControlX, Keys.ControlC)(handlers.controlx_controlc)
- registry.add_binding(Keys.ControlX)(handlers.control_x)
- registry.add_binding(Keys.ControlD)(handlers.control_d)
- registry.add_binding(
- Keys.ControlSquareClose, Keys.Any)(handlers.control_square_close_any)
-
- return registry
-
-
-@pytest.fixture
-def processor(registry):
- return InputProcessor(registry, lambda: None)
-
-
-def test_feed_simple(processor, handlers):
- processor.feed(KeyPress(Keys.ControlX, '\x18'))
- processor.feed(KeyPress(Keys.ControlC, '\x03'))
- processor.process_keys()
-
- assert handlers.called == ['controlx_controlc']
-
-
-def test_feed_several(processor, handlers):
- # First an unknown key first.
- processor.feed(KeyPress(Keys.ControlQ, ''))
- processor.process_keys()
-
- assert handlers.called == []
-
- # Followed by a know key sequence.
- processor.feed(KeyPress(Keys.ControlX, ''))
- processor.feed(KeyPress(Keys.ControlC, ''))
- processor.process_keys()
-
- assert handlers.called == ['controlx_controlc']
-
- # Followed by another unknown sequence.
- processor.feed(KeyPress(Keys.ControlR, ''))
- processor.feed(KeyPress(Keys.ControlS, ''))
-
- # Followed again by a know key sequence.
- processor.feed(KeyPress(Keys.ControlD, ''))
- processor.process_keys()
-
- assert handlers.called == ['controlx_controlc', 'control_d']
-
-
-def test_control_square_closed_any(processor, handlers):
- processor.feed(KeyPress(Keys.ControlSquareClose, ''))
- processor.feed(KeyPress('C', 'C'))
- processor.process_keys()
-
- assert handlers.called == ['control_square_close_any']
-
-
-def test_common_prefix(processor, handlers):
- # Sending Control_X should not yet do anything, because there is
- # another sequence starting with that as well.
- processor.feed(KeyPress(Keys.ControlX, ''))
- processor.process_keys()
-
- assert handlers.called == []
-
- # When another key is pressed, we know that we did not meant the longer
- # "ControlX ControlC" sequence and the callbacks are called.
- processor.feed(KeyPress(Keys.ControlD, ''))
- processor.process_keys()
-
- assert handlers.called == ['control_x', 'control_d']
-
-
-def test_previous_key_sequence(processor, handlers):
- """
- test whether we receive the correct previous_key_sequence.
- """
- events = []
- def handler(event):
- events.append(event)
-
- # Build registry.
- registry = Registry()
- registry.add_binding('a', 'a')(handler)
- registry.add_binding('b', 'b')(handler)
- processor = InputProcessor(registry, lambda: None)
-
- # Create processor and feed keys.
- processor.feed(KeyPress('a', 'a'))
- processor.feed(KeyPress('a', 'a'))
- processor.feed(KeyPress('b', 'b'))
- processor.feed(KeyPress('b', 'b'))
- processor.process_keys()
-
- # Test.
- assert len(events) == 2
- assert len(events[0].key_sequence) == 2
- assert events[0].key_sequence[0].key == 'a'
- assert events[0].key_sequence[0].data == 'a'
- assert events[0].key_sequence[1].key == 'a'
- assert events[0].key_sequence[1].data == 'a'
- assert events[0].previous_key_sequence == []
-
- assert len(events[1].key_sequence) == 2
- assert events[1].key_sequence[0].key == 'b'
- assert events[1].key_sequence[0].data == 'b'
- assert events[1].key_sequence[1].key == 'b'
- assert events[1].key_sequence[1].data == 'b'
- assert len(events[1].previous_key_sequence) == 2
- assert events[1].previous_key_sequence[0].key == 'a'
- assert events[1].previous_key_sequence[0].data == 'a'
- assert events[1].previous_key_sequence[1].key == 'a'
- assert events[1].previous_key_sequence[1].data == 'a'
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_layout.py b/contrib/python/prompt-toolkit/py2/tests/test_layout.py
deleted file mode 100644
index 6c9e67b4de..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_layout.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.layout.utils import split_lines
-from prompt_toolkit.token import Token
-
-
-def test_split_lines():
- lines = list(split_lines([(Token.A, 'line1\nline2\nline3')]))
-
- assert lines == [
- [(Token.A, 'line1')],
- [(Token.A, 'line2')],
- [(Token.A, 'line3')],
- ]
-
-
-def test_split_lines_2():
- lines = list(split_lines([
- (Token.A, 'line1'),
- (Token.B, 'line2\nline3\nline4')
- ]))
-
- assert lines == [
- [(Token.A, 'line1'), (Token.B, 'line2')],
- [(Token.B, 'line3')],
- [(Token.B, 'line4')],
- ]
-
-
-def test_split_lines_3():
- " Edge cases: inputs ending with newlines. "
- # -1-
- lines = list(split_lines([
- (Token.A, 'line1\nline2\n')
- ]))
-
- assert lines == [
- [(Token.A, 'line1')],
- [(Token.A, 'line2')],
- [(Token.A, '')],
- ]
-
- # -2-
- lines = list(split_lines([
- (Token.A, '\n'),
- ]))
-
- assert lines == [
- [],
- [(Token.A, '')],
- ]
-
- # -3-
- lines = list(split_lines([
- (Token.A, ''),
- ]))
-
- assert lines == [
- [(Token.A, '')],
- ]
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_print_tokens.py b/contrib/python/prompt-toolkit/py2/tests/test_print_tokens.py
deleted file mode 100644
index c3b5826b36..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_print_tokens.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""
-Test `shortcuts.print_tokens`.
-"""
-from __future__ import unicode_literals
-from prompt_toolkit.shortcuts import print_tokens
-from prompt_toolkit.token import Token
-from prompt_toolkit.styles import style_from_dict
-
-
-class _Capture:
- " Emulate an stdout object. "
- encoding = 'utf-8'
-
- def __init__(self):
- self._data = []
-
- def write(self, data):
- self._data.append(data)
-
- @property
- def data(self):
- return b''.join(self._data)
-
- def flush(self):
- pass
-
- def isatty(self):
- return True
-
-
-def test_print_tokens():
- f = _Capture()
- print_tokens([(Token, 'hello'), (Token, 'world')], file=f)
- assert b'hello' in f.data
- assert b'world' in f.data
-
-
-def test_with_style():
- f = _Capture()
- style = style_from_dict({
- Token.Hello: '#ff0066',
- Token.World: '#44ff44 italic',
- })
- tokens = [
- (Token.Hello, 'Hello '),
- (Token.World, 'world'),
- ]
- print_tokens(tokens, style=style, file=f)
- assert b'\x1b[0;38;5;197mHello' in f.data
- assert b'\x1b[0;38;5;83;3mworld' in f.data
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_regular_languages.py b/contrib/python/prompt-toolkit/py2/tests/test_regular_languages.py
deleted file mode 100644
index 6ece5cdeb5..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_regular_languages.py
+++ /dev/null
@@ -1,110 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.completion import CompleteEvent, Completer, Completion
-from prompt_toolkit.contrib.regular_languages import compile
-from prompt_toolkit.contrib.regular_languages.compiler import Match, Variables
-from prompt_toolkit.contrib.regular_languages.completion import \
- GrammarCompleter
-from prompt_toolkit.document import Document
-
-
-def test_simple_match():
- g = compile('hello|world')
-
- m = g.match('hello')
- assert isinstance(m, Match)
-
- m = g.match('world')
- assert isinstance(m, Match)
-
- m = g.match('somethingelse')
- assert m is None
-
-
-def test_variable_varname():
- """
- Test `Variable` with varname.
- """
- g = compile('((?P<varname>hello|world)|test)')
-
- m = g.match('hello')
- variables = m.variables()
- assert isinstance(variables, Variables)
- assert variables.get('varname') == 'hello'
- assert variables['varname'] == 'hello'
-
- m = g.match('world')
- variables = m.variables()
- assert isinstance(variables, Variables)
- assert variables.get('varname') == 'world'
- assert variables['varname'] == 'world'
-
- m = g.match('test')
- variables = m.variables()
- assert isinstance(variables, Variables)
- assert variables.get('varname') is None
- assert variables['varname'] is None
-
-
-def test_prefix():
- """
- Test `match_prefix`.
- """
- g = compile(r'(hello\ world|something\ else)')
-
- m = g.match_prefix('hello world')
- assert isinstance(m, Match)
-
- m = g.match_prefix('he')
- assert isinstance(m, Match)
-
- m = g.match_prefix('')
- assert isinstance(m, Match)
-
- m = g.match_prefix('som')
- assert isinstance(m, Match)
-
- m = g.match_prefix('hello wor')
- assert isinstance(m, Match)
-
- m = g.match_prefix('no-match')
- assert m.trailing_input().start == 0
- assert m.trailing_input().stop == len('no-match')
-
- m = g.match_prefix('hellotest')
- assert m.trailing_input().start == len('hello')
- assert m.trailing_input().stop == len('hellotest')
-
-
-def test_completer():
- class completer1(Completer):
-
- def get_completions(self, document, complete_event):
- yield Completion(
- 'before-%s-after' % document.text, -len(document.text))
- yield Completion(
- 'before-%s-after-B' % document.text, -len(document.text))
-
- class completer2(Completer):
-
- def get_completions(self, document, complete_event):
- yield Completion(
- 'before2-%s-after2' % document.text, -len(document.text))
- yield Completion(
- 'before2-%s-after2-B' % document.text, -len(document.text))
-
- # Create grammar. "var1" + "whitespace" + "var2"
- g = compile(r'(?P<var1>[a-z]*) \s+ (?P<var2>[a-z]*)')
-
- # Test 'get_completions()'
- completer = GrammarCompleter(
- g, {'var1': completer1(), 'var2': completer2()})
- completions = list(completer.get_completions(
- Document('abc def', len('abc def')),
- CompleteEvent()))
-
- assert len(completions) == 2
- assert completions[0].text == 'before2-def-after2'
- assert completions[0].start_position == -3
- assert completions[1].text == 'before2-def-after2-B'
- assert completions[1].start_position == -3
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_shortcuts.py b/contrib/python/prompt-toolkit/py2/tests/test_shortcuts.py
deleted file mode 100644
index 8c13510ea8..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_shortcuts.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from prompt_toolkit.shortcuts import _split_multiline_prompt
-from prompt_toolkit.token import Token
-
-
-def test_split_multiline_prompt():
- # Test 1: no newlines:
- tokens = [(Token, 'ab')]
- has_before_tokens, before, first_input_line = _split_multiline_prompt(lambda cli: tokens)
- assert has_before_tokens(None) is False
- assert before(None) == []
- assert first_input_line(None) == [
- (Token, 'a'),
- (Token, 'b'),
- ]
-
- # Test 1: multiple lines.
- tokens = [(Token, 'ab\ncd\nef')]
- has_before_tokens, before, first_input_line = _split_multiline_prompt(lambda cli: tokens)
- assert has_before_tokens(None) is True
- assert before(None) == [
- (Token, 'a'),
- (Token, 'b'),
- (Token, '\n'),
- (Token, 'c'),
- (Token, 'd'),
- ]
- assert first_input_line(None) == [
- (Token, 'e'),
- (Token, 'f'),
- ]
-
- # Edge case 1: starting with a newline.
- tokens = [(Token, '\nab')]
- has_before_tokens, before, first_input_line = _split_multiline_prompt(lambda cli: tokens)
- assert has_before_tokens(None) is True
- assert before(None) == []
- assert first_input_line(None) == [
- (Token, 'a'),
- (Token, 'b')
- ]
-
- # Edge case 2: starting with two newlines.
- tokens = [(Token, '\n\nab')]
- has_before_tokens, before, first_input_line = _split_multiline_prompt(lambda cli: tokens)
- assert has_before_tokens(None) is True
- assert before(None) == [(Token, '\n')]
- assert first_input_line(None) == [
- (Token, 'a'),
- (Token, 'b')
- ]
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_style.py b/contrib/python/prompt-toolkit/py2/tests/test_style.py
deleted file mode 100644
index fc839ec95f..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_style.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.styles import Attrs, style_from_dict
-from prompt_toolkit.token import Token
-
-
-def test_style_from_dict():
- style = style_from_dict({
- Token.A: '#ff0000 bold underline italic',
- Token.B: 'bg:#00ff00 blink reverse',
- })
-
- expected = Attrs(color='ff0000', bgcolor=None, bold=True,
- underline=True, italic=True, blink=False, reverse=False)
- assert style.get_attrs_for_token(Token.A) == expected
-
- expected = Attrs(color=None, bgcolor='00ff00', bold=False,
- underline=False, italic=False, blink=True, reverse=True)
- assert style.get_attrs_for_token(Token.B) == expected
-
-
-def test_style_inheritance():
- style = style_from_dict({
- Token: '#ff0000',
- Token.A.B.C: 'bold',
- Token.A.B.C.D: '#ansired',
- Token.A.B.C.D.E: 'noinherit blink'
- })
-
- expected = Attrs(color='ff0000', bgcolor=None, bold=True,
- underline=False, italic=False, blink=False, reverse=False)
- assert style.get_attrs_for_token(Token.A.B.C) == expected
-
- expected = Attrs(color='ansired', bgcolor=None, bold=True,
- underline=False, italic=False, blink=False, reverse=False)
- assert style.get_attrs_for_token(Token.A.B.C.D) == expected
-
- expected = Attrs(color=None, bgcolor=None, bold=False,
- underline=False, italic=False, blink=True, reverse=False)
- assert style.get_attrs_for_token(Token.A.B.C.D.E) == expected
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_utils.py b/contrib/python/prompt-toolkit/py2/tests/test_utils.py
deleted file mode 100644
index 1e3d92cda6..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_utils.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.utils import take_using_weights
-
-import itertools
-
-
-def test_using_weights():
- def take(generator, count):
- return list(itertools.islice(generator, 0, count))
-
- # Check distribution.
- data = take(take_using_weights(['A', 'B', 'C'], [5, 10, 20]), 35)
- assert data.count('A') == 5
- assert data.count('B') == 10
- assert data.count('C') == 20
-
- assert data == [
- 'A', 'B', 'C', 'C', 'B', 'C', 'C', 'A', 'B', 'C', 'C', 'B', 'C',
- 'C', 'A', 'B', 'C', 'C', 'B', 'C', 'C', 'A', 'B', 'C', 'C',
- 'B', 'C', 'C', 'A', 'B', 'C', 'C', 'B', 'C', 'C']
-
- # Another order.
- data = take(take_using_weights(['A', 'B', 'C'], [20, 10, 5]), 35)
- assert data.count('A') == 20
- assert data.count('B') == 10
- assert data.count('C') == 5
-
- # Bigger numbers.
- data = take(take_using_weights(['A', 'B', 'C'], [20, 10, 5]), 70)
- assert data.count('A') == 40
- assert data.count('B') == 20
- assert data.count('C') == 10
-
- # Negative numbers.
- data = take(take_using_weights(['A', 'B', 'C'], [-20, 10, 0]), 70)
- assert data.count('A') == 0
- assert data.count('B') == 70
- assert data.count('C') == 0
diff --git a/contrib/python/prompt-toolkit/py2/tests/test_yank_nth_arg.py b/contrib/python/prompt-toolkit/py2/tests/test_yank_nth_arg.py
deleted file mode 100644
index 1ccec7bf7b..0000000000
--- a/contrib/python/prompt-toolkit/py2/tests/test_yank_nth_arg.py
+++ /dev/null
@@ -1,85 +0,0 @@
-from __future__ import unicode_literals
-from prompt_toolkit.buffer import Buffer
-from prompt_toolkit.history import InMemoryHistory
-
-import pytest
-
-
-@pytest.fixture
-def _history():
- " Prefilled history. "
- history = InMemoryHistory()
- history.append('alpha beta gamma delta')
- history.append('one two three four')
- return history
-
-
-# Test yank_last_arg.
-
-
-def test_empty_history():
- buf = Buffer()
- buf.yank_last_arg()
- assert buf.document.current_line == ''
-
-
-def test_simple_search(_history):
- buff = Buffer(history=_history)
- buff.yank_last_arg()
- assert buff.document.current_line == 'four'
-
-
-def test_simple_search_with_quotes(_history):
- _history.append("""one two "three 'x' four"\n""")
- buff = Buffer(history=_history)
- buff.yank_last_arg()
- assert buff.document.current_line == '''"three 'x' four"'''
-
-
-def test_simple_search_with_arg(_history):
- buff = Buffer(history=_history)
- buff.yank_last_arg(n=2)
- assert buff.document.current_line == 'three'
-
-
-def test_simple_search_with_arg_out_of_bounds(_history):
- buff = Buffer(history=_history)
- buff.yank_last_arg(n=8)
- assert buff.document.current_line == ''
-
-
-def test_repeated_search(_history):
- buff = Buffer(history=_history)
- buff.yank_last_arg()
- buff.yank_last_arg()
- assert buff.document.current_line == 'delta'
-
-
-def test_repeated_search_with_wraparound(_history):
- buff = Buffer(history=_history)
- buff.yank_last_arg()
- buff.yank_last_arg()
- buff.yank_last_arg()
- assert buff.document.current_line == 'four'
-
-
-# Test yank_last_arg.
-
-
-def test_yank_nth_arg(_history):
- buff = Buffer(history=_history)
- buff.yank_nth_arg()
- assert buff.document.current_line == 'two'
-
-
-def test_repeated_yank_nth_arg(_history):
- buff = Buffer(history=_history)
- buff.yank_nth_arg()
- buff.yank_nth_arg()
- assert buff.document.current_line == 'beta'
-
-
-def test_yank_nth_arg_with_arg(_history):
- buff = Buffer(history=_history)
- buff.yank_nth_arg(n=2)
- assert buff.document.current_line == 'three'