diff -Nru prompt-toolkit-3.0.5/appveyor.yml prompt-toolkit-3.0.6/appveyor.yml --- prompt-toolkit-3.0.5/appveyor.yml 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/appveyor.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -environment: - matrix: - - PYTHON: "C:\\Python36" - PYTHON_VERSION: "3.6" - - PYTHON: "C:\\Python36-x64" - PYTHON_VERSION: "3.6" - - - PYTHON: "C:\\Python35" - PYTHON_VERSION: "3.5" - - PYTHON: "C:\\Python35-x64" - PYTHON_VERSION: "3.5" - - - PYTHON: "C:\\Python34" - PYTHON_VERSION: "3.4" - - PYTHON: "C:\\Python34-x64" - PYTHON_VERSION: "3.4" - - - PYTHON: "C:\\Python33" - PYTHON_VERSION: "3.3" - - PYTHON: "C:\\Python33-x64" - PYTHON_VERSION: "3.3" - - - PYTHON: "C:\\Python27" - PYTHON_VERSION: "2.7" - - PYTHON: "C:\\Python27-x64" - PYTHON_VERSION: "2.7" - - - PYTHON: "C:\\Python26" - PYTHON_VERSION: "2.6" - - PYTHON: "C:\\Python27-x64" - PYTHON_VERSION: "2.6" - -install: - - "set PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - - pip install . pytest coverage codecov flake8 - - pip list - -build: false - -test_script: - - If not ($env:PYTHON_VERSION==2.6) flake8 prompt_toolkit - - coverage run -m pytest - -after_test: - - codecov diff -Nru prompt-toolkit-3.0.5/CHANGELOG prompt-toolkit-3.0.6/CHANGELOG --- prompt-toolkit-3.0.5/CHANGELOG 2020-03-26 08:03:05.000000000 +0000 +++ prompt-toolkit-3.0.6/CHANGELOG 2020-08-10 09:52:02.000000000 +0000 @@ -1,12 +1,46 @@ CHANGELOG ========= +3.0.6: 2020-08-10 +----------------- + +New features: +- The SSH/Telnet adaptors have been refactored and improved in several ways. + See issues #876 and PR #1150 and #1184 on GitHub. + * Handle terminal types for both telnet and SSH sessions. + * Added pipe input abstraction. (base class for `PosixPipeInput` and + `Win32PipeInput`). + * The color depth logic has been refactored and moved to the `Output` + implementations. Added `get_default_color_depth` method to `Output` + objects. + * All line feets are now preceded by a carriage return in the telnet + connection stdout. +- Introduce `REPLACE_SINGLE` input mode for Vi key bindings. +- Improvements to the checkbox implementation: + * Hide the scrollbar for a single checkbox. + * Added a "checked" setter to the checkbox. +- Expose `KeyPressEvent` in key_binding/__init__.py (often used in type + annotations). +- The renderer has been optimized so that no trailing spaces are generated + (this improves copying in some terminals). + +Fixes: +- Ignore F21..F24 key bindings by default. +- Fix auto_suggest key bindings when suggestion text is empty. +- Bugfix in SIGWINCH handling. +- Handle bug in HSplit/VSplit when the number of children is zero. +- Bugfix in CPR handling in renderer. Proper cancellation of pending tasks. +- Ensure rprompt aligns with input. +- Use `sys.stdin.encoding` for decoding stdin stream. + + 3.0.5: 2020-03-26 ----------------- Fixes: - Bugfix in mouse handling on Windows. + 3.0.4: 2020-03-06 ----------------- diff -Nru prompt-toolkit-3.0.5/.codecov.yml prompt-toolkit-3.0.6/.codecov.yml --- prompt-toolkit-3.0.5/.codecov.yml 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/.codecov.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -comment: off diff -Nru prompt-toolkit-3.0.5/debian/changelog prompt-toolkit-3.0.6/debian/changelog --- prompt-toolkit-3.0.5/debian/changelog 2020-05-04 15:54:35.000000000 +0000 +++ prompt-toolkit-3.0.6/debian/changelog 2020-08-10 18:54:34.000000000 +0000 @@ -1,3 +1,9 @@ +prompt-toolkit (3.0.6-1) unstable; urgency=medium + + * New upstream version 3.0.6 + + -- Gordon Ball Mon, 10 Aug 2020 18:54:34 +0000 + prompt-toolkit (3.0.5-2) unstable; urgency=medium * Upload to unstable diff -Nru prompt-toolkit-3.0.5/docs/conf.py prompt-toolkit-3.0.6/docs/conf.py --- prompt-toolkit-3.0.5/docs/conf.py 2020-03-26 08:03:38.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/conf.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,269 +0,0 @@ -# -*- coding: utf-8 -*- -# -# prompt_toolkit documentation build configuration file, created by -# sphinx-quickstart on Thu Jul 31 14:17:08 2014. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import os -import sys - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.graphviz' ] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'prompt_toolkit' -copyright = u'2014-2020, Jonathan Slenders' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '3.0.5' -# The full version, including alpha/beta/rc tags. -release = '3.0.5' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. - -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' - -if on_rtd: - html_theme = 'default' -else: - try: - import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - except ImportError: - html_theme = 'pyramid' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -html_logo = 'images/logo_400px.png' - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'prompt_toolkitdoc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ('index', 'prompt_toolkit.tex', u'prompt_toolkit Documentation', - u'Jonathan Slenders', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'prompt_toolkit', u'prompt_toolkit Documentation', - [u'Jonathan Slenders'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'prompt_toolkit', u'prompt_toolkit Documentation', - u'Jonathan Slenders', 'prompt_toolkit', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/auto-suggestion.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/auto-suggestion.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/bottom-toolbar.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/bottom-toolbar.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/colored-prompt.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/colored-prompt.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/colorful-completions.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/colorful-completions.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/dialogs/button.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/dialogs/button.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/dialogs/confirm.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/dialogs/confirm.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/dialogs/inputbox.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/dialogs/inputbox.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/dialogs/messagebox.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/dialogs/messagebox.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/dialogs/styled.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/dialogs/styled.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/hello-world-prompt.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/hello-world-prompt.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/html-completion.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/html-completion.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/html-input.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/html-input.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/logo_400px.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/logo_400px.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/multiline-input.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/multiline-input.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/number-validator.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/number-validator.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/progress-bars/apt-get.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/progress-bars/apt-get.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/progress-bars/colored-title-and-label.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/progress-bars/colored-title-and-label.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/progress-bars/custom-key-bindings.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/progress-bars/custom-key-bindings.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/progress-bars/simple-progress-bar.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/progress-bars/simple-progress-bar.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/progress-bars/two-tasks.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/progress-bars/two-tasks.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/ptpython-2.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/ptpython-2.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/ptpython-history-help.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/ptpython-history-help.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/ptpython-menu.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/ptpython-menu.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/ptpython.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/ptpython.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/pymux.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/pymux.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/pyvim.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/pyvim.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/repl/sqlite-1.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/repl/sqlite-1.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/repl/sqlite-2.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/repl/sqlite-2.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/repl/sqlite-3.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/repl/sqlite-3.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/repl/sqlite-4.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/repl/sqlite-4.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/repl/sqlite-5.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/repl/sqlite-5.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/repl/sqlite-6.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/repl/sqlite-6.png differ Binary files /tmp/tmpvdKl2K/uscqR_v1lZ/prompt-toolkit-3.0.5/docs/images/rprompt.png and /tmp/tmpvdKl2K/2efChZGOvC/prompt-toolkit-3.0.6/docs/images/rprompt.png differ diff -Nru prompt-toolkit-3.0.5/docs/index.rst prompt-toolkit-3.0.6/docs/index.rst --- prompt-toolkit-3.0.5/docs/index.rst 2020-03-26 08:01:04.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/index.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -Python Prompt Toolkit 3.0 -========================= - -.. warning:: - - Notice that this is the prompt_toolkit 3.0 documentation. It is mostly - compatible with the 2.0 branch. The difference is that prompt_toolkit 3.0 - requires at least Python 3.6. On the plus side, it uses asyncio natively - (rather than it's own event loop), and we have type annotations everywhere. - -`prompt_toolkit` is a library for building powerful interactive command line -and terminal applications in Python. - - -It can be a very advanced pure Python replacement for `GNU readline -`_, but it can also be -used for building full screen applications. - -.. image:: images/ptpython-2.png - -Some features: - -- Syntax highlighting of the input while typing. (For instance, with a Pygments lexer.) -- Multi-line input editing. -- Advanced code completion. -- Selecting text for copy/paste. (Both Emacs and Vi style.) -- Mouse support for cursor positioning and scrolling. -- Auto suggestions. (Like `fish shell `_.) -- No global state. - -Like readline: - -- Both Emacs and Vi key bindings. -- Reverse and forward incremental search. -- Works well with Unicode double width characters. (Chinese input.) - -Works everywhere: - -- Pure Python. Runs on all Python versions starting at Python 3.6. - (Python 2.6 - 3.x is supported in prompt_toolkit 2.0; not 3.0). -- Runs on Linux, OS X, OpenBSD and Windows systems. -- Lightweight, the only dependencies are Pygments, six and wcwidth. -- No assumptions about I/O are made. Every prompt_toolkit application should - also run in a telnet/ssh server or an `asyncio - `_ process. - -Have a look at :ref:`the gallery ` to get an idea of what is possible. - -Getting started ---------------- - -Go to :ref:`getting started ` and build your first prompt. - - -Thanks to: ----------- - -A special thanks to `all the contributors -`_ -for making prompt_toolkit possible. - -Also, a special thanks to the `Pygments `_ and `wcwidth -`_ libraries. - - -Table of contents ------------------ - -.. toctree:: - :maxdepth: 2 - - pages/gallery - pages/getting_started - pages/upgrading/index - pages/printing_text - pages/asking_for_input - pages/dialogs - pages/progress_bars - pages/full_screen_apps - pages/tutorials/index - pages/advanced_topics/index - pages/reference - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - -Prompt_toolkit was created by `Jonathan Slenders -`_. diff -Nru prompt-toolkit-3.0.5/docs/make.bat prompt-toolkit-3.0.6/docs/make.bat --- prompt-toolkit-3.0.5/docs/make.bat 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/make.bat 1970-01-01 00:00:00.000000000 +0000 @@ -1,242 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=_build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . -set I18NSPHINXOPTS=%SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. xml to make Docutils-native XML files - echo. pseudoxml to make pseudoxml-XML files for display purposes - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - - -%SPHINXBUILD% 2> nul -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\xline.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\xline.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdf" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdfja" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf-ja - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -if "%1" == "xml" ( - %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The XML files are in %BUILDDIR%/xml. - goto end -) - -if "%1" == "pseudoxml" ( - %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. - goto end -) - -:end diff -Nru prompt-toolkit-3.0.5/docs/Makefile prompt-toolkit-3.0.6/docs/Makefile --- prompt-toolkit-3.0.5/docs/Makefile 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/Makefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,177 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/prompt_toolkit.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/prompt_toolkit.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/prompt_toolkit" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/prompt_toolkit" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff -Nru prompt-toolkit-3.0.5/docs/pages/advanced_topics/architecture.rst prompt-toolkit-3.0.6/docs/pages/advanced_topics/architecture.rst --- prompt-toolkit-3.0.5/docs/pages/advanced_topics/architecture.rst 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/advanced_topics/architecture.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -.. _architecture: - - -Architecture -============ - -TODO: this is a little outdated. - -:: - - +---------------------------------------------------------------+ - | InputStream | - | =========== | - | - Parses the input stream coming from a VT100 | - | compatible terminal. Translates it into data input | - | and control characters. Calls the corresponding | - | handlers of the `InputStreamHandler` instance. | - | | - | e.g. Translate '\x1b[6~' into "Keys.PageDown", call | - | the `feed_key` method of `InputProcessor`. | - +---------------------------------------------------------------+ - | - v - +---------------------------------------------------------------+ - | InputStreamHandler | - | ================== | - | - Has a `Registry` of key bindings, it calls the | - | bindings according to the received keys and the | - | input mode. | - | | - | We have Vi and Emacs bindings. - +---------------------------------------------------------------+ - | - v - +---------------------------------------------------------------+ - | Key bindings | - | ============ | - | - Every key binding consists of a function that | - | receives an `Event` and usually it operates on | - | the `Buffer` object. (It could insert data or | - | move the cursor for example.) | - +---------------------------------------------------------------+ - | - | Most of the key bindings operate on a `Buffer` object, but - | they don't have to. They could also change the visibility - | of a menu for instance, or change the color scheme. - | - v - +---------------------------------------------------------------+ - | Buffer | - | ====== | - | - Contains a data structure to hold the current | - | input (text and cursor position). This class | - | implements all text manipulations and cursor | - | movements (Like e.g. cursor_forward, insert_char | - | or delete_word.) | - | | - | +-----------------------------------------------+ | - | | Document (text, cursor_position) | | - | | ================================ | | - | | Accessed as the `document` property of the | | - | | `Buffer` class. This is a wrapper around the | | - | | text and cursor position, and contains | | - | | methods for querying this data , e.g. to give | | - | | the text before the cursor. | | - | +-----------------------------------------------+ | - +---------------------------------------------------------------+ - | - | Normally after every key press, the output will be - | rendered again. This happens in the event loop of - | the `Application` where `Renderer.render` is called. - v - +---------------------------------------------------------------+ - | Layout | - | ====== | - | - When the renderer should redraw, the renderer | - | asks the layout what the output should look like. | - | - The layout operates on a `Screen` object that he | - | received from the `Renderer` and will put the | - | toolbars, menus, highlighted content and prompt | - | in place. | - | | - | +-----------------------------------------------+ | - | | Menus, toolbars, prompt | | - | | ======================= | | - | | | | - | +-----------------------------------------------+ | - +---------------------------------------------------------------+ - | - v - +---------------------------------------------------------------+ - | Renderer | - | ======== | - | - Calculates the difference between the last output | - | and the new one and writes it to the terminal | - | output. | - +---------------------------------------------------------------+ diff -Nru prompt-toolkit-3.0.5/docs/pages/advanced_topics/asyncio.rst prompt-toolkit-3.0.6/docs/pages/advanced_topics/asyncio.rst --- prompt-toolkit-3.0.5/docs/pages/advanced_topics/asyncio.rst 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/advanced_topics/asyncio.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -.. _asyncio: - -Running on top of the `asyncio` event loop -========================================== - -.. note:: - - New in prompt_toolkit 3.0. (In prompt_toolkit 2.0 this was possible using a - work-around). - -Prompt_toolkit 3.0 uses asyncio natively. Calling ``Application.run()`` will -automatically run the asyncio event loop. - -If however you want to run a prompt_toolkit ``Application`` within an asyncio -environment, you have to call the ``prompt_async`` method, like this: - -.. code:: python - - from prompt_toolkit.application import Application - - async def main(): - # Define application. - application = Application( - ... - ) - - result = await application.run_async() - print(result) - - asyncio.get_event_loop().run_until_complete(main()) diff -Nru prompt-toolkit-3.0.5/docs/pages/advanced_topics/filters.rst prompt-toolkit-3.0.6/docs/pages/advanced_topics/filters.rst --- prompt-toolkit-3.0.5/docs/pages/advanced_topics/filters.rst 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/advanced_topics/filters.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,169 +0,0 @@ -.. _filters: - -Filters -======= - -Many places in `prompt_toolkit` require a boolean value that can change over -time. For instance: - -- to specify whether a part of the layout needs to be visible or not; -- or to decide whether a certain key binding needs to be active or not; -- or the ``wrap_lines`` option of - :class:`~prompt_toolkit.layout.BufferControl`; -- etcetera. - -These booleans are often dynamic and can change at runtime. For instance, the -search toolbar should only be visible when the user is actually searching (when -the search buffer has the focus). The ``wrap_lines`` option could be changed -with a certain key binding. And that key binding could only work when the -default buffer got the focus. - -In `prompt_toolkit`, we decided to reduce the amount of state in the whole -framework, and apply a simple kind of reactive programming to describe the flow -of these booleans as expressions. (It's one-way only: if a key binding needs to -know whether it's active or not, it can follow this flow by evaluating an -expression.) - -The (abstract) base class is :class:`~prompt_toolkit.filters.Filter`, which -wraps an expression that takes no input and evaluates to a boolean. Getting the -state of a filter is done by simply calling it. - - -An example ----------- - -The most obvious way to create such a :class:`~prompt_toolkit.filters.Filter` -instance is by creating a :class:`~prompt_toolkit.filters.Condition` instance -from a function. For instance, the following condition will evaluate to -``True`` when the user is searching: - -.. code:: python - - from prompt_toolkit.application.current import get_app - from prompt_toolkit.filters import Condition - - is_searching = Condition(lambda: get_app().is_searching) - -A different way of writing this, is by using the decorator syntax: - -.. code:: python - - from prompt_toolkit.application.current import get_app - from prompt_toolkit.filters import Condition - - @Condition - def is_searching(): - return get_app().is_searching - -This filter can then be used in a key binding, like in the following snippet: - -.. code:: python - - from prompt_toolkit.key_binding import KeyBindings - - kb = KeyBindings() - - @kb.add('c-t', filter=is_searching) - def _(event): - # Do, something, but only when searching. - pass - -If we want to know the boolean value of this filter, we have to call it like a -function: - -.. code:: python - - print(is_searching()) - - -Built-in filters ----------------- - -There are many built-in filters, ready to use. All of them have a lowercase -name, because they represent the wrapped function underneath, and can be called -as a function. - -- :class:`~prompt_toolkit.filters.app.has_arg` -- :class:`~prompt_toolkit.filters.app.has_completions` -- :class:`~prompt_toolkit.filters.app.has_focus` -- :class:`~prompt_toolkit.filters.app.buffer_has_focus` -- :class:`~prompt_toolkit.filters.app.has_selection` -- :class:`~prompt_toolkit.filters.app.has_validation_error` -- :class:`~prompt_toolkit.filters.app.is_aborting` -- :class:`~prompt_toolkit.filters.app.is_done` -- :class:`~prompt_toolkit.filters.app.is_read_only` -- :class:`~prompt_toolkit.filters.app.is_multiline` -- :class:`~prompt_toolkit.filters.app.renderer_height_is_known` -- :class:`~prompt_toolkit.filters.app.in_editing_mode` -- :class:`~prompt_toolkit.filters.app.in_paste_mode` - -- :class:`~prompt_toolkit.filters.app.vi_mode` -- :class:`~prompt_toolkit.filters.app.vi_navigation_mode` -- :class:`~prompt_toolkit.filters.app.vi_insert_mode` -- :class:`~prompt_toolkit.filters.app.vi_insert_multiple_mode` -- :class:`~prompt_toolkit.filters.app.vi_replace_mode` -- :class:`~prompt_toolkit.filters.app.vi_selection_mode` -- :class:`~prompt_toolkit.filters.app.vi_waiting_for_text_object_mode` -- :class:`~prompt_toolkit.filters.app.vi_digraph_mode` - -- :class:`~prompt_toolkit.filters.app.emacs_mode` -- :class:`~prompt_toolkit.filters.app.emacs_insert_mode` -- :class:`~prompt_toolkit.filters.app.emacs_selection_mode` - -- :class:`~prompt_toolkit.filters.app.is_searching` -- :class:`~prompt_toolkit.filters.app.control_is_searchable` -- :class:`~prompt_toolkit.filters.app.vi_search_direction_reversed` - - -Combining filters ------------------ - -Filters can be chained with the ``&`` (AND) and ``|`` (OR) operators and -negated with the ``~`` (negation) operator. - -Some examples: - -.. code:: python - - from prompt_toolkit.key_binding import KeyBindings - from prompt_toolkit.filters import has_selection, has_selection - - kb = KeyBindings() - - @kb.add('c-t', filter=~is_searching) - def _(event): - " Do something, but not while searching. " - pass - - @kb.add('c-t', filter=has_search | has_selection) - def _(event): - " Do something, but only when searching or when there is a selection. " - pass - - -to_filter ---------- - -Finally, in many situations you want your code to expose an API that is able to -deal with both booleans as well as filters. For instance, when for most users a -boolean works fine because they don't need to change the value over time, while -some advanced users want to be able this value to a certain setting or event -that does changes over time. - -In order to handle both use cases, there is a utility called -:func:`~prompt_toolkit.filters.utils.to_filter`. - -This is a function that takes -either a boolean or an actual :class:`~prompt_toolkit.filters.Filter` -instance, and always returns a :class:`~prompt_toolkit.filters.Filter`. - -.. code:: python - - from prompt_toolkit.filters.utils import to_filter - - # In each of the following three examples, 'f' will be a `Filter` - # instance. - f = to_filter(True) - f = to_filter(False) - f = to_filter(Condition(lambda: True)) - f = to_filter(has_search | has_selection) diff -Nru prompt-toolkit-3.0.5/docs/pages/advanced_topics/index.rst prompt-toolkit-3.0.6/docs/pages/advanced_topics/index.rst --- prompt-toolkit-3.0.5/docs/pages/advanced_topics/index.rst 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/advanced_topics/index.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -.. _advanced_topics: - -Advanced topics -=============== - -.. toctree:: - :caption: Contents: - :maxdepth: 1 - - key_bindings - styling - filters - rendering_flow - asyncio - input_hooks - architecture - rendering_pipeline diff -Nru prompt-toolkit-3.0.5/docs/pages/advanced_topics/input_hooks.rst prompt-toolkit-3.0.6/docs/pages/advanced_topics/input_hooks.rst --- prompt-toolkit-3.0.5/docs/pages/advanced_topics/input_hooks.rst 2020-03-26 08:01:04.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/advanced_topics/input_hooks.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -.. _input_hooks: - - -Input hooks -=========== - -Input hooks are a tool for inserting an external event loop into the -prompt_toolkit event loop, so that the other loop can run as long as -prompt_toolkit (actually asyncio) is idle. This is used in applications like -`IPython `_, so that GUI toolkits can display their -windows while we wait at the prompt for user input. - -As a consequence, we will "trampoline" back and forth between two event loops. - -.. note:: - - This will use a :class:`~asyncio.SelectorEventLoop`, not the :class: - :class:`~asyncio.ProactorEventLoop` (on Windows) due to the way the - implementation works (contributions are welcome to make that work). - - -.. code:: python - - from prompt_toolkit.eventloop.inputhook import set_eventloop_with_inputhook - - def inputhook(inputhook_context): - # At this point, we run the other loop. This loop is supposed to run - # until either `inputhook_context.fileno` becomes ready for reading or - # `inputhook_context.input_is_ready()` returns True. - - # A good way is to register this file descriptor in this other event - # loop with a callback that stops this loop when this FD becomes ready. - # There is no need to actually read anything from the FD. - - while True: - ... - - set_eventloop_with_inputhook(inputhook) - - # Any asyncio code at this point will now use this new loop, with input - # hook installed. diff -Nru prompt-toolkit-3.0.5/docs/pages/advanced_topics/key_bindings.rst prompt-toolkit-3.0.6/docs/pages/advanced_topics/key_bindings.rst --- prompt-toolkit-3.0.5/docs/pages/advanced_topics/key_bindings.rst 2020-03-06 06:42:35.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/advanced_topics/key_bindings.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,339 +0,0 @@ -.. _key_bindings: - -More about key bindings -======================= - -This page contains a few additional notes about key bindings. - - -Key bindings can be defined as follows by creating a -:class:`~prompt_toolkit.key_binding.KeyBindings` instance: - - -.. code:: python - - from prompt_toolkit.key_binding import KeyBindings - - bindings = KeyBindings() - - @bindings.add('a') - def _(event): - " Do something if 'a' has been pressed. " - ... - - - @bindings.add('c-t') - def _(event): - " Do something if Control-T has been pressed. " - ... - -.. note:: - - :kbd:`c-q` (control-q) and :kbd:`c-s` (control-s) are often captured by the - terminal, because they were used traditionally for software flow control. - When this is enabled, the application will automatically freeze when - :kbd:`c-s` is pressed, until :kbd:`c-q` is pressed. It won't be possible to - bind these keys. - - In order to disable this, execute type the following in your shell, or even - add it to your `.bashrc`. - - .. code:: - - stty -ixon - -Key bindings can even consist of a sequence of multiple keys. The binding is -only triggered when all the keys in this sequence are pressed. - -.. code:: python - - @bindings.add('a', 'b') - def _(event): - " Do something if 'a' is pressed and then 'b' is pressed. " - ... - -If the user presses only `a`, then nothing will happen until either a second -key (like `b`) has been pressed or until the timeout expires (see later). - - -List of special keys --------------------- - -Besides literal characters, any of the following keys can be used in a key -binding: - -+-------------------+-----------------------------------------+ -| Name + Possible keys | -+===================+=========================================+ -| Escape | :kbd:`escape` | -| Shift + escape | :kbd:`s-escape` | -+-------------------+-----------------------------------------+ -| Arrows | :kbd:`left`, | -| | :kbd:`right`, | -| | :kbd:`up`, | -| | :kbd:`down` | -+-------------------+-----------------------------------------+ -| Navigation | :kbd:`home`, | -| | :kbd:`end`, | -| | :kbd:`delete`, | -| | :kbd:`pageup`, | -| | :kbd:`pagedown`, | -| | :kbd:`insert` | -+-------------------+-----------------------------------------+ -| Control+letter | :kbd:`c-a`, :kbd:`c-b`, :kbd:`c-c`, | -| | :kbd:`c-d`, :kbd:`c-e`, :kbd:`c-f`, | -| | :kbd:`c-g`, :kbd:`c-h`, :kbd:`c-i`, | -| | :kbd:`c-j`, :kbd:`c-k`, :kbd:`c-l`, | -| | | -| | :kbd:`c-m`, :kbd:`c-n`, :kbd:`c-o`, | -| | :kbd:`c-p`, :kbd:`c-q`, :kbd:`c-r`, | -| | :kbd:`c-s`, :kbd:`c-t`, :kbd:`c-u`, | -| | :kbd:`c-v`, :kbd:`c-w`, :kbd:`c-x`, | -| | | -| | :kbd:`c-y`, :kbd:`c-z` | -+-------------------+-----------------------------------------+ -| Control + number | :kbd:`c-1`, :kbd:`c-2`, :kbd:`c-3`, | -| | :kbd:`c-4`, :kbd:`c-5`, :kbd:`c-6`, | -| | :kbd:`c-7`, :kbd:`c-8`, :kbd:`c-9`, | -| | :kbd:`c-0` | -+-------------------+-----------------------------------------+ -| Control + arrow | :kbd:`c-left`, | -| | :kbd:`c-right`, | -| | :kbd:`c-up`, | -| | :kbd:`c-down` | -+-------------------+-----------------------------------------+ -| Other control | :kbd:`c-@`, | -| keys | :kbd:`c-\\`, | -| | :kbd:`c-]`, | -| | :kbd:`c-^`, | -| | :kbd:`c-_`, | -| | :kbd:`c-delete` | -+-------------------+-----------------------------------------+ -| Shift + arrow | :kbd:`s-left`, | -| | :kbd:`s-right`, | -| | :kbd:`s-up`, | -| | :kbd:`s-down` | -+-------------------+-----------------------------------------+ -| Control + Shift + | :kbd:`c-s-left`, | -| arrow | :kbd:`c-s-right`, | -| | :kbd:`c-s-up`, | -| | :kbd:`c-s-down` | -+-------------------+-----------------------------------------+ -| Other shift | :kbd:`s-delete`, | -| keys | :kbd:`s-tab` | -+-------------------+-----------------------------------------+ -| F-keys | :kbd:`f1`, :kbd:`f2`, :kbd:`f3`, | -| | :kbd:`f4`, :kbd:`f5`, :kbd:`f6`, | -| | :kbd:`f7`, :kbd:`f8`, :kbd:`f9`, | -| | :kbd:`f10`, :kbd:`f11`, :kbd:`f12`, | -| | | -| | :kbd:`f13`, :kbd:`f14`, :kbd:`f15`, | -| | :kbd:`f16`, :kbd:`f17`, :kbd:`f18`, | -| | :kbd:`f19`, :kbd:`f20`, :kbd:`f21`, | -| | :kbd:`f22`, :kbd:`f23`, :kbd:`f24` | -+-------------------+-----------------------------------------+ - -There are a couple of useful aliases as well: - -+-------------------+-------------------+ -| :kbd:`c-h` | :kbd:`backspace` | -+-------------------+-------------------+ -| :kbd:`c-@` | :kbd:`c-space` | -+-------------------+-------------------+ -| :kbd:`c-m` | :kbd:`enter` | -+-------------------+-------------------+ -| :kbd:`c-i` | :kbd:`tab` | -+-------------------+-------------------+ - -.. note:: - - Note that the supported keys are limited to what typical VT100 terminals - offer. Binding :kbd:`c-7` (control + number 7) for instance is not - supported. - - -Binding alt+something, option+something or meta+something ---------------------------------------------------------- - -Vt100 terminals translate the alt key into a leading :kbd:`escape` key. -For instance, in order to handle :kbd:`alt-f`, we have to handle -:kbd:`escape` + :kbd:`f`. Notice that we receive this as two individual keys. -This means that it's exactly the same as first typing :kbd:`escape` and then -typing :kbd:`f`. Something this alt-key is also known as option or meta. - -In code that looks as follows: - -.. code:: python - - @bindings.add('escape', 'f') - def _(event): - " Do something if alt-f or meta-f have been pressed. " - - -Wildcards ---------- - -Sometimes you want to catch any key that follows after a certain key stroke. -This is possible by binding the '' key: - -.. code:: python - - @bindings.add('a', '') - def _(event): - ... - -This will handle `aa`, `ab`, `ac`, etcetera. The key binding can check the -`event` object for which keys exactly have been pressed. - - -Attaching a filter (condition) ------------------------------- - -In order to enable a key binding according to a certain condition, we have to -pass it a :class:`~prompt_toolkit.filters.Filter`, usually a -:class:`~prompt_toolkit.filters.Condition` instance. (:ref:`Read more about -filters `.) - -.. code:: python - - from prompt_toolkit.filters import Condition - - @Condition - def is_active(): - " Only activate key binding on the second half of each minute. " - return datetime.datetime.now().second > 30 - - @bindings.add('c-t', filter=is_active) - def _(event): - # ... - pass - -The key binding will be ignored when this condition is not satisfied. - - -ConditionalKeyBindings: Disabling a set of key bindings -------------------------------------------------------- - -Sometimes you want to enable or disable a whole set of key bindings according -to a certain condition. This is possible by wrapping it in a -:class:`~prompt_toolkit.key_binding.ConditionalKeyBindings` object. - -.. code:: python - - from prompt_toolkit.key_binding import ConditionalKeyBindings - - @Condition - def is_active(): - " Only activate key binding on the second half of each minute. " - return datetime.datetime.now().second > 30 - - bindings = ConditionalKeyBindings( - key_bindings=my_bindings, - filter=is_active) - -If the condition is not satisfied, all the key bindings in `my_bindings` above -will be ignored. - - -Merging key bindings --------------------- - -Sometimes you have different parts of your application generate a collection of -key bindings. It is possible to merge them together through the -:func:`~prompt_toolkit.key_binding.merge_key_bindings` function. This is -preferred above passing a :class:`~prompt_toolkit.key_binding.KeyBindings` -object around and having everyone populate it. - -.. code:: python - - from prompt_toolkit.key_binding import merge_key_bindings - - bindings = merge_key_bindings([ - bindings1, - bindings2, - ]) - - -Eager ------ - -Usually not required, but if ever you have to override an existing key binding, -the `eager` flag can be useful. - -Suppose that there is already an active binding for `ab` and you'd like to add -a second binding that only handles `a`. When the user presses only `a`, -prompt_toolkit has to wait for the next key press in order to know which -handler to call. - -By passing the `eager` flag to this second binding, we are actually saying that -prompt_toolkit shouldn't wait for longer matches when all the keys in this key -binding are matched. So, if `a` has been pressed, this second binding will be -called, even if there's an active `ab` binding. - -.. code:: python - - @bindings.add('a', 'b') - def binding_1(event): - ... - - @bindings.add('a', eager=True) - def binding_2(event): - ... - -This is mainly useful in order to conditionally override another binding. - - -Timeouts --------- - -There are two timeout settings that effect the handling of keys. - -- ``Application.ttimeoutlen``: Like Vim's `ttimeoutlen` option. - When to flush the input (For flushing escape keys.) This is important on - terminals that use vt100 input. We can't distinguish the escape key from for - instance the left-arrow key, if we don't know what follows after "\x1b". This - little timer will consider "\x1b" to be escape if nothing did follow in this - time span. This seems to work like the `ttimeoutlen` option in Vim. - -- ``KeyProcessor.timeoutlen``: like Vim's `timeoutlen` option. - This can be `None` or a float. For instance, suppose that we have a key - binding AB and a second key binding A. If the uses presses A and then waits, - we don't handle this binding yet (unless it was marked 'eager'), because we - don't know what will follow. This timeout is the maximum amount of time that - we wait until we call the handlers anyway. Pass `None` to disable this - timeout. - - -Recording macros ----------------- - -Both Emacs and Vi mode allow macro recording. By default, all key presses are -recorded during a macro, but it is possible to exclude certain keys by setting -the `record_in_macro` parameter to `False`: - -.. code:: python - - @bindings.add('c-t', record_in_macro=False) - def _(event): - # ... - pass - - -Creating new Vi text objects and operators ------------------------------------------- - -We tried very hard to ship prompt_toolkit with as many as possible Vi text -objects and operators, so that text editing feels as natural as possible to Vi -users. - -If you wish to create a new text object or key binding, that is actually -possible. Check the `custom-vi-operator-and-text-object.py` example for more -information. - - -Processing `.inputrc` ---------------------- - -GNU readline can be configured using an `.inputrc` configuration file. This can -could key bindings as well as certain settings. Right now, prompt_toolkit -doesn't support `.inputrc` yet, but it should be possible in the future. diff -Nru prompt-toolkit-3.0.5/docs/pages/advanced_topics/rendering_flow.rst prompt-toolkit-3.0.6/docs/pages/advanced_topics/rendering_flow.rst --- prompt-toolkit-3.0.5/docs/pages/advanced_topics/rendering_flow.rst 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/advanced_topics/rendering_flow.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -.. _rendering_flow: - -The rendering flow -================== - -Understanding the rendering flow is important for understanding how -:class:`~prompt_toolkit.layout.Container` and -:class:`~prompt_toolkit.layout.UIControl` objects interact. We will demonstrate -it by explaining the flow around a -:class:`~prompt_toolkit.layout.BufferControl`. - -.. note:: - - A :class:`~prompt_toolkit.layout.BufferControl` is a - :class:`~prompt_toolkit.layout.UIControl` for displaying the content of a - :class:`~prompt_toolkit.buffer.Buffer`. A buffer is the object that holds - any editable region of text. Like all controls, it has to be wrapped into a - :class:`~prompt_toolkit.layout.Window`. - -Let's take the following code: - -.. code:: python - - from prompt_toolkit.enums import DEFAULT_BUFFER - from prompt_toolkit.layout.containers import Window - from prompt_toolkit.layout.controls import BufferControl - from prompt_toolkit.buffer import Buffer - - b = Buffer(name=DEFAULT_BUFFER) - Window(content=BufferControl(buffer=b)) - -What happens when a :class:`~prompt_toolkit.renderer.Renderer` objects wants a -:class:`~prompt_toolkit.layout.Container` to be rendered on a certain -:class:`~prompt_toolkit.layout.screen.Screen`? - -The visualisation happens in several steps: - -1. The :class:`~prompt_toolkit.renderer.Renderer` calls the - :meth:`~prompt_toolkit.layout.Container.write_to_screen` method - of a :class:`~prompt_toolkit.layout.Container`. - This is a request to paint the layout in a rectangle of a certain size. - - The :class:`~prompt_toolkit.layout.Window` object then requests - the :class:`~prompt_toolkit.layout.UIControl` to create a - :class:`~prompt_toolkit.layout.UIContent` instance (by calling - :meth:`~prompt_toolkit.layout.UIControl.create_content`). - The user control receives the dimensions of the window, but can still - decide to create more or less content. - - Inside the :meth:`~prompt_toolkit.layout.UIControl.create_content` - method of :class:`~prompt_toolkit.layout.UIControl`, there are several - steps: - - 2. First, the buffer's text is passed to the - :meth:`~prompt_toolkit.lexers.Lexer.lex_document` method of a - :class:`~prompt_toolkit.lexers.Lexer`. This returns a function which - for a given line number, returns a "formatted text list" for that line - (that's a list of ``(style_string, text)`` tuples). - - 3. This list is passed through a list of - :class:`~prompt_toolkit.layout.processors.Processor` objects. - Each processor can do a transformation for each line. - (For instance, they can insert or replace some text, highlight the - selection or search string, etc...) - - 4. The :class:`~prompt_toolkit.layout.UIControl` returns a - :class:`~prompt_toolkit.layout.UIContent` instance which - generates such a token lists for each lines. - -The :class:`~prompt_toolkit.layout.Window` receives the -:class:`~prompt_toolkit.layout.UIContent` and then: - -5. It calculates the horizontal and vertical scrolling, if applicable - (if the content would take more space than what is available). - -6. The content is copied to the correct absolute position - :class:`~prompt_toolkit.layout.screen.Screen`, as requested by the - :class:`~prompt_toolkit.renderer.Renderer`. While doing this, the - :class:`~prompt_toolkit.layout.Window` can possible wrap the - lines, if line wrapping was configured. - -Note that this process is lazy: if a certain line is not displayed in the -:class:`~prompt_toolkit.layout.Window`, then it is not requested -from the :class:`~prompt_toolkit.layout.UIContent`. And from there, the line is -not passed through the processors or even asked from the -:class:`~prompt_toolkit.lexers.Lexer`. diff -Nru prompt-toolkit-3.0.5/docs/pages/advanced_topics/rendering_pipeline.rst prompt-toolkit-3.0.6/docs/pages/advanced_topics/rendering_pipeline.rst --- prompt-toolkit-3.0.5/docs/pages/advanced_topics/rendering_pipeline.rst 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/advanced_topics/rendering_pipeline.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,157 +0,0 @@ -The rendering pipeline -====================== - -This document is an attempt to describe how prompt_toolkit applications are -rendered. It's a complex but logical process that happens more or less after -every key stroke. We'll go through all the steps from the point where the user -hits a key, until the character appears on the screen. - - -Waiting for user input ----------------------- - -Most of the time when a prompt_toolkit application is running, it is idle. It's -sitting in the event loop, waiting for some I/O to happen. The most important -kind of I/O we're waiting for is user input. So, within the event loop, we have -one file descriptor that represents the input device from where we receive key -presses. The details are a little different between operating systems, but it -comes down to a selector (like select or epoll) which waits for one or more -file descriptor. The event loop is then responsible for calling the appropriate -feedback when one of the file descriptors becomes ready. - -It is like that when the user presses a key: the input device becomes ready for -reading, and the appropriate callback is called. This is the `read_from_input` -function somewhere in `application.py`. It will read the input from the -:class:`~prompt_toolkit.input.Input` object, by calling -:meth:`~prompt_toolkit.input.Input.read_keys`. - - -Reading the user input ----------------------- - -The actual reading is also operating system dependent. For instance, on a Linux -machine with a vt100 terminal, we read the input from the pseudo terminal -device, by calling `os.read`. This however returns a sequence of bytes. There -are two difficulties: - -- The input could be UTF-8 encoded, and there is always the possibility that we - receive only a portion of a multi-byte character. -- vt100 key presses consist of multiple characters. For instance the "left - arrow" would generate something like ``\x1b[D``. It could be that when we - read this input stream, that at some point we only get the first part of such - a key press, and we have to wait for the rest to arrive. - -Both problems are implemented using state machines. - -- The UTF-8 problem is solved using `codecs.getincrementaldecoder`, which is an - object in which we can feed the incoming bytes, and it will only return the - complete UTF-8 characters that we have so far. The rest is buffered for the - next read operation. -- Vt100 parsing is solved by the - :class:`~prompt_toolkit.input.vt100_parser.Vt100Parser` state machine. The - state machine itself is implemented using a generator. We feed the incoming - characters to the generator, and it will call the appropriate callback for - key presses once they arrive. One thing here to keep in mind is that the - characters for some key presses are a prefix of other key presses, like for - instance, escape (``\x1b``) is a prefix of the left arrow key (``\x1b[D``). - So for those, we don't know what key is pressed until more data arrives or - when the input is flushed because of a timeout. - -For Windows systems, it's a little different. Here we use Win32 syscalls for -reading the console input. - - -Processing the key presses --------------------------- - -The ``Key`` objects that we receive are then passed to the -:class:`~prompt_toolkit.key_binding.key_processor.KeyProcessor` for matching -against the currently registered and active key bindings. - -This is another state machine, because key bindings are linked to a sequence of -key presses. We cannot call the handler until all of these key presses arrive -and until we're sure that this combination is not a prefix of another -combination. For instance, sometimes people bind ``jj`` (a double ``j`` key -press) to ``esc`` in Vi mode. This is convenient, but we want to make sure that -pressing ``j`` once only, followed by a different key will still insert the -``j`` character as usual. - -Now, there are hundreds of key bindings in prompt_toolkit (in ptpython, right -now we have 585 bindings). This is mainly caused by the way that Vi key -bindings are generated. In order to make this efficient, we keep a cache of -handlers which match certain sequences of keys. - -Of course, key bindings also have filters attached for enabling/disabling them. -So, if at some point, we get a list of handlers from that cache, we still have -to discard the inactive bindings. Luckily, many bindings share exactly the same -filter, and we have to check every filter only once. - -:ref:`Read more about key bindings ...` - - -The key handlers ----------------- - -Once a key sequence is matched, the handler is called. This can do things like -text manipulation, changing the focus or anything else. - -After the handler is called, the user interface is invalidated and rendered -again. - - -Rendering the user interface ----------------------------- - -The rendering is pretty complex for several reasons: - -- We have to compute the dimensions of all user interface elements. Sometimes - they are given, but sometimes this requires calculating the size of - :class:`~prompt_toolkit.layout.UIControl` objects. -- It needs to be very efficient, because it's something that happens on every - single key stroke. -- We should output as little as possible on stdout in order to reduce latency - on slow network connections and older terminals. - - -Calculating the total UI height -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Unless the application is a full screen application, we have to know how much -vertical space is going to be consumed. The total available width is given, but -the vertical space is more dynamic. We do this by asking the root -:class:`~prompt_toolkit.layout.Container` object to calculate its preferred -height. If this is a :class:`~prompt_toolkit.layout.VSplit` or -:class:`~prompt_toolkit.layout.HSplit` then this involves recursively querying -the child objects for their preferred widths and heights and either summing it -up, or taking maximum values depending on the actual layout. -In the end, we get the preferred height, for which we make sure it's at least -the distance from the cursor position to the bottom of the screen. - - -Painting to the screen -^^^^^^^^^^^^^^^^^^^^^^ - -Then we create a :class:`~prompt_toolkit.layout.screen.Screen` object. This is -like a canvas on which user controls can paint their content. The -:meth:`~prompt_toolkit.layout.Container.write_to_screen` method of the root -`Container` is called with the screen dimensions. This will call recursively -:meth:`~prompt_toolkit.layout.Container.write_to_screen` methods of nested -child containers, each time passing smaller dimensions while we traverse what -is a tree of `Container` objects. - -The most inner containers are :class:`~prompt_toolkit.layout.Window` objects, -they will do the actual painting of the -:class:`~prompt_toolkit.layout.UIControl` to the screen. This involves line -wrapping the `UIControl`'s text and maybe scrolling the content horizontally or -vertically. - - -Rendering to stdout -^^^^^^^^^^^^^^^^^^^ - -Finally, when we have painted the screen, this needs to be rendered to stdout. -This is done by taking the difference of the previously rendered screen and the -new one. The algorithm that we have is heavily optimized to compute this -difference as quickly as possible, and call the appropriate output functions of -the :class:`~prompt_toolkit.output.Output` back-end. At the end, it will -position the cursor in the right place. diff -Nru prompt-toolkit-3.0.5/docs/pages/advanced_topics/styling.rst prompt-toolkit-3.0.6/docs/pages/advanced_topics/styling.rst --- prompt-toolkit-3.0.5/docs/pages/advanced_topics/styling.rst 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/advanced_topics/styling.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,320 +0,0 @@ -.. _styling: - -More about styling -================== - -This page will attempt to explain in more detail how to use styling in -prompt_toolkit. - -To some extent, it is very similar to how `Pygments `_ -styling works. - - -Style strings -------------- - -Many user interface controls, like :class:`~prompt_toolkit.layout.Window` -accept a ``style`` argument which can be used to pass the formatting as a -string. For instance, we can select a foreground color: - -- ``"fg:ansired"`` (ANSI color palette) -- ``"fg:ansiblue"`` (ANSI color palette) -- ``"fg:#ffaa33"`` (hexadecimal notation) -- ``"fg:darkred"`` (named color) - -Or a background color: - -- ``"bg:ansired"`` (ANSI color palette) -- ``"bg:#ffaa33"`` (hexadecimal notation) - -Or we can add one of the following flags: - -- ``"bold"`` -- ``"italic"`` -- ``"underline"`` -- ``"blink"`` -- ``"reverse"`` (reverse foreground and background on the terminal.) -- ``"hidden"`` - -Or their negative variants: - -- ``"nobold"`` -- ``"noitalic"`` -- ``"nounderline"`` -- ``"noblink"`` -- ``"noreverse"`` -- ``"nohidden"`` - -All of these formatting options can be combined as well: - -- ``"fg:ansiyellow bg:black bold underline"`` - -The style string can be given to any user control directly, or to a -:class:`~prompt_toolkit.layout.Container` object from where it will propagate -to all its children. A style defined by a parent user control can be overridden -by any of its children. The parent can for instance say ``style="bold -underline"`` where a child overrides this style partly by specifying -``style="nobold bg:ansired"``. - -.. note:: - - These styles are actually compatible with - `Pygments `_ styles, with additional support for - `reverse` and `blink`. Further, we ignore flags like `roman`, `sans`, - `mono` and `border`. - -The following ANSI colors are available (both for foreground and background): - -.. code:: - - # Low intensity, dark. (One or two components 0x80, the other 0x00.) - ansiblack, ansired, ansigreen, ansiyellow, ansiblue - ansimagenta, 'ansicyan, ansigray - - # High intensity, bright. - ansibrightblack, ansibrightred, ansibrightgreen, ansibrightyellow - ansibrightblue, ansibrightmagenta, ansibrightcyan, ansiwhite - -In order to know which styles are actually used in an application, it is -possible to call :meth:`~Application.get_used_style_strings`, when the -application is done. - - -Class names ------------ - -Like we do for web design, it is not a good habit to specify all styling -inline. Instead, we can attach class names to UI controls and have a style -sheet that refers to these class names. The -:class:`~prompt_toolkit.styles.Style` can be passed as an argument to the -:class:`~prompt_toolkit.application.Application`. - -.. code:: python - - from prompt_toolkit.layout import VSplit, Window - from prompt_toolkit.styles import Style - - layout = VSplit([ - Window(BufferControl(...), style='class:left'), - HSplit([ - Window(BufferControl(...), style='class:top'), - Window(BufferControl(...), style='class:bottom'), - ], style='class:right') - ]) - - style = Style([ - ('left', 'bg:ansired'), - ('top', 'fg:#00aaaa'), - ('bottom', 'underline bold'), - ]) - -It is possible to add multiple class names to an element. That way we'll -combine the styling for these class names. Multiple classes can be passed by -using a comma separated list, or by using the ``class:`` prefix twice. - -.. code:: python - - Window(BufferControl(...), style='class:left,bottom'), - Window(BufferControl(...), style='class:left class:bottom'), - -It is possible to combine class names and inline styling. The order in which -the class names and inline styling is specified determines the order of -priority. In the following example for instance, we'll take first the style of -the "header" class, and then override that with a red background color. - -.. code:: python - - Window(BufferControl(...), style='class:header bg:red'), - - -Dot notation in class names ---------------------------- - -The dot operator has a special meaning in a class name. If we write: -``style="class:a.b.c"``, then this will actually expand to the following: -``style="class:a class:a.b class:a.b.c"``. - -This is mainly added for `Pygments `_ lexers, which -specify "Tokens" like this, but it's useful in other situations as well. - - -Multiple classes in a style sheet ---------------------------------- - -A style sheet can be more complex as well. We can for instance specify two -class names. The following will underline the left part within the header, or -whatever has both the class "left" and the class "header" (the order doesn't -matter). - -.. code:: python - - style = Style([ - ('header left', 'underline'), - ]) - - -If you have a dotted class, then it's required to specify the whole path in the -style sheet (just typing ``c`` or ``b.c`` doesn't work if the class is -``a.b.c``): - -.. code:: python - - style = Style([ - ('a.b.c', 'underline'), - ]) - -It is possible to combine this: - -.. code:: python - - style = Style([ - ('header body left.text', 'underline'), - ]) - - -Evaluation order of rules in a style sheet ------------------------------------------- - -The style is determined as follows: - -- First, we concatenate all the style strings from the root control through all - the parents to the child in one big string. (Things at the right take - precedence anyway.) - - E.g: ``class:body bg:#aaaaaa #000000 class:header.focused class:left.text.highlighted underline`` - -- Then we go through this style from left to right, starting from the default - style. Inline styling is applied directly. - - If we come across a class name, then we generate all combinations of the - class names that we collected so far (this one and all class names to the - left), and for each combination which includes the new class name, we look - for matching rules in our style sheet. All these rules are then applied - (later rules have higher priority). - - If we find a dotted class name, this will be expanded in the individual names - (like ``class:left class:left.text class:left.text.highlighted``), and all - these are applied like any class names. - -- Then this final style is applied to this user interface element. - - -Using a dictionary as a style sheet ------------------------------------ - -The order of the rules in a style sheet is meaningful, so typically, we use a -list of tuples to specify the style. But is also possible to use a dictionary -as a style sheet. This makes sense for Python 3.6, where dictionaries remember -their ordering. An ``OrderedDict`` works as well. - -.. code:: python - - from prompt_toolkit.styles import Style - - style = Style.from_dict({ - 'header body left.text': 'underline', - }) - - -Loading a style from Pygments ------------------------------ - -`Pygments `_ has a slightly different notation for -specifying styles, because it maps styling to Pygments "Tokens". A Pygments -style can however be loaded and used as follows: - -.. code:: python - - from prompt_toolkit.styles.from_pygments import style_from_pygments_cls - from pygments.styles import get_style_by_name - - style = style_from_pygments_cls(get_style_by_name('monokai')) - - -Merging styles together ------------------------ - -Multiple :class:`~prompt_toolkit.styles.Style` objects can be merged together as -follows: - -.. code:: python - - from prompt_toolkit.styles import merge_styles - - style = merge_styles([ - style1, - style2, - style3 - ]) - - -Color depths ------------- - -There are four different levels of color depths available: - -+--------+-----------------+-----------------------------+---------------------------------+ -| 1 bit | Black and white | ``ColorDepth.DEPTH_1_BIT`` | ``ColorDepth.MONOCHROME`` | -+--------+-----------------+-----------------------------+---------------------------------+ -| 4 bit | ANSI colors | ``ColorDepth.DEPTH_4_BIT`` | ``ColorDepth.ANSI_COLORS_ONLY`` | -+--------+-----------------+-----------------------------+---------------------------------+ -| 8 bit | 256 colors | ``ColorDepth.DEPTH_8_BIT`` | ``ColorDepth.DEFAULT`` | -+--------+-----------------+-----------------------------+---------------------------------+ -| 24 bit | True colors | ``ColorDepth.DEPTH_24_BIT`` | ``ColorDepth.TRUE_COLOR`` | -+--------+-----------------+-----------------------------+---------------------------------+ - -By default, 256 colors are used, because this is what most terminals support -these days. If the ``TERM`` enviroment variable is set to ``linux`` or -``eterm-color``, then only ANSI colors are used, because of these terminals. 24 -bit true color output needs to be enabled explicitely. When 4 bit color output -is chosen, all colors will be mapped to the closest ANSI color. - -Setting the default color depth for any prompt_toolkit application can be done -by setting the ``PROMPT_TOOLKIT_COLOR_DEPTH`` environment variable. You could -for instance copy the following into your `.bashrc` file. - -.. code:: shell - - # export PROMPT_TOOLKIT_COLOR_DEPTH=DEPTH_1_BIT - export PROMPT_TOOLKIT_COLOR_DEPTH=DEPTH_4_BIT - # export PROMPT_TOOLKIT_COLOR_DEPTH=DEPTH_8_BIT - # export PROMPT_TOOLKIT_COLOR_DEPTH=DEPTH_24_BIT - -An application can also decide to set the color depth manually by passing a -:class:`~prompt_toolkit.output.ColorDepth` value to the -:class:`~prompt_toolkit.application.Application` object: - -.. code:: python - - from prompt_toolkit.output.color_depth import ColorDepth - - app = Application( - color_depth=ColorDepth.ANSI_COLORS_ONLY, - # ... - ) - - -Style transformations ---------------------- - -Prompt_toolkit supports a way to apply certain transformations to the styles -near the end of the rendering pipeline. This can be used for instance to change -certain colors to improve the rendering in some terminals. - -One useful example is the -:class:`~prompt_toolkit.styles.AdjustBrightnessStyleTransformation` class, -which takes `min_brightness` and `max_brightness` as arguments which by default -have 0.0 and 1.0 as values. In the following code snippet, we increase the -minimum brightness to improve rendering on terminals with a dark background. - -.. code:: python - - from prompt_toolkit.styles import AdjustBrightnessStyleTransformation - - app = Application( - style_transformation=AdjustBrightnessStyleTransformation( - min_brightness=0.5, # Increase the minimum brightness. - max_brightness=1.0, - ) - # ... - ) diff -Nru prompt-toolkit-3.0.5/docs/pages/asking_for_input.rst prompt-toolkit-3.0.6/docs/pages/asking_for_input.rst --- prompt-toolkit-3.0.5/docs/pages/asking_for_input.rst 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/asking_for_input.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,959 +0,0 @@ -.. _asking_for_input: - -Asking for input (prompts) -========================== - -This page is about building prompts. Pieces of code that we can embed in a -program for asking the user for input. Even if you want to use `prompt_toolkit` -for building full screen terminal applications, it is probably still a good -idea to read this first, before heading to the :ref:`building full screen -applications ` page. - -In this page, we will cover autocompletion, syntax highlighting, key bindings, -and so on. - - -Hello world ------------ - -The following snippet is the most simple example, it uses the -:func:`~prompt_toolkit.shortcuts.prompt` function to asks the user for input -and returns the text. Just like ``(raw_)input``. - -.. code:: python - - from prompt_toolkit import prompt - - text = prompt('Give me some input: ') - print('You said: %s' % text) - -.. image:: ../images/hello-world-prompt.png - -What we get here is a simple prompt that supports the Emacs key bindings like -readline, but further nothing special. However, -:func:`~prompt_toolkit.shortcuts.prompt` has a lot of configuration options. -In the following sections, we will discover all these parameters. - - -The `PromptSession` object --------------------------- - -Instead of calling the :func:`~prompt_toolkit.shortcuts.prompt` function, it's -also possible to create a :class:`~prompt_toolkit.shortcuts.PromptSession` -instance followed by calling its -:meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` method for every input -call. This creates a kind of an input session. - -.. code:: python - - from prompt_toolkit import PromptSession - - # Create prompt object. - session = PromptSession() - - # Do multiple input calls. - text1 = session.prompt() - text2 = session.prompt() - -This has mainly two advantages: - -- The input history will be kept between consecutive - :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` calls. - -- The :func:`~prompt_toolkit.shortcuts.PromptSession` instance and its - :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` method take about the - same arguments, like all the options described below (highlighting, - completion, etc...). So if you want to ask for multiple inputs, but each - input call needs about the same arguments, they can be passed to the - :func:`~prompt_toolkit.shortcuts.PromptSession` instance as well, and they - can be overridden by passing values to the - :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` method. - - -Syntax highlighting -------------------- - -Adding syntax highlighting is as simple as adding a lexer. All of the `Pygments -`_ lexers can be used after wrapping them in a -:class:`~prompt_toolkit.lexers.PygmentsLexer`. It is also possible to create a -custom lexer by implementing the :class:`~prompt_toolkit.lexers.Lexer` abstract -base class. - -.. code:: python - - from pygments.lexers.html import HtmlLexer - from prompt_toolkit.shortcuts import prompt - from prompt_toolkit.lexers import PygmentsLexer - - text = prompt('Enter HTML: ', lexer=PygmentsLexer(HtmlLexer)) - print('You said: %s' % text) - -.. image:: ../images/html-input.png - -The default Pygments colorscheme is included as part of the default style in -prompt_toolkit. If you want to use another Pygments style along with the lexer, -you can do the following: - -.. code:: python - - from pygments.lexers.html import HtmlLexer - from pygments.styles import get_style_by_name - from prompt_toolkit.shortcuts import prompt - from prompt_toolkit.lexers import PygmentsLexer - from prompt_toolkit.styles.pygments import style_from_pygments_cls - - style = style_from_pygments_cls(get_style_by_name('monokai')) - text = prompt('Enter HTML: ', lexer=PygmentsLexer(HtmlLexer), style=style, - include_default_pygments_style=False) - print('You said: %s' % text) - -We pass ``include_default_pygments_style=False``, because otherwise, both -styles will be merged, possibly giving slightly different colors in the outcome -for cases where where our custom Pygments style doesn't specify a color. - -.. _colors: - -Colors ------- - -The colors for syntax highlighting are defined by a -:class:`~prompt_toolkit.styles.Style` instance. By default, a neutral -built-in style is used, but any style instance can be passed to the -:func:`~prompt_toolkit.shortcuts.prompt` function. A simple way to create a -style, is by using the :meth:`~prompt_toolkit.styles.Style.from_dict` -function: - -.. code:: python - - from pygments.lexers.html import HtmlLexer - from prompt_toolkit.shortcuts import prompt - from prompt_toolkit.styles import Style - from prompt_toolkit.lexers import PygmentsLexer - - our_style = Style.from_dict({ - 'pygments.comment': '#888888 bold', - 'pygments.keyword': '#ff88ff bold', - }) - - text = prompt('Enter HTML: ', lexer=PygmentsLexer(HtmlLexer), - style=our_style) - - -The style dictionary is very similar to the Pygments ``styles`` dictionary, -with a few differences: - -- The `roman`, `sans`, `mono` and `border` options are ignored. -- The style has a few additions: ``blink``, ``noblink``, ``reverse`` and ``noreverse``. -- Colors can be in the ``#ff0000`` format, but they can be one of the built-in - ANSI color names as well. In that case, they map directly to the 16 color - palette of the terminal. - -:ref:`Read more about styling `. - - -Using a Pygments style -^^^^^^^^^^^^^^^^^^^^^^ - -All Pygments style classes can be used as well, when they are wrapped through -:func:`~prompt_toolkit.styles.style_from_pygments_cls`. - -Suppose we'd like to use a Pygments style, for instance -``pygments.styles.tango.TangoStyle``, that is possible like this: - -Creating a custom style could be done like this: - -.. code:: python - - from prompt_toolkit.shortcuts import prompt - from prompt_toolkit.styles import style_from_pygments_cls, merge_styles - from prompt_toolkit.lexers import PygmentsLexer - - from pygments.styles.tango import TangoStyle - from pygments.lexers.html import HtmlLexer - - our_style = merge_styles([ - style_from_pygments_cls(TangoStyle), - Style.from_dict({ - 'pygments.comment': '#888888 bold', - 'pygments.keyword': '#ff88ff bold', - }) - ]) - - text = prompt('Enter HTML: ', lexer=PygmentsLexer(HtmlLexer), - style=our_style) - - -Coloring the prompt itself -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It is possible to add some colors to the prompt itself. For this, we need to -build some :ref:`formatted text `. One way of doing this is by -creating a list of style/text tuples. In the following example, we use class -names to refer to the style. - -.. code:: python - - from prompt_toolkit.shortcuts import prompt - from prompt_toolkit.styles import Style - - style = Style.from_dict({ - # User input (default text). - '': '#ff0066', - - # Prompt. - 'username': '#884444', - 'at': '#00aa00', - 'colon': '#0000aa', - 'pound': '#00aa00', - 'host': '#00ffff bg:#444400', - 'path': 'ansicyan underline', - }) - - message = [ - ('class:username', 'john'), - ('class:at', '@'), - ('class:host', 'localhost'), - ('class:colon', ':'), - ('class:path', '/user/john'), - ('class:pound', '# '), - ] - - text = prompt(message, style=style) - -.. image:: ../images/colored-prompt.png - -The `message` can be any kind of formatted text, as discussed :ref:`here -`. It can also be a callable that returns some formatted text. - -By default, colors are taking from the 256 color palette. If you want to have -24bit true color, this is possible by adding the ``true_color=True`` option to -the :func:`~prompt_toolkit.shortcuts.prompt.prompt` function. - -.. code:: python - - text = prompt(message, style=style, true_color=True) - - -Autocompletion --------------- - -Autocompletion can be added by passing a ``completer`` parameter. This should -be an instance of the :class:`~prompt_toolkit.completion.Completer` abstract -base class. :class:`~prompt_toolkit.completion.WordCompleter` is an example of -a completer that implements that interface. - -.. code:: python - - from prompt_toolkit import prompt - from prompt_toolkit.completion import WordCompleter - - html_completer = WordCompleter(['', '', '', '']) - text = prompt('Enter HTML: ', completer=html_completer) - print('You said: %s' % text) - -:class:`~prompt_toolkit.completion.WordCompleter` is a simple completer that -completes the last word before the cursor with any of the given words. - -.. image:: ../images/html-completion.png - -.. note:: - - Note that in prompt_toolkit 2.0, the auto completion became synchronous. This - means that if it takes a long time to compute the completions, that this - will block the event loop and the input processing. - - For heavy completion algorithms, it is recommended to wrap the completer in - a :class:`~prompt_toolkit.completion.ThreadedCompleter` in order to run it - in a background thread. - - -Nested completion -^^^^^^^^^^^^^^^^^ - -Sometimes you have a command line interface where the completion depends on the -previous words from the input. Examples are the CLIs from routers and switches. -A simple :class:`~prompt_toolkit.completion.WordCompleter` is not enough in -that case. We want to to be able to define completions at multiple hierarchical -levels. :class:`~prompt_toolkit.completion.NestedCompleter` solves this issue: - -.. code:: python - - from prompt_toolkit import prompt - from prompt_toolkit.completion import NestedCompleter - - completer = NestedCompleter.from_nested_dict({ - 'show': { - 'version': None, - 'clock': None, - 'ip': { - 'interface': {'brief'} - } - }, - 'exit': None, - }) - - text = prompt('# ', completer=completer) - print('You said: %s' % text) - -Whenever there is a ``None`` value in the dictionary, it means that there is no -further nested completion at that point. When all values of a dictionary would -be ``None``, it can also be replaced with a set. - - -A custom completer -^^^^^^^^^^^^^^^^^^ - -For more complex examples, it makes sense to create a custom completer. For -instance: - -.. code:: python - - from prompt_toolkit import prompt - from prompt_toolkit.completion import Completer, Completion - - class MyCustomCompleter(Completer): - def get_completions(self, document, complete_event): - yield Completion('completion', start_position=0) - - text = prompt('> ', completer=MyCustomCompleter()) - -A :class:`~prompt_toolkit.completion.Completer` class has to implement a -generator named :meth:`~prompt_toolkit.completion.Completer.get_completions` -that takes a :class:`~prompt_toolkit.document.Document` and yields the current -:class:`~prompt_toolkit.completion.Completion` instances. Each completion -contains a portion of text, and a position. - -The position is used for fixing text before the cursor. Pressing the tab key -could for instance turn parts of the input from lowercase to uppercase. This -makes sense for a case insensitive completer. Or in case of a fuzzy completion, -it could fix typos. When ``start_position`` is something negative, this amount -of characters will be deleted and replaced. - - -Styling individual completions -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Each completion can provide a custom style, which is used when it is rendered -in the completion menu or toolbar. This is possible by passing a style to each -:class:`~prompt_toolkit.completion.Completion` instance. - -.. code:: python - - from prompt_toolkit.completion import Completer, Completion - - class MyCustomCompleter(Completer): - def get_completions(self, document, complete_event): - # Display this completion, black on yellow. - yield Completion('completion1', start_position=0, - style='bg:ansiyellow fg:ansiblack') - - # Underline completion. - yield Completion('completion2', start_position=0, - style='underline') - - # Specify class name, which will be looked up in the style sheet. - yield Completion('completion3', start_position=0, - style='class:special-completion') - -The "colorful-prompts.py" example uses completion styling: - -.. image:: ../images/colorful-completions.png - -Finally, it is possible to pass :ref:`formatted text <formatted_text>` for the -``display`` attribute of a :class:`~prompt_toolkit.completion.Completion`. This -provides all the freedom you need to display the text in any possible way. It -can also be combined with the ``style`` attribute. For instance: - -.. code:: python - - - from prompt_toolkit.completion import Completer, Completion - from prompt_toolkit.formatted_text import HTML - - class MyCustomCompleter(Completer): - def get_completions(self, document, complete_event): - yield Completion( - 'completion1', start_position=0, - display=HTML('<b>completion</b><ansired>1</ansired>'), - style='bg:ansiyellow') - - -Fuzzy completion -^^^^^^^^^^^^^^^^ - -If one possible completions is "django_migrations", a fuzzy completer would -allow you to get this by typing "djm" only, a subset of characters for this -string. - -Prompt_toolkit ships with a :class:`~prompt_toolkit.completion.FuzzyCompleter` -and :class:`~prompt_toolkit.completion.FuzzyWordCompleter` class. These provide -the means for doing this kind of "fuzzy completion". The first one can take any -completer instance and wrap it so that it becomes a fuzzy completer. The second -one behaves like a :class:`~prompt_toolkit.completion.WordCompleter` wrapped -into a :class:`~prompt_toolkit.completion.FuzzyCompleter`. - - -Complete while typing -^^^^^^^^^^^^^^^^^^^^^ - -Autcompletions can be generated automatically while typing or when the user -presses the tab key. This can be configured with the ``complete_while_typing`` -option: - -.. code:: python - - text = prompt('Enter HTML: ', completer=my_completer, - complete_while_typing=True) - -Notice that this setting is incompatible with the ``enable_history_search`` -option. The reason for this is that the up and down key bindings would conflict -otherwise. So, make sure to disable history search for this. - - -Asynchronous completion -^^^^^^^^^^^^^^^^^^^^^^^ - -When generating the completions takes a lot of time, it's better to do this in -a background thread. This is possible by wrapping the completer in a -:class:`~prompt_toolkit.completion.ThreadedCompleter`, but also by passing the -`complete_in_thread=True` argument. - - -.. code:: python - - text = prompt('> ', completer=MyCustomCompleter(), complete_in_thread=True) - - -Input validation ----------------- - -A prompt can have a validator attached. This is some code that will check -whether the given input is acceptable and it will only return it if that's the -case. Otherwise it will show an error message and move the cursor to a given -position. - -A validator should implements the :class:`~prompt_toolkit.validation.Validator` -abstract base class. This requires only one method, named ``validate`` that -takes a :class:`~prompt_toolkit.document.Document` as input and raises -:class:`~prompt_toolkit.validation.ValidationError` when the validation fails. - -.. code:: python - - from prompt_toolkit.validation import Validator, ValidationError - from prompt_toolkit import prompt - - class NumberValidator(Validator): - def validate(self, document): - text = document.text - - if text and not text.isdigit(): - i = 0 - - # Get index of fist non numeric character. - # We want to move the cursor here. - for i, c in enumerate(text): - if not c.isdigit(): - break - - raise ValidationError(message='This input contains non-numeric characters', - cursor_position=i) - - number = int(prompt('Give a number: ', validator=NumberValidator())) - print('You said: %i' % number) - -.. image:: ../images/number-validator.png - -By default, the input is only validated when the user presses the enter key, -but prompt_toolkit can also validate in real-time while typing: - -.. code:: python - - prompt('Give a number: ', validator=NumberValidator(), - validate_while_typing=True) - -If the input validation contains some heavy CPU intensive code, but you don't -want to block the event loop, then it's recommended to wrap the validator class -in a :class:`~prompt_toolkit.validation.ThreadedValidator`. - -Validator from a callable -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Instead of implementing the :class:`~prompt_toolkit.validation.Validator` -abstract base class, it is also possible to start from a simple function and -use the :meth:`~prompt_toolkit.validation.Validator.from_callable` classmethod. -This is easier and sufficient for probably 90% of the validators. It looks as -follows: - -.. code:: python - - from prompt_toolkit.validation import Validator - from prompt_toolkit import prompt - - def is_number(text): - return text.isdigit() - - validator = Validator.from_callable( - is_number, - error_message='This input contains non-numeric characters', - move_cursor_to_end=True) - - number = int(prompt('Give a number: ', validator=validator)) - print('You said: %i' % number) - -We define a function that takes a string, and tells whether it's valid input or -not by returning a boolean. -:meth:`~prompt_toolkit.validation.Validator.from_callable` turns that into a -:class:`~prompt_toolkit.validation.Validator` instance. Notice that setting the -cursor position is not possible this way. - - -History -------- - -A :class:`~prompt_toolkit.history.History` object keeps track of all the -previously entered strings, so that the up-arrow can reveal previously entered -items. - -The recommended way is to use a -:class:`~prompt_toolkit.shortcuts.PromptSession`, which uses an -:class:`~prompt_toolkit.history.InMemoryHistory` for the entire session by -default. The following example has a history out of the box: - -.. code:: python - - from prompt_toolkit import PromptSession - - session = PromptSession() - - while True: - session.prompt() - -To persist a history to disk, use a :class:`~prompt_toolkit.history.FileHistory` -instead of the default -:class:`~prompt_toolkit.history.InMemoryHistory`. This history object can be -passed either to a :class:`~prompt_toolkit.shortcuts.PromptSession` or to the -:meth:`~prompt_toolkit.shortcuts.prompt` function. For instance: - -.. code:: python - - from prompt_toolkit import PromptSession - from prompt_toolkit.history import FileHistory - - session = PromptSession(history=FileHistory('~/.myhistory')) - - while True: - session.prompt() - - -Auto suggestion ---------------- - -Auto suggestion is a way to propose some input completions to the user like the -`fish shell <http://fishshell.com/>`_. - -Usually, the input is compared to the history and when there is another entry -starting with the given text, the completion will be shown as gray text behind -the current input. Pressing the right arrow :kbd:`→` or :kbd:`c-e` will insert -this suggestion, :kbd:`alt-f` will insert the first word of the suggestion. - -.. note:: - - When suggestions are based on the history, don't forget to share one - :class:`~prompt_toolkit.history.History` object between consecutive - :func:`~prompt_toolkit.shortcuts.prompt` calls. Using a - :class:`~prompt_toolkit.shortcuts.PromptSession` does this for you. - -Example: - -.. code:: python - - from prompt_toolkit import PromptSession - from prompt_toolkit.history import InMemoryHistory - from prompt_toolkit.auto_suggest import AutoSuggestFromHistory - - session = PromptSession() - - while True: - text = session.prompt('> ', auto_suggest=AutoSuggestFromHistory()) - print('You said: %s' % text) - -.. image:: ../images/auto-suggestion.png - -A suggestion does not have to come from the history. Any implementation of the -:class:`~prompt_toolkit.auto_suggest.AutoSuggest` abstract base class can be -passed as an argument. - - -Adding a bottom toolbar ------------------------ - -Adding a bottom toolbar is as easy as passing a ``bottom_toolbar`` argument to -:func:`~prompt_toolkit.shortcuts.prompt`. This argument be either plain text, -:ref:`formatted text <formatted_text>` or a callable that returns plain or -formatted text. - -When a function is given, it will be called every time the prompt is rendered, -so the bottom toolbar can be used to display dynamic information. - -The toolbar is always erased when the prompt returns. -Here we have an example of a callable that returns an -:class:`~prompt_toolkit.formatted_text.HTML` object. By default, the toolbar -has the **reversed style**, which is why we are setting the background instead -of the foreground. - -.. code:: python - - from prompt_toolkit import prompt - from prompt_toolkit.formatted_text import HTML - - def bottom_toolbar(): - return HTML('This is a <b><style bg="ansired">Toolbar</style></b>!') - - text = prompt('> ', bottom_toolbar=bottom_toolbar) - print('You said: %s' % text) - -.. image:: ../images/bottom-toolbar.png - -Similar, we could use a list of style/text tuples. - -.. code:: python - - from prompt_toolkit import prompt - from prompt_toolkit.styles import Style - - def bottom_toolbar(): - return [('class:bottom-toolbar', ' This is a toolbar. ')] - - style = Style.from_dict({ - 'bottom-toolbar': '#ffffff bg:#333333', - }) - - text = prompt('> ', bottom_toolbar=bottom_toolbar, style=style) - print('You said: %s' % text) - -The default class name is ``bottom-toolbar`` and that will also be used to fill -the background of the toolbar. - - -Adding a right prompt ---------------------- - -The :func:`~prompt_toolkit.shortcuts.prompt` function has out of the box -support for right prompts as well. People familiar to ZSH could recognise this -as the `RPROMPT` option. - -So, similar to adding a bottom toolbar, we can pass an ``rprompt`` argument. -This can be either plain text, :ref:`formatted text <formatted_text>` or a -callable which returns either. - -.. code:: python - - from prompt_toolkit import prompt - from prompt_toolkit.styles import Style - - example_style = Style.from_dict({ - 'rprompt': 'bg:#ff0066 #ffffff', - }) - - def get_rprompt(): - return '<rprompt>' - - answer = prompt('> ', rprompt=get_rprompt, style=example_style) - -.. image:: ../images/rprompt.png - -The ``get_rprompt`` function can return any kind of formatted text such as -:class:`~prompt_toolkit.formatted_text.HTML`. it is also possible to pass text -directly to the ``rprompt`` argument of the -:func:`~prompt_toolkit.shortcuts.prompt` function. It does not have to be a -callable. - - -Vi input mode -------------- - -Prompt-toolkit supports both Emacs and Vi key bindings, similar to Readline. -The :func:`~prompt_toolkit.shortcuts.prompt` function will use Emacs bindings by -default. This is done because on most operating systems, also the Bash shell -uses Emacs bindings by default, and that is more intuitive. If however, Vi -binding are required, just pass ``vi_mode=True``. - -.. code:: python - - from prompt_toolkit import prompt - - prompt('> ', vi_mode=True) - - -Adding custom key bindings --------------------------- - -By default, every prompt already has a set of key bindings which implements the -usual Vi or Emacs behaviour. We can extend this by passing another -:class:`~prompt_toolkit.key_binding.KeyBindings` instance to the -``key_bindings`` argument of the :func:`~prompt_toolkit.shortcuts.prompt` -function or the :class:`~prompt_toolkit.shortcuts.PromptSession` class. - -An example of a prompt that prints ``'hello world'`` when :kbd:`Control-T` is pressed. - -.. code:: python - - from prompt_toolkit import prompt - from prompt_toolkit.application import run_in_terminal - from prompt_toolkit.key_binding import KeyBindings - - bindings = KeyBindings() - - @bindings.add('c-t') - def _(event): - " Say 'hello' when `c-t` is pressed. " - def print_hello(): - print('hello world') - run_in_terminal(print_hello) - - @bindings.add('c-x') - def _(event): - " Exit when `c-x` is pressed. " - event.app.exit() - - text = prompt('> ', key_bindings=bindings) - print('You said: %s' % text) - - -Note that we use -:meth:`~prompt_toolkit.application.run_in_terminal` for the first key binding. -This ensures that the output of the print-statement and the prompt don't mix -up. If the key bindings doesn't print anything, then it can be handled directly -without nesting functions. - - -Enable key bindings according to a condition -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Often, some key bindings can be enabled or disabled according to a certain -condition. For instance, the Emacs and Vi bindings will never be active at the -same time, but it is possible to switch between Emacs and Vi bindings at run -time. - -In order to enable a key binding according to a certain condition, we have to -pass it a :class:`~prompt_toolkit.filters.Filter`, usually a -:class:`~prompt_toolkit.filters.Condition` instance. (:ref:`Read more about -filters <filters>`.) - -.. code:: python - - from prompt_toolkit import prompt - from prompt_toolkit.filters import Condition - from prompt_toolkit.key_binding import KeyBindings - - bindings = KeyBindings() - - @Condition - def is_active(): - " Only activate key binding on the second half of each minute. " - return datetime.datetime.now().second > 30 - - @bindings.add('c-t', filter=is_active) - def _(event): - # ... - pass - - prompt('> ', key_bindings=bindings) - - -Dynamically switch between Emacs and Vi mode -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The :class:`~prompt_toolkit.application.Application` has an ``editing_mode`` -attribute. We can change the key bindings by changing this attribute from -``EditingMode.VI`` to ``EditingMode.EMACS``. - -.. code:: python - - from prompt_toolkit import prompt - from prompt_toolkit.application.current import get_app - from prompt_toolkit.enums import EditingMode - from prompt_toolkit.key_binding import KeyBindings - - def run(): - # Create a set of key bindings. - bindings = KeyBindings() - - # Add an additional key binding for toggling this flag. - @bindings.add('f4') - def _(event): - " Toggle between Emacs and Vi mode. " - app = event.app - - if app.editing_mode == EditingMode.VI: - app.editing_mode = EditingMode.EMACS - else: - app.editing_mode = EditingMode.VI - - # Add a toolbar at the bottom to display the current input mode. - def bottom_toolbar(): - " Display the current input mode. " - text = 'Vi' if get_app().editing_mode == EditingMode.VI else 'Emacs' - return [ - ('class:toolbar', ' [F4] %s ' % text) - ] - - prompt('> ', key_bindings=bindings, bottom_toolbar=bottom_toolbar) - - run() - -:ref:`Read more about key bindings ...<key_bindings>` - -Using control-space for completion -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -An popular short cut that people sometimes use it to use control-space for -opening the autocompletion menu instead of the tab key. This can be done with -the following key binding. - -.. code:: python - - kb = KeyBindings() - - @kb.add('c-space') - def _(event): - " Initialize autocompletion, or select the next completion. " - buff = event.app.current_buffer - if buff.complete_state: - buff.complete_next() - else: - buff.start_completion(select_first=False) - - -Other prompt options --------------------- - -Multiline input -^^^^^^^^^^^^^^^ - -Reading multiline input is as easy as passing the ``multiline=True`` parameter. - -.. code:: python - - from prompt_toolkit import prompt - - prompt('> ', multiline=True) - -A side effect of this is that the enter key will now insert a newline instead -of accepting and returning the input. The user will now have to press -:kbd:`Meta+Enter` in order to accept the input. (Or :kbd:`Escape` followed by -:kbd:`Enter`.) - -It is possible to specify a continuation prompt. This works by passing a -``prompt_continuation`` callable to :func:`~prompt_toolkit.shortcuts.prompt`. -This function is supposed to return :ref:`formatted text <formatted_text>`, or -a list of ``(style, text)`` tuples. The width of the returned text should not -exceed the given width. (The width of the prompt margin is defined by the -prompt.) - -.. code:: python - - from prompt_toolkit import prompt - - def prompt_continuation(width, line_number, is_soft_wrap): - return '.' * width - # Or: return [('', '.' * width)] - - prompt('multiline input> ', multiline=True, - prompt_continuation=prompt_continuation) - -.. image:: ../images/multiline-input.png - - -Passing a default -^^^^^^^^^^^^^^^^^ - -A default value can be given: - -.. code:: python - - from prompt_toolkit import prompt - import getpass - - prompt('What is your name: ', default='%s' % getpass.getuser()) - - -Mouse support -^^^^^^^^^^^^^ - -There is limited mouse support for positioning the cursor, for scrolling (in -case of large multiline inputs) and for clicking in the autocompletion menu. - -Enabling can be done by passing the ``mouse_support=True`` option. - -.. code:: python - - from prompt_toolkit import prompt - import getpass - - prompt('What is your name: ', mouse_support=True) - - -Line wrapping -^^^^^^^^^^^^^ - -Line wrapping is enabled by default. This is what most people are used to and -this is what GNU Readline does. When it is disabled, the input string will -scroll horizontally. - -.. code:: python - - from prompt_toolkit import prompt - import getpass - - prompt('What is your name: ', wrap_lines=False) - - -Password input -^^^^^^^^^^^^^^ - -When the ``is_password=True`` flag has been given, the input is replaced by -asterisks (``*`` characters). - -.. code:: python - - from prompt_toolkit import prompt - import getpass - - prompt('Enter password: ', is_password=True) - - -Prompt in an `asyncio` application ----------------------------------- - -.. note:: - - New in prompt_toolkit 3.0. (In prompt_toolkit 2.0 this was possible using a - work-around). - -For `asyncio <https://docs.python.org/3/library/asyncio.html>`_ applications, -it's very important to never block the eventloop. However, -:func:`~prompt_toolkit.shortcuts.prompt` is blocking, and calling this would -freeze the whole application. Asyncio actually won't even allow us to run that -function within a coroutine. - -The answer is to call -:meth:`~prompt_toolkit.shortcuts.PromptSession.prompt_async` instead of -:meth:`~prompt_toolkit.shortcuts.PromptSession.prompt`. The async variation -returns a coroutines and is awaitable. - -.. code:: python - - from prompt_toolkit import PromptSession - from prompt_toolkit.patch_stdout import patch_stdout - - async def my_coroutine(): - session = PromptSession() - while True: - with patch_stdout(): - result = await session.prompt_async('Say something: ') - print('You said: %s' % result) - -The :func:`~prompt_toolkit.patch_stdout.patch_stdout` context manager is -optional, but it's recommended, because other coroutines could print to stdout. -This ensures that other output won't destroy the prompt. diff -Nru prompt-toolkit-3.0.5/docs/pages/dialogs.rst prompt-toolkit-3.0.6/docs/pages/dialogs.rst --- prompt-toolkit-3.0.5/docs/pages/dialogs.rst 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/dialogs.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,270 +0,0 @@ -.. _dialogs: - -Dialogs -======= - -Prompt_toolkit ships with a high level API for displaying dialogs, similar to -the Whiptail program, but in pure Python. - - -Message box ------------ - -Use the :func:`~prompt_toolkit.shortcuts.message_dialog` function to display a -simple message box. For instance: - -.. code:: python - - from prompt_toolkit.shortcuts import message_dialog - - message_dialog( - title='Example dialog window', - text='Do you want to continue?\nPress ENTER to quit.').run() - -.. image:: ../images/dialogs/messagebox.png - - -Input box ---------- - -The :func:`~prompt_toolkit.shortcuts.input_dialog` function can display an -input box. It will return the user input as a string. - -.. code:: python - - from prompt_toolkit.shortcuts import input_dialog - - text = input_dialog( - title='Input dialog example', - text='Please type your name:').run() - -.. image:: ../images/dialogs/inputbox.png - - -The ``password=True`` option can be passed to the -:func:`~prompt_toolkit.shortcuts.input_dialog` function to turn this into a -password input box. - - -Yes/No confirmation dialog --------------------------- - -The :func:`~prompt_toolkit.shortcuts.yes_no_dialog` function displays a yes/no -confirmation dialog. It will return a boolean according to the selection. - -.. code:: python - - from prompt_toolkit.shortcuts import yes_no_dialog - - result = yes_no_dialog( - title='Yes/No dialog example', - text='Do you want to confirm?').run() - -.. image:: ../images/dialogs/confirm.png - - -Button dialog -------------- - -The :func:`~prompt_toolkit.shortcuts.button_dialog` function displays a dialog -with choices offered as buttons. Buttons are indicated as a list of tuples, -each providing the label (first) and return value if clicked (second). - -.. code:: python - - from prompt_toolkit.shortcuts import button_dialog - - result = button_dialog( - title='Button dialog example', - text='Do you want to confirm?', - buttons=[ - ('Yes', True), - ('No', False), - ('Maybe...', None) - ], - ).run() - -.. image:: ../images/dialogs/button.png - - -Radio list dialog ------------------ - -The :func:`~prompt_toolkit.shortcuts.radiolist_dialog` functiom displays a dialog -with choices offered as a radio list. The values are provided as a list of tuples, -each providing the return value (first element) and the displayed value (second element). - -.. code:: python - - from prompt_toolkit.shortcuts import radiolist_dialog - - result = radiolist_dialog( - title="RadioList dialog", - text="Which breakfast would you like ?", - values=[ - ("breakfast1", "Eggs and beacon"), - ("breakfast2", "French breakfast"), - ("breakfast3", "Equestrian breakfast") - ] - ).run() - - -Checkbox list dialog --------------------- - -The :func:`~prompt_toolkit.shortcuts.checkboxlist_dialog` has the same usage and purpose than the Radiolist dialog, but allows several values to be selected and therefore returned. - -.. code:: python - - from prompt_toolkit.shortcuts import checkboxlist_dialog - - results_array = checkboxlist_dialog( - title="CheckboxList dialog", - text="What would you like in your breakfast ?", - values=[ - ("eggs", "Eggs"), - ("bacon", "Bacon"), - ("croissants", "20 Croissants"), - ("daily", "The breakfast of the day") - ] - ).run() - - -Styling of dialogs ------------------- - -A custom :class:`~prompt_toolkit.styles.Style` instance can be passed to all -dialogs to override the default style. Also, text can be styled by passing an -:class:`~prompt_toolkit.formatted_text.HTML` object. - - -.. code:: python - - from prompt_toolkit.formatted_text import HTML - from prompt_toolkit.shortcuts import message_dialog - from prompt_toolkit.styles import Style - - example_style = Style.from_dict({ - 'dialog': 'bg:#88ff88', - 'dialog frame.label': 'bg:#ffffff #000000', - 'dialog.body': 'bg:#000000 #00ff00', - 'dialog shadow': 'bg:#00aa00', - }) - - message_dialog( - title=HTML('<style bg="blue" fg="white">Styled</style> ' - '<style fg="ansired">dialog</style> window'), - text='Do you want to continue?\nPress ENTER to quit.', - style=example_style).run() - -.. image:: ../images/dialogs/styled.png - -Styling reference sheet ------------------------ - -In reality, the shortcut commands presented above build a full-screen frame by using a list of components. The two tables below allow you to get the classnames available for each shortcut, therefore you will be able to provide a custom style for every element that is displayed, using the method provided above. - -.. note:: All the shortcuts use the ``Dialog`` component, therefore it isn't specified explicitely below. - -+--------------------------+-------------------------+ -| Shortcut | Components used | -+==========================+=========================+ -| ``yes_no_dialog`` | - ``Label`` | -| | - ``Button`` (x2) | -+--------------------------+-------------------------+ -| ``button_dialog`` | - ``Label`` | -| | - ``Button`` | -+--------------------------+-------------------------+ -| ``input_dialog`` | - ``TextArea`` | -| | - ``Button`` (x2) | -+--------------------------+-------------------------+ -| ``message_dialog`` | - ``Label`` | -| | - ``Button`` | -+--------------------------+-------------------------+ -| ``radiolist_dialog`` | - ``Label`` | -| | - ``RadioList`` | -| | - ``Button`` (x2) | -+--------------------------+-------------------------+ -| ``checkboxlist_dialog`` | - ``Label`` | -| | - ``CheckboxList`` | -| | - ``Button`` (x2) | -+--------------------------+-------------------------+ -| ``progress_dialog`` | - ``Label`` | -| | - ``TextArea`` (locked) | -| | - ``ProgressBar`` | -+--------------------------+-------------------------+ - -+----------------+-----------------------------+ -| Components | Available classnames | -+================+=============================+ -| Dialog | - ``dialog`` | -| | - ``dialog.body`` | -+----------------+-----------------------------+ -| TextArea | - ``text-area`` | -| | - ``text-area.prompt`` | -+----------------+-----------------------------+ -| Label | - ``label`` | -+----------------+-----------------------------+ -| Button | - ``button`` | -| | - ``button.focused`` | -| | - ``button.arrow`` | -| | - ``button.text`` | -+----------------+-----------------------------+ -| Frame | - ``frame`` | -| | - ``frame.border`` | -| | - ``frame.label`` | -+----------------+-----------------------------+ -| Shadow | - ``shadow`` | -+----------------+-----------------------------+ -| RadioList | - ``radio-list`` | -| | - ``radio`` | -| | - ``radio-checked`` | -| | - ``radio-selected`` | -+----------------+-----------------------------+ -| CheckboxList | - ``checkbox-list`` | -| | - ``checkbox`` | -| | - ``checkbox-checked`` | -| | - ``checkbox-selected`` | -+----------------+-----------------------------+ -| VerticalLine | - ``line`` | -| | - ``vertical-line`` | -+----------------+-----------------------------+ -| HorizontalLine | - ``line`` | -| | - ``horizontal-line`` | -+----------------+-----------------------------+ -| ProgressBar | - ``progress-bar`` | -| | - ``progress-bar.used`` | -+----------------+-----------------------------+ - -Example -_______ - -Let's customize the example of the ``checkboxlist_dialog``. - -It uses 2 ``Button``, a ``CheckboxList`` and a ``Label``, packed inside a ``Dialog``. -Threfore we can customize each of these elements separately, using for instance: - -.. code:: python - - from prompt_toolkit.shortcuts import checkboxlist_dialog - from prompt_toolkit.styles import Style - - results = checkboxlist_dialog( - title="CheckboxList dialog", - text="What would you like in your breakfast ?", - values=[ - ("eggs", "Eggs"), - ("bacon", "Bacon"), - ("croissants", "20 Croissants"), - ("daily", "The breakfast of the day") - ], - style=Style.from_dict({ - 'dialog': 'bg:#cdbbb3', - 'button': 'bg:#bf99a4', - 'checkbox': '#e8612c', - 'dialog.body': 'bg:#a9cfd0', - 'dialog shadow': 'bg:#c98982', - 'frame.label': '#fcaca3', - 'dialog.body label': '#fd8bb6', - }) - ).run() diff -Nru prompt-toolkit-3.0.5/docs/pages/full_screen_apps.rst prompt-toolkit-3.0.6/docs/pages/full_screen_apps.rst --- prompt-toolkit-3.0.5/docs/pages/full_screen_apps.rst 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/full_screen_apps.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,411 +0,0 @@ -.. _full_screen_applications: - -Building full screen applications -================================= - -`prompt_toolkit` can be used to create complex full screen terminal -applications. Typically, an application consists of a layout (to describe the -graphical part) and a set of key bindings. - -The sections below describe the components required for full screen -applications (or custom, non full screen applications), and how to assemble -them together. - -Before going through this page, it could be helpful to go through :ref:`asking -for input <asking_for_input>` (prompts) first. Many things that apply to an -input prompt, like styling, key bindings and so on, also apply to full screen -applications. - -.. note:: - - Also remember that the ``examples`` directory of the prompt_toolkit - repository contains plenty of examples. Each example is supposed to explain - one idea. So, this as well should help you get started. - - Don't hesitate to open a GitHub issue if you feel that a certain example is - missing. - - -A simple application --------------------- - -Every prompt_toolkit application is an instance of an -:class:`~prompt_toolkit.application.Application` object. The simplest full -screen example would look like this: - -.. code:: python - - from prompt_toolkit import Application - - app = Application(full_screen=True) - app.run() - -This will display a dummy application that says "No layout specified. Press -ENTER to quit.". - -.. note:: - - If we wouldn't set the ``full_screen`` option, the application would - not run in the alternate screen buffer, and only consume the least - amount of space required for the layout. - -An application consists of several components. The most important are: - -- I/O objects: the input and output device. -- The layout: this defines the graphical structure of the application. For - instance, a text box on the left side, and a button on the right side. - You can also think of the layout as a collection of 'widgets'. -- A style: this defines what colors and underline/bold/italic styles are used - everywhere. -- A set of key bindings. - -We will discuss all of these in more detail below. - - -I/O objects ------------ - -Every :class:`~prompt_toolkit.application.Application` instance requires an I/O -objects for input and output: - - - An :class:`~prompt_toolkit.input.Input` instance, which is an abstraction - of the input stream (stdin). - - An :class:`~prompt_toolkit.output.Output` instance, which is an - abstraction of the output stream, and is called by the renderer. - -Both are optional and normally not needed to pass explicitly. Usually, the -default works fine. - -There is a third I/O object which is also required by the application, but not -passed inside. This is the event loop, an -:class:`~prompt_toolkit.eventloop.EventLoop` instance. This is basically a -while-true loop that waits for user input, and when it receives something (like -a key press), it will send that to the the appropriate handler, like for -instance, a key binding. - -When :func:`~prompt_toolkit.application.Application.run()` is called, the event -loop will run until the application is done. An application will quit when -:func:`~prompt_toolkit.application.Application.exit()` is called. - - -The layout ----------- - -A layered layout architecture -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -There are several ways to create a prompt_toolkit layout, depending on how -customizable you want things to be. In fact, there are several layers of -abstraction. - -- The most low-level way of creating a layout is by combining - :class:`~prompt_toolkit.layout.Container` and - :class:`~prompt_toolkit.layout.UIControl` objects. - - Examples of :class:`~prompt_toolkit.layout.Container` objects are - :class:`~prompt_toolkit.layout.VSplit` (vertical split), - :class:`~prompt_toolkit.layout.HSplit` (horizontal split) and - :class:`~prompt_toolkit.layout.FloatContainer`. These containers arrange the - layout and can split it in multiple regions. Each container can recursively - contain multiple other containers. They can be combined in any way to define - the "shape" of the layout. - - The :class:`~prompt_toolkit.layout.Window` object is a special kind of - container that can contain a :class:`~prompt_toolkit.layout.UIControl` - object. The :class:`~prompt_toolkit.layout.UIControl` object is responsible - for the generation of the actual content. The - :class:`~prompt_toolkit.layout.Window` object acts as an adaptor between the - :class:`~prompt_toolkit.layout.UIControl` and other containers, but it's also - responsible for the scrolling and line wrapping of the content. - - Examples of :class:`~prompt_toolkit.layout.UIControl` objects are - :class:`~prompt_toolkit.layout.BufferControl` for showing the content of an - editable/scrollable buffer, and - :class:`~prompt_toolkit.layout.FormattedTextControl` for displaying - (:ref:`formatted <formatted_text>`) text. - - Normally, it is never needed to create new - :class:`~prompt_toolkit.layout.UIControl` or - :class:`~prompt_toolkit.layout.Container` classes, but instead you would - create the layout by composing instances of the existing built-ins. - -- A higher level abstraction of building a layout is by using "widgets". A - widget is a reusable layout component that can contain multiple containers - and controls. It should have a ``__pt__container__`` function, which is - supposed to return the root container for this widget. Prompt_toolkit - contains a couple of widgets like - :class:`~prompt_toolkit.widgets.TextArea`, - :class:`~prompt_toolkit.widgets.Button`, - :class:`~prompt_toolkit.widgets.Frame`, - :class:`~prompt_toolkit.widgets.VerticalLine` and so on. - -- The highest level abstractions can be found in the ``shortcuts`` module. - There we don't have to think about the layout, controls and containers at - all. This is the simplest way to use prompt_toolkit, but is only meant for - specific use cases, like a prompt or a simple dialog window. - -Containers and controls -^^^^^^^^^^^^^^^^^^^^^^^ - -The biggest difference between containers and controls is that containers -arrange the layout by splitting the screen in many regions, while controls are -responsible for generating the actual content. - -.. note:: - - Under the hood, the difference is: - - - containers use *absolute coordinates*, and paint on a - :class:`~prompt_toolkit.layout.screen.Screen` instance. - - user controls create a :class:`~prompt_toolkit.layout.controls.UIContent` - instance. This is a collection of lines that represent the actual - content. A :class:`~prompt_toolkit.layout.controls.UIControl` is not aware - of the screen. - -+---------------------------------------------+------------------------------------------------------+ -| Abstract base class | Examples | -+=============================================+======================================================+ -| :class:`~prompt_toolkit.layout.Container` | :class:`~prompt_toolkit.layout.HSplit` | -| | :class:`~prompt_toolkit.layout.VSplit` | -| | :class:`~prompt_toolkit.layout.FloatContainer` | -| | :class:`~prompt_toolkit.layout.Window` | -+---------------------------------------------+------------------------------------------------------+ -| :class:`~prompt_toolkit.layout.UIControl` | :class:`~prompt_toolkit.layout.BufferControl` | -| | :class:`~prompt_toolkit.layout.FormattedTextControl` | -+---------------------------------------------+------------------------------------------------------+ - -The :class:`~prompt_toolkit.layout.Window` class itself is -particular: it is a :class:`~prompt_toolkit.layout.Container` that -can contain a :class:`~prompt_toolkit.layout.UIControl`. Thus, it's the adaptor -between the two. The :class:`~prompt_toolkit.layout.Window` class also takes -care of scrolling the content and wrapping the lines if needed. - -Finally, there is the :class:`~prompt_toolkit.layout.Layout` class which wraps -the whole layout. This is responsible for keeping track of which window has the -focus. - -Here is an example of a layout that displays the content of the default buffer -on the left, and displays ``"Hello world"`` on the right. In between it shows a -vertical line: - -.. code:: python - - from prompt_toolkit import Application - from prompt_toolkit.buffer import Buffer - from prompt_toolkit.layout.containers import VSplit, Window - from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl - from prompt_toolkit.layout.layout import Layout - - buffer1 = Buffer() # Editable buffer. - - root_container = VSplit([ - # One window that holds the BufferControl with the default buffer on - # the left. - Window(content=BufferControl(buffer=buffer1)), - - # A vertical line in the middle. We explicitly specify the width, to - # make sure that the layout engine will not try to divide the whole - # width by three for all these windows. The window will simply fill its - # content by repeating this character. - Window(width=1, char='|'), - - # Display the text 'Hello world' on the right. - Window(content=FormattedTextControl(text='Hello world')), - ]) - - layout = Layout(root_container) - - app = Application(layout=layout, full_screen=True) - app.run() # You won't be able to Exit this app - -Notice that if you execute this right now, there is no way to quit this -application yet. This is something we explain in the next section below. - -More complex layouts can be achieved by nesting multiple -:class:`~prompt_toolkit.layout.VSplit`, -:class:`~prompt_toolkit.layout.HSplit` and -:class:`~prompt_toolkit.layout.FloatContainer` objects. - -If you want to make some part of the layout only visible when a certain -condition is satisfied, use a -:class:`~prompt_toolkit.layout.ConditionalContainer`. - - -Focusing windows -^^^^^^^^^^^^^^^^^ - -Focussing something can be done by calling the -:meth:`~prompt_toolkit.layout.Layout.focus` method. This method is very -flexible and accepts a :class:`~prompt_toolkit.layout.Window`, a -:class:`~prompt_toolkit.buffer.Buffer`, a -:class:`~prompt_toolkit.layout.controls.UIControl` and more. - -In the following example, we use :func:`~prompt_toolkit.application.get_app` -for getting the active application. - -.. code:: python - - from prompt_toolkit.application import get_app - - # This window was created earlier. - w = Window() - - # ... - - # Now focus it. - get_app().layout.focus(w) - -Changing the focus is something which is typically done in a key binding, so -read on to see how to define key bindings. - -Key bindings ------------- - -In order to react to user actions, we need to create a -:class:`~prompt_toolkit.key_binding.KeyBindings` object and pass -that to our :class:`~prompt_toolkit.application.Application`. - -There are two kinds of key bindings: - -- Global key bindings, which are always active. -- Key bindings that belong to a certain - :class:`~prompt_toolkit.layout.controls.UIControl` and are only active when - this control is focused. Both - :class:`~prompt_toolkit.layout.BufferControl` - :class:`~prompt_toolkit.layout.FormattedTextControl` take a ``key_bindings`` - argument. - - -Global key bindings -^^^^^^^^^^^^^^^^^^^ - -Key bindings can be passed to the application as follows: - -.. code:: python - - from prompt_toolkit import Application - from prompt_toolkit.key_binding import KeyBindings - - kb = KeyBindings() - app = Application(key_bindings=kb) - app.run() - -To register a new keyboard shortcut, we can use the -:meth:`~prompt_toolkit.key_binding.KeyBindings.add` method as a decorator of -the key handler: - -.. code:: python - - from prompt_toolkit import Application - from prompt_toolkit.key_binding import KeyBindings - - kb = KeyBindings() - - @kb.add('c-q') - def exit_(event): - """ - Pressing Ctrl-Q will exit the user interface. - - Setting a return value means: quit the event loop that drives the user - interface and return this value from the `Application.run()` call. - """ - event.app.exit() - - app = Application(key_bindings=kb, full_screen=True) - app.run() - -The callback function is named ``exit_`` for clarity, but it could have been -named ``_`` (underscore) as well, because the we won't refer to this name. - -:ref:`Read more about key bindings ...<key_bindings>` - - -Modal containers -^^^^^^^^^^^^^^^^ - -All container objects, like :class:`~prompt_toolkit.layout.VSplit` and -:class:`~prompt_toolkit.layout.HSplit` take a ``modal`` argument. - -If this flag has been set, then key bindings from the parent account are not -taken into account if one of the children windows has the focus. - -This is useful in a complex layout, where many controls have their own key -bindings, but you only want to enable the key bindings for a certain region of -the layout. - -The global key bindings are always active. - - -More about the Window class ---------------------------- - -As said earlier, a :class:`~prompt_toolkit.layout.Window` is a -:class:`~prompt_toolkit.layout.Container` that wraps a -:class:`~prompt_toolkit.layout.UIControl`, like a -:class:`~prompt_toolkit.layout.BufferControl` or -:class:`~prompt_toolkit.layout.FormattedTextControl`. - -.. note:: - - Basically, windows are the leafs in the tree structure that represent the UI. - -A :class:`~prompt_toolkit.layout.Window` provides a "view" on the -:class:`~prompt_toolkit.layout.UIControl`, which provides lines of content. The -window is in the first place responsible for the line wrapping and scrolling of -the content, but there are much more options. - -- Adding left or right margins. These are used for displaying scroll bars or - line numbers. -- There are the `cursorline` and `cursorcolumn` options. These allow - highlighting the line or column of the cursor position. -- Alignment of the content. The content can be left aligned, right aligned or - centered. -- Finally, the background can be filled with a default character. - - -More about buffers and `BufferControl` --------------------------------------- - - - -Input processors -^^^^^^^^^^^^^^^^ - -A :class:`~prompt_toolkit.layout.processors.Processor` is used to postprocess -the content of a :class:`~prompt_toolkit.layout.BufferControl` before it's -displayed. It can for instance highlight matching brackets or change the -visualisation of tabs and so on. - -A :class:`~prompt_toolkit.layout.processors.Processor` operates on individual -lines. Basically, it takes a (formatted) line and produces a new (formatted) -line. - -Some build-in processors: - -+----------------------------------------------------------------------------+-----------------------------------------------------------+ -| Processor | Usage: | -+============================================================================+===========================================================+ -| :class:`~prompt_toolkit.layout.processors.HighlightSearchProcessor` | Highlight the current search results. | -+----------------------------------------------------------------------------+-----------------------------------------------------------+ -| :class:`~prompt_toolkit.layout.processors.HighlightSelectionProcessor` | Highlight the selection. | -+----------------------------------------------------------------------------+-----------------------------------------------------------+ -| :class:`~prompt_toolkit.layout.processors.PasswordProcessor` | Display input as asterisks. (``*`` characters). | -+----------------------------------------------------------------------------+-----------------------------------------------------------+ -| :class:`~prompt_toolkit.layout.processors.BracketsMismatchProcessor` | Highlight open/close mismatches for brackets. | -+----------------------------------------------------------------------------+-----------------------------------------------------------+ -| :class:`~prompt_toolkit.layout.processors.BeforeInput` | Insert some text before. | -+----------------------------------------------------------------------------+-----------------------------------------------------------+ -| :class:`~prompt_toolkit.layout.processors.AfterInput` | Insert some text after. | -+----------------------------------------------------------------------------+-----------------------------------------------------------+ -| :class:`~prompt_toolkit.layout.processors.AppendAutoSuggestion` | Append auto suggestion text. | -+----------------------------------------------------------------------------+-----------------------------------------------------------+ -| :class:`~prompt_toolkit.layout.processors.ShowLeadingWhiteSpaceProcessor` | Visualise leading whitespace. | -+----------------------------------------------------------------------------+-----------------------------------------------------------+ -| :class:`~prompt_toolkit.layout.processors.ShowTrailingWhiteSpaceProcessor` | Visualise trailing whitespace. | -+----------------------------------------------------------------------------+-----------------------------------------------------------+ -| :class:`~prompt_toolkit.layout.processors.TabsProcessor` | Visualise tabs as `n` spaces, or some symbols. | -+----------------------------------------------------------------------------+-----------------------------------------------------------+ - -A :class:`~prompt_toolkit.layout.BufferControl` takes only one processor as -input, but it is possible to "merge" multiple processors into one with the -:func:`~prompt_toolkit.layout.processors.merge_processors` function. diff -Nru prompt-toolkit-3.0.5/docs/pages/gallery.rst prompt-toolkit-3.0.6/docs/pages/gallery.rst --- prompt-toolkit-3.0.5/docs/pages/gallery.rst 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/gallery.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -.. _gallery: - -Gallery -======= - -Showcase, demonstrating the possibilities of prompt_toolkit. - -Ptpython, a Python REPL -^^^^^^^^^^^^^^^^^^^^^^^ - -The prompt: - -.. image:: ../images/ptpython.png - -The configuration menu of ptpython. - -.. image:: ../images/ptpython-menu.png - -The history page with its help. (This is a full-screen layout.) - -.. image:: ../images/ptpython-history-help.png - -Pyvim, a Vim clone -^^^^^^^^^^^^^^^^^^ - -.. image:: ../images/pyvim.png - - -Pymux, a terminal multiplexer (like tmux) in Python -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: ../images/pymux.png diff -Nru prompt-toolkit-3.0.5/docs/pages/getting_started.rst prompt-toolkit-3.0.6/docs/pages/getting_started.rst --- prompt-toolkit-3.0.5/docs/pages/getting_started.rst 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/getting_started.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -.. _getting_started: - -Getting started -=============== - -Installation ------------- - -:: - - pip install prompt_toolkit - -For Conda, do: - -:: - - conda install -c https://conda.anaconda.org/conda-forge prompt_toolkit - - -Several use cases: prompts versus full screen terminal applications --------------------------------------------------------------------- - -`prompt_toolkit` was in the first place meant to be a replacement for readline. -However, when it became more mature, we realised that all the components for -full screen applications are there and `prompt_toolkit` is very capable of -handling many use situations. `Pyvim -<http://github.com/jonathanslenders/pyvim>`_ and `pymux -<http://github.com/jonathanslenders/pymux>`_ are examples of full screen -applications. - -.. image:: ../images/pyvim.png - -Basically, at the core, `prompt_toolkit` has a layout engine, that supports -horizontal and vertical splits as well as floats, where each "window" can -display a user control. The API for user controls is simple yet powerful. - -When `prompt_toolkit` is used as a readline replacement, (to simply read some -input from the user), it uses a rather simple built-in layout. One that -displays the default input buffer and the prompt, a float for the -autocompletions and a toolbar for input validation which is hidden by default. - -For full screen applications, usually we build a custom layout ourselves. - -Further, there is a very flexible key binding system that can be programmed for -all the needs of full screen applications. - - -A simple prompt ---------------- - -The following snippet is the most simple example, it uses the -:func:`~prompt_toolkit.shortcuts.prompt` function to asks the user for input -and returns the text. Just like ``(raw_)input``. - -.. code:: python - - from prompt_toolkit import prompt - - text = prompt('Give me some input: ') - print('You said: %s' % text) - - -Learning `prompt_toolkit` -------------------------- - -In order to learn and understand `prompt_toolkit`, it is best to go through the -all sections in the order below. Also don't forget to have a look at all the -examples `examples -<https://github.com/jonathanslenders/python-prompt-toolkit/tree/master/examples>`_ -in the repository. - -- First, :ref:`learn how to print text <printing_text>`. This is important, - because it covers how to use "formatted text", which is something you'll use - whenever you want to use colors anywhere. - -- Secondly, go through the :ref:`asking for input <asking_for_input>` section. - This is useful for almost any use case, even for full screen applications. - It covers autocompletions, syntax highlighting, key bindings, and so on. - -- Then, learn about :ref:`dialogs`, which is easy and fun. - -- Finally, learn about :ref:`full screen applications - <full_screen_applications>` and read through :ref:`the advanced topics - <advanced_topics>`. diff -Nru prompt-toolkit-3.0.5/docs/pages/printing_text.rst prompt-toolkit-3.0.6/docs/pages/printing_text.rst --- prompt-toolkit-3.0.5/docs/pages/printing_text.rst 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/printing_text.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,274 +0,0 @@ -.. _printing_text: - -Printing (and using) formatted text -=================================== - -Prompt_toolkit ships with a -:func:`~prompt_toolkit.shortcuts.print_formatted_text` function that's meant to -be (as much as possible) compatible with the built-in print function, but on -top of that, also supports colors and formatting. - -On Linux systems, this will output VT100 escape sequences, while on Windows it -will use Win32 API calls or VT100 sequences, depending on what is available. - -.. note:: - - This page is also useful if you'd like to learn how to use formatting - in other places, like in a prompt or a toolbar. Just like - :func:`~prompt_toolkit.shortcuts.print_formatted_text` takes any kind - of "formatted text" as input, prompts and toolbars also accept - "formatted text". - -Printing plain text -------------------- - -The print function can be imported as follows: - -.. code:: python - - from prompt_toolkit import print_formatted_text - - print_formatted_text('Hello world') - -You can replace the built in ``print`` function as follows, if you want to. - -.. code:: python - - from prompt_toolkit import print_formatted_text as print - - print('Hello world') - -.. note:: - - If you're using Python 2, make sure to add ``from __future__ import - print_function``. Otherwise, it will not be possible to import a function - named ``print``. - -.. _formatted_text: - -Formatted text --------------- - -There are several ways to display colors: - -- By creating an :class:`~prompt_toolkit.formatted_text.HTML` object. -- By creating an :class:`~prompt_toolkit.formatted_text.ANSI` object that - contains ANSI escape sequences. -- By creating a list of ``(style, text)`` tuples. -- By creating a list of ``(pygments.Token, text)`` tuples, and wrapping it in - :class:`~prompt_toolkit.formatted_text.PygmentsTokens`. - -An instance of any of these four kinds of objects is called "formatted text". -There are various places in prompt toolkit, where we accept not just plain text -(as a strings), but also formatted text. - -HTML -^^^^ - -:class:`~prompt_toolkit.formatted_text.HTML` can be used to indicate that a -string contains HTML-like formatting. It recognizes the basic tags for bold, -italic and underline: ``<b>``, ``<i>`` and ``<u>``. - -.. code:: python - - from prompt_toolkit import print_formatted_text, HTML - - print_formatted_text(HTML('<b>This is bold</b>')) - print_formatted_text(HTML('<i>This is italic</i>')) - print_formatted_text(HTML('<u>This is underlined</u>')) - -Further, it's possible to use tags for foreground colors: - -.. code:: python - - # Colors from the ANSI palette. - print_formatted_text(HTML('<ansired>This is red</ansired>')) - print_formatted_text(HTML('<ansigreen>This is green</ansigreen>')) - - # Named colors (256 color palette, or true color, depending on the output). - print_formatted_text(HTML('<skyblue>This is sky blue</skyblue>')) - print_formatted_text(HTML('<seagreen>This is sea green</seagreen>')) - print_formatted_text(HTML('<violet>This is violet</violet>')) - -Both foreground and background colors can also be specified setting the `fg` -and `bg` attributes of any HTML tag: - -.. code:: python - - # Colors from the ANSI palette. - print_formatted_text(HTML('<aaa fg="ansiwhite" bg="ansigreen">White on green</aaa>')) - -Underneath, all HTML tags are mapped to classes from a stylesheet, so you can -assign a style for a custom tag. - -.. code:: python - - from prompt_toolkit import print_formatted_text, HTML - from prompt_toolkit.styles import Style - - style = Style.from_dict({ - 'aaa': '#ff0066', - 'bbb': '#44ff00 italic', - }) - - print_formatted_text(HTML('<aaa>Hello</aaa> <bbb>world</bbb>!'), style=style) - - -ANSI -^^^^ - -Some people like to use the VT100 ANSI escape sequences to generate output. -Natively, this is however only supported on VT100 terminals, but prompt_toolkit -can parse these, and map them to formatted text instances. This means that they -will work on Windows as well. The :class:`~prompt_toolkit.formatted_text.ANSI` -class takes care of that. - -.. code:: python - - from prompt_toolkit import print_formatted_text, ANSI - - print_formatted_text(ANSI('\x1b[31mhello \x1b[32mworld')) - -Keep in mind that even on a Linux VT100 terminal, the final output produced by -prompt_toolkit, is not necessarily exactly the same. Depending on the color -depth, it is possible that colors are mapped to different colors, and unknown -tags will be removed. - - -(style, text) tuples -^^^^^^^^^^^^^^^^^^^^ - -Internally, both :class:`~prompt_toolkit.formatted_text.HTML` and -:class:`~prompt_toolkit.formatted_text.ANSI` objects are mapped to a list of -``(style, text)`` tuples. It is however also possible to create such a list -manually with :class:`~prompt_toolkit.formatted_text.FormattedText` class. -This is a little more verbose, but it's probably the most powerful -way of expressing formatted text. - -.. code:: python - - from prompt_toolkit import print_formatted_text - from prompt_toolkit.formatted_text import FormattedText - - text = FormattedText([ - ('#ff0066', 'Hello'), - ('', ' '), - ('#44ff00 italic', 'World'), - ]) - - print_formatted_text(text) - -Similar to the :class:`~prompt_toolkit.formatted_text.HTML` example, it is also -possible to use class names, and separate the styling in a style sheet. - -.. code:: python - - from prompt_toolkit import print_formatted_text - from prompt_toolkit.formatted_text import FormattedText - from prompt_toolkit.styles import Style - - # The text. - text = FormattedText([ - ('class:aaa', 'Hello'), - ('', ' '), - ('class:bbb', 'World'), - ]) - - # The style sheet. - style = Style.from_dict({ - 'aaa': '#ff0066', - 'bbb': '#44ff00 italic', - }) - - print_formatted_text(text, style=style) - - -Pygments ``(Token, text)`` tuples -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -When you have a list of `Pygments <http://pygments.org/>`_ ``(Token, text)`` -tuples, then these can be printed by wrapping them in a -:class:`~prompt_toolkit.formatted_text.PygmentsTokens` object. - -.. code:: python - - from pygments.token import Token - from prompt_toolkit import print_formatted_text - from prompt_toolkit.formatted_text import PygmentsTokens - - text = [ - (Token.Keyword, 'print'), - (Token.Punctuation, '('), - (Token.Literal.String.Double, '"'), - (Token.Literal.String.Double, 'hello'), - (Token.Literal.String.Double, '"'), - (Token.Punctuation, ')'), - (Token.Text, '\n'), - ] - - print_formatted_text(PygmentsTokens(text)) - - -Similarly, it is also possible to print the output of a Pygments lexer: - -.. code:: python - - import pygments - from pygments.token import Token - from pygments.lexers.python import PythonLexer - - from prompt_toolkit.formatted_text import PygmentsTokens - from prompt_toolkit import print_formatted_text - - # Printing the output of a pygments lexer. - tokens = list(pygments.lex('print("Hello")', lexer=PythonLexer())) - print_formatted_text(PygmentsTokens(tokens)) - -Prompt_toolkit ships with a default colorscheme which styles it just like -Pygments would do, but if you'd like to change the colors, keep in mind that -Pygments tokens map to classnames like this: - -+-----------------------------------+---------------------------------------------+ -| pygments.Token | prompt_toolkit classname | -+===================================+=============================================+ -| - ``Token.Keyword`` | - ``"class:pygments.keyword"`` | -| - ``Token.Punctuation`` | - ``"class:pygments.punctuation"`` | -| - ``Token.Literal.String.Double`` | - ``"class:pygments.literal.string.double"``| -| - ``Token.Text`` | - ``"class:pygments.text"`` | -| - ``Token`` | - ``"class:pygments"`` | -+-----------------------------------+---------------------------------------------+ - -A classname like ``pygments.literal.string.double`` is actually decomposed in -the following four classnames: ``pygments``, ``pygments.literal``, -``pygments.literal.string`` and ``pygments.literal.string.double``. The final -style is computed by combining the style for these four classnames. So, -changing the style from these Pygments tokens can be done as follows: - -.. code:: python - - from prompt_toolkit.styles import Style - - style = Style.from_dict({ - 'pygments.keyword': 'underline', - 'pygments.literal.string': 'bg:#00ff00 #ffffff', - }) - print_formatted_text(PygmentsTokens(tokens), style=style) - - -to_formatted_text -^^^^^^^^^^^^^^^^^ - -A useful function to know about is -:func:`~prompt_toolkit.formatted_text.to_formatted_text`. This ensures that the -given input is valid formatted text. While doing so, an additional style can be -applied as well. - -.. code:: python - - from prompt_toolkit.formatted_text import to_formatted_text, HTML - from prompt_toolkit import print_formatted_text - - html = HTML('<aaa>Hello</aaa> <bbb>world</bbb>!') - text = to_formatted_text(html, style='class:my_html bg:#00ff00 italic') - - print_formatted_text(text) diff -Nru prompt-toolkit-3.0.5/docs/pages/progress_bars.rst prompt-toolkit-3.0.6/docs/pages/progress_bars.rst --- prompt-toolkit-3.0.5/docs/pages/progress_bars.rst 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/progress_bars.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,246 +0,0 @@ -.. _progress_bars: - -Progress bars -============= - -Prompt_toolkit ships with a high level API for displaying progress bars, -inspired by `tqdm <https://github.com/tqdm/tqdm>`_ - -.. warning:: - - The API for the prompt_toolkit progress bars is still very new and can - possibly change in the future. It is usable and tested, but keep this in - mind when upgrading. - -Remember that the examples directory of the prompt_toolkit repository ships -with many progress bar examples as well. - - -Simple progress bar -------------------- - -Creating a new progress bar can be done by calling the -:class:`~prompt_toolkit.shortcuts.ProgressBar` context manager. - -The progress can be displayed for any iterable. This works by wrapping the -iterable (like ``range``) with the -:class:`~prompt_toolkit.shortcuts.ProgressBar` context manager itself. This -way, the progress bar knows when the next item is consumed by the forloop and -when progress happens. - -.. code:: python - - from prompt_toolkit.shortcuts import ProgressBar - import time - - - with ProgressBar() as pb: - for i in pb(range(800)): - time.sleep(.01) - -.. image:: ../images/progress-bars/simple-progress-bar.png - -Keep in mind that not all iterables can report their total length. This happens -with a typical generator. In that case, you can still pass the total as follows -in order to make displaying the progress possible: - -.. code:: python - - def some_iterable(): - yield ... - - with ProgressBar() as pb: - for i in pb(some_iterable, total=1000): - time.sleep(.01) - - -Multiple parallel tasks ------------------------ - -A prompt_toolkit :class:`~prompt_toolkit.shortcuts.ProgressBar` can display the -progress of multiple tasks running in parallel. Each task can run in a separate -thread and the :class:`~prompt_toolkit.shortcuts.ProgressBar` user interface -runs in its own thread. - -Notice that we set the "daemon" flag for both threads that run the tasks. This -is because control-c will stop the progress and quit our application. We don't -want the application to wait for the background threads to finish. Whether you -want this depends on the application. - -.. code:: python - - from prompt_toolkit.shortcuts import ProgressBar - import time - import threading - - - with ProgressBar() as pb: - # Two parallel tasks. - def task_1(): - for i in pb(range(100)): - time.sleep(.05) - - def task_2(): - for i in pb(range(150)): - time.sleep(.08) - - # Start threads. - t1 = threading.Thread(target=task_1) - t2 = threading.Thread(target=task_2) - t1.daemon = True - t2.daemon = True - t1.start() - t2.start() - - # Wait for the threads to finish. We use a timeout for the join() call, - # because on Windows, join cannot be interrupted by Control-C or any other - # signal. - for t in [t1, t2]: - while t.is_alive(): - t.join(timeout=.5) - -.. image:: ../images/progress-bars/two-tasks.png - - -Adding a title and label ------------------------- - -Each progress bar can have one title, and for each task an individual label. -Both the title and the labels can be :ref:`formatted text <formatted_text>`. - -.. code:: python - - from prompt_toolkit.shortcuts import ProgressBar - from prompt_toolkit.formatted_text import HTML - import time - - title = HTML('Downloading <style bg="yellow" fg="black">4 files...</style>') - label = HTML('<ansired>some file</ansired>: ') - - with ProgressBar(title=title) as pb: - for i in pb(range(800), label=label): - time.sleep(.01) - -.. image:: ../images/progress-bars/colored-title-and-label.png - - -Formatting the progress bar ---------------------------- - -The visualisation of a :class:`~prompt_toolkit.shortcuts.ProgressBar` can be -customized by using a different sequence of formatters. The default formatting -looks something like this: - -.. code:: python - - from prompt_toolkit.shortcuts.progress_bar.formatters import * - - default_formatting = [ - Label(), - Text(' '), - Percentage(), - Text(' '), - Bar(), - Text(' '), - Progress(), - Text(' '), - Text('eta [', style='class:time-left'), - TimeLeft(), - Text(']', style='class:time-left'), - Text(' '), - ] - -That sequence of -:class:`~prompt_toolkit.shortcuts.progress_bar.formatters.Formatter` can be -passed to the `formatter` argument of -:class:`~prompt_toolkit.shortcuts.ProgressBar`. So, we could change this and -modify the progress bar to look like an apt-get style progress bar: - -.. code:: python - - from prompt_toolkit.shortcuts import ProgressBar - from prompt_toolkit.styles import Style - from prompt_toolkit.shortcuts.progress_bar import formatters - import time - - style = Style.from_dict({ - 'label': 'bg:#ffff00 #000000', - 'percentage': 'bg:#ffff00 #000000', - 'current': '#448844', - 'bar': '', - }) - - - custom_formatters = [ - formatters.Label(), - formatters.Text(': [', style='class:percentage'), - formatters.Percentage(), - formatters.Text(']', style='class:percentage'), - formatters.Text(' '), - formatters.Bar(sym_a='#', sym_b='#', sym_c='.'), - formatters.Text(' '), - ] - - with ProgressBar(style=style, formatters=custom_formatters) as pb: - for i in pb(range(1600), label='Installing'): - time.sleep(.01) - -.. image:: ../images/progress-bars/apt-get.png - - -Adding key bindings and toolbar -------------------------------- - -Like other prompt_toolkit applications, we can add custom key bindings, by -passing a :class:`~prompt_toolkit.key_binding.KeyBindings` object: - -.. code:: python - - from prompt_toolkit import HTML - from prompt_toolkit.key_binding import KeyBindings - from prompt_toolkit.patch_stdout import patch_stdout - from prompt_toolkit.shortcuts import ProgressBar - - import time - - bottom_toolbar = HTML(' <b>[f]</b> Print "f" <b>[x]</b> Abort.') - - # Create custom key bindings first. - kb = KeyBindings() - cancel = [False] - - @kb.add('f') - def _(event): - print('You pressed `f`.') - - @kb.add('x') - def _(event): - " Send Abort (control-c) signal. " - cancel[0] = True - os.kill(os.getpid(), signal.SIGINT) - - # Use `patch_stdout`, to make sure that prints go above the - # application. - with patch_stdout(): - with ProgressBar(key_bindings=kb, bottom_toolbar=bottom_toolbar) as pb: - for i in pb(range(800)): - time.sleep(.01) - - # Stop when the cancel flag has been set. - if cancel[0]: - break - -Notice that we use :func:`~prompt_toolkit.patch_stdout.patch_stdout` to make -printing text possible while the progress bar is displayed. This ensures that -printing happens above the progress bar. - -Further, when "x" is pressed, we set a cancel flag, which stops the progress. -It would also be possible to send `SIGINT` to the mean thread, but that's not -always considered a clean way of cancelling something. - -In the example above, we also display a toolbar at the bottom which shows the -key bindings. - -.. image:: ../images/progress-bars/custom-key-bindings.png - -:ref:`Read more about key bindings ...<key_bindings>` diff -Nru prompt-toolkit-3.0.5/docs/pages/reference.rst prompt-toolkit-3.0.6/docs/pages/reference.rst --- prompt-toolkit-3.0.5/docs/pages/reference.rst 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/reference.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,282 +0,0 @@ -Reference -========= - -Application ------------ - -.. automodule:: prompt_toolkit.application - :members: Application, get_app, set_app, NoRunningApplicationError, - DummyApplication, run_in_terminal, run_coroutine_in_terminal - - -Formatted text --------------- - -.. automodule:: prompt_toolkit.formatted_text - :members: - - -Buffer ------- - -.. automodule:: prompt_toolkit.buffer - :members: - - -Selection ---------- - -.. automodule:: prompt_toolkit.selection - :members: - - -Clipboard ---------- - -.. automodule:: prompt_toolkit.clipboard - :members: Clipboard, ClipboardData, DummyClipboard, DynamicClipboard, InMemoryClipboard - -.. automodule:: prompt_toolkit.clipboard.pyperclip - :members: - - -Auto completion ---------------- - -.. automodule:: prompt_toolkit.completion - :members: - - -Document --------- - -.. automodule:: prompt_toolkit.document - :members: - - -Enums ------ - -.. automodule:: prompt_toolkit.enums - :members: - - -History -------- - -.. automodule:: prompt_toolkit.history - :members: - - -Keys ----- - -.. automodule:: prompt_toolkit.keys - :members: - - -Style ------ - -.. automodule:: prompt_toolkit.styles - :members: Attrs, ANSI_COLOR_NAMES, BaseStyle, DummyStyle, DynamicStyle, - Style, Priority, merge_styles, style_from_pygments_cls, - style_from_pygments_dict, pygments_token_to_classname, NAMED_COLORS - -.. automodule:: prompt_toolkit.styles - :members: StyleTransformation, SwapLightAndDarkStyleTransformation, - AdjustBrightnessStyleTransformation, merge_style_transformations, - DummyStyleTransformation, ConditionalStyleTransformation, - DynamicStyleTransformation - - -Shortcuts ---------- - -.. automodule:: prompt_toolkit.shortcuts - :members: prompt, PromptSession, confirm, CompleteStyle, - create_confirm_session, clear, clear_title, print_formatted_text, - set_title, ProgressBar, input_dialog, message_dialog, progress_dialog, - radiolist_dialog, yes_no_dialog, button_dialog - -.. automodule:: prompt_toolkit.shortcuts.progress_bar.formatters - :members: - - -Validation ----------- - -.. automodule:: prompt_toolkit.validation - :members: - - -Auto suggestion ---------------- - -.. automodule:: prompt_toolkit.auto_suggest - :members: - - -Renderer --------- - -.. automodule:: prompt_toolkit.renderer - :members: - -Lexers ------- - -.. automodule:: prompt_toolkit.lexers - :members: - - -Layout ------- - -The layout class itself -^^^^^^^^^^^^^^^^^^^^^^^ - -.. automodule:: prompt_toolkit.layout - :members: Layout, InvalidLayoutError, walk - - -Containers -^^^^^^^^^^ - -.. automodule:: prompt_toolkit.layout - :members: Container, HSplit, VSplit, FloatContainer, Float, Window, - WindowAlign, ConditionalContainer, ScrollOffsets, ColorColumn, - to_container, to_window, is_container, HorizontalAlign, VerticalAlign - - -Controls -^^^^^^^^ - -.. automodule:: prompt_toolkit.layout - :members: BufferControl, SearchBufferControl, DummyControl, - FormattedTextControl, UIControl, UIContent - - -Other -^^^^^ - -.. automodule:: prompt_toolkit.layout - :members: Dimension, Margin, NumberedMargin, ScrollbarMargin, - ConditionalMargin, PromptMargin, CompletionsMenu, - MultiColumnCompletionsMenu - -.. automodule:: prompt_toolkit.layout.processors - :members: - -.. automodule:: prompt_toolkit.layout.utils - :members: - -.. automodule:: prompt_toolkit.layout.screen - :members: - - -Widgets -------- - -.. automodule:: prompt_toolkit.widgets - :members: TextArea, Label, Button, Frame, Shadow, Box, VerticalLine, - HorizontalLine, RadioList, Checkbox, ProgressBar, CompletionsToolbar, - FormattedTextToolbar, SearchToolbar, SystemToolbar, ValidationToolbar, - MenuContainer, MenuItem - - -Filters -------- - -.. automodule:: prompt_toolkit.filters - :members: - -.. autoclass:: prompt_toolkit.filters.Filter - :members: - -.. autoclass:: prompt_toolkit.filters.Condition - :members: - -.. automodule:: prompt_toolkit.filters.utils - :members: - -.. automodule:: prompt_toolkit.filters.app - :members: - - -Key binding ------------ - -.. automodule:: prompt_toolkit.key_binding - :members: KeyBindingsBase, KeyBindings, ConditionalKeyBindings, - merge_key_bindings, DynamicKeyBindings - -.. automodule:: prompt_toolkit.key_binding.defaults - :members: - -.. automodule:: prompt_toolkit.key_binding.vi_state - :members: - -.. automodule:: prompt_toolkit.key_binding.key_processor - :members: - - -Eventloop ---------- - -.. automodule:: prompt_toolkit.eventloop - :members: EventLoop, get_traceback_from_context, From, Return, - ensure_future, create_event_loop, create_asyncio_event_loop, - get_event_loop, set_event_loop, run_in_executor, call_from_executor, - run_until_complete, Future, InvalidStateError - -.. automodule:: prompt_toolkit.eventloop.posix - :members: - -.. automodule:: prompt_toolkit.eventloop.win32 - :members: - -.. automodule:: prompt_toolkit.eventloop.asyncio_win32 - :members: - -.. automodule:: prompt_toolkit.eventloop.asyncio_posix - :members: - - -Input ------ - -.. automodule:: prompt_toolkit.input - :members: Input, DummyInput, create_input, get_default_input, set_default_input - -.. automodule:: prompt_toolkit.input.vt100 - :members: - -.. automodule:: prompt_toolkit.input.vt100_parser - :members: - -.. automodule:: prompt_toolkit.input.ansi_escape_sequences - :members: - -.. automodule:: prompt_toolkit.input.win32 - :members: - -Output ------- - -.. automodule:: prompt_toolkit.output - :members: Output, DummyOutput, ColorDepth, create_output, - get_default_output, set_default_output - -.. automodule:: prompt_toolkit.output.vt100 - :members: - -.. automodule:: prompt_toolkit.output.win32 - :members: - - -Patch stdout ------------- - -.. automodule:: prompt_toolkit.patch_stdout - :members: patch_stdout, StdoutProxy diff -Nru prompt-toolkit-3.0.5/docs/pages/tutorials/index.rst prompt-toolkit-3.0.6/docs/pages/tutorials/index.rst --- prompt-toolkit-3.0.5/docs/pages/tutorials/index.rst 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/tutorials/index.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -.. _tutorials: - -Tutorials -========= - -.. toctree:: - :caption: Contents: - :maxdepth: 1 - - repl diff -Nru prompt-toolkit-3.0.5/docs/pages/tutorials/repl.rst prompt-toolkit-3.0.6/docs/pages/tutorials/repl.rst --- prompt-toolkit-3.0.5/docs/pages/tutorials/repl.rst 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/tutorials/repl.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,341 +0,0 @@ -.. _tutorial_repl: - -Tutorial: Build an SQLite REPL -============================== - -The aim of this tutorial is to build an interactive command line interface for -an SQLite database using prompt_toolkit_. - -First, install the library using pip, if you haven't done this already. - -.. code:: - - pip install prompt_toolkit - - -Read User Input ---------------- - -Let's start accepting input using the -:func:`~prompt_toolkit.shortcuts.prompt()` function. This will ask the user for -input, and echo back whatever the user typed. We wrap it in a ``main()`` -function as a good practise. - -.. code:: python - - from prompt_toolkit import prompt - - def main(): - text = prompt('> ') - print('You entered:', text) - - if __name__ == '__main__': - main() - -.. image:: ../../images/repl/sqlite-1.png - - -Loop The REPL -------------- - -Now we want to call the :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` -method in a loop. In order to keep the history, the easiest way to do it is to -use a :class:`~prompt_toolkit.shortcuts.PromptSession`. This uses an -:class:`~prompt_toolkit.history.InMemoryHistory` underneath that keeps track of -the history, so that if the user presses the up-arrow, he'll see the previous -entries. - -The :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` method raises -``KeyboardInterrupt`` when ControlC has been pressed and ``EOFError`` when -ControlD has been pressed. This is what people use for cancelling commands and -exiting in a REPL. The try/except below handles these error conditions and make -sure that we go to the next iteration of the loop or quit the loop -respectively. - -.. code:: python - - from prompt_toolkit import PromptSession - - def main(): - session = PromptSession() - - while True: - try: - text = session.prompt('> ') - except KeyboardInterrupt: - continue - except EOFError: - break - else: - print('You entered:', text) - print('GoodBye!') - - if __name__ == '__main__': - main() - -.. image:: ../../images/repl/sqlite-2.png - - -Syntax Highlighting -------------------- - -This is where things get really interesting. Let's step it up a notch by adding -syntax highlighting to the user input. We know that users will be entering SQL -statements, so we can leverage the Pygments_ library for coloring the input. -The ``lexer`` parameter allows us to set the syntax lexer. We're going to use -the ``SqlLexer`` from the Pygments_ library for highlighting. - -Notice that in order to pass a Pygments lexer to prompt_toolkit, it needs to be -wrapped into a :class:`~prompt_toolkit.lexers.PygmentsLexer`. - -.. code:: python - - from prompt_toolkit import PromptSession - from prompt_toolkit.lexers import PygmentsLexer - from pygments.lexers.sql import SqlLexer - - def main(): - session = PromptSession(lexer=PygmentsLexer(SqlLexer)) - - while True: - try: - text = session.prompt('> ') - except KeyboardInterrupt: - continue - except EOFError: - break - else: - print('You entered:', text) - print('GoodBye!') - - if __name__ == '__main__': - main() - -.. image:: ../../images/repl/sqlite-3.png - - -Auto-completion ---------------- - -Now we are going to add auto completion. We'd like to display a drop down menu -of `possible keywords <https://www.sqlite.org/lang_keywords.html>`_ when the -user starts typing. - -We can do this by creating an `sql_completer` object from the -:class:`~prompt_toolkit.completion.WordCompleter` class, defining a set of -`keywords` for the auto-completion. - -Like the lexer, this ``sql_completer`` instance can be passed to either the -:class:`~prompt_toolkit.shortcuts.PromptSession` class or the -:meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` method. - -.. code:: python - - from prompt_toolkit import PromptSession - from prompt_toolkit.completion import WordCompleter - from prompt_toolkit.lexers import PygmentsLexer - from pygments.lexers.sql import SqlLexer - - sql_completer = WordCompleter([ - 'abort', 'action', 'add', 'after', 'all', 'alter', 'analyze', 'and', - 'as', 'asc', 'attach', 'autoincrement', 'before', 'begin', 'between', - 'by', 'cascade', 'case', 'cast', 'check', 'collate', 'column', - 'commit', 'conflict', 'constraint', 'create', 'cross', 'current_date', - 'current_time', 'current_timestamp', 'database', 'default', - 'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct', - 'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive', - 'exists', 'explain', 'fail', 'for', 'foreign', 'from', 'full', 'glob', - 'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index', - 'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect', - 'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit', - 'match', 'natural', 'no', 'not', 'notnull', 'null', 'of', 'offset', - 'on', 'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query', - 'raise', 'recursive', 'references', 'regexp', 'reindex', 'release', - 'rename', 'replace', 'restrict', 'right', 'rollback', 'row', - 'savepoint', 'select', 'set', 'table', 'temp', 'temporary', 'then', - 'to', 'transaction', 'trigger', 'union', 'unique', 'update', 'using', - 'vacuum', 'values', 'view', 'virtual', 'when', 'where', 'with', - 'without'], ignore_case=True) - - def main(): - session = PromptSession( - lexer=PygmentsLexer(SqlLexer), completer=sql_completer) - - while True: - try: - text = session.prompt('> ') - except KeyboardInterrupt: - continue - except EOFError: - break - else: - print('You entered:', text) - print('GoodBye!') - - if __name__ == '__main__': - main() - -.. image:: ../../images/repl/sqlite-4.png - -In about 30 lines of code we got ourselves an auto completing, syntax -highlighting REPL. Let's make it even better. - - -Styling the menus ------------------ - -If we want, we can now change the colors of the completion menu. This is -possible by creating a :class:`~prompt_toolkit.styles.Style` instance and -passing it to the :meth:`~prompt_toolkit.shortcuts.PromptSession.prompt` -function. - -.. code:: python - - from prompt_toolkit import PromptSession - from prompt_toolkit.completion import WordCompleter - from prompt_toolkit.lexers import PygmentsLexer - from prompt_toolkit.styles import Style - from pygments.lexers.sql import SqlLexer - - sql_completer = WordCompleter([ - 'abort', 'action', 'add', 'after', 'all', 'alter', 'analyze', 'and', - 'as', 'asc', 'attach', 'autoincrement', 'before', 'begin', 'between', - 'by', 'cascade', 'case', 'cast', 'check', 'collate', 'column', - 'commit', 'conflict', 'constraint', 'create', 'cross', 'current_date', - 'current_time', 'current_timestamp', 'database', 'default', - 'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct', - 'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive', - 'exists', 'explain', 'fail', 'for', 'foreign', 'from', 'full', 'glob', - 'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index', - 'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect', - 'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit', - 'match', 'natural', 'no', 'not', 'notnull', 'null', 'of', 'offset', - 'on', 'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query', - 'raise', 'recursive', 'references', 'regexp', 'reindex', 'release', - 'rename', 'replace', 'restrict', 'right', 'rollback', 'row', - 'savepoint', 'select', 'set', 'table', 'temp', 'temporary', 'then', - 'to', 'transaction', 'trigger', 'union', 'unique', 'update', 'using', - 'vacuum', 'values', 'view', 'virtual', 'when', 'where', 'with', - 'without'], ignore_case=True) - - style = Style.from_dict({ - 'completion-menu.completion': 'bg:#008888 #ffffff', - 'completion-menu.completion.current': 'bg:#00aaaa #000000', - 'scrollbar.background': 'bg:#88aaaa', - 'scrollbar.button': 'bg:#222222', - }) - - def main(): - session = PromptSession( - lexer=PygmentsLexer(SqlLexer), completer=sql_completer, style=style) - - while True: - try: - text = session.prompt('> ') - except KeyboardInterrupt: - continue - except EOFError: - break - else: - print('You entered:', text) - print('GoodBye!') - - if __name__ == '__main__': - main() - -.. image:: ../../images/repl/sqlite-5.png - -All that's left is hooking up the sqlite backend, which is left as an exercise -for the reader. Just kidding... Keep reading. - - -Hook up Sqlite --------------- - -This step is the final step to make the SQLite REPL actually work. It's time -to relay the input to SQLite. - -Obviously I haven't done the due diligence to deal with the errors. But it -gives a good idea of how to get started. - -.. code:: python - - #!/usr/bin/env python - import sys - import sqlite3 - - from prompt_toolkit import PromptSession - from prompt_toolkit.completion import WordCompleter - from prompt_toolkit.lexers import PygmentsLexer - from prompt_toolkit.styles import Style - from pygments.lexers.sql import SqlLexer - - sql_completer = WordCompleter([ - 'abort', 'action', 'add', 'after', 'all', 'alter', 'analyze', 'and', - 'as', 'asc', 'attach', 'autoincrement', 'before', 'begin', 'between', - 'by', 'cascade', 'case', 'cast', 'check', 'collate', 'column', - 'commit', 'conflict', 'constraint', 'create', 'cross', 'current_date', - 'current_time', 'current_timestamp', 'database', 'default', - 'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct', - 'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive', - 'exists', 'explain', 'fail', 'for', 'foreign', 'from', 'full', 'glob', - 'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index', - 'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect', - 'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit', - 'match', 'natural', 'no', 'not', 'notnull', 'null', 'of', 'offset', - 'on', 'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query', - 'raise', 'recursive', 'references', 'regexp', 'reindex', 'release', - 'rename', 'replace', 'restrict', 'right', 'rollback', 'row', - 'savepoint', 'select', 'set', 'table', 'temp', 'temporary', 'then', - 'to', 'transaction', 'trigger', 'union', 'unique', 'update', 'using', - 'vacuum', 'values', 'view', 'virtual', 'when', 'where', 'with', - 'without'], ignore_case=True) - - style = Style.from_dict({ - 'completion-menu.completion': 'bg:#008888 #ffffff', - 'completion-menu.completion.current': 'bg:#00aaaa #000000', - 'scrollbar.background': 'bg:#88aaaa', - 'scrollbar.button': 'bg:#222222', - }) - - def main(database): - connection = sqlite3.connect(database) - session = PromptSession( - lexer=PygmentsLexer(SqlLexer), completer=sql_completer, style=style) - - while True: - try: - text = session.prompt('> ') - except KeyboardInterrupt: - continue # Control-C pressed. Try again. - except EOFError: - break # Control-D pressed. - - with connection: - try: - messages = connection.execute(text) - except Exception as e: - print(repr(e)) - else: - for message in messages: - print(message) - - print('GoodBye!') - - if __name__ == '__main__': - if len(sys.argv) < 2: - db = ':memory:' - else: - db = sys.argv[1] - - main(db) - -.. image:: ../../images/repl/sqlite-6.png - -I hope that gives an idea of how to get started on building command line -interfaces. - -The End. - -.. _prompt_toolkit: https://github.com/jonathanslenders/python-prompt-toolkit -.. _Pygments: http://pygments.org/ diff -Nru prompt-toolkit-3.0.5/docs/pages/upgrading/2.0.rst prompt-toolkit-3.0.6/docs/pages/upgrading/2.0.rst --- prompt-toolkit-3.0.5/docs/pages/upgrading/2.0.rst 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/upgrading/2.0.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,221 +0,0 @@ -.. _upgrading_2_0: - -Upgrading to prompt_toolkit 2.0 -=============================== - -Prompt_toolkit 2.0 is not compatible with 1.0, however you probably want to -upgrade your applications. This page explains why we have these differences and -how to upgrade. - -If you experience some difficulties or you feel that some information is -missing from this page, don't hesitate to open a GitHub issue for help. - - -Why all these breaking changes? -------------------------------- - -After more and more custom prompt_toolkit applications were developed, it -became clear that prompt_toolkit 1.0 was not flexible enough for certain use -cases. Mostly, the development of full screen applications was not really -natural. All the important components, like the rendering, key bindings, input -and output handling were present, but the API was in the first place designed -for simple command line prompts. This was mostly notably in the following two -places: - -- First, there was the focus which was always pointing to a - :class:`~prompt_toolkit.buffer.Buffer` (or text input widget), but in full - screen applications there are other widgets, like menus and buttons which - can be focused. -- And secondly, it was impossible to make reusable UI components. All the key - bindings for the entire applications were stored together in one - ``KeyBindings`` object, and similar, all - :class:`~prompt_toolkit.buffer.Buffer` objects were stored together in one - dictionary. This didn't work well. You want reusable components to define - their own key bindings and everything. It's the idea of encapsulation. - -For simple prompts, the changes wouldn't be that invasive, but given that there -would be some, I took the opportunity to fix a couple of other things. For -instance: - -- In prompt_toolkit 1.0, we translated `\\r` into `\\n` during the input - processing. This was not a good idea, because some people wanted to handle - these keys individually. This makes sense if you keep in mind that they - correspond to `Control-M` and `Control-J`. However, we couldn't fix this - without breaking everyone's enter key, which happens to be the most important - key in prompts. - -Given that we were going to break compatibility anyway, we changed a couple of -other important things that effect both simple prompt applications and -full screen applications. These are the most important: - -- We no longer depend on Pygments for styling. While we like Pygments, it was - not flexible enough to provide all the styling options that we need, and the - Pygments tokens were not ideal for styling anything besides tokenized text. - - Instead we created something similar to CSS. All UI components can attach - classnames to themselves, as well as define an inline style. The final style is - then computed by combining the inline styles, the classnames and the style - sheet. - - There are still adaptors available for using Pygments lexers as well as for - Pygments styles. - -- The way that key bindings were defined was too complex. - ``KeyBindingsManager`` was too complex and no longer exists. Every set of key - bindings is now a - :class:`~prompt_toolkit.key_binding.KeyBindings` object and multiple of these - can be merged together at any time. The runtime performance remains the same, - but it's now easier for users. - -- The separation between the ``CommandLineInterface`` and - :class:`~prompt_toolkit.application.Application` class was confusing and in - the end, didn't really had an advantage. These two are now merged together in - one :class:`~prompt_toolkit.application.Application` class. - -- We no longer pass around the active ``CommandLineInterface``. This was one of - the most annoying things. Key bindings need it in order to change anything - and filters need it in order to evaluate their state. It was pretty annoying, - especially because there was usually only one application active at a time. - So, :class:`~prompt_toolkit.application.Application` became a ``TaskLocal``. - That is like a global variable, but scoped in the current coroutine or - context. The way this works is still not 100% correct, but good enough for - the projects that need it (like Pymux), and hopefully Python will get support - for this in the future thanks to PEP521, PEP550 or PEP555. - -All of these changes have been tested for many months, and I can say with -confidence that prompt_toolkit 2.0 is a better prompt_toolkit. - - -Some new features ------------------ - -Apart from the breaking changes above, there are also some exciting new -features. - -- We now support vt100 escape codes for Windows consoles on Windows 10. This - means much faster rendering, and full color support. - -- We have a concept of formatted text. This is an object that evaluates to - styled text. Every input that expects some text, like the message in a - prompt, or the text in a toolbar, can take any kind of formatted text as input. - This means you can pass in a plain string, but also a list of `(style, - text)` tuples (similar to a Pygments tokenized string), or an - :class:`~prompt_toolkit.formatted_text.HTML` object. This simplifies many - APIs. - -- New utilities were added. We now have function for printing formatted text - and an experimental module for displaying progress bars. - -- Autocompletion, input validation, and auto suggestion can now either be - asynchronous or synchronous. By default they are synchronous, but by wrapping - them in :class:`~prompt_toolkit.completion.ThreadedCompleter`, - :class:`~prompt_toolkit.validation.ThreadedValidator` or - :class:`~prompt_toolkit.auto_suggest.ThreadedAutoSuggest`, they will become - asynchronous by running in a background thread. - - Further, if the autocompletion code runs in a background thread, we will show - the completions as soon as they arrive. This means that the autocompletion - algorithm could for instance first yield the most trivial completions and then - take time to produce the completions that take more time. - - -Upgrading ---------- - -More guidelines on how to upgrade will follow. - - -`AbortAction` has been removed -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Prompt_toolkit 1.0 had an argument ``abort_action`` for both the -``Application`` class as well as for the ``prompt`` function. This has been -removed. The recommended way to handle this now is by capturing -``KeyboardInterrupt`` and ``EOFError`` manually. - - -Calling `create_eventloop` usually not required anymore -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Prompt_toolkit 2.0 will automatically create the appropriate event loop when -it's needed for the first time. There is no need to create one and pass it -around. If you want to run an application on top of asyncio (without using an -executor), it still needs to be activated by calling -:func:`~prompt_toolkit.eventloop.use_asyncio_event_loop` at the beginning. - - -Pygments styles and tokens -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -prompt_toolkit 2.0 no longer depends on `Pygments <http://pygments.org/>`_, but -that definitely doesn't mean that you can't use any Pygments functionality -anymore. The only difference is that Pygments stuff needs to be wrapped in an -adaptor to make it compatible with the native prompt_toolkit objects. - -- For instance, if you have a list of ``(pygments.Token, text)`` tuples for - formatting, then this needs to be wrapped in a - :class:`~prompt_toolkit.formatted_text.PygmentsTokens` object. This is an - adaptor that turns it into prompt_toolkit "formatted text". Feel free to keep - using this. - -- Pygments lexers need to be wrapped in a - :class:`~prompt_toolkit.lexers.PygmentsLexer`. This will convert the list of - Pygments tokens into prompt_toolkit formatted text. - -- If you have a Pygments style, then this needs to be converted as well. A - Pygments style class can be converted in a prompt_toolkit - :class:`~prompt_toolkit.styles.Style` with the - :func:`~prompt_toolkit.styles.pygments.style_from_pygments_cls` function - (which used to be called ``style_from_pygments``). A Pygments style - dictionary can be converted using - :func:`~prompt_toolkit.styles.pygments.style_from_pygments_dict`. - - Multiple styles can be merged together using - :func:`~prompt_toolkit.styles.merge_styles`. - - -Wordcompleter -^^^^^^^^^^^^^ - -`WordCompleter` was moved from -:class:`prompt_toolkit.contrib.completers.base.WordCompleter` to -:class:`prompt_toolkit.completion.word_completer.WordCompleter`. - - -Asynchronous autocompletion -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -By default, prompt_toolkit 2.0 completion is now synchronous. If you still want -asynchronous auto completion (which is often good thing), then you have to wrap -the completer in a :class:`~prompt_toolkit.completion.ThreadedCompleter`. - - -Filters -^^^^^^^ - -We don't distiguish anymore between `CLIFilter` and `SimpleFilter`, because the -application object is no longer passed around. This means that all filters are -a `Filter` from now on. - -All filters have been turned into functions. For instance, `IsDone` became -`is_done` and `HasCompletions` became `has_completions`. - -This was done because almost all classes were called without any arguments in -the `__init__` causing additional braces everywhere. This means that -`HasCompletions()` has to be replaced by `has_completions` (without -parenthesis). - -The few filters that took arguments as input, became functions, but still have -to be called with the given arguments. - -For new filters, it is recommended to use the `@Condition` decorator, -rather then inheriting from `Filter`. For instance: - -.. code:: python - - from prompt_toolkit.filters import Condition - - @Condition - def my_filter(); - return True # Or False - diff -Nru prompt-toolkit-3.0.5/docs/pages/upgrading/3.0.rst prompt-toolkit-3.0.6/docs/pages/upgrading/3.0.rst --- prompt-toolkit-3.0.5/docs/pages/upgrading/3.0.rst 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/upgrading/3.0.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -.. _upgrading_3_0: - -Upgrading to prompt_toolkit 3.0 -=============================== - -There are two major changes in 3.0 to be aware of: - -- First, prompt_toolkit uses the asyncio event loop natively, rather then using - its own implementations of event loops. This means that all coroutines are - now asyncio coroutines, and all Futures are asyncio futures. Asynchronous - generators became real asynchronous generators as well. - -- Prompt_toolkit uses type annotations (almost) everywhere. This should not - break any code, but its very helpful in many ways. - -There are some minor breaking changes: - -- The dialogs API had to change (see below). - - -Detecting the prompt_toolkit version ------------------------------------- - -Detecting whether version 3 is being used can be done as follows: - -.. code:: python - - from prompt_toolkit import __version__ as ptk_version - - PTK3 = ptk_version.startswith('3.') - - -Fixing calls to `get_event_loop` --------------------------------- - -Every usage of ``get_event_loop`` has to be fixed. An easy way to do this is by -changing the imports like this: - -.. code:: python - - if PTK3: - from asyncio import get_event_loop - else: - from prompt_toolkit.eventloop import get_event_loop - -Notice that for prompt_toolkit 2.0, ``get_event_loop`` returns a prompt_toolkit -``EventLoop`` object. This is not an asyncio eventloop, but the API is -similar. - -There are some changes to the eventloop API: - -+-----------------------------------+--------------------------------------+ -| version 2.0 | version 3.0 (asyncio) | -+===================================+======================================+ -| loop.run_in_executor(callback) | loop.run_in_executor(None, callback) | -+-----------------------------------+--------------------------------------+ -| loop.call_from_executor(callback) | loop.call_soon_threadsafe(callback) | -+-----------------------------------+--------------------------------------+ - - -Running on top of asyncio -------------------------- - -For 2.0, you had tell prompt_toolkit to run on top of the asyncio event loop. -Now it's the default. So, you can simply remove the following two lines: - -.. code:: - - from prompt_toolkit.eventloop.defaults import use_asyncio_event_loop - use_asyncio_event_loop() - -There is a few little breaking changes though. The following: - -.. code:: - - # For 2.0 - result = await PromptSession().prompt('Say something: ', async_=True) - -has to be changed into: - -.. code:: - - # For 3.0 - result = await PromptSession().prompt_async('Say something: ') - -Further, it's impossible to call the `prompt()` function within an asyncio -application (within a coroutine), because it will try to run the event loop -again. In that case, always use `prompt_async()`. - - -Changes to the dialog functions -------------------------------- - -The original way of using dialog boxes looked like this: - -.. code:: python - - from prompt_toolkit.shortcuts import input_dialog - - result = input_dialog(title='...', text='...') - -Now, the dialog functions return a prompt_toolkit Application object. You have -to call either its ``run`` or ``run_async`` method to display the dialog. The -``async_`` parameter has been removed everywhere. - -.. code:: python - - if PTK3: - result = input_dialog(title='...', text='...').run() - else: - result = input_dialog(title='...', text='...') - - # Or - - if PTK3: - result = await input_dialog(title='...', text='...').run_async() - else: - result = await input_dialog(title='...', text='...', async_=True) diff -Nru prompt-toolkit-3.0.5/docs/pages/upgrading/index.rst prompt-toolkit-3.0.6/docs/pages/upgrading/index.rst --- prompt-toolkit-3.0.5/docs/pages/upgrading/index.rst 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/docs/pages/upgrading/index.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -.. _upgrading: - -Upgrading -========= - -.. toctree:: - :caption: Contents: - :maxdepth: 1 - - 2.0 - 3.0 diff -Nru prompt-toolkit-3.0.5/examples/gevent-get-input.py prompt-toolkit-3.0.6/examples/gevent-get-input.py --- prompt-toolkit-3.0.5/examples/gevent-get-input.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/examples/gevent-get-input.py 2020-08-01 20:16:17.000000000 +0000 @@ -4,6 +4,7 @@ patches are applied. """ from gevent.monkey import patch_all + from prompt_toolkit.eventloop.defaults import create_event_loop from prompt_toolkit.shortcuts import PromptSession diff -Nru prompt-toolkit-3.0.5/examples/prompts/fancy-zsh-prompt.py prompt-toolkit-3.0.6/examples/prompts/fancy-zsh-prompt.py --- prompt-toolkit-3.0.5/examples/prompts/fancy-zsh-prompt.py 1970-01-01 00:00:00.000000000 +0000 +++ prompt-toolkit-3.0.6/examples/prompts/fancy-zsh-prompt.py 2020-07-31 10:42:29.000000000 +0000 @@ -0,0 +1,79 @@ +#!/usr/bin/env python +""" +Example of the fancy ZSH prompt that @anki-code was using. + +The theme is coming from the xonsh plugin from the xhh project: +https://github.com/xxh/xxh-plugin-xonsh-theme-bar + +See: +- https://github.com/xonsh/xonsh/issues/3356 +- https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1111 +""" +import datetime + +from prompt_toolkit import prompt +from prompt_toolkit.application import get_app +from prompt_toolkit.formatted_text import ( + HTML, + fragment_list_width, + merge_formatted_text, + to_formatted_text, +) +from prompt_toolkit.styles import Style + +style = Style.from_dict( + { + "username": "#aaaaaa italic", + "path": "#ffffff bold", + "branch": "bg:#666666", + "branch exclamation-mark": "#ff0000", + "env": "bg:#666666", + "left-part": "bg:#444444", + "right-part": "bg:#444444", + "padding": "bg:#444444", + } +) + + +def get_prompt() -> HTML: + """ + Build the prompt dynamically every time its rendered. + """ + left_part = HTML( + "<left-part>" + " <username>root</username> " + " abc " + "<path>~/.oh-my-zsh/themes</path>" + "</left-part>" + ) + right_part = HTML( + "<right-part> " + "<branch> master<exclamation-mark>!</exclamation-mark> </branch> " + " <env> py36 </env> " + " <time>%s</time> " + "</right-part>" + ) % (datetime.datetime.now().isoformat(),) + + used_width = sum( + [ + fragment_list_width(to_formatted_text(left_part)), + fragment_list_width(to_formatted_text(right_part)), + ] + ) + + total_width = get_app().output.get_size().columns + padding_size = total_width - used_width + + padding = HTML("<padding>%s</padding>") % (" " * padding_size,) + + return merge_formatted_text([left_part, padding, right_part, "\n", "# "]) + + +def main() -> None: + while True: + answer = prompt(get_prompt, style=style, refresh_interval=1) + print("You said: %s" % answer) + + +if __name__ == "__main__": + main() diff -Nru prompt-toolkit-3.0.5/examples/prompts/inputhook.py prompt-toolkit-3.0.6/examples/prompts/inputhook.py --- prompt-toolkit-3.0.5/examples/prompts/inputhook.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/examples/prompts/inputhook.py 2020-08-01 20:16:17.000000000 +0000 @@ -11,10 +11,10 @@ `InputHookContext.input_is_ready()`. Another way is to check for `InputHookContext.fileno()` to be ready. In this example we do the latter. """ -from pygments.lexers.python import PythonLexer - import gobject import gtk +from pygments.lexers.python import PythonLexer + from prompt_toolkit.eventloop.defaults import create_event_loop from prompt_toolkit.lexers import PygmentsLexer from prompt_toolkit.patch_stdout import patch_stdout diff -Nru prompt-toolkit-3.0.5/examples/ssh/asyncssh-server.py prompt-toolkit-3.0.6/examples/ssh/asyncssh-server.py --- prompt-toolkit-3.0.5/examples/ssh/asyncssh-server.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/examples/ssh/asyncssh-server.py 2020-08-01 20:16:17.000000000 +0000 @@ -9,7 +9,7 @@ from pygments.lexers.html import HtmlLexer from prompt_toolkit.completion import WordCompleter -from prompt_toolkit.contrib.ssh import PromptToolkitSSHServer +from prompt_toolkit.contrib.ssh import PromptToolkitSSHServer, PromptToolkitSSHSession from prompt_toolkit.lexers import PygmentsLexer from prompt_toolkit.shortcuts import ProgressBar, print_formatted_text from prompt_toolkit.shortcuts.dialogs import input_dialog, yes_no_dialog @@ -54,7 +54,7 @@ ) -async def interact() -> None: +async def interact(ssh_session: PromptToolkitSSHSession) -> None: """ The application interaction. diff -Nru prompt-toolkit-3.0.5/examples/tutorial/README.md prompt-toolkit-3.0.6/examples/tutorial/README.md --- prompt-toolkit-3.0.5/examples/tutorial/README.md 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/examples/tutorial/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -See http://python-prompt-toolkit.readthedocs.io/en/stable/pages/tutorials/repl.html diff -Nru prompt-toolkit-3.0.5/.gitignore prompt-toolkit-3.0.6/.gitignore --- prompt-toolkit-3.0.5/.gitignore 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -*.py[cod] - -# C extensions -*.so - -# Packages -*.egg -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs -.installed.cfg -lib -lib64 -__pycache__ - -# Python 3rd Party -Pipfile* - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox -nosetests.xml -.pytest_cache - -# Translations -*.mo - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# Generated documentation -docs/_build - -# pycharm metadata -.idea diff -Nru prompt-toolkit-3.0.5/mypy.ini prompt-toolkit-3.0.6/mypy.ini --- prompt-toolkit-3.0.5/mypy.ini 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/mypy.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -[mypy] -ignore_missing_imports = True -no_implicit_optional = True -platform = win32 -strict_equality = True -strict_optional = True diff -Nru prompt-toolkit-3.0.5/PKG-INFO prompt-toolkit-3.0.6/PKG-INFO --- prompt-toolkit-3.0.5/PKG-INFO 2020-03-26 08:06:11.000000000 +0000 +++ prompt-toolkit-3.0.6/PKG-INFO 2020-08-10 09:54:46.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: prompt_toolkit -Version: 3.0.5 +Version: 3.0.6 Summary: Library for building powerful interactive command lines in Python Home-page: https://github.com/prompt-toolkit/python-prompt-toolkit Author: Jonathan Slenders @@ -171,6 +171,7 @@ Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python Classifier: Topic :: Software Development diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/application/application.py prompt-toolkit-3.0.6/prompt_toolkit/application/application.py --- prompt-toolkit-3.0.5/prompt_toolkit/application/application.py 2020-03-06 06:53:18.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/application/application.py 2020-08-06 10:13:52.000000000 +0000 @@ -15,6 +15,7 @@ set_event_loop, sleep, ) +from contextlib import contextmanager from subprocess import Popen from traceback import format_tb from typing import ( @@ -23,6 +24,7 @@ Callable, Dict, FrozenSet, + Generator, Generic, Hashable, Iterable, @@ -103,6 +105,9 @@ _AppResult = TypeVar("_AppResult") ApplicationEventHandler = Callable[["Application[_AppResult]"], None] +_SIGWINCH = getattr(signal, "SIGWINCH", None) +_SIGTSTP = getattr(signal, "SIGTSTP", None) + class Application(Generic[_AppResult]): """ @@ -156,7 +161,7 @@ don't want this for the implementation of a REPL. By default, this is enabled if `full_screen` is set. - Callbacks (all of these should accept a + Callbacks (all of these should accept an :class:`~prompt_toolkit.application.Application` object as input.) :param on_reset: Called during reset. @@ -361,15 +366,23 @@ @property def color_depth(self) -> ColorDepth: """ - Active :class:`.ColorDepth`. + The active :class:`.ColorDepth`. + + The current value is determined as follows: + - If a color depth was given explicitely to this application, use that + value. + - Otherwise, fall back to the color depth that is reported by the + :class:`.Output` implementation. If the :class:`.Output` class was + created using `output.defaults.create_output`, then this value is + coming from the $PROMPT_TOOLKIT_COLOR_DEPTH environment variable. """ depth = self._color_depth if callable(depth): - return depth() or ColorDepth.default() + depth = depth() if depth is None: - return ColorDepth.default() + depth = self.output.get_default_color_depth() return depth @@ -678,64 +691,55 @@ if self.input.closed: f.set_exception(EOFError) - # Enter raw mode. - with self.input.raw_mode(): - with self.input.attach(read_from_input): - # Draw UI. - self._request_absolute_cursor_position() - self._redraw() - self._start_auto_refresh_task() - - has_sigwinch = hasattr(signal, "SIGWINCH") and in_main_thread() - if has_sigwinch: - previous_winch_handler = signal.getsignal(signal.SIGWINCH) - loop.add_signal_handler(signal.SIGWINCH, self._on_resize) - - # Wait for UI to finish. + # Enter raw mode, attach input and attach WINCH event handler. + with self.input.raw_mode(), self.input.attach( + read_from_input + ), attach_winch_signal_handler(self._on_resize): + # Draw UI. + self._request_absolute_cursor_position() + self._redraw() + self._start_auto_refresh_task() + + # Wait for UI to finish. + try: + result = await f + finally: + # In any case, when the application finishes. + # (Successful, or because of an error.) try: - result = await f + self._redraw(render_as_done=True) finally: - # In any case, when the application finishes. (Successful, - # or because of an error.) - try: - self._redraw(render_as_done=True) - finally: - # _redraw has a good chance to fail if it calls widgets - # with bad code. Make sure to reset the renderer anyway. - self.renderer.reset() - - # Unset `is_running`, this ensures that possibly - # scheduled draws won't paint during the following - # yield. - self._is_running = False - - # Detach event handlers for invalidate events. - # (Important when a UIControl is embedded in - # multiple applications, like ptterm in pymux. An - # invalidate should not trigger a repaint in - # terminated applications.) - for ev in self._invalidate_events: - ev -= self._invalidate_handler - self._invalidate_events = [] - - # Wait for CPR responses. - if self.input.responds_to_cpr: - await self.renderer.wait_for_cpr_responses() - - if has_sigwinch: - loop.remove_signal_handler(signal.SIGWINCH) - signal.signal(signal.SIGWINCH, previous_winch_handler) - - # Wait for the run-in-terminals to terminate. - previous_run_in_terminal_f = self._running_in_terminal_f - - if previous_run_in_terminal_f: - await previous_run_in_terminal_f - - # Store unprocessed input as typeahead for next time. - store_typeahead( - self.input, self.key_processor.empty_queue() - ) + # _redraw has a good chance to fail if it calls widgets + # with bad code. Make sure to reset the renderer + # anyway. + self.renderer.reset() + + # Unset `is_running`, this ensures that possibly + # scheduled draws won't paint during the following + # yield. + self._is_running = False + + # Detach event handlers for invalidate events. + # (Important when a UIControl is embedded in multiple + # applications, like ptterm in pymux. An invalidate + # should not trigger a repaint in terminated + # applications.) + for ev in self._invalidate_events: + ev -= self._invalidate_handler + self._invalidate_events = [] + + # Wait for CPR responses. + if self.input.responds_to_cpr: + await self.renderer.wait_for_cpr_responses() + + # Wait for the run-in-terminals to terminate. + previous_run_in_terminal_f = self._running_in_terminal_f + + if previous_run_in_terminal_f: + await previous_run_in_terminal_f + + # Store unprocessed input as typeahead for next time. + store_typeahead(self.input, self.key_processor.empty_queue()) return result @@ -990,18 +994,18 @@ """ # Only suspend when the operating system supports it. # (Not on Windows.) - if hasattr(signal, "SIGTSTP"): + if _SIGTSTP is not None: def run() -> None: - # Send `SIGSTP` to own process. + # Send `SIGTSTP` to own process. # This will cause it to suspend. # Usually we want the whole process group to be suspended. This # handles the case when input is piped from another process. if suspend_group: - os.kill(0, signal.SIGTSTP) + os.kill(0, _SIGTSTP) else: - os.kill(os.getpid(), signal.SIGTSTP) + os.kill(os.getpid(), _SIGTSTP) run_in_terminal(run) @@ -1172,3 +1176,48 @@ message=wait_text, key_bindings=key_bindings ) await session.app.run_async() + + +@contextmanager +def attach_winch_signal_handler( + handler: Callable[[], None] +) -> Generator[None, None, None]: + """ + Attach the given callback as a WINCH signal handler within the context + manager. Restore the original signal handler when done. + + The `Application.run` method will register SIGWINCH, so that it will + properly repaint when the terminal window resizes. However, using + `run_in_terminal`, we can temporarily send an application to the + background, and run an other app in between, which will then overwrite the + SIGWINCH. This is why it's important to restore the handler when the app + terminates. + """ + # The tricky part here is that signals are registered in the Unix event + # loop with a wakeup fd, but another application could have registered + # signals using signal.signal directly. For now, the implementation is + # hard-coded for the `asyncio.unix_events._UnixSelectorEventLoop`. + + # No WINCH? Then don't do anything. + sigwinch = getattr(signal, "SIGWINCH", None) + if sigwinch is None or not in_main_thread(): + yield + return + + # Keep track of the previous handler. + # (Only UnixSelectorEventloop has `_signal_handlers`.) + loop = asyncio.get_event_loop() + previous_winch_handler = getattr(loop, "_signal_handlers", {}).get(sigwinch) + + try: + loop.add_signal_handler(sigwinch, handler) + yield + finally: + # Restore the previous signal handler. + loop.remove_signal_handler(sigwinch) + if previous_winch_handler is not None: + loop.add_signal_handler( + sigwinch, + previous_winch_handler._callback, + *previous_winch_handler._args, + ) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/application/current.py prompt-toolkit-3.0.6/prompt_toolkit/application/current.py --- prompt-toolkit-3.0.5/prompt_toolkit/application/current.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/application/current.py 2020-08-01 20:16:17.000000000 +0000 @@ -8,11 +8,13 @@ from prompt_toolkit.eventloop.dummy_contextvars import ContextVar # type: ignore if TYPE_CHECKING: - from .application import Application from prompt_toolkit.input.defaults import Input from prompt_toolkit.output.defaults import Output + from .application import Application + __all__ = [ + "AppSession", "get_app_session", "get_app", "get_app_or_none", @@ -29,6 +31,9 @@ The input/output device is not supposed to change during one session. + Warning: Always use the `create_app_session` function to create an + instance, so that it gets activated correctly. + :param input: Use this as a default input for all applications running in this session, unless an input is passed to the `Application` explicitely. diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/application/__init__.py prompt-toolkit-3.0.6/prompt_toolkit/application/__init__.py --- prompt-toolkit-3.0.5/prompt_toolkit/application/__init__.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/application/__init__.py 2020-07-31 10:42:30.000000000 +0000 @@ -1,5 +1,6 @@ from .application import Application from .current import ( + AppSession, create_app_session, get_app, get_app_or_none, @@ -13,6 +14,7 @@ # Application. "Application", # Current. + "AppSession", "get_app_session", "create_app_session", "get_app", diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/clipboard/pyperclip.py prompt-toolkit-3.0.6/prompt_toolkit/clipboard/pyperclip.py --- prompt-toolkit-3.0.5/prompt_toolkit/clipboard/pyperclip.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/clipboard/pyperclip.py 2020-08-01 20:16:17.000000000 +0000 @@ -1,6 +1,7 @@ from typing import Optional import pyperclip + from prompt_toolkit.selection import SelectionType from .base import Clipboard, ClipboardData diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/completion/word_completer.py prompt-toolkit-3.0.6/prompt_toolkit/completion/word_completer.py --- prompt-toolkit-3.0.5/prompt_toolkit/completion/word_completer.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/completion/word_completer.py 2020-07-31 10:42:30.000000000 +0000 @@ -23,8 +23,9 @@ contain spaces. (Can not be used together with the WORD option.) :param match_middle: When True, match not only the start, but also in the middle of the word. - :param pattern: Optional regex. When given, use this regex - pattern instead of default one. + :param pattern: Optional compiled regex for finding the word before + the cursor to complete. When given, use this regex pattern instead of + default one (see document._FIND_WORD_RE) """ def __init__( diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/contrib/completers/__init__.py prompt-toolkit-3.0.6/prompt_toolkit/contrib/completers/__init__.py --- prompt-toolkit-3.0.5/prompt_toolkit/contrib/completers/__init__.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/contrib/completers/__init__.py 2020-07-31 10:42:30.000000000 +0000 @@ -1 +1,3 @@ from .system import SystemCompleter + +__all__ = ["SystemCompleter"] diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/contrib/regular_languages/__init__.py prompt-toolkit-3.0.6/prompt_toolkit/contrib/regular_languages/__init__.py --- prompt-toolkit-3.0.5/prompt_toolkit/contrib/regular_languages/__init__.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/contrib/regular_languages/__init__.py 2020-07-31 10:42:30.000000000 +0000 @@ -73,3 +73,5 @@ - How to create a parser from this grammar. """ from .compiler import compile + +__all__ = ["compile"] diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/contrib/regular_languages/validation.py prompt-toolkit-3.0.6/prompt_toolkit/contrib/regular_languages/validation.py --- prompt-toolkit-3.0.5/prompt_toolkit/contrib/regular_languages/validation.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/contrib/regular_languages/validation.py 2020-07-31 10:42:30.000000000 +0000 @@ -53,7 +53,7 @@ raise ValidationError( cursor_position=v.start + e.cursor_position, message=e.message, - ) + ) from e else: raise ValidationError( cursor_position=len(document.text), message="Invalid command" diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/contrib/ssh/__init__.py prompt-toolkit-3.0.6/prompt_toolkit/contrib/ssh/__init__.py --- prompt-toolkit-3.0.5/prompt_toolkit/contrib/ssh/__init__.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/contrib/ssh/__init__.py 2020-08-01 20:16:17.000000000 +0000 @@ -1,6 +1,6 @@ -from .server import PromptToolkitSession, PromptToolkitSSHServer +from .server import PromptToolkitSSHServer, PromptToolkitSSHSession __all__ = [ - "PromptToolkitSession", + "PromptToolkitSSHSession", "PromptToolkitSSHServer", ] diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/contrib/ssh/server.py prompt-toolkit-3.0.6/prompt_toolkit/contrib/ssh/server.py --- prompt-toolkit-3.0.5/prompt_toolkit/contrib/ssh/server.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/contrib/ssh/server.py 2020-08-10 09:53:15.000000000 +0000 @@ -9,17 +9,16 @@ from prompt_toolkit.application.current import AppSession, create_app_session from prompt_toolkit.data_structures import Size -from prompt_toolkit.input.posix_pipe import PosixPipeInput +from prompt_toolkit.input import create_pipe_input from prompt_toolkit.output.vt100 import Vt100_Output -__all__ = [ - "PromptToolkitSession", - "PromptToolkitSSHServer", -] +__all__ = ["PromptToolkitSSHSession", "PromptToolkitSSHServer"] -class PromptToolkitSession(asyncssh.SSHServerSession): - def __init__(self, interact: Callable[[], Awaitable[None]]) -> None: +class PromptToolkitSSHSession(asyncssh.SSHServerSession): + def __init__( + self, interact: Callable[["PromptToolkitSSHSession"], Awaitable[None]] + ) -> None: self.interact = interact self._chan = None self.app_session: Optional[AppSession] = None @@ -27,7 +26,8 @@ # PipInput object, for sending input in the CLI. # (This is something that we can use in the prompt_toolkit event loop, # but still write date in manually.) - self._input = PosixPipeInput() + self._input = create_pipe_input() + self._output = None # Output object. Don't render to the real stdout, but write everything # in the SSH channel. @@ -39,9 +39,7 @@ def flush(s): pass - self._output = Vt100_Output( - cast(TextIO, Stdout()), self._get_size, write_binary=False - ) + self.stdout = cast(TextIO, Stdout()) def _get_size(self) -> Size: """ @@ -70,11 +68,15 @@ # Disable the line editing provided by asyncssh. Prompt_toolkit # provides the line editing. self._chan.set_line_mode(False) + term = self._chan.get_terminal_type() + self._output = Vt100_Output( + self.stdout, self._get_size, term=term, write_binary=False + ) with create_app_session(input=self._input, output=self._output) as session: self.app_session = session try: - await self.interact() + await self.interact(self) except BaseException: traceback.print_exc() finally: @@ -103,7 +105,7 @@ .. code:: python - async def interact() -> None: + async def interact(ssh_session: PromptToolkitSSHSession) -> None: await yes_no_dialog("my title", "my text").run_async() prompt_session = PromptSession() @@ -123,12 +125,14 @@ loop.run_forever() """ - def __init__(self, interact: Callable[[], Awaitable[None]]) -> None: + def __init__( + self, interact: Callable[[PromptToolkitSSHSession], Awaitable[None]] + ) -> None: self.interact = interact def begin_auth(self, username): # No authentication. return False - def session_requested(self) -> PromptToolkitSession: - return PromptToolkitSession(self.interact) + def session_requested(self) -> PromptToolkitSSHSession: + return PromptToolkitSSHSession(self.interact) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/contrib/telnet/protocol.py prompt-toolkit-3.0.6/prompt_toolkit/contrib/telnet/protocol.py --- prompt-toolkit-3.0.5/prompt_toolkit/contrib/telnet/protocol.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/contrib/telnet/protocol.py 2020-08-01 20:16:17.000000000 +0000 @@ -36,6 +36,10 @@ LINEMODE = int2byte(34) SUPPRESS_GO_AHEAD = int2byte(3) +TTYPE = int2byte(24) +SEND = int2byte(1) +IS = int2byte(0) + DM = int2byte(242) BRK = int2byte(243) IP = int2byte(244) @@ -65,10 +69,12 @@ self, data_received_callback: Callable[[bytes], None], size_received_callback: Callable[[int, int], None], + ttype_received_callback: Callable[[str], None], ) -> None: self.data_received_callback = data_received_callback self.size_received_callback = size_received_callback + self.ttype_received_callback = ttype_received_callback self._parser = self._parse_coroutine() self._parser.send(None) # type: ignore @@ -121,6 +127,17 @@ else: logger.warning("Wrong number of NAWS bytes") + def ttype(self, data: bytes) -> None: + """ + Received terminal type. + """ + subcmd, data = data[0:1], data[1:] + if subcmd == IS: + ttype = data.decode("ascii") + self.ttype_received_callback(ttype) + else: + logger.warning("Received a non-IS terminal type Subnegotiation") + def negotiate(self, data: bytes) -> None: """ Got negotiate data. @@ -129,6 +146,8 @@ if command == NAWS: self.naws(payload) + elif command == TTYPE: + self.ttype(payload) else: logger.info("Negotiate (%r got bytes)", len(data)) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/contrib/telnet/server.py prompt-toolkit-3.0.6/prompt_toolkit/contrib/telnet/server.py --- prompt-toolkit-3.0.5/prompt_toolkit/contrib/telnet/server.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/contrib/telnet/server.py 2020-08-01 20:16:17.000000000 +0000 @@ -11,7 +11,7 @@ from prompt_toolkit.application.run_in_terminal import run_in_terminal from prompt_toolkit.data_structures import Size from prompt_toolkit.formatted_text import AnyFormattedText, to_formatted_text -from prompt_toolkit.input.posix_pipe import PosixPipeInput +from prompt_toolkit.input import create_pipe_input from prompt_toolkit.output.vt100 import Vt100_Output from prompt_toolkit.renderer import print_formatted_text as print_formatted_text from prompt_toolkit.styles import BaseStyle, DummyStyle @@ -26,7 +26,9 @@ NAWS, SB, SE, + SEND, SUPPRESS_GO_AHEAD, + TTYPE, WILL, TelnetProtocolParser, ) @@ -59,6 +61,15 @@ # Negotiate window size connection.send(IAC + DO + NAWS) + # Negotiate terminal type + # Assume the client will accept the negociation with `IAC + WILL + TTYPE` + connection.send(IAC + DO + TTYPE) + + # We can then select the first terminal type supported by the client, + # which is generally the best type the client supports + # The client should reply with a `IAC + SB + TTYPE + IS + ttype + IAC + SE` + connection.send(IAC + SB + TTYPE + SEND + IAC + SE) + class _ConnectionStdout: """ @@ -73,6 +84,7 @@ self._buffer: List[bytes] = [] def write(self, data: str) -> None: + data = data.replace("\n", "\r\n") self._buffer.append(data.encode(self._encoding, errors=self._errors)) self.flush() @@ -115,6 +127,8 @@ self.encoding = encoding self.style = style self._closed = False + self._ready = asyncio.Event() + self.vt100_output = None # Create "Output" object. self.size = Size(rows=40, columns=79) @@ -123,14 +137,13 @@ _initialize_telnet(conn) # Create input. - self.vt100_input = PosixPipeInput() + self.vt100_input = create_pipe_input() # Create output. def get_size() -> Size: return self.size self.stdout = cast(TextIO, _ConnectionStdout(conn, encoding=encoding)) - self.vt100_output = Vt100_Output(self.stdout, get_size, write_binary=False) def data_received(data: bytes) -> None: """ TelnetProtocolParser 'data_received' callback """ @@ -139,9 +152,17 @@ def size_received(rows: int, columns: int) -> None: """ TelnetProtocolParser 'size_received' callback """ self.size = Size(rows=rows, columns=columns) - get_app()._on_resize() + if self.vt100_output is not None: + get_app()._on_resize() + + def ttype_received(ttype: str) -> None: + """ TelnetProtocolParser 'ttype_received' callback """ + self.vt100_output = Vt100_Output( + self.stdout, get_size, term=ttype, write_binary=False + ) + self._ready.set() - self.parser = TelnetProtocolParser(data_received, size_received) + self.parser = TelnetProtocolParser(data_received, size_received, ttype_received) self.context: Optional[contextvars.Context] = None async def run_application(self) -> None: @@ -158,25 +179,24 @@ logger.info("Connection closed by client. %r %r" % self.addr) self.close() - async def run() -> None: - # Add reader. - loop = get_event_loop() - loop.add_reader(self.conn, handle_incoming_data) + # Add reader. + loop = get_event_loop() + loop.add_reader(self.conn, handle_incoming_data) - try: + try: + # Wait for v100_output to be properly instantiated + await self._ready.wait() + with create_app_session(input=self.vt100_input, output=self.vt100_output): + self.context = contextvars.copy_context() await self.interact(self) - except Exception as e: - print("Got %s" % type(e).__name__, e) - import traceback - - traceback.print_exc() - raise - finally: - self.close() - - with create_app_session(input=self.vt100_input, output=self.vt100_output): - self.context = contextvars.copy_context() - await run() + except Exception as e: + print("Got %s" % type(e).__name__, e) + import traceback + + traceback.print_exc() + raise + finally: + self.close() def feed(self, data: bytes) -> None: """ @@ -199,6 +219,8 @@ """ Send text to the client. """ + if self.vt100_output is None: + return formatted_text = to_formatted_text(formatted_text) print_formatted_text( self.vt100_output, formatted_text, self.style or DummyStyle() @@ -224,6 +246,8 @@ """ Erase the screen and move the cursor to the top. """ + if self.vt100_output is None: + return self.vt100_output.erase_screen() self.vt100_output.cursor_goto(0, 0) self.vt100_output.flush() diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/document.py prompt-toolkit-3.0.6/prompt_toolkit/document.py --- prompt-toolkit-3.0.5/prompt_toolkit/document.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/document.py 2020-07-31 10:42:30.000000000 +0000 @@ -825,7 +825,9 @@ """ # Look for a match. - for A, B in "()", "[]", "{}", "<>": + for pair in "()", "[]", "{}", "<>": + A = pair[0] + B = pair[1] if self.current_char == A: return self.find_enclosing_bracket_right(A, B, end_pos=end_pos) or 0 elif self.current_char == B: diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/eventloop/async_context_manager.py prompt-toolkit-3.0.6/prompt_toolkit/eventloop/async_context_manager.py --- prompt-toolkit-3.0.5/prompt_toolkit/eventloop/async_context_manager.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/eventloop/async_context_manager.py 2020-08-01 20:16:17.000000000 +0000 @@ -2,10 +2,11 @@ @asynccontextmanager code, copied from Python 3.7's contextlib. For usage in Python 3.6. """ -import _collections_abc import abc from functools import wraps +import _collections_abc + __all__ = ["asynccontextmanager"] diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/filters/app.py prompt-toolkit-3.0.6/prompt_toolkit/filters/app.py --- prompt-toolkit-3.0.5/prompt_toolkit/filters/app.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/filters/app.py 2020-08-01 20:16:17.000000000 +0000 @@ -52,9 +52,9 @@ Enable when this buffer has the focus. """ from prompt_toolkit.buffer import Buffer - from prompt_toolkit.layout.controls import UIControl - from prompt_toolkit.layout.containers import to_container, Window, Container from prompt_toolkit.layout import walk + from prompt_toolkit.layout.containers import Container, Window, to_container + from prompt_toolkit.layout.controls import UIControl if isinstance(value, str): @@ -287,6 +287,25 @@ @Condition +def vi_replace_single_mode() -> bool: + from prompt_toolkit.key_binding.vi_state import InputMode + + app = get_app() + + if ( + app.editing_mode != EditingMode.VI + or app.vi_state.operator_func + or app.vi_state.waiting_for_digraph + or app.current_buffer.selection_state + or app.vi_state.temporary_navigation_mode + or app.current_buffer.read_only() + ): + return False + + return app.vi_state.input_mode == InputMode.REPLACE_SINGLE + + +@Condition def vi_selection_mode() -> bool: app = get_app() if app.editing_mode != EditingMode.VI: diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/formatted_text/base.py prompt-toolkit-3.0.6/prompt_toolkit/formatted_text/base.py --- prompt-toolkit-3.0.5/prompt_toolkit/formatted_text/base.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/formatted_text/base.py 2020-08-01 20:16:17.000000000 +0000 @@ -55,8 +55,9 @@ fragments. (Which is the canonical form of formatted text.) The outcome is always a `FormattedText` instance, which is a list of (style, text) tuples. - It can take an `HTML` object, a plain text string, or anything that - implements `__pt_formatted_text__`. + It can take a plain text string, an `HTML` or `ANSI` object, anything that + implements `__pt_formatted_text__` or a callable that takes no arguments and + returns one of those. :param style: An additional style string which is applied to all text fragments. diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/__init__.py prompt-toolkit-3.0.6/prompt_toolkit/__init__.py --- prompt-toolkit-3.0.5/prompt_toolkit/__init__.py 2020-03-26 08:03:28.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/__init__.py 2020-08-10 09:51:40.000000000 +0000 @@ -18,7 +18,7 @@ from .shortcuts import PromptSession, print_formatted_text, prompt # Don't forget to update in `docs/conf.py`! -__version__ = "3.0.5" +__version__ = "3.0.6" # Version tuple. VERSION = tuple(__version__.split(".")) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/input/base.py prompt-toolkit-3.0.6/prompt_toolkit/input/base.py --- prompt-toolkit-3.0.5/prompt_toolkit/input/base.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/input/base.py 2020-08-01 20:16:17.000000000 +0000 @@ -95,6 +95,20 @@ pass +class PipeInput(Input): + """ + Abstraction for pipe input. + """ + + @abstractmethod + def send_bytes(self, data: bytes) -> None: + """Feed byte string into the pipe""" + + @abstractmethod + def send_text(self, data: str) -> None: + """Feed a text string into the pipe""" + + class DummyInput(Input): """ Input for use in a `DummyApplication` diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/input/defaults.py prompt-toolkit-3.0.6/prompt_toolkit/input/defaults.py --- prompt-toolkit-3.0.5/prompt_toolkit/input/defaults.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/input/defaults.py 2020-08-01 20:16:17.000000000 +0000 @@ -3,7 +3,7 @@ from prompt_toolkit.utils import is_windows -from .base import Input +from .base import Input, PipeInput __all__ = [ "create_input", @@ -43,7 +43,7 @@ return Vt100Input(stdin) -def create_pipe_input() -> Input: +def create_pipe_input(responds_to_cpr: bool = True) -> PipeInput: """ Create an input pipe. This is mostly useful for unit testing. @@ -51,8 +51,8 @@ if is_windows(): from .win32_pipe import Win32PipeInput - return Win32PipeInput() + return Win32PipeInput(responds_to_cpr=responds_to_cpr) else: from .posix_pipe import PosixPipeInput - return PosixPipeInput() + return PosixPipeInput(responds_to_cpr=responds_to_cpr) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/input/posix_pipe.py prompt-toolkit-3.0.6/prompt_toolkit/input/posix_pipe.py --- prompt-toolkit-3.0.5/prompt_toolkit/input/posix_pipe.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/input/posix_pipe.py 2020-08-01 20:16:17.000000000 +0000 @@ -2,6 +2,7 @@ from typing import ContextManager, TextIO, cast from ..utils import DummyContext +from .base import PipeInput from .vt100 import Vt100Input __all__ = [ @@ -9,7 +10,7 @@ ] -class PosixPipeInput(Vt100Input): +class PosixPipeInput(Vt100Input, PipeInput): """ Input that is send through a pipe. This is useful if we want to send the input programmatically into the @@ -23,10 +24,13 @@ _id = 0 - def __init__(self, text: str = "") -> None: + def __init__(self, text: str = "", responds_to_cpr: bool = True) -> None: + self._responds_to_cpr = True self._r, self._w = os.pipe() class Stdin: + encoding = "utf-8" + def isatty(stdin) -> bool: return True @@ -42,7 +46,7 @@ @property def responds_to_cpr(self) -> bool: - return False + return self._responds_to_cpr def send_bytes(self, data: bytes) -> None: os.write(self._w, data) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/input/posix_utils.py prompt-toolkit-3.0.6/prompt_toolkit/input/posix_utils.py --- prompt-toolkit-3.0.5/prompt_toolkit/input/posix_utils.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/input/posix_utils.py 2020-07-31 10:42:30.000000000 +0000 @@ -33,14 +33,16 @@ # of junk. One occurrence of this that I had was when using iTerm2 on OS X, # with "Option as Meta" checked (You should choose "Option as +Esc".) - def __init__(self, stdin_fd: int, errors: str = "surrogateescape") -> None: + def __init__( + self, stdin_fd: int, errors: str = "surrogateescape", encoding: str = "utf-8" + ) -> None: self.stdin_fd = stdin_fd self.errors = errors # Create incremental decoder for decoding stdin. # We can not just do `os.read(stdin.fileno(), 1024).decode('utf-8')`, because # it could be that we are in the middle of a utf-8 byte sequence. - self._stdin_decoder_cls = getincrementaldecoder("utf-8") + self._stdin_decoder_cls = getincrementaldecoder(encoding) self._stdin_decoder = self._stdin_decoder_cls(errors=errors) #: True when there is nothing anymore to read. diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/input/vt100.py prompt-toolkit-3.0.6/prompt_toolkit/input/vt100.py --- prompt-toolkit-3.0.5/prompt_toolkit/input/vt100.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/input/vt100.py 2020-08-01 20:16:17.000000000 +0000 @@ -48,13 +48,13 @@ try: # This should not raise, but can return 0. stdin.fileno() - except io.UnsupportedOperation: + except io.UnsupportedOperation as e: if "idlelib.run" in sys.modules: raise io.UnsupportedOperation( "Stdin is not a terminal. Running from Idle is not supported." - ) + ) from e else: - raise io.UnsupportedOperation("Stdin is not a terminal.") + raise io.UnsupportedOperation("Stdin is not a terminal.") from e # Even when we have a file descriptor, it doesn't mean it's a TTY. # Normally, this requires a real TTY device, but people instantiate @@ -78,7 +78,7 @@ self._fileno = stdin.fileno() self._buffer: List[KeyPress] = [] # Buffer to collect the Key objects. - self.stdin_reader = PosixStdinReader(self._fileno) + self.stdin_reader = PosixStdinReader(self._fileno, encoding=stdin.encoding) self.vt100_parser = Vt100Parser( lambda key_press: self._buffer.append(key_press) ) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/input/win32_pipe.py prompt-toolkit-3.0.6/prompt_toolkit/input/win32_pipe.py --- prompt-toolkit-3.0.5/prompt_toolkit/input/win32_pipe.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/input/win32_pipe.py 2020-08-01 20:16:17.000000000 +0000 @@ -5,13 +5,14 @@ from ..key_binding import KeyPress from ..utils import DummyContext +from .base import PipeInput from .vt100_parser import Vt100Parser from .win32 import _Win32InputBase, attach_win32_input, detach_win32_input __all__ = ["Win32PipeInput"] -class Win32PipeInput(_Win32InputBase): +class Win32PipeInput(_Win32InputBase, PipeInput): """ This is an input pipe that works on Windows. Text or bytes can be feed into the pipe, and key strokes can be read from @@ -29,7 +30,7 @@ _id = 0 - def __init__(self) -> None: + def __init__(self, responds_to_cpr: bool = True) -> None: super().__init__() # Event (handle) for registering this input in the event loop. # This event is set when there is data available to read from the pipe. @@ -39,6 +40,7 @@ self._event = create_win32_event() self._closed = False + self._responds_to_cpr = responds_to_cpr # Parser for incoming keys. self._buffer: List[KeyPress] = [] # Buffer to collect the Key objects. @@ -105,7 +107,7 @@ @property def responds_to_cpr(self) -> bool: - return False + return self._responds_to_cpr def send_bytes(self, data: bytes) -> None: " Send bytes to the input. " diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/key_binding/bindings/auto_suggest.py prompt-toolkit-3.0.6/prompt_toolkit/key_binding/bindings/auto_suggest.py --- prompt-toolkit-3.0.5/prompt_toolkit/key_binding/bindings/auto_suggest.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/key_binding/bindings/auto_suggest.py 2020-08-06 11:42:19.000000000 +0000 @@ -31,6 +31,7 @@ app = get_app() return ( app.current_buffer.suggestion is not None + and len(app.current_buffer.suggestion.text) > 0 and app.current_buffer.document.is_cursor_at_the_end ) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/key_binding/bindings/basic.py prompt-toolkit-3.0.6/prompt_toolkit/key_binding/bindings/basic.py --- prompt-toolkit-3.0.5/prompt_toolkit/key_binding/bindings/basic.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/key_binding/bindings/basic.py 2020-08-10 09:14:32.000000000 +0000 @@ -78,6 +78,10 @@ @handle("f18") @handle("f19") @handle("f20") + @handle("f21") + @handle("f22") + @handle("f23") + @handle("f24") @handle("c-@") # Also c-space. @handle("c-\\") @handle("c-]") diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/key_binding/bindings/completion.py prompt-toolkit-3.0.6/prompt_toolkit/key_binding/bindings/completion.py --- prompt-toolkit-3.0.5/prompt_toolkit/key_binding/bindings/completion.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/key_binding/bindings/completion.py 2020-08-01 20:16:17.000000000 +0000 @@ -87,8 +87,8 @@ This will ask for a confirmation if there are too many completions to fit on a single page and provide a paginator to walk through them. """ - from prompt_toolkit.shortcuts.prompt import create_confirm_session from prompt_toolkit.formatted_text import to_formatted_text + from prompt_toolkit.shortcuts.prompt import create_confirm_session # Get terminal dimensions. term_size = app.output.get_size() diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/key_binding/bindings/named_commands.py prompt-toolkit-3.0.6/prompt_toolkit/key_binding/bindings/named_commands.py --- prompt-toolkit-3.0.5/prompt_toolkit/key_binding/bindings/named_commands.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/key_binding/bindings/named_commands.py 2020-08-01 20:16:17.000000000 +0000 @@ -55,8 +55,8 @@ """ try: return _readline_commands[name] - except KeyError: - raise KeyError("Unknown Readline command: %r" % name) + except KeyError as e: + raise KeyError("Unknown Readline command: %r" % name) from e # diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/key_binding/bindings/vi.py prompt-toolkit-3.0.6/prompt_toolkit/key_binding/bindings/vi.py --- prompt-toolkit-3.0.5/prompt_toolkit/key_binding/bindings/vi.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/key_binding/bindings/vi.py 2020-08-06 10:27:33.000000000 +0000 @@ -27,6 +27,7 @@ vi_navigation_mode, vi_recording_macro, vi_replace_mode, + vi_replace_single_mode, vi_search_direction_reversed, vi_selection_mode, vi_waiting_for_text_object_mode, @@ -797,13 +798,12 @@ data, count=event.arg, paste_mode=PasteMode.VI_BEFORE ) - @handle("r", Keys.Any, filter=vi_navigation_mode) + @handle("r", filter=vi_navigation_mode) def _replace(event: E) -> None: """ - Replace single character under cursor + Go to 'replace-single'-mode. """ - event.current_buffer.insert_text(event.data * event.arg, overwrite=True) - event.current_buffer.cursor_position -= 1 + event.app.vi_state.input_mode = InputMode.REPLACE_SINGLE @handle("R", filter=vi_navigation_mode) def _replace_mode(event: E) -> None: @@ -1883,6 +1883,15 @@ """ event.current_buffer.insert_text(event.data, overwrite=True) + @handle(Keys.Any, filter=vi_replace_single_mode) + def _replace_single(event: E) -> None: + """ + Replace single character at cursor position. + """ + event.current_buffer.insert_text(event.data, overwrite=True) + event.current_buffer.cursor_position -= 1 + event.app.vi_state.input_mode = InputMode.NAVIGATION + @handle( Keys.Any, filter=vi_insert_multiple_mode, diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/key_binding/__init__.py prompt-toolkit-3.0.6/prompt_toolkit/key_binding/__init__.py --- prompt-toolkit-3.0.5/prompt_toolkit/key_binding/__init__.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/key_binding/__init__.py 2020-07-31 10:42:30.000000000 +0000 @@ -5,13 +5,16 @@ KeyBindingsBase, merge_key_bindings, ) -from .key_processor import KeyPress +from .key_processor import KeyPress, KeyPressEvent __all__ = [ + # key_bindings. "ConditionalKeyBindings", "DynamicKeyBindings", "KeyBindings", "KeyBindingsBase", "merge_key_bindings", + # key_processor "KeyPress", + "KeyPressEvent", ] diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/key_binding/vi_state.py prompt-toolkit-3.0.6/prompt_toolkit/key_binding/vi_state.py --- prompt-toolkit-3.0.5/prompt_toolkit/key_binding/vi_state.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/key_binding/vi_state.py 2020-08-01 20:16:17.000000000 +0000 @@ -4,8 +4,8 @@ from prompt_toolkit.clipboard import ClipboardData if TYPE_CHECKING: - from .key_processor import KeyPressEvent from .key_bindings.vi import TextObject + from .key_processor import KeyPressEvent __all__ = [ "InputMode", @@ -21,6 +21,7 @@ INSERT_MULTIPLE = "vi-insert-multiple" NAVIGATION = "vi-navigation" # Normal mode. REPLACE = "vi-replace" + REPLACE_SINGLE = "vi-replace-single" class CharacterFind: diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/layout/containers.py prompt-toolkit-3.0.6/prompt_toolkit/layout/containers.py --- prompt-toolkit-3.0.5/prompt_toolkit/layout/containers.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/layout/containers.py 2020-08-01 20:16:17.000000000 +0000 @@ -64,6 +64,7 @@ NotImplementedOrNone = object __all__ = [ + "AnyContainer", "Container", "HorizontalAlign", "VerticalAlign", @@ -353,7 +354,8 @@ style=self.padding_style, ) ) - result.pop() + if result: + result.pop() # Padding right. if self.align in (VerticalAlign.CENTER, VerticalAlign.TOP): @@ -605,7 +607,8 @@ style=self.padding_style, ) ) - result.pop() + if result: + result.pop() # Padding right. if self.align in (HorizontalAlign.CENTER, HorizontalAlign.LEFT): @@ -1105,7 +1108,7 @@ class WindowRenderInfo: """ - Render information, for the last render time of this control. + Render information for the last render time of this control. It stores mapping information between the input buffers (in case of a :class:`~prompt_toolkit.layout.controls.BufferControl`) and the actual render position on the output screen. @@ -2616,7 +2619,7 @@ class DynamicContainer(Container): """ - Container class that can dynamically returns any Container. + Container class that dynamically returns any Container. :param get_container: Callable that returns a :class:`.Container` instance or any widget with a ``__pt_container__`` method. @@ -2672,7 +2675,7 @@ elif hasattr(container, "__pt_container__"): return to_container(cast("MagicContainer", container).__pt_container__()) else: - raise ValueError("Not a container object.") + raise ValueError("Not a container object: %r" % (container,)) def to_window(container: AnyContainer) -> Window: diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/layout/controls.py prompt-toolkit-3.0.6/prompt_toolkit/layout/controls.py --- prompt-toolkit-3.0.5/prompt_toolkit/layout/controls.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/layout/controls.py 2020-08-01 20:16:17.000000000 +0000 @@ -270,10 +270,10 @@ """ Control that displays formatted text. This can be either plain text, an :class:`~prompt_toolkit.formatted_text.HTML` object an - :class:`~prompt_toolkit.formatted_text.ANSI` object or a list of - ``(style_str, text)`` tuples, depending on how you prefer to do the - formatting. See ``prompt_toolkit.layout.formatted_text`` for more - information. + :class:`~prompt_toolkit.formatted_text.ANSI` object, a list of ``(style_str, + text)`` tuples or a callable that takes no argument and returns one of + those, depending on how you prefer to do the formatting. See + ``prompt_toolkit.layout.formatted_text`` for more information. (It's mostly optimized for rather small widgets, like toolbars, menus, etc...) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/layout/dimension.py prompt-toolkit-3.0.6/prompt_toolkit/layout/dimension.py --- prompt-toolkit-3.0.5/prompt_toolkit/layout/dimension.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/layout/dimension.py 2020-08-01 20:16:17.000000000 +0000 @@ -27,8 +27,8 @@ :param max: Maximum size. :param weight: For a VSplit/HSplit, the actual size will be determined by taking the proportion of weights from all the children. - E.g. When there are two children, one width a weight of 1, - and the other with a weight of 2. The second will always be + E.g. When there are two children, one with a weight of 1, + and the other with a weight of 2, the second will always be twice as big as the first, if the min/max values allow it. :param preferred: Preferred size. """ diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/layout/__init__.py prompt-toolkit-3.0.6/prompt_toolkit/layout/__init__.py --- prompt-toolkit-3.0.5/prompt_toolkit/layout/__init__.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/layout/__init__.py 2020-07-31 10:42:30.000000000 +0000 @@ -45,6 +45,7 @@ """ from .containers import ( + AnyContainer, ColorColumn, ConditionalContainer, Container, @@ -104,6 +105,7 @@ "to_dimension", "is_dimension", # Containers. + "AnyContainer", "Container", "HorizontalAlign", "VerticalAlign", diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/layout/layout.py prompt-toolkit-3.0.6/prompt_toolkit/layout/layout.py --- prompt-toolkit-3.0.5/prompt_toolkit/layout/layout.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/layout/layout.py 2020-08-01 20:16:17.000000000 +0000 @@ -59,10 +59,10 @@ if focused_element is None: try: self._stack.append(next(self.find_all_windows())) - except StopIteration: + except StopIteration as e: raise InvalidLayoutError( "Invalid layout. The layout does not contain any Window object." - ) + ) from e else: self.focus(focused_element) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/lexers/pygments.py prompt-toolkit-3.0.6/prompt_toolkit/lexers/pygments.py --- prompt-toolkit-3.0.5/prompt_toolkit/lexers/pygments.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/lexers/pygments.py 2020-08-01 20:16:17.000000000 +0000 @@ -211,8 +211,8 @@ Create a `Lexer` from a filename. """ # Inline imports: the Pygments dependency is optional! - from pygments.util import ClassNotFound from pygments.lexers import get_lexer_for_filename + from pygments.util import ClassNotFound try: pygments_lexer = get_lexer_for_filename(filename) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/output/base.py prompt-toolkit-3.0.6/prompt_toolkit/output/base.py --- prompt-toolkit-3.0.5/prompt_toolkit/output/base.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/output/base.py 2020-08-01 20:16:17.000000000 +0000 @@ -163,6 +163,23 @@ " For Windows only. " raise NotImplementedError + @abstractmethod + def get_default_color_depth(self) -> ColorDepth: + """ + Get default color depth for this output. + + This value will be used if no color depth was explicitely passed to the + `Application`. + + .. note:: + + If the `$PROMPT_TOOLKIT_COLOR_DEPTH` environment variable has been + set, then `outputs.defaults.create_output` will pass this value to + the implementation as the default_color_depth, which is returned + here. (This is not used when the output corresponds to a + prompt_toolkit SSH/Telnet session.) + """ + class DummyOutput(Output): """ @@ -265,3 +282,6 @@ def get_rows_below_cursor_position(self) -> int: return 40 + + def get_default_color_depth(self) -> ColorDepth: + return ColorDepth.DEPTH_1_BIT diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/output/color_depth.py prompt-toolkit-3.0.6/prompt_toolkit/output/color_depth.py --- prompt-toolkit-3.0.5/prompt_toolkit/output/color_depth.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/output/color_depth.py 2020-08-01 20:16:17.000000000 +0000 @@ -2,8 +2,6 @@ from enum import Enum from typing import Optional -from prompt_toolkit.utils import is_dumb_terminal, is_windows - __all__ = [ "ColorDepth", ] @@ -35,40 +33,26 @@ TRUE_COLOR = DEPTH_24_BIT @classmethod - def default(cls, term: Optional[str] = None) -> "ColorDepth": + def from_env(cls) -> Optional["ColorDepth"]: """ - Return the default color depth, according to the $TERM value. - - We prefer 256 colors almost always, because this is what most terminals - support these days, and is a good default. - - The $PROMPT_TOOLKIT_COLOR_DEPTH environment variable can be used to - override this outcome. This is a way to enforce a certain color depth - in all prompt_toolkit applications. + Return the color depth if the $PROMPT_TOOLKIT_COLOR_DEPTH environment + variable has been set. - If no `term` parameter is given, we use the $TERM environment variable. + This is a way to enforce a certain color depth in all prompt_toolkit + applications. """ - # Take `TERM` value from environment variable if nothing was passed. - if term is None: - term = os.environ.get("TERM", "") - - if is_dumb_terminal(term): - return cls.DEPTH_1_BIT - - if term in ("linux", "eterm-color"): - return cls.DEPTH_4_BIT - - # For now, always use 4 bit color on Windows 10 by default, even when - # vt100 escape sequences with ENABLE_VIRTUAL_TERMINAL_PROCESSING are - # supported. We don't have a reliable way yet to know whether our - # console supports true color or only 4-bit. - if is_windows() and "PROMPT_TOOLKIT_COLOR_DEPTH" not in os.environ: - return cls.DEPTH_4_BIT - # Check the `PROMPT_TOOLKIT_COLOR_DEPTH` environment variable. all_values = [i.value for i in ColorDepth] - if os.environ.get("PROMPT_TOOLKIT_COLOR_DEPTH") in all_values: return cls(os.environ["PROMPT_TOOLKIT_COLOR_DEPTH"]) - return cls.DEPTH_8_BIT + return None + + @classmethod + def default(cls) -> "ColorDepth": + """ + Return the default color depth for the default output. + """ + from .defaults import create_output + + return create_output().get_default_color_depth() diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/output/conemu.py prompt-toolkit-3.0.6/prompt_toolkit/output/conemu.py --- prompt-toolkit-3.0.5/prompt_toolkit/output/conemu.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/output/conemu.py 2020-08-01 20:16:17.000000000 +0000 @@ -1,8 +1,9 @@ -from typing import Any, TextIO +from typing import Any, Optional, TextIO from prompt_toolkit.data_structures import Size from prompt_toolkit.renderer import Output +from .color_depth import ColorDepth from .vt100 import Vt100_Output from .win32 import Win32Output @@ -27,9 +28,13 @@ http://gooseberrycreative.com/cmder/ """ - def __init__(self, stdout: TextIO) -> None: - self.win32_output = Win32Output(stdout) - self.vt100_output = Vt100_Output(stdout, lambda: Size(0, 0)) + def __init__( + self, stdout: TextIO, default_color_depth: Optional[ColorDepth] = None + ) -> None: + self.win32_output = Win32Output(stdout, default_color_depth=default_color_depth) + self.vt100_output = Vt100_Output( + stdout, lambda: Size(0, 0), default_color_depth=default_color_depth + ) def __getattr__(self, name: str) -> Any: if name in ( diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/output/defaults.py prompt-toolkit-3.0.6/prompt_toolkit/output/defaults.py --- prompt-toolkit-3.0.5/prompt_toolkit/output/defaults.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/output/defaults.py 2020-08-01 20:16:17.000000000 +0000 @@ -9,6 +9,7 @@ ) from .base import Output +from .color_depth import ColorDepth __all__ = [ "create_output", @@ -28,6 +29,12 @@ consumed by something other then a terminal, so this is a reasonable default.) """ + # Consider TERM and PROMPT_TOOLKIT_COLOR_DEPTH environment variables. + # Notice that PROMPT_TOOLKIT_COLOR_DEPTH value is the default that's used + # if the Application doesn't override it. + term_from_env = get_term_environment_variable() + color_depth_from_env = ColorDepth.from_env() + if stdout is None: # By default, render to stdout. If the output is piped somewhere else, # render to stderr. @@ -48,15 +55,22 @@ if is_windows(): from .conemu import ConEmuOutput from .win32 import Win32Output - from .windows10 import is_win_vt100_enabled, Windows10_Output + from .windows10 import Windows10_Output, is_win_vt100_enabled if is_win_vt100_enabled(): - return cast(Output, Windows10_Output(stdout)) + return cast( + Output, + Windows10_Output(stdout, default_color_depth=color_depth_from_env), + ) if is_conemu_ansi(): - return cast(Output, ConEmuOutput(stdout)) + return cast( + Output, ConEmuOutput(stdout, default_color_depth=color_depth_from_env) + ) else: - return Win32Output(stdout) + return Win32Output(stdout, default_color_depth=color_depth_from_env) else: from .vt100 import Vt100_Output - return Vt100_Output.from_pty(stdout, term=get_term_environment_variable()) + return Vt100_Output.from_pty( + stdout, term=term_from_env, default_color_depth=color_depth_from_env + ) diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/output/vt100.py prompt-toolkit-3.0.6/prompt_toolkit/output/vt100.py --- prompt-toolkit-3.0.5/prompt_toolkit/output/vt100.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/output/vt100.py 2020-08-01 20:16:17.000000000 +0000 @@ -26,6 +26,7 @@ from prompt_toolkit.data_structures import Size from prompt_toolkit.output import Output from prompt_toolkit.styles import ANSI_COLOR_NAMES, Attrs +from prompt_toolkit.utils import is_dumb_terminal from .color_depth import ColorDepth @@ -415,6 +416,7 @@ get_size: Callable[[], Size], term: Optional[str] = None, write_binary: bool = True, + default_color_depth: Optional[ColorDepth] = None, ) -> None: assert all(hasattr(stdout, a) for a in ("write", "flush")) @@ -425,8 +427,9 @@ self._buffer: List[str] = [] self.stdout = stdout self.write_binary = write_binary + self.default_color_depth = default_color_depth self._get_size = get_size - self.term = term or "xterm" + self.term = term # Cache for escape codes. self._escape_code_caches: Dict[ColorDepth, _EscapeCodeCache] = { @@ -437,7 +440,12 @@ } @classmethod - def from_pty(cls, stdout: TextIO, term: Optional[str] = None) -> "Vt100_Output": + def from_pty( + cls, + stdout: TextIO, + term: Optional[str] = None, + default_color_depth: Optional[ColorDepth] = None, + ) -> "Vt100_Output": """ Create an Output class from a pseudo terminal. (This will take the dimensions by reading the pseudo @@ -470,7 +478,7 @@ pass return Size(rows=rows or 24, columns=columns or 80) - return cls(stdout, get_size, term=term) + return cls(stdout, get_size, term=term, default_color_depth=default_color_depth) def get_size(self) -> Size: return self._get_size() @@ -683,3 +691,27 @@ " Sound bell. " self.write_raw("\a") self.flush() + + def get_default_color_depth(self) -> ColorDepth: + """ + Return the default color depth for a vt100 terminal, according to the + our term value. + + We prefer 256 colors almost always, because this is what most terminals + support these days, and is a good default. + """ + if self.default_color_depth is not None: + return self.default_color_depth + + term = self.term + + if term is None: + return ColorDepth.DEFAULT + + if is_dumb_terminal(term): + return ColorDepth.DEPTH_1_BIT + + if term in ("linux", "eterm-color"): + return ColorDepth.DEPTH_4_BIT + + return ColorDepth.DEFAULT diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/output/win32.py prompt-toolkit-3.0.6/prompt_toolkit/output/win32.py --- prompt-toolkit-3.0.5/prompt_toolkit/output/win32.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/output/win32.py 2020-08-01 20:16:17.000000000 +0000 @@ -10,7 +10,7 @@ windll, ) from ctypes.wintypes import DWORD, HANDLE -from typing import Dict, List, TextIO, Tuple +from typing import Dict, List, Optional, TextIO, Tuple from prompt_toolkit.data_structures import Size from prompt_toolkit.renderer import Output @@ -85,8 +85,14 @@ (cmd.exe and similar.) """ - def __init__(self, stdout: TextIO, use_complete_width: bool = False) -> None: + def __init__( + self, + stdout: TextIO, + use_complete_width: bool = False, + default_color_depth: Optional[ColorDepth] = None, + ) -> None: self.use_complete_width = use_complete_width + self.default_color_depth = default_color_depth self._buffer: List[str] = [] self.stdout = stdout @@ -479,6 +485,23 @@ RDW_INVALIDATE = 0x0001 windll.user32.RedrawWindow(handle, None, None, c_uint(RDW_INVALIDATE)) + def get_default_color_depth(self) -> ColorDepth: + """ + Return the default color depth for a windows terminal. + + Contrary to the Vt100 implementation, this doesn't depend on a $TERM + variable. + """ + if self.default_color_depth is not None: + return self.default_color_depth + + # For now, by default, always use 4 bit color on Windows 10 by default, + # even when vt100 escape sequences with + # ENABLE_VIRTUAL_TERMINAL_PROCESSING are supported. We don't have a + # reliable way yet to know whether our console supports true color or + # only 4-bit. + return ColorDepth.DEPTH_4_BIT + class FOREGROUND_COLOR: BLACK = 0x0000 diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/output/windows10.py prompt-toolkit-3.0.6/prompt_toolkit/output/windows10.py --- prompt-toolkit-3.0.5/prompt_toolkit/output/windows10.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/output/windows10.py 2020-08-01 20:16:17.000000000 +0000 @@ -1,12 +1,13 @@ from ctypes import byref, windll from ctypes.wintypes import DWORD, HANDLE -from typing import Any, TextIO +from typing import Any, Optional, TextIO from prompt_toolkit.data_structures import Size from prompt_toolkit.renderer import Output from prompt_toolkit.utils import is_windows from prompt_toolkit.win32_types import STD_OUTPUT_HANDLE +from .color_depth import ColorDepth from .vt100 import Vt100_Output from .win32 import Win32Output @@ -24,9 +25,13 @@ Windows 10 output abstraction. This enables and uses vt100 escape sequences. """ - def __init__(self, stdout: TextIO) -> None: - self.win32_output = Win32Output(stdout) - self.vt100_output = Vt100_Output(stdout, lambda: Size(0, 0)) + def __init__( + self, stdout: TextIO, default_color_depth: Optional[ColorDepth] = None + ) -> None: + self.win32_output = Win32Output(stdout, default_color_depth=default_color_depth) + self.vt100_output = Vt100_Output( + stdout, lambda: Size(0, 0), default_color_depth=default_color_depth + ) self._hconsole = HANDLE(windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)) def flush(self) -> None: @@ -60,6 +65,7 @@ "get_win32_screen_buffer_info", "enable_bracketed_paste", "disable_bracketed_paste", + "get_default_color_depth", ): return getattr(self.win32_output, name) else: diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/renderer.py prompt-toolkit-3.0.6/prompt_toolkit/renderer.py --- prompt-toolkit-3.0.5/prompt_toolkit/renderer.py 2020-03-26 07:59:51.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/renderer.py 2020-08-01 20:16:17.000000000 +0000 @@ -21,7 +21,6 @@ DummyStyleTransformation, StyleTransformation, ) -from prompt_toolkit.utils import is_windows if TYPE_CHECKING: from prompt_toolkit.application import Application @@ -45,6 +44,7 @@ is_done: bool, # XXX: drop is_done full_screen: bool, attrs_for_style_string: "_StyleStringToAttrsCache", + style_string_has_style: "_StyleStringHasStyleCache", size: Size, previous_width: int, ) -> Tuple[Point, Optional[str]]: @@ -139,6 +139,27 @@ write(char.char) last_style = char.style + def get_max_column_index(row: Dict[int, Char]) -> int: + """ + Return max used column index, ignoring whitespace (without style) at + the end of the line. This is important for people that copy/paste + terminal output. + + There are two reasons we are sometimes seeing whitespace at the end: + - `BufferControl` adds a trailing space to each line, because it's a + possible cursor position, so that the line wrapping won't change if + the cursor position moves around. + - The `Window` adds a style class to the current line for highlighting + (cursor-line). + """ + numbers = [ + index + for index, cell in row.items() + if cell.char != " " or style_string_has_style[cell.style] + ] + numbers.append(0) + return max(numbers) + # Render for the first time: reset styling. if not previous_screen: reset_attributes() @@ -175,14 +196,12 @@ previous_row = previous_screen.data_buffer[y] zero_width_escapes_row = screen.zero_width_escapes[y] - new_max_line_len = min(width - 1, max(new_row.keys()) if new_row else 0) - previous_max_line_len = min( - width - 1, max(previous_row.keys()) if previous_row else 0 - ) + new_max_line_len = min(width - 1, get_max_column_index(new_row)) + previous_max_line_len = min(width - 1, get_max_column_index(previous_row)) # Loop over the columns. c = 0 - while c < new_max_line_len + 1: + while c <= new_max_line_len: new_char = new_row[c] old_char = previous_row[c] char_width = new_char.width or 1 @@ -270,6 +289,34 @@ return attrs +class _StyleStringHasStyleCache(Dict[str, bool]): + """ + Cache for remember which style strings don't render the default output + style (default fg/bg, no underline and no reverse and no blink). That way + we know that we should render these cells, even when they're empty (when + they contain a space). + + Note: we don't consider bold/italic/hidden because they don't change the + output if there's no text in the cell. + """ + + def __init__(self, style_string_to_attrs: Dict[str, Attrs]) -> None: + self.style_string_to_attrs = style_string_to_attrs + + def __missing__(self, style_str: str) -> bool: + attrs = self.style_string_to_attrs[style_str] + is_default = bool( + attrs.color + or attrs.bgcolor + or attrs.underline + or attrs.blink + or attrs.reverse + ) + + self[style_str] = is_default + return is_default + + class CPR_Support(Enum): " Enum: whether or not CPR is supported. " SUPPORTED = "SUPPORTED" @@ -319,6 +366,7 @@ # Cache for the style. self._attrs_for_style: Optional[_StyleStringToAttrsCache] = None + self._style_string_has_style: Optional[_StyleStringHasStyleCache] = None self._last_style_hash: Optional[Hashable] = None self._last_transformation_hash: Optional[Hashable] = None self._last_color_depth: Optional[ColorDepth] = None @@ -347,7 +395,8 @@ # In case of Windows, also make sure to scroll to the current cursor # position. (Only when rendering the first time.) - if is_windows() and _scroll: + # It does nothing for vt100 terminals. + if _scroll: self.output.scroll_buffer_to_prompt() # Quit alternate screen. @@ -383,9 +432,13 @@ is known. (It's often nicer to draw bottom toolbars only if the height is known, in order to avoid flickering when the CPR response arrives.) """ - return ( - self.full_screen or self._min_available_height > 0 or is_windows() - ) # On Windows, we don't have to wait for a CPR. + if self.full_screen or self._min_available_height > 0: + return True + try: + self._min_available_height = self.output.get_rows_below_cursor_position() + return True + except NotImplementedError: + return False @property def rows_above_layout(self) -> int: @@ -419,42 +472,48 @@ # In full-screen mode, always use the total height as min-available-height. if self.full_screen: self._min_available_height = self.output.get_size().rows + return # For Win32, we have an API call to get the number of rows below the # cursor. - elif is_windows(): + try: self._min_available_height = self.output.get_rows_below_cursor_position() + return + except NotImplementedError: + pass # Use CPR. - else: - if self.cpr_support == CPR_Support.NOT_SUPPORTED: - return + if self.cpr_support == CPR_Support.NOT_SUPPORTED: + return + + def do_cpr() -> None: + # Asks for a cursor position report (CPR). + self._waiting_for_cpr_futures.append(Future()) + self.output.ask_for_cpr() + + if self.cpr_support == CPR_Support.SUPPORTED: + do_cpr() + return - def do_cpr() -> None: - # Asks for a cursor position report (CPR). - self._waiting_for_cpr_futures.append(Future()) - self.output.ask_for_cpr() - - if self.cpr_support == CPR_Support.SUPPORTED: - do_cpr() - - # If we don't know whether CPR is supported, only do a request if - # none is pending, and test it, using a timer. - elif self.cpr_support == CPR_Support.UNKNOWN and not self.waiting_for_cpr: - do_cpr() - - async def timer() -> None: - await sleep(self.CPR_TIMEOUT) - - # Not set in the meantime -> not supported. - if self.cpr_support == CPR_Support.UNKNOWN: - self.cpr_support = CPR_Support.NOT_SUPPORTED - - if self.cpr_not_supported_callback: - # Make sure to call this callback in the main thread. - self.cpr_not_supported_callback() + # If we don't know whether CPR is supported, only do a request if + # none is pending, and test it, using a timer. + if self.waiting_for_cpr: + return - get_app().create_background_task(timer()) + do_cpr() + + async def timer() -> None: + await sleep(self.CPR_TIMEOUT) + + # Not set in the meantime -> not supported. + if self.cpr_support == CPR_Support.UNKNOWN: + self.cpr_support = CPR_Support.NOT_SUPPORTED + + if self.cpr_not_supported_callback: + # Make sure to call this callback in the main thread. + self.cpr_not_supported_callback() + + get_app().create_background_task(timer()) def report_absolute_cursor_row(self, row: int) -> None: """ @@ -505,13 +564,17 @@ await sleep(timeout) # Got timeout, erase queue. + for response_f in cpr_futures: + response_f.cancel() self._waiting_for_cpr_futures = deque() coroutines = [ wait_for_responses(), wait_for_timeout(), ] - await wait(coroutines, return_when=FIRST_COMPLETED) + _, pending = await wait(coroutines, return_when=FIRST_COMPLETED) + for task in pending: + task.cancel() def render( self, app: "Application[Any]", layout: "Layout", is_done: bool = False @@ -585,11 +648,16 @@ ): self._last_screen = None self._attrs_for_style = None + self._style_string_has_style = None if self._attrs_for_style is None: self._attrs_for_style = _StyleStringToAttrsCache( self.style.get_attrs_for_style_str, app.style_transformation ) + if self._style_string_has_style is None: + self._style_string_has_style = _StyleStringHasStyleCache( + self._attrs_for_style + ) self._last_style_hash = self.style.invalidation_hash() self._last_transformation_hash = app.style_transformation.invalidation_hash() @@ -621,6 +689,7 @@ is_done, full_screen=self.full_screen, attrs_for_style_string=self._attrs_for_style, + style_string_has_style=self._style_string_has_style, size=size, previous_width=(self._last_size.columns if self._last_size else 0), ) @@ -685,7 +754,7 @@ """ fragments = to_formatted_text(formatted_text) style_transformation = style_transformation or DummyStyleTransformation() - color_depth = color_depth or ColorDepth.default() + color_depth = color_depth or output.get_default_color_depth() # Reset first. output.reset_attributes() diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/shortcuts/__init__.py prompt-toolkit-3.0.6/prompt_toolkit/shortcuts/__init__.py --- prompt-toolkit-3.0.5/prompt_toolkit/shortcuts/__init__.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/shortcuts/__init__.py 2020-07-31 10:42:30.000000000 +0000 @@ -37,6 +37,7 @@ # Utils. "clear", "clear_title", + "print_container", "print_formatted_text", "set_title", ] diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/shortcuts/progress_bar/base.py prompt-toolkit-3.0.6/prompt_toolkit/shortcuts/progress_bar/base.py --- prompt-toolkit-3.0.5/prompt_toolkit/shortcuts/progress_bar/base.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/shortcuts/progress_bar/base.py 2020-08-01 20:16:17.000000000 +0000 @@ -15,6 +15,7 @@ import traceback from asyncio import get_event_loop, new_event_loop, set_event_loop from typing import ( + TYPE_CHECKING, Generic, Iterable, List, @@ -56,15 +57,17 @@ try: import contextvars except ImportError: - from prompt_toolkit.eventloop import ( # type: ignore - dummy_contextvars as contextvars, - ) + from prompt_toolkit.eventloop import dummy_contextvars + + contextvars = dummy_contextvars # type: ignore __all__ = ["ProgressBar"] E = KeyPressEvent +_SIGWINCH = getattr(signal, "SIGWINCH", None) + def create_key_bindings() -> KeyBindings: """ @@ -142,11 +145,15 @@ self._loop = get_event_loop() self._app_loop = new_event_loop() - self._previous_winch_handler = ( - signal.getsignal(signal.SIGWINCH) if hasattr(signal, "SIGWINCH") else None - ) + + self._previous_winch_handler = None self._has_sigwinch = False + if TYPE_CHECKING: + # Infer type from getsignal result, as defined in typeshed. Too + # complex to repeat here. + self._previous_winch_handler = signal.getsignal(_SIGWINCH) + def __enter__(self) -> "ProgressBar": # Create UI Application. title_toolbar = ConditionalContainer( @@ -225,10 +232,10 @@ # Attach WINCH signal handler in main thread. # (Interrupt that we receive during resize events.) - self._has_sigwinch = hasattr(signal, "SIGWINCH") and in_main_thread() + self._has_sigwinch = _SIGWINCH is not None and in_main_thread() if self._has_sigwinch: - self._previous_winch_handler = signal.getsignal(signal.SIGWINCH) - self._loop.add_signal_handler(signal.SIGWINCH, self.invalidate) + self._previous_winch_handler = signal.getsignal(_SIGWINCH) + self._loop.add_signal_handler(_SIGWINCH, self.invalidate) return self @@ -239,8 +246,8 @@ # Remove WINCH handler. if self._has_sigwinch: - self._loop.remove_signal_handler(signal.SIGWINCH) - signal.signal(signal.SIGWINCH, self._previous_winch_handler) + self._loop.remove_signal_handler(_SIGWINCH) + signal.signal(_SIGWINCH, self._previous_winch_handler) if self._thread is not None: self._thread.join() diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/shortcuts/prompt.py prompt-toolkit-3.0.6/prompt_toolkit/shortcuts/prompt.py --- prompt-toolkit-3.0.5/prompt_toolkit/shortcuts/prompt.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/shortcuts/prompt.py 2020-07-31 10:42:30.000000000 +0000 @@ -662,7 +662,7 @@ # The right prompt. Float( right=0, - top=0, + bottom=0, hide_when_covering_content=True, content=_RPrompt(lambda: self.rprompt), ), diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/shortcuts/utils.py prompt-toolkit-3.0.6/prompt_toolkit/shortcuts/utils.py --- prompt-toolkit-3.0.5/prompt_toolkit/shortcuts/utils.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/shortcuts/utils.py 2020-08-01 20:16:17.000000000 +0000 @@ -114,7 +114,7 @@ assert isinstance(output, Output) # Get color depth. - color_depth = color_depth or ColorDepth.default() + color_depth = color_depth or output.get_default_color_depth() # Merges values. def to_text(val: Any) -> StyleAndTextTuples: diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/styles/pygments.py prompt-toolkit-3.0.6/prompt_toolkit/styles/pygments.py --- prompt-toolkit-3.0.5/prompt_toolkit/styles/pygments.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/styles/pygments.py 2020-08-01 20:16:17.000000000 +0000 @@ -11,8 +11,8 @@ from .style import Style if TYPE_CHECKING: - from pygments.token import Token from pygments.style import Style as PygmentsStyle + from pygments.token import Token __all__ = [ diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/utils.py prompt-toolkit-3.0.6/prompt_toolkit/utils.py --- prompt-toolkit-3.0.5/prompt_toolkit/utils.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/utils.py 2020-08-01 20:16:17.000000000 +0000 @@ -26,6 +26,7 @@ "is_conemu_ansi", "is_windows", "in_main_thread", + "get_term_environment_variable", "take_using_weights", "to_str", "to_int", diff -Nru prompt-toolkit-3.0.5/prompt_toolkit/widgets/base.py prompt-toolkit-3.0.6/prompt_toolkit/widgets/base.py --- prompt-toolkit-3.0.5/prompt_toolkit/widgets/base.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit/widgets/base.py 2020-08-01 20:16:17.000000000 +0000 @@ -59,7 +59,11 @@ from prompt_toolkit.layout.dimension import AnyDimension from prompt_toolkit.layout.dimension import Dimension as D from prompt_toolkit.layout.dimension import to_dimension -from prompt_toolkit.layout.margins import NumberedMargin, ScrollbarMargin +from prompt_toolkit.layout.margins import ( + ConditionalMargin, + NumberedMargin, + ScrollbarMargin, +) from prompt_toolkit.layout.processors import ( AppendAutoSuggestion, BeforeInput, @@ -275,7 +279,7 @@ @text.setter def text(self, value: str) -> None: - self.buffer.set_document(Document(value, 0), bypass_readonly=True) + self.document = Document(value, 0) @property def document(self) -> Document: @@ -286,7 +290,7 @@ @document.setter def document(self, value: Document) -> None: - self.buffer.document = value + self.buffer.set_document(value, bypass_readonly=True) @property def accept_handler(self) -> Optional[BufferAcceptHandler]: @@ -639,6 +643,7 @@ selected_style: str = "" checked_style: str = "" multiple_selection: bool = False + show_scrollbar: bool = True def __init__(self, values: Sequence[Tuple[_T, AnyFormattedText]]) -> None: assert len(values) > 0 @@ -702,7 +707,12 @@ self.window = Window( content=self.control, style=self.container_style, - right_margins=[ScrollbarMargin(display_arrows=True),], + right_margins=[ + ConditionalMargin( + margin=ScrollbarMargin(display_arrows=True), + filter=Condition(lambda: self.show_scrollbar), + ), + ], dont_extend_height=True, ) @@ -804,14 +814,24 @@ :param text: the text """ - def __init__(self, text: AnyFormattedText = "") -> None: + show_scrollbar = False + + def __init__(self, text: AnyFormattedText = "", checked: bool = False) -> None: values = [("value", text)] CheckboxList.__init__(self, values) + self.checked = checked @property def checked(self) -> bool: return "value" in self.current_values + @checked.setter + def checked(self, value: bool) -> None: + if value: + self.current_values = ["value"] + else: + self.current_values = [] + class VerticalLine(object): """ diff -Nru prompt-toolkit-3.0.5/prompt_toolkit.egg-info/PKG-INFO prompt-toolkit-3.0.6/prompt_toolkit.egg-info/PKG-INFO --- prompt-toolkit-3.0.5/prompt_toolkit.egg-info/PKG-INFO 2020-03-26 08:06:10.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit.egg-info/PKG-INFO 2020-08-10 09:54:44.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: prompt-toolkit -Version: 3.0.5 +Version: 3.0.6 Summary: Library for building powerful interactive command lines in Python Home-page: https://github.com/prompt-toolkit/python-prompt-toolkit Author: Jonathan Slenders @@ -171,6 +171,7 @@ Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python Classifier: Topic :: Software Development diff -Nru prompt-toolkit-3.0.5/prompt_toolkit.egg-info/SOURCES.txt prompt-toolkit-3.0.6/prompt_toolkit.egg-info/SOURCES.txt --- prompt-toolkit-3.0.5/prompt_toolkit.egg-info/SOURCES.txt 2020-03-26 08:06:10.000000000 +0000 +++ prompt-toolkit-3.0.6/prompt_toolkit.egg-info/SOURCES.txt 2020-08-10 09:54:44.000000000 +0000 @@ -1,77 +1,12 @@ -.codecov.yml -.gitignore -.travis.yml AUTHORS.rst CHANGELOG LICENSE MANIFEST.in PROJECTS.rst README.rst -appveyor.yml -mypy.ini pyproject.toml setup.cfg setup.py -tox.ini -docs/Makefile -docs/conf.py -docs/index.rst -docs/make.bat -docs/images/auto-suggestion.png -docs/images/bottom-toolbar.png -docs/images/colored-prompt.png -docs/images/colorful-completions.png -docs/images/hello-world-prompt.png -docs/images/html-completion.png -docs/images/html-input.png -docs/images/logo_400px.png -docs/images/multiline-input.png -docs/images/number-validator.png -docs/images/ptpython-2.png -docs/images/ptpython-history-help.png -docs/images/ptpython-menu.png -docs/images/ptpython.png -docs/images/pymux.png -docs/images/pyvim.png -docs/images/rprompt.png -docs/images/dialogs/button.png -docs/images/dialogs/confirm.png -docs/images/dialogs/inputbox.png -docs/images/dialogs/messagebox.png -docs/images/dialogs/styled.png -docs/images/progress-bars/apt-get.png -docs/images/progress-bars/colored-title-and-label.png -docs/images/progress-bars/custom-key-bindings.png -docs/images/progress-bars/simple-progress-bar.png -docs/images/progress-bars/two-tasks.png -docs/images/repl/sqlite-1.png -docs/images/repl/sqlite-2.png -docs/images/repl/sqlite-3.png -docs/images/repl/sqlite-4.png -docs/images/repl/sqlite-5.png -docs/images/repl/sqlite-6.png -docs/pages/asking_for_input.rst -docs/pages/dialogs.rst -docs/pages/full_screen_apps.rst -docs/pages/gallery.rst -docs/pages/getting_started.rst -docs/pages/printing_text.rst -docs/pages/progress_bars.rst -docs/pages/reference.rst -docs/pages/advanced_topics/architecture.rst -docs/pages/advanced_topics/asyncio.rst -docs/pages/advanced_topics/filters.rst -docs/pages/advanced_topics/index.rst -docs/pages/advanced_topics/input_hooks.rst -docs/pages/advanced_topics/key_bindings.rst -docs/pages/advanced_topics/rendering_flow.rst -docs/pages/advanced_topics/rendering_pipeline.rst -docs/pages/advanced_topics/styling.rst -docs/pages/tutorials/index.rst -docs/pages/tutorials/repl.rst -docs/pages/upgrading/2.0.rst -docs/pages/upgrading/3.0.rst -docs/pages/upgrading/index.rst examples/gevent-get-input.py examples/dialogs/button_dialog.py examples/dialogs/checkbox_dialog.py @@ -138,6 +73,7 @@ examples/prompts/custom-key-binding.py examples/prompts/custom-lexer.py examples/prompts/custom-vi-operator-and-text-object.py +examples/prompts/fancy-zsh-prompt.py examples/prompts/finalterm-shell-integration.py examples/prompts/get-input-vi-mode.py examples/prompts/get-input-with-default.py @@ -180,7 +116,6 @@ examples/telnet/dialog.py examples/telnet/hello-world.py examples/telnet/toolbar.py -examples/tutorial/README.md examples/tutorial/sqlite-cli.py prompt_toolkit/__init__.py prompt_toolkit/auto_suggest.py @@ -194,6 +129,7 @@ prompt_toolkit/log.py prompt_toolkit/mouse_events.py prompt_toolkit/patch_stdout.py +prompt_toolkit/py.typed prompt_toolkit/renderer.py prompt_toolkit/search.py prompt_toolkit/selection.py @@ -345,5 +281,4 @@ tests/test_style_transformation.py tests/test_utils.py tests/test_vt100_output.py -tests/test_yank_nth_arg.py -tools/debug_vt100_input.py \ No newline at end of file +tests/test_yank_nth_arg.py \ No newline at end of file diff -Nru prompt-toolkit-3.0.5/setup.py prompt-toolkit-3.0.6/setup.py --- prompt-toolkit-3.0.5/setup.py 2020-03-06 06:19:13.000000000 +0000 +++ prompt-toolkit-3.0.6/setup.py 2020-07-31 10:42:30.000000000 +0000 @@ -27,6 +27,7 @@ long_description=long_description, long_description_content_type="text/x-rst", packages=find_packages("."), + package_data={"prompt_toolkit": ["py.typed"]}, install_requires=["wcwidth",], # We require Python 3.6.1 for two reasons: # - Syntax for variable annotations - PEP 526. @@ -48,6 +49,7 @@ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python", "Topic :: Software Development", diff -Nru prompt-toolkit-3.0.5/tools/debug_vt100_input.py prompt-toolkit-3.0.6/tools/debug_vt100_input.py --- prompt-toolkit-3.0.5/tools/debug_vt100_input.py 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/tools/debug_vt100_input.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -#!/usr/bin/env python -""" -Parse vt100 input and print keys. -For testing terminal input. -""" -import sys - -from prompt_toolkit.input.vt100 import raw_mode -from prompt_toolkit.input.vt100_parser import Vt100Parser -from prompt_toolkit.keys import Keys - - -def callback(key_press): - print(key_press) - - if key_press.key == Keys.ControlC: - sys.exit(0) - - -def main(): - stream = Vt100Parser(callback) - - with raw_mode(sys.stdin.fileno()): - while True: - c = sys.stdin.read(1) - stream.feed(c) - - -if __name__ == '__main__': - main() diff -Nru prompt-toolkit-3.0.5/tox.ini prompt-toolkit-3.0.6/tox.ini --- prompt-toolkit-3.0.5/tox.ini 2020-01-12 17:01:43.000000000 +0000 +++ prompt-toolkit-3.0.6/tox.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -# Tox (http://tox.testrun.org/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. To use it, "pip install tox" -# and then run "tox" from this directory. - -[tox] -envlist = py26, py27, py33, py34, py35, pypy, pypy3 - -[testenv] -commands = py.test [] - -deps= - pytest diff -Nru prompt-toolkit-3.0.5/.travis.yml prompt-toolkit-3.0.6/.travis.yml --- prompt-toolkit-3.0.5/.travis.yml 2020-03-06 06:18:08.000000000 +0000 +++ prompt-toolkit-3.0.6/.travis.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -sudo: false -cache: pip -language: python - -matrix: - include: - - python: 3.7 - dist: xenial - sudo: required - - python: 3.6 - -install: - - pip install . pytest coverage codecov flake8 mypy - - pip install isort black - - pip list - -script: - - echo "$TRAVIS_PYTHON_VERSION" - - flake8 prompt_toolkit - - coverage run -m pytest - - # Run type checker. - - mypy prompt_toolkit - - # Check wheather the imports were sorted correctly. - # When this fails, please run ./tools/sort-imports.sh - - isort -c -rc prompt_toolkit examples tests setup.py - - - black --check prompt_toolkit examples tests setup.py - -after_success: - - codecov