diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
commit | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch) | |
tree | 64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/python/prompt-toolkit/py2 | |
parent | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff) | |
download | ydb-e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/prompt-toolkit/py2')
50 files changed, 3531 insertions, 3531 deletions
diff --git a/contrib/python/prompt-toolkit/py2/.dist-info/METADATA b/contrib/python/prompt-toolkit/py2/.dist-info/METADATA index 2eef0447f0..24d0343b30 100644 --- a/contrib/python/prompt-toolkit/py2/.dist-info/METADATA +++ b/contrib/python/prompt-toolkit/py2/.dist-info/METADATA @@ -1,198 +1,198 @@ -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 - - +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 index 9bc5fd72d9..29392dfc5b 100644 --- a/contrib/python/prompt-toolkit/py2/.dist-info/top_level.txt +++ b/contrib/python/prompt-toolkit/py2/.dist-info/top_level.txt @@ -1 +1 @@ -prompt_toolkit +prompt_toolkit diff --git a/contrib/python/prompt-toolkit/py2/AUTHORS.rst b/contrib/python/prompt-toolkit/py2/AUTHORS.rst index c79b244a3d..f7c8f60f40 100644 --- a/contrib/python/prompt-toolkit/py2/AUTHORS.rst +++ b/contrib/python/prompt-toolkit/py2/AUTHORS.rst @@ -1,11 +1,11 @@ -Authors -======= - -Creator -------- -Jonathan Slenders <jonathan AT slenders.be> - -Contributors ------------- - -- Amjith Ramanujam <amjith.r AT gmail.com> +Authors +======= + +Creator +------- +Jonathan Slenders <jonathan AT slenders.be> + +Contributors +------------ + +- Amjith Ramanujam <amjith.r AT gmail.com> diff --git a/contrib/python/prompt-toolkit/py2/README.rst b/contrib/python/prompt-toolkit/py2/README.rst index a73dbd2389..35b1745614 100644 --- a/contrib/python/prompt-toolkit/py2/README.rst +++ b/contrib/python/prompt-toolkit/py2/README.rst @@ -1,171 +1,171 @@ -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 +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 index 01a3d44c27..2830ea41db 100644 --- a/contrib/python/prompt-toolkit/py2/patches/01-fix-tests.patch +++ b/contrib/python/prompt-toolkit/py2/patches/01-fix-tests.patch @@ -1,12 +1,12 @@ ---- 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)) +--- 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 index 310f653209..6478ba4f9a 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/__init__.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/__init__.py @@ -19,4 +19,4 @@ from .shortcuts import prompt, prompt_async # Don't forget to update in `docs/conf.py`! -__version__ = '1.0.18' +__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 index 61ff79de4c..272d8bbcbb 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/application.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/application.py @@ -8,8 +8,8 @@ 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 .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 @@ -50,17 +50,17 @@ class Application(object): :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. + :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. + :param reverse_vi_search_direction: Normally, in Vi mode, a '/' searches + forward and a '?' searches backward. In readline mode, this is usually + reversed. Filters: @@ -94,7 +94,7 @@ class Application(object): paste_mode=False, ignore_case=False, editing_mode=EditingMode.EMACS, erase_when_done=False, - reverse_vi_search_direction=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, @@ -103,12 +103,12 @@ class Application(object): 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) + 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 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 @@ -151,7 +151,7 @@ class Application(object): self.style = style or DEFAULT_STYLE if key_bindings_registry is None: - key_bindings_registry = load_key_bindings() + key_bindings_registry = load_key_bindings() if get_title is None: get_title = lambda: None @@ -168,7 +168,7 @@ class Application(object): 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 + self.reverse_vi_search_direction = reverse_vi_search_direction def dummy_handler(cli): " Dummy event handler. " @@ -181,12 +181,12 @@ class Application(object): 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 = [] + + # 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/buffer.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py index 4047fd8c5c..f5df289827 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py @@ -12,7 +12,7 @@ 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 .selection import SelectionType, SelectionState, PasteMode from .utils import Event from .cache import FastDictCache from .validation import ValidationError @@ -21,7 +21,7 @@ from six.moves import range import os import re -import shlex +import shlex import six import subprocess import tempfile @@ -87,27 +87,27 @@ class AcceptAction(object): def _return_document_handler(cli, buffer): - # Set return value. + # 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) + # 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 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. @@ -285,7 +285,7 @@ class Buffer(object): # `ValidationError` instance. (Will be set when the input is wrong.) self.validation_error = None - self.validation_state = ValidationState.UNKNOWN + self.validation_state = ValidationState.UNKNOWN # State of the selection. self.selection_state = None @@ -304,10 +304,10 @@ class Buffer(object): # 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 - + # 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 @@ -413,10 +413,10 @@ class Buffer(object): def _text_changed(self): # Remove any validation errors and complete state. self.validation_error = None - self.validation_state = ValidationState.UNKNOWN + self.validation_state = ValidationState.UNKNOWN self.complete_state = None self.yank_nth_arg_state = None - self.document_before_paste = None + self.document_before_paste = None self.selection_state = None self.suggestion = None self.preferred_column = None @@ -427,10 +427,10 @@ class Buffer(object): def _cursor_position_changed(self): # Remove any validation errors and complete state. self.validation_error = None - self.validation_state = ValidationState.UNKNOWN + self.validation_state = ValidationState.UNKNOWN self.complete_state = None self.yank_nth_arg_state = None - self.document_before_paste = None + self.document_before_paste = None # Unset preferred_column. (Will be set after the cursor movement, if # required.) @@ -849,7 +849,7 @@ class Buffer(object): """ 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 + self.history_search_text = self.document.text_before_cursor else: self.history_search_text = None @@ -986,20 +986,20 @@ class Buffer(object): """ return self.copy_selection(_cut=True) - def paste_clipboard_data(self, data, paste_mode=PasteMode.EMACS, count=1): + 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 - + 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. @@ -1093,10 +1093,10 @@ class Buffer(object): """ 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 + # 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: @@ -1107,12 +1107,12 @@ class Buffer(object): cursor_position = e.cursor_position self.cursor_position = min(max(0, cursor_position), len(self.text)) - self.validation_state = ValidationState.INVALID + self.validation_state = ValidationState.INVALID self.validation_error = e return False - self.validation_state = ValidationState.VALID - self.validation_error = None + self.validation_state = ValidationState.VALID + self.validation_error = None return True def append_to_history(self): @@ -1297,13 +1297,13 @@ class Buffer(object): Return True when we received a zero return code. """ - # If the 'VISUAL' or 'EDITOR' environment variable has been set, use that. + # 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') + visual = os.environ.get('VISUAL') editor = os.environ.get('EDITOR') editors = [ - visual, + visual, editor, # Order of preference. @@ -1317,9 +1317,9 @@ class Buffer(object): for e in editors: if e: try: - # Use 'shlex.split()', because $VISUAL can contain spaces - # and quotes. - returncode = subprocess.call(shlex.split(e) + [filename]) + # Use 'shlex.split()', because $VISUAL can contain spaces + # and quotes. + returncode = subprocess.call(shlex.split(e) + [filename]) return returncode == 0 except OSError: diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/base.py index 985a506ad6..803c0b0e7d 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/base.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/base.py @@ -50,11 +50,11 @@ class Clipboard(with_metaclass(ABCMeta, object)): assert isinstance(text, six.string_types) self.set_data(ClipboardData(text)) - def rotate(self): - """ - For Emacs mode, rotate the kill ring. - """ - + def rotate(self): + """ + For Emacs mode, rotate the kill ring. + """ + @abstractmethod def get_data(self): """ 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 index f81f4056d1..081666ab80 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/in_memory.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/in_memory.py @@ -1,7 +1,7 @@ from .base import Clipboard, ClipboardData -from collections import deque - +from collections import deque + __all__ = ( 'InMemoryClipboard', ) @@ -11,32 +11,32 @@ class InMemoryClipboard(Clipboard): """ Default clipboard implementation. Just keep the data in memory. - - This implements a kill-ring, for Emacs mode. + + This implements a kill-ring, for Emacs mode. """ - def __init__(self, data=None, max_size=60): + def __init__(self, data=None, max_size=60): assert data is None or isinstance(data, ClipboardData) - assert max_size >= 1 + assert max_size >= 1 + + self.max_size = max_size + self._ring = deque() + if data is not None: + self.set_data(data) - 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) + self._ring.appendleft(data) + + while len(self._ring) > self.max_size: + self._ring.pop() - 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()) + 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/document.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py index 4a06348a23..25d817ddd0 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py @@ -10,7 +10,7 @@ import string import weakref from six.moves import range, map -from .selection import SelectionType, SelectionState, PasteMode +from .selection import SelectionType, SelectionState, PasteMode from .clipboard import ClipboardData __all__ = ('Document',) @@ -874,31 +874,31 @@ class Document(object): else: return self, ClipboardData('') - def paste_clipboard_data(self, data, paste_mode=PasteMode.EMACS, count=1): + 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 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) + assert paste_mode in (PasteMode.VI_BEFORE, PasteMode.VI_AFTER, PasteMode.EMACS) + + before = (paste_mode == PasteMode.VI_BEFORE) + after = (paste_mode == PasteMode.VI_AFTER) - before = (paste_mode == PasteMode.VI_BEFORE) - after = (paste_mode == PasteMode.VI_AFTER) - if data.type == SelectionType.CHARACTERS: - if after: + 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 + 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 - 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: 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 index 3c54992beb..426ed96f67 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py @@ -22,7 +22,7 @@ class PosixAsyncioEventLoop(EventLoop): self.loop = loop or asyncio.get_event_loop() self.closed = False - self._stopped_f = asyncio.Future(loop=self.loop) + self._stopped_f = asyncio.Future(loop=self.loop) @asyncio.coroutine def run_as_coroutine(self, stdin, callbacks): @@ -41,7 +41,7 @@ class PosixAsyncioEventLoop(EventLoop): try: # Create a new Future every time. - self._stopped_f = asyncio.Future(loop=self.loop) + self._stopped_f = asyncio.Future(loop=self.loop) # Handle input timouts def timeout_handler(): diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py index e13c4c22ee..18e356f088 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py @@ -36,7 +36,7 @@ class Win32EventLoop(EventLoop): def __init__(self, inputhook=None, recognize_paste=True): assert inputhook is None or callable(inputhook) - self._event = HANDLE(_create_event()) + self._event = HANDLE(_create_event()) self._console_input_reader = ConsoleInputReader(recognize_paste=recognize_paste) self._calls_from_executor = [] @@ -74,14 +74,14 @@ class Win32EventLoop(EventLoop): # Wait for the next event. handle = self._ready_for_reading(remaining_timeout) - if handle == self._console_input_reader.handle.value: + 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: + 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() diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py index bf5111542b..e1e0e56393 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py @@ -87,9 +87,9 @@ class CommandLineInterface(object): #: 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 - + #: 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() @@ -148,10 +148,10 @@ class CommandLineInterface(object): def clipboard(self): return self.application.clipboard - @property - def pre_run_callables(self): - return self.application.pre_run_callables - + @property + def pre_run_callables(self): + return self.application.pre_run_callables + def add_buffer(self, name, buffer, focus=False): """ Insert a new buffer. @@ -275,10 +275,10 @@ class CommandLineInterface(object): """ 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. + :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 @@ -372,27 +372,27 @@ class CommandLineInterface(object): 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 _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 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. """ @@ -402,10 +402,10 @@ class CommandLineInterface(object): self._is_running = True self.on_start.fire() - self.reset() + self.reset() # Call pre_run. - self._pre_run(pre_run) + self._pre_run(pre_run) # Run eventloop in raw mode. with self.input.raw_mode(): @@ -454,10 +454,10 @@ class CommandLineInterface(object): self._is_running = True self.on_start.fire() - self.reset() + self.reset() # Call pre_run. - self._pre_run(pre_run) + self._pre_run(pre_run) with self.input.raw_mode(): self.renderer.request_absolute_cursor_position() @@ -611,7 +611,7 @@ class CommandLineInterface(object): if self.eventloop: self.eventloop.stop() - def run_in_terminal(self, func, render_cli_done=False, cooked_mode=True): + def run_in_terminal(self, func, render_cli_done=False, cooked_mode=True): """ Run function on the terminal above the prompt. @@ -624,8 +624,8 @@ class CommandLineInterface(object): :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. + :param cooked_mode: When True (the default), switch the input to + cooked mode while executing the function. :returns: the result of `func`. """ @@ -639,10 +639,10 @@ class CommandLineInterface(object): self._return_value = None # Run system command. - if cooked_mode: - with self.input.cooked_mode(): - result = func() - else: + if cooked_mode: + with self.input.cooked_mode(): + result = func() + else: result = func() # Redraw interface again. 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 index 6b36bc30f5..401135dec0 100644 --- 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 @@ -2,7 +2,7 @@ from __future__ import unicode_literals from prompt_toolkit.enums import DEFAULT_BUFFER -from prompt_toolkit.filters import HasSelection, Condition, EmacsInsertMode, ViInsertMode +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 @@ -10,7 +10,7 @@ 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 +from ..registry import Registry __all__ = ( @@ -26,10 +26,10 @@ def if_no_repeat(event): return not event.is_repeat -def load_basic_bindings(): - registry = Registry() +def load_basic_bindings(): + registry = Registry() insert_mode = ViInsertMode() | EmacsInsertMode() - handle = registry.add_binding + handle = registry.add_binding has_selection = HasSelection() @handle(Keys.ControlA) @@ -141,8 +141,8 @@ def load_basic_bindings(): 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.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')) @@ -181,7 +181,7 @@ def load_basic_bindings(): data = event.current_buffer.cut_selection() event.cli.clipboard.set_data(data) - # Global bindings. + # Global bindings. @handle(Keys.ControlZ) def _(event): @@ -196,7 +196,7 @@ def load_basic_bindings(): """ event.current_buffer.insert_text(event.data) - @handle(Keys.CPRResponse, save_before=lambda e: False) + @handle(Keys.CPRResponse, save_before=lambda e: False) def _(event): """ Handle incoming Cursor-Position-Request response. @@ -208,7 +208,7 @@ def load_basic_bindings(): # Report absolute cursor position to the renderer. event.cli.renderer.report_absolute_cursor_row(row) - @handle(Keys.BracketedPaste) + @handle(Keys.BracketedPaste) def _(event): " Pasting from clipboard. " data = event.data @@ -221,24 +221,24 @@ def load_basic_bindings(): 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(): + @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 = Registry() + @registry.add_binding(Keys.Vt100MouseEvent) def _(event): """ @@ -335,15 +335,15 @@ def load_mouse_bindings(): handler(event.cli, MouseEvent(position=Point(x=x, y=y), event_type=event_type)) - return registry + return registry + - -def load_abort_and_exit_bindings(): +def load_abort_and_exit_bindings(): """ Basic bindings for abort (Ctrl-C) and exit (Ctrl-D). """ - registry = Registry() - handle = registry.add_binding + registry = Registry() + handle = registry.add_binding @handle(Keys.ControlC) def _(event): @@ -359,34 +359,34 @@ def load_abort_and_exit_bindings(): handle(Keys.ControlD, filter=ctrl_d_condition)(get_by_name('end-of-file')) - return registry + return registry + - -def load_basic_system_bindings(): +def load_basic_system_bindings(): """ Basic system bindings (For both Emacs and Vi mode.) """ - registry = Registry() + registry = Registry() suspend_supported = Condition( lambda cli: suspend_to_background_supported()) - @registry.add_binding(Keys.ControlZ, filter=suspend_supported) + @registry.add_binding(Keys.ControlZ, filter=suspend_supported) def _(event): """ Suspend process to background. """ event.cli.suspend_to_background() - return registry + return registry - -def load_auto_suggestion_bindings(): + +def load_auto_suggestion_bindings(): """ Key bindings for accepting auto suggestion text. """ - registry = Registry() - handle = registry.add_binding + registry = Registry() + handle = registry.add_binding suggestion_available = Condition( lambda cli: @@ -403,5 +403,5 @@ def load_auto_suggestion_bindings(): if suggestion: b.insert_text(suggestion.text) - - return registry + + return registry 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 index 0f4ea37b01..bccdb04ff3 100644 --- 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 @@ -3,12 +3,12 @@ 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.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 +from ..registry import Registry, ConditionalRegistry __all__ = ( 'load_emacs_bindings', @@ -18,14 +18,14 @@ __all__ = ( ) -def load_emacs_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 + registry = ConditionalRegistry(Registry(), EmacsMode()) + handle = registry.add_binding insert_mode = EmacsInsertMode() has_selection = HasSelection() @@ -57,9 +57,9 @@ def load_emacs_bindings(): 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, '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)( @@ -75,18 +75,18 @@ def load_emacs_bindings(): 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.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. " @@ -144,13 +144,13 @@ def load_emacs_bindings(): @handle(Keys.ControlSquareClose, Keys.Any) def _(event): " When Ctl-] + a character is pressed. go to that character. " - # Also named 'character-search' + # 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' + # Also named 'character-search-backward' character_search(event.current_buffer, event.data, -event.arg) @handle(Keys.Escape, 'a') @@ -296,26 +296,26 @@ def load_emacs_bindings(): unindent(buffer, from_, to + 1, count=event.arg) - return registry + return registry - -def load_emacs_open_in_editor_bindings(): + +def load_emacs_open_in_editor_bindings(): """ Pressing C-X C-E will open the buffer in an external editor. """ - registry = Registry() + registry = Registry() + + registry.add_binding(Keys.ControlX, Keys.ControlE, + filter=EmacsMode() & ~HasSelection())( + get_by_name('edit-and-execute-command')) - registry.add_binding(Keys.ControlX, Keys.ControlE, - filter=EmacsMode() & ~HasSelection())( - get_by_name('edit-and-execute-command')) + return registry - return registry - -def load_emacs_system_bindings(): - registry = ConditionalRegistry(Registry(), EmacsMode()) - handle = registry.add_binding - +def load_emacs_system_bindings(): + registry = ConditionalRegistry(Registry(), EmacsMode()) + handle = registry.add_binding + has_focus = HasFocus(SYSTEM_BUFFER) @handle(Keys.Escape, '!', filter= ~has_focus) @@ -347,13 +347,13 @@ def load_emacs_system_bindings(): # Focus previous buffer again. event.cli.pop_focus() - return registry + return registry + +def load_emacs_search_bindings(get_search_state=None): + registry = ConditionalRegistry(Registry(), EmacsMode()) + handle = registry.add_binding -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) @@ -375,7 +375,7 @@ def load_emacs_search_bindings(get_search_state=None): event.cli.pop_focus() @handle(Keys.ControlJ, filter=has_focus) - @handle(Keys.Escape, filter=has_focus, eager=True) + @handle(Keys.Escape, filter=has_focus, eager=True) def _(event): """ When enter pressed in isearch, quit isearch mode. (Multiline @@ -433,20 +433,20 @@ def load_emacs_search_bindings(get_search_state=None): def _(event): incremental_search(event.cli, IncrementalSearchDirection.FORWARD, count=event.arg) - return registry + return registry - -def load_extra_emacs_page_navigation_bindings(): + +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 + 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 + + 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 index d045b1268f..f80c439fc6 100644 --- 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 @@ -5,15 +5,15 @@ 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 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 +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', @@ -134,13 +134,13 @@ def accept_line(event): @register('previous-history') def previous_history(event): - " Move `back` through the history list, fetching the previous command. " + " 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. " + " Move `forward` through the history list, fetching the next command. " event.current_buffer.history_forward(count=event.arg) @@ -163,13 +163,13 @@ def end_of_history(event): @register('reverse-search-history') def reverse_search_history(event): """ - Search backward starting at the current line and moving `up` through + 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 # @@ -267,16 +267,16 @@ def capitalize_word(event): 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 - - + +@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. # @@ -316,13 +316,13 @@ def kill_word(event): @register('unix-word-rubout') -def unix_word_rubout(event, WORD=True): +def unix_word_rubout(event, WORD=True): """ - Kill the word behind point, using whitespace as a word boundary. - Usually bound to ControlW. + 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) + 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 @@ -344,15 +344,15 @@ def unix_word_rubout(event, WORD=True): 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('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. " @@ -387,7 +387,7 @@ def yank(event): Paste before cursor. """ event.current_buffer.paste_clipboard_data( - event.cli.clipboard.get_data(), count=event.arg, paste_mode=PasteMode.EMACS) + event.cli.clipboard.get_data(), count=event.arg, paste_mode=PasteMode.EMACS) @register('yank-nth-arg') def yank_nth_arg(event): @@ -408,86 +408,86 @@ def yank_last_arg(event): 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) - +@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.) - """ + " 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() - +@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) + # -# 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. # @@ -495,84 +495,84 @@ def print_last_kbd_macro(event): 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) + + +@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/vi.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/vi.py index 25133196af..72568ee273 100644 --- 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 @@ -3,17 +3,17 @@ 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 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 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 +from .named_commands import get_by_name +from ..registry import Registry, ConditionalRegistry, BaseRegistry import prompt_toolkit.filters as filters from six.moves import range @@ -137,168 +137,168 @@ class TextObject(object): return new_document, clipboard_data -def create_text_object_decorator(registry): +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): """ - 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: @@ -316,8 +316,8 @@ def load_vi_bindings(get_search_state=None): # 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 + registry = ConditionalRegistry(Registry(), ViMode()) + handle = registry.add_binding # Default get_search_state. if get_search_state is None: @@ -348,9 +348,9 @@ def load_vi_bindings(get_search_state=None): (('~', ), 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')) - + # Insert a character literally (quoted insert). + handle(Keys.ControlV, filter=insert_mode)(get_by_name('quoted-insert')) + @handle(Keys.Escape) def _(event): """ @@ -635,8 +635,8 @@ def load_vi_bindings(get_search_state=None): """ event.current_buffer.paste_clipboard_data( event.cli.clipboard.get_data(), - count=event.arg, - paste_mode=PasteMode.VI_AFTER) + count=event.arg, + paste_mode=PasteMode.VI_AFTER) @handle('P', filter=navigation_mode) def _(event): @@ -645,8 +645,8 @@ def load_vi_bindings(get_search_state=None): """ event.current_buffer.paste_clipboard_data( event.cli.clipboard.get_data(), - count=event.arg, - paste_mode=PasteMode.VI_BEFORE) + count=event.arg, + paste_mode=PasteMode.VI_BEFORE) @handle('"', Keys.Any, 'p', filter=navigation_mode) def _(event): @@ -655,8 +655,8 @@ def load_vi_bindings(get_search_state=None): 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) + event.current_buffer.paste_clipboard_data( + data, count=event.arg, paste_mode=PasteMode.VI_AFTER) @handle('"', Keys.Any, 'P', filter=navigation_mode) def _(event): @@ -666,7 +666,7 @@ def load_vi_bindings(get_search_state=None): 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) + data, count=event.arg, paste_mode=PasteMode.VI_BEFORE) @handle('r', Keys.Any, filter=navigation_mode) def _(event): @@ -723,7 +723,7 @@ def load_vi_bindings(get_search_state=None): else: event.current_buffer.exit_selection() - @handle('v', filter=navigation_mode) + @handle('v', filter=navigation_mode) def _(event): " Enter character selection mode. " event.current_buffer.start_selection(selection_type=SelectionType.CHARACTERS) @@ -910,8 +910,8 @@ def load_vi_bindings(get_search_state=None): # XXX: should become text_object. pass - operator = create_operator_decorator(registry) - text_object = create_text_object_decorator(registry) + operator = create_operator_decorator(registry) + text_object = create_text_object_decorator(registry) @text_object(Keys.Any, filter=operator_given) def _(event): @@ -1705,25 +1705,25 @@ def load_vi_bindings(get_search_state=None): event.cli.vi_state.waiting_for_digraph = False event.cli.vi_state.digraph_symbol1 = None - return registry + return registry + - -def load_vi_open_in_editor_bindings(): +def load_vi_open_in_editor_bindings(): """ Pressing 'v' in navigation mode will open the buffer in an external editor. """ - registry = Registry() + registry = Registry() navigation_mode = ViNavigationMode() - registry.add_binding('v', filter=navigation_mode)( - get_by_name('edit-and-execute-command')) - return registry + 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 - +def load_vi_system_bindings(): + registry = ConditionalRegistry(Registry(), ViMode()) + handle = registry.add_binding + has_focus = filters.HasFocus(SYSTEM_BUFFER) navigation_mode = ViNavigationMode() @@ -1759,28 +1759,28 @@ def load_vi_system_bindings(): # Focus previous buffer again. event.cli.pop_focus() - return registry + return registry + - -def load_vi_search_bindings(get_search_state=None, - search_buffer_name=SEARCH_BUFFER): +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 - + 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) + 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): """ @@ -1793,8 +1793,8 @@ def load_vi_search_bindings(get_search_state=None, # 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('?', 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): """ @@ -1808,7 +1808,7 @@ def load_vi_search_bindings(get_search_state=None, event.cli.vi_state.input_mode = InputMode.INSERT @handle(Keys.ControlJ, filter=has_focus) - @handle(Keys.Escape, filter=has_focus) + @handle(Keys.Escape, filter=has_focus) def _(event): """ Apply the search. (At the / or ? prompt.) @@ -1870,16 +1870,16 @@ def load_vi_search_bindings(get_search_state=None, event.cli.pop_focus() event.cli.buffers[search_buffer_name].reset() - return registry + return registry + - -def load_extra_vi_page_navigation_bindings(): +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 + registry = ConditionalRegistry(Registry(), ViMode()) + handle = registry.add_binding handle(Keys.ControlF)(scroll_forward) handle(Keys.ControlB)(scroll_backward) @@ -1890,9 +1890,9 @@ def load_extra_vi_page_navigation_bindings(): handle(Keys.PageDown)(scroll_page_down) handle(Keys.PageUp)(scroll_page_up) - return registry + return registry + - class ViStateFilter(Filter): " Deprecated! " def __init__(self, get_vi_state, 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 index a7396b82cc..fb2c1070f7 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/defaults.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/defaults.py @@ -1,119 +1,119 @@ -""" -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) +""" +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/input_processor.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/input_processor.py index 7c1da5de90..51a3110827 100644 --- 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 @@ -12,7 +12,7 @@ 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 .registry import BaseRegistry from collections import deque from six.moves import range @@ -67,11 +67,11 @@ class InputProcessor(object): # Now the ControlX-ControlC callback will be called if this sequence is # registered in the registry. - :param registry: `BaseRegistry` instance. + :param registry: `BaseRegistry` instance. :param cli_ref: weakref to `CommandLineInterface`. """ def __init__(self, registry, cli_ref): - assert isinstance(registry, BaseRegistry) + assert isinstance(registry, BaseRegistry) self._registry = registry self._cli_ref = cli_ref @@ -86,14 +86,14 @@ class InputProcessor(object): # (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 = [] - + # Simple macro recording. (Like readline does.) + self.record_macro = False + self.macro = [] + self.reset() def reset(self): - self._previous_key_sequence = [] + self._previous_key_sequence = [] self._previous_handler = None self._process_coroutine = self._process() @@ -103,19 +103,19 @@ class InputProcessor(object): #: 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 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 @@ -163,17 +163,17 @@ class InputProcessor(object): 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 + # 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[:]) + self._call_handler(matches[-1], key_sequence=buffer[:]) del buffer[:] # Keep reference. # No match found. @@ -227,7 +227,7 @@ class InputProcessor(object): cli.invalidate() def _call_handler(self, handler, key_sequence=None): - was_recording = self.record_macro + was_recording = self.record_macro arg = self.arg self.arg = None @@ -255,11 +255,11 @@ class InputProcessor(object): 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) - + # 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 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 index 7bad16a6c5..83612c2a5c 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/manager.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/manager.py @@ -1,7 +1,7 @@ """ -DEPRECATED: -Use `prompt_toolkit.key_binding.defaults.load_key_bindings` instead. - +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. @@ -11,12 +11,12 @@ You don't have to use this, but it's practical. Usage:: manager = KeyBindingManager() - app = Application(key_bindings_registry=manager.registry) + app = Application(key_bindings_registry=manager.registry) """ from __future__ import unicode_literals -from .defaults import load_key_bindings +from .defaults import load_key_bindings from prompt_toolkit.filters import to_cli_filter -from prompt_toolkit.key_binding.registry import Registry, ConditionalRegistry, MergedRegistry +from prompt_toolkit.key_binding.registry import Registry, ConditionalRegistry, MergedRegistry __all__ = ( 'KeyBindingManager', @@ -40,37 +40,37 @@ class KeyBindingManager(object): :param enable_vi_mode: Deprecated! """ - def __init__(self, - registry=None, # XXX: not used anymore. + def __init__(self, + registry=None, # XXX: not used anymore. enable_vi_mode=None, # (`enable_vi_mode` is deprecated.) - enable_all=True, # + 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): + 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) - ]) + 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): 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 index 5d6bc3493c..24d0e729a1 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/registry.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/registry.py @@ -1,42 +1,42 @@ -""" -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. -""" +""" +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 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 +from six import text_type, with_metaclass __all__ = ( - 'BaseRegistry', + 'BaseRegistry', 'Registry', - 'ConditionalRegistry', - 'MergedRegistry', + 'ConditionalRegistry', + 'MergedRegistry', ) @@ -65,36 +65,36 @@ class _Binding(object): self.__class__.__name__, self.keys, self.handler) -class BaseRegistry(with_metaclass(ABCMeta, object)): +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): + 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. """ - 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. + self._version = 0 # For cache invalidation. def _clear_cache(self): - self._version += 1 + self._version += 1 self._get_bindings_for_keys_cache.clear() self._get_bindings_starting_with_keys_cache.clear() @@ -215,136 +215,136 @@ class Registry(BaseRegistry): 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 + + +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/layout/containers.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py index f91a15a1e1..0bdafe18e0 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py @@ -1046,8 +1046,8 @@ class Window(Container): def _get_digraph_char(self, cli): " Return `False`, or the Digraph symbol to be used. " - if cli.quoted_insert: - return '^' + if cli.quoted_insert: + return '^' if cli.vi_state.waiting_for_digraph: if cli.vi_state.digraph_symbol1: return cli.vi_state.digraph_symbol1 diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py index 7c3cc3c8f7..a928fd8226 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py @@ -150,17 +150,17 @@ 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')) - + 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 diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py index 412c602207..2934dfc9a7 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py @@ -231,10 +231,10 @@ class PromptMargin(Margin): # 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)) + # 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 = [] diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py index 5104b22f2b..7a8fde55b3 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py @@ -21,8 +21,8 @@ __all__ = ( 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 + 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. @@ -109,17 +109,17 @@ def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_ write(char.char) last_token[0] = char.token - # Render for the first time: reset styling. + # 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() - + # 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?? @@ -194,7 +194,7 @@ def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_ else: current_pos = move_cursor(screen.cursor_position) - if is_done or not use_alternate_screen: + if is_done or not use_alternate_screen: output.enable_autowrap() # Always reset the color attributes. This is important because a background @@ -444,7 +444,7 @@ class Renderer(object): 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, + 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)) @@ -480,7 +480,7 @@ class Renderer(object): output.cursor_up(self._cursor_pos.y) output.erase_down() output.reset_attributes() - output.enable_autowrap() + output.enable_autowrap() output.flush() # Erase title. diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py index 10cf160e28..6582921222 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals __all__ = ( 'SelectionType', - 'PasteMode', + 'PasteMode', 'SelectionState', ) @@ -24,12 +24,12 @@ class SelectionType(object): 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 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. diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py index 566fc23319..9893624c6e 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py @@ -27,7 +27,7 @@ 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.defaults import load_key_bindings_for_prompt from .key_binding.registry import Registry from .keys import Keys from .layout import Window, HSplit, FloatContainer, Float @@ -77,10 +77,10 @@ __all__ = ( 'prompt', 'prompt_async', 'create_confirm_application', - 'run_application', + 'run_application', 'confirm', 'print_tokens', - 'clear', + 'clear', ) @@ -449,9 +449,9 @@ def create_prompt_application( be edited by the user.) """ if key_bindings_registry is None: - key_bindings_registry = load_key_bindings_for_prompt( + key_bindings_registry = load_key_bindings_for_prompt( enable_system_bindings=enable_system_bindings, - enable_open_in_editor=enable_open_in_editor) + enable_open_in_editor=enable_open_in_editor) # Ensure backwards-compatibility, when `vi_mode` is passed. if vi_mode: @@ -506,7 +506,7 @@ def create_prompt_application( mouse_support=mouse_support, editing_mode=editing_mode, erase_when_done=erase_when_done, - reverse_vi_search_direction=True, + reverse_vi_search_direction=True, on_abort=on_abort, on_exit=on_exit) @@ -594,7 +594,7 @@ def run_application( cli.on_stop += stop_refresh_loop # Replace stdout. - patch_context = cli.patch_stdout_context(raw=True) if patch_stdout else DummyContext() + patch_context = cli.patch_stdout_context(raw=True) if patch_stdout else DummyContext() # Read input and return it. if return_asyncio_coroutine: @@ -610,7 +610,7 @@ def run_application( @asyncio.coroutine def run(): with patch_context: - result = yield from cli.run_async() + result = yield from cli.run_async() if isinstance(result, Document): # Backwards-compatibility. return result.text @@ -622,7 +622,7 @@ def run_application( else: try: with patch_context: - result = cli.run() + result = cli.run() if isinstance(result, Document): # Backwards-compatibility. return result.text @@ -671,7 +671,7 @@ def confirm(message='Confirm (y or n) '): return run_application(app) -def print_tokens(tokens, style=None, true_color=False, file=None): +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.:: @@ -689,13 +689,13 @@ def print_tokens(tokens, style=None, true_color=False, file=None): :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`. + :param file: The output file. This can be `sys.stdout` or `sys.stderr`. """ - if style is None: - style = DEFAULT_STYLE + if style is None: + style = DEFAULT_STYLE assert isinstance(style, Style) - output = create_output(true_color=true_color, stdout=file) + output = create_output(true_color=true_color, stdout=file) renderer_print_tokens(output, tokens, style) 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 index e17cac4564..b50325710f 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_dict.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_dict.py @@ -6,10 +6,10 @@ This is very similar to the Pygments style dictionary, with some additions: - 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 +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 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 index ad4861346c..0af8c53cf2 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_pygments.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_pygments.py @@ -33,12 +33,12 @@ def style_from_pygments(style_cls=pygments_DefaultStyle, 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')) - + 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. 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 index 5f7ad8b298..74841312fa 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py @@ -170,9 +170,9 @@ ANSI_SEQUENCES = { '\x1b[5C': Keys.ControlRight, '\x1b[5D': Keys.ControlLeft, - '\x1bOc': Keys.ControlRight, # rxvt - '\x1bOd': Keys.ControlLeft, # rxvt - + '\x1bOc': Keys.ControlRight, # rxvt + '\x1bOd': Keys.ControlLeft, # rxvt + '\x1b[200~': Keys.BracketedPaste, # Start of bracketed paste. # Meta + arrow keys. Several terminals handle this differently. @@ -459,14 +459,14 @@ class raw_mode(object): 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 - + + # 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.) 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 index 04a6a12804..b800aaacec 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py @@ -28,48 +28,48 @@ FG_ANSI_COLORS = { 'ansidefault': 39, # Low intensity. - 'ansiblack': 30, + 'ansiblack': 30, 'ansidarkred': 31, 'ansidarkgreen': 32, 'ansibrown': 33, 'ansidarkblue': 34, 'ansipurple': 35, 'ansiteal': 36, - 'ansilightgray': 37, + 'ansilightgray': 37, # High intensity. - 'ansidarkgray': 90, + 'ansidarkgray': 90, 'ansired': 91, 'ansigreen': 92, 'ansiyellow': 93, 'ansiblue': 94, 'ansifuchsia': 95, 'ansiturquoise': 96, - 'ansiwhite': 97, + 'ansiwhite': 97, } BG_ANSI_COLORS = { 'ansidefault': 49, # Low intensity. - 'ansiblack': 40, + 'ansiblack': 40, 'ansidarkred': 41, 'ansidarkgreen': 42, 'ansibrown': 43, 'ansidarkblue': 44, 'ansipurple': 45, 'ansiteal': 46, - 'ansilightgray': 47, + 'ansilightgray': 47, # High intensity. - 'ansidarkgray': 100, + 'ansidarkgray': 100, 'ansired': 101, 'ansigreen': 102, 'ansiyellow': 103, 'ansiblue': 104, 'ansifuchsia': 105, 'ansiturquoise': 106, - 'ansiwhite': 107, + 'ansiwhite': 107, } @@ -424,9 +424,9 @@ class Vt100_Output(Output): 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)) + # 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) 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 index 2a66351221..410e5fa517 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals from ctypes import windll, pointer -from ctypes.wintypes import DWORD, HANDLE +from ctypes.wintypes import DWORD, HANDLE from six.moves import range from prompt_toolkit.key_binding.input_processor import KeyPress @@ -111,10 +111,10 @@ class ConsoleInputReader(object): # 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)) + 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)) + self.handle = HANDLE(msvcrt.get_osfhandle(self._fdcon)) def close(self): " Close fdcon. " @@ -321,7 +321,7 @@ class raw_mode(object): `raw_input` method of `.vt100_input`. """ def __init__(self, fileno=None): - self.handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE)) + self.handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE)) def __enter__(self): # Remember original mode. 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 index 19788652d2..d4dddbab42 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py @@ -1,7 +1,7 @@ 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 ctypes.wintypes import DWORD, HANDLE from prompt_toolkit.renderer import Output from prompt_toolkit.styles import ANSI_COLOR_NAMES @@ -70,7 +70,7 @@ class Win32Output(Output): self._buffer = [] self.stdout = stdout - self.hconsole = HANDLE(windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)) + self.hconsole = HANDLE(windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)) self._in_alternate_screen = False @@ -141,31 +141,31 @@ class Win32Output(Output): """ 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() + # 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)) - + success = windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(sbinfo)) + + # success = self._winapi(windll.kernel32.GetConsoleScreenBufferInfo, + # self.hconsole, byref(sbinfo)) + if success: return sbinfo else: @@ -346,8 +346,8 @@ class Win32Output(Output): 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)) + 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 @@ -358,7 +358,7 @@ class Win32Output(Output): Make stdout again the active buffer. """ if self._in_alternate_screen: - stdout = HANDLE(self._winapi(windll.kernel32.GetStdHandle, STD_OUTPUT_HANDLE)) + 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 @@ -366,7 +366,7 @@ class Win32Output(Output): def enable_mouse_support(self): ENABLE_MOUSE_INPUT = 0x10 - handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE)) + handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE)) original_mode = DWORD() self._winapi(windll.kernel32.GetConsoleMode, handle, pointer(original_mode)) @@ -374,7 +374,7 @@ class Win32Output(Output): def disable_mouse_support(self): ENABLE_MOUSE_INPUT = 0x10 - handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE)) + handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE)) original_mode = DWORD() self._winapi(windll.kernel32.GetConsoleMode, handle, pointer(original_mode)) @@ -396,7 +396,7 @@ class Win32Output(Output): to a bug in the Windows Console. Sending a repaint request solves it. """ # Get console handle - handle = HANDLE(windll.kernel32.GetConsoleWindow()) + handle = HANDLE(windll.kernel32.GetConsoleWindow()) RDW_INVALIDATE = 0x0001 windll.user32.RedrawWindow(handle, None, None, c_uint(RDW_INVALIDATE)) diff --git a/contrib/python/prompt-toolkit/py2/tests/test_buffer.py b/contrib/python/prompt-toolkit/py2/tests/test_buffer.py index 9ef53956e7..a9cff19024 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_buffer.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_buffer.py @@ -1,111 +1,111 @@ -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' +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 index 403b6163d4..68ca3d03f0 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_cli.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_cli.py @@ -1,629 +1,629 @@ -# 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 +# 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 index bf9fc5e064..64765d3f1a 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_contrib.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_contrib.py @@ -1,254 +1,254 @@ -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) +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 index 0cc1762c3e..8c0cf5704c 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_document.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_document.py @@ -1,74 +1,74 @@ -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) +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 index b9cf8fb239..5aee62a9a9 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_filter.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_filter.py @@ -1,168 +1,168 @@ -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) +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 index d3521be710..de10c0f9a9 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_inputstream.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_inputstream.py @@ -1,142 +1,142 @@ -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 +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 index 468ff9b080..d706c4443b 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_key_binding.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_key_binding.py @@ -1,140 +1,140 @@ -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' +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 index 5d388e6400..6c9e67b4de 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_layout.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_layout.py @@ -1,60 +1,60 @@ -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, '')], - ] +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 index a8d0c33048..c3b5826b36 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_print_tokens.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_print_tokens.py @@ -1,50 +1,50 @@ -""" -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 +""" +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 index beb976abcc..6ece5cdeb5 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_regular_languages.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_regular_languages.py @@ -1,110 +1,110 @@ -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 +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 index c677306859..8c13510ea8 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_shortcuts.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_shortcuts.py @@ -1,50 +1,50 @@ -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') - ] +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 index 655237a24f..fc839ec95f 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_style.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_style.py @@ -1,40 +1,40 @@ -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 +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 index b3b56eb738..1e3d92cda6 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_utils.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_utils.py @@ -1,39 +1,39 @@ -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 +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 index d7cc0aa8c9..1ccec7bf7b 100644 --- a/contrib/python/prompt-toolkit/py2/tests/test_yank_nth_arg.py +++ b/contrib/python/prompt-toolkit/py2/tests/test_yank_nth_arg.py @@ -1,85 +1,85 @@ -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' +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' diff --git a/contrib/python/prompt-toolkit/py2/tests/ya.make b/contrib/python/prompt-toolkit/py2/tests/ya.make index c1db893e64..afd26fbfe7 100644 --- a/contrib/python/prompt-toolkit/py2/tests/ya.make +++ b/contrib/python/prompt-toolkit/py2/tests/ya.make @@ -1,28 +1,28 @@ -PY2TEST() - -OWNER(g:python-contrib) - -PEERDIR( - contrib/python/prompt-toolkit -) - -TEST_SRCS( - test_buffer.py - test_cli.py - test_contrib.py - test_document.py - test_filter.py - test_inputstream.py - test_key_binding.py - test_layout.py - test_print_tokens.py - test_regular_languages.py - test_shortcuts.py - test_style.py - test_utils.py - test_yank_nth_arg.py -) - -NO_LINT() - -END() +PY2TEST() + +OWNER(g:python-contrib) + +PEERDIR( + contrib/python/prompt-toolkit +) + +TEST_SRCS( + test_buffer.py + test_cli.py + test_contrib.py + test_document.py + test_filter.py + test_inputstream.py + test_key_binding.py + test_layout.py + test_print_tokens.py + test_regular_languages.py + test_shortcuts.py + test_style.py + test_utils.py + test_yank_nth_arg.py +) + +NO_LINT() + +END() diff --git a/contrib/python/prompt-toolkit/py2/ya.make b/contrib/python/prompt-toolkit/py2/ya.make index 75aaf74e01..db22aa0a70 100644 --- a/contrib/python/prompt-toolkit/py2/ya.make +++ b/contrib/python/prompt-toolkit/py2/ya.make @@ -1,36 +1,36 @@ -PY2_LIBRARY() +PY2_LIBRARY() -OWNER(blinkov nslus g:python-contrib) +OWNER(blinkov nslus g:python-contrib) -VERSION(1.0.18) +VERSION(1.0.18) -LICENSE(BSD-3-Clause) +LICENSE(BSD-3-Clause) PEERDIR( - contrib/python/six + contrib/python/six contrib/python/wcwidth ) -NO_LINT() - +NO_LINT() + NO_CHECK_IMPORTS( prompt_toolkit.clipboard.pyperclip - prompt_toolkit.contrib.telnet.* + prompt_toolkit.contrib.telnet.* prompt_toolkit.eventloop.asyncio_posix prompt_toolkit.eventloop.asyncio_win32 - prompt_toolkit.eventloop.posix + prompt_toolkit.eventloop.posix prompt_toolkit.eventloop.win32 - prompt_toolkit.input.win32 - prompt_toolkit.input.win32_pipe - prompt_toolkit.output.conemu - prompt_toolkit.output.win32 - prompt_toolkit.output.windows10 + prompt_toolkit.input.win32 + prompt_toolkit.input.win32_pipe + prompt_toolkit.output.conemu + prompt_toolkit.output.win32 + prompt_toolkit.output.windows10 prompt_toolkit.terminal.conemu_output - prompt_toolkit.terminal.vt100_input - prompt_toolkit.terminal.vt100_output + prompt_toolkit.terminal.vt100_input + prompt_toolkit.terminal.vt100_output prompt_toolkit.terminal.win32_input prompt_toolkit.terminal.win32_output - prompt_toolkit.win32_types + prompt_toolkit.win32_types ) PY_SRCS( @@ -95,7 +95,7 @@ PY_SRCS( prompt_toolkit/key_binding/bindings/scroll.py prompt_toolkit/key_binding/bindings/utils.py prompt_toolkit/key_binding/bindings/vi.py - prompt_toolkit/key_binding/defaults.py + prompt_toolkit/key_binding/defaults.py prompt_toolkit/key_binding/digraphs.py prompt_toolkit/key_binding/input_processor.py prompt_toolkit/key_binding/manager.py @@ -140,14 +140,14 @@ PY_SRCS( prompt_toolkit/win32_types.py ) -RESOURCE_FILES( - PREFIX contrib/python/prompt-toolkit/py2/ - .dist-info/METADATA - .dist-info/top_level.txt -) - +RESOURCE_FILES( + PREFIX contrib/python/prompt-toolkit/py2/ + .dist-info/METADATA + .dist-info/top_level.txt +) + END() -RECURSE_FOR_TESTS( - tests -) +RECURSE_FOR_TESTS( + tests +) |