├── .gitignore ├── LICENSE ├── README.md ├── images └── example.gif ├── lib └── python3.7 │ └── site-packages │ ├── prompt_toolkit │ ├── __init__.py │ ├── application │ │ ├── __init__.py │ │ ├── application.py │ │ ├── current.py │ │ ├── dummy.py │ │ └── run_in_terminal.py │ ├── auto_suggest.py │ ├── buffer.py │ ├── cache.py │ ├── clipboard │ │ ├── __init__.py │ │ ├── base.py │ │ ├── in_memory.py │ │ └── pyperclip.py │ ├── completion │ │ ├── __init__.py │ │ ├── base.py │ │ ├── filesystem.py │ │ ├── fuzzy_completer.py │ │ ├── nested.py │ │ └── word_completer.py │ ├── contrib │ │ ├── __init__.py │ │ ├── completers │ │ │ ├── __init__.py │ │ │ └── system.py │ │ ├── regular_languages │ │ │ ├── __init__.py │ │ │ ├── compiler.py │ │ │ ├── completion.py │ │ │ ├── lexer.py │ │ │ ├── regex_parser.py │ │ │ └── validation.py │ │ ├── ssh │ │ │ ├── __init__.py │ │ │ └── server.py │ │ └── telnet │ │ │ ├── __init__.py │ │ │ ├── log.py │ │ │ ├── protocol.py │ │ │ └── server.py │ ├── data_structures.py │ ├── document.py │ ├── enums.py │ ├── eventloop │ │ ├── __init__.py │ │ ├── async_context_manager.py │ │ ├── async_generator.py │ │ ├── dummy_contextvars.py │ │ ├── inputhook.py │ │ ├── utils.py │ │ └── win32.py │ ├── filters │ │ ├── __init__.py │ │ ├── app.py │ │ ├── base.py │ │ ├── cli.py │ │ └── utils.py │ ├── formatted_text │ │ ├── __init__.py │ │ ├── ansi.py │ │ ├── base.py │ │ ├── html.py │ │ ├── pygments.py │ │ └── utils.py │ ├── history.py │ ├── input │ │ ├── __init__.py │ │ ├── ansi_escape_sequences.py │ │ ├── base.py │ │ ├── defaults.py │ │ ├── posix_pipe.py │ │ ├── posix_utils.py │ │ ├── typeahead.py │ │ ├── vt100.py │ │ ├── vt100_parser.py │ │ ├── win32.py │ │ └── win32_pipe.py │ ├── key_binding │ │ ├── __init__.py │ │ ├── bindings │ │ │ ├── __init__.py │ │ │ ├── auto_suggest.py │ │ │ ├── basic.py │ │ │ ├── completion.py │ │ │ ├── cpr.py │ │ │ ├── emacs.py │ │ │ ├── focus.py │ │ │ ├── mouse.py │ │ │ ├── named_commands.py │ │ │ ├── open_in_editor.py │ │ │ ├── page_navigation.py │ │ │ ├── scroll.py │ │ │ ├── search.py │ │ │ └── vi.py │ │ ├── defaults.py │ │ ├── digraphs.py │ │ ├── emacs_state.py │ │ ├── key_bindings.py │ │ ├── key_processor.py │ │ └── vi_state.py │ ├── keys.py │ ├── layout │ │ ├── __init__.py │ │ ├── containers.py │ │ ├── controls.py │ │ ├── dimension.py │ │ ├── dummy.py │ │ ├── layout.py │ │ ├── margins.py │ │ ├── menus.py │ │ ├── mouse_handlers.py │ │ ├── processors.py │ │ ├── screen.py │ │ └── utils.py │ ├── lexers │ │ ├── __init__.py │ │ ├── base.py │ │ └── pygments.py │ ├── log.py │ ├── mouse_events.py │ ├── output │ │ ├── __init__.py │ │ ├── base.py │ │ ├── color_depth.py │ │ ├── conemu.py │ │ ├── defaults.py │ │ ├── vt100.py │ │ ├── win32.py │ │ └── windows10.py │ ├── patch_stdout.py │ ├── renderer.py │ ├── search.py │ ├── selection.py │ ├── shortcuts │ │ ├── __init__.py │ │ ├── dialogs.py │ │ ├── progress_bar │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ └── formatters.py │ │ ├── prompt.py │ │ └── utils.py │ ├── styles │ │ ├── __init__.py │ │ ├── base.py │ │ ├── defaults.py │ │ ├── named_colors.py │ │ ├── pygments.py │ │ ├── style.py │ │ └── style_transformation.py │ ├── token.py │ ├── utils.py │ ├── validation.py │ ├── widgets │ │ ├── __init__.py │ │ ├── base.py │ │ ├── dialogs.py │ │ ├── menus.py │ │ └── toolbars.py │ └── win32_types.py │ └── wcwidth │ ├── __init__.py │ ├── table_wide.py │ ├── table_zero.py │ ├── tests │ ├── __init__.py │ └── test_core.py │ ├── version.json │ └── wcwidth.py ├── recall.py └── zsh-recall.plugin.zsh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | **/__pycache__/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Mingyu Kim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zsh-recall 2 | zsh plugin to use history more comfortably 3 | 4 | ![example](images/example.gif) 5 | 6 | ## How to install 7 | Add this repo to zsh plugin directory(`~/.oh-my-zsh/custom/plugins/`) 8 | 9 | Then, add plugin to plugin lists from `~/.zshrc` 10 | ``` 11 | plugins=( 12 | git 13 | zsh-syntax-highlighting 14 | zsh-autosuggestions 15 | zsh-recall # here! 16 | ... 17 | ) 18 | ``` 19 | 20 | ## How to use 21 | 22 | ``` 23 | rec 24 | recall 25 | ``` 26 | -------------------------------------------------------------------------------- /images/example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mango-tree/zsh-recall/e30cdf5b1034428ee4b944774a6369070078cf6c/images/example.gif -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | prompt_toolkit 3 | ============== 4 | 5 | Author: Jonathan Slenders 6 | 7 | Description: prompt_toolkit is a Library for building powerful interactive 8 | command lines in Python. It can be a replacement for GNU 9 | Readline, but it can be much more than that. 10 | 11 | See the examples directory to learn about the usage. 12 | 13 | Probably, to get started, you might also want to have a look at 14 | `prompt_toolkit.shortcuts.prompt`. 15 | """ 16 | from .application import Application 17 | from .formatted_text import ANSI, HTML 18 | from .shortcuts import PromptSession, print_formatted_text, prompt 19 | 20 | # Don't forget to update in `docs/conf.py`! 21 | __version__ = "3.0.5" 22 | 23 | # Version tuple. 24 | VERSION = tuple(__version__.split(".")) 25 | 26 | 27 | __all__ = [ 28 | # Application. 29 | "Application", 30 | # Shortcuts. 31 | "prompt", 32 | "PromptSession", 33 | "print_formatted_text", 34 | # Formatted text. 35 | "HTML", 36 | "ANSI", 37 | ] 38 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/application/__init__.py: -------------------------------------------------------------------------------- 1 | from .application import Application 2 | from .current import ( 3 | create_app_session, 4 | get_app, 5 | get_app_or_none, 6 | get_app_session, 7 | set_app, 8 | ) 9 | from .dummy import DummyApplication 10 | from .run_in_terminal import in_terminal, run_in_terminal 11 | 12 | __all__ = [ 13 | # Application. 14 | "Application", 15 | # Current. 16 | "get_app_session", 17 | "create_app_session", 18 | "get_app", 19 | "get_app_or_none", 20 | "set_app", 21 | # Dummy. 22 | "DummyApplication", 23 | # Run_in_terminal 24 | "in_terminal", 25 | "run_in_terminal", 26 | ] 27 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/application/current.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from contextlib import contextmanager 3 | from typing import TYPE_CHECKING, Any, Generator, Optional 4 | 5 | try: 6 | from contextvars import ContextVar 7 | except ImportError: 8 | from prompt_toolkit.eventloop.dummy_contextvars import ContextVar # type: ignore 9 | 10 | if TYPE_CHECKING: 11 | from .application import Application 12 | from prompt_toolkit.input.defaults import Input 13 | from prompt_toolkit.output.defaults import Output 14 | 15 | __all__ = [ 16 | "get_app_session", 17 | "get_app", 18 | "get_app_or_none", 19 | "set_app", 20 | "create_app_session", 21 | ] 22 | 23 | 24 | class AppSession: 25 | """ 26 | An AppSession is an interactive session, usually connected to one terminal. 27 | Within one such session, interaction with many applications can happen, one 28 | after the other. 29 | 30 | The input/output device is not supposed to change during one session. 31 | 32 | :param input: Use this as a default input for all applications 33 | running in this session, unless an input is passed to the `Application` 34 | explicitely. 35 | :param output: Use this as a default output. 36 | """ 37 | 38 | def __init__( 39 | self, input: Optional["Input"] = None, output: Optional["Output"] = None 40 | ) -> None: 41 | 42 | self._input = input 43 | self._output = output 44 | 45 | # The application will be set dynamically by the `set_app` context 46 | # manager. This is called in the application itself. 47 | self.app: Optional["Application[Any]"] = None 48 | 49 | def __repr__(self) -> str: 50 | return "AppSession(app=%r)" % (self.app,) 51 | 52 | @property 53 | def input(self) -> "Input": 54 | if self._input is None: 55 | from prompt_toolkit.input.defaults import create_input 56 | 57 | self._input = create_input() 58 | return self._input 59 | 60 | @property 61 | def output(self) -> "Output": 62 | if self._output is None: 63 | from prompt_toolkit.output.defaults import create_output 64 | 65 | self._output = create_output() 66 | return self._output 67 | 68 | 69 | _current_app_session: ContextVar["AppSession"] = ContextVar( 70 | "_current_app_session", default=AppSession() 71 | ) 72 | 73 | 74 | def get_app_session() -> AppSession: 75 | return _current_app_session.get() 76 | 77 | 78 | def get_app() -> "Application[Any]": 79 | """ 80 | Get the current active (running) Application. 81 | An :class:`.Application` is active during the 82 | :meth:`.Application.run_async` call. 83 | 84 | We assume that there can only be one :class:`.Application` active at the 85 | same time. There is only one terminal window, with only one stdin and 86 | stdout. This makes the code significantly easier than passing around the 87 | :class:`.Application` everywhere. 88 | 89 | If no :class:`.Application` is running, then return by default a 90 | :class:`.DummyApplication`. For practical reasons, we prefer to not raise 91 | an exception. This way, we don't have to check all over the place whether 92 | an actual `Application` was returned. 93 | 94 | (For applications like pymux where we can have more than one `Application`, 95 | we'll use a work-around to handle that.) 96 | """ 97 | session = _current_app_session.get() 98 | if session.app is not None: 99 | return session.app 100 | 101 | from .dummy import DummyApplication 102 | 103 | return DummyApplication() 104 | 105 | 106 | def get_app_or_none() -> Optional["Application[Any]"]: 107 | """ 108 | Get the current active (running) Application, or return `None` if no 109 | application is running. 110 | """ 111 | session = _current_app_session.get() 112 | return session.app 113 | 114 | 115 | @contextmanager 116 | def set_app(app: "Application[Any]") -> Generator[None, None, None]: 117 | """ 118 | Context manager that sets the given :class:`.Application` active in an 119 | `AppSession`. 120 | 121 | This should only be called by the `Application` itself. 122 | The application will automatically be active while its running. If you want 123 | the application to be active in other threads/coroutines, where that's not 124 | the case, use `contextvars.copy_context()`, or use `Application.context` to 125 | run it in the appropriate context. 126 | """ 127 | session = _current_app_session.get() 128 | 129 | previous_app = session.app 130 | session.app = app 131 | try: 132 | yield 133 | finally: 134 | session.app = previous_app 135 | 136 | 137 | @contextmanager 138 | def create_app_session( 139 | input: Optional["Input"] = None, output: Optional["Output"] = None 140 | ) -> Generator[AppSession, None, None]: 141 | """ 142 | Create a separate AppSession. 143 | 144 | This is useful if there can be multiple individual `AppSession`s going on. 145 | Like in the case of an Telnet/SSH server. This functionality uses 146 | contextvars and requires at least Python 3.7. 147 | """ 148 | if sys.version_info <= (3, 6): 149 | raise RuntimeError("Application sessions require Python 3.7.") 150 | 151 | # If no input/output is specified, fall back to the current input/output, 152 | # whatever that is. 153 | if input is None: 154 | input = get_app_session().input 155 | if output is None: 156 | output = get_app_session().output 157 | 158 | # Create new `AppSession` and activate. 159 | session = AppSession(input=input, output=output) 160 | 161 | token = _current_app_session.set(session) 162 | try: 163 | yield session 164 | finally: 165 | _current_app_session.reset(token) 166 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/application/dummy.py: -------------------------------------------------------------------------------- 1 | from typing import Callable, Optional 2 | 3 | from prompt_toolkit.formatted_text import AnyFormattedText 4 | from prompt_toolkit.input import DummyInput 5 | from prompt_toolkit.output import DummyOutput 6 | 7 | from .application import Application 8 | 9 | __all__ = [ 10 | "DummyApplication", 11 | ] 12 | 13 | 14 | class DummyApplication(Application[None]): 15 | """ 16 | When no :class:`.Application` is running, 17 | :func:`.get_app` will run an instance of this :class:`.DummyApplication` instead. 18 | """ 19 | 20 | def __init__(self) -> None: 21 | super().__init__(output=DummyOutput(), input=DummyInput()) 22 | 23 | def run( 24 | self, 25 | pre_run: Optional[Callable[[], None]] = None, 26 | set_exception_handler: bool = True, 27 | ) -> None: 28 | raise NotImplementedError("A DummyApplication is not supposed to run.") 29 | 30 | async def run_async( 31 | self, 32 | pre_run: Optional[Callable[[], None]] = None, 33 | set_exception_handler: bool = True, 34 | ) -> None: 35 | raise NotImplementedError("A DummyApplication is not supposed to run.") 36 | 37 | async def run_system_command( 38 | self, 39 | command: str, 40 | wait_for_enter: bool = True, 41 | display_before_text: AnyFormattedText = "", 42 | wait_text: str = "", 43 | ) -> None: 44 | raise NotImplementedError 45 | 46 | def suspend_to_background(self, suspend_group: bool = True) -> None: 47 | raise NotImplementedError 48 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/application/run_in_terminal.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tools for running functions on the terminal above the current application or prompt. 3 | """ 4 | from asyncio import Future, ensure_future 5 | from typing import AsyncGenerator, Awaitable, Callable, TypeVar 6 | 7 | from prompt_toolkit.eventloop import run_in_executor_with_context 8 | 9 | from .current import get_app_or_none 10 | 11 | try: 12 | from contextlib import asynccontextmanager # type: ignore 13 | except ImportError: 14 | from prompt_toolkit.eventloop.async_context_manager import asynccontextmanager 15 | 16 | 17 | __all__ = [ 18 | "run_in_terminal", 19 | "in_terminal", 20 | ] 21 | 22 | _T = TypeVar("_T") 23 | 24 | 25 | def run_in_terminal( 26 | func: Callable[[], _T], render_cli_done: bool = False, in_executor: bool = False 27 | ) -> Awaitable[_T]: 28 | """ 29 | Run function on the terminal above the current application or prompt. 30 | 31 | What this does is first hiding the prompt, then running this callable 32 | (which can safely output to the terminal), and then again rendering the 33 | prompt which causes the output of this function to scroll above the 34 | prompt. 35 | 36 | ``func`` is supposed to be a synchronous function. If you need an 37 | asynchronous version of this function, use the ``in_terminal`` context 38 | manager directly. 39 | 40 | :param func: The callable to execute. 41 | :param render_cli_done: When True, render the interface in the 42 | 'Done' state first, then execute the function. If False, 43 | erase the interface first. 44 | :param in_executor: When True, run in executor. (Use this for long 45 | blocking functions, when you don't want to block the event loop.) 46 | 47 | :returns: A `Future`. 48 | """ 49 | 50 | async def run() -> _T: 51 | async with in_terminal(render_cli_done=render_cli_done): 52 | if in_executor: 53 | return await run_in_executor_with_context(func) 54 | else: 55 | return func() 56 | 57 | return ensure_future(run()) 58 | 59 | 60 | @asynccontextmanager 61 | async def in_terminal(render_cli_done: bool = False) -> AsyncGenerator[None, None]: 62 | """ 63 | Asynchronous context manager that suspends the current application and runs 64 | the body in the terminal. 65 | 66 | .. code:: 67 | 68 | async def f(): 69 | async with in_terminal(): 70 | call_some_function() 71 | await call_some_async_function() 72 | """ 73 | app = get_app_or_none() 74 | if app is None or not app._is_running: 75 | yield 76 | return 77 | 78 | # When a previous `run_in_terminal` call was in progress. Wait for that 79 | # to finish, before starting this one. Chain to previous call. 80 | previous_run_in_terminal_f = app._running_in_terminal_f 81 | new_run_in_terminal_f: Future[None] = Future() 82 | app._running_in_terminal_f = new_run_in_terminal_f 83 | 84 | # Wait for the previous `run_in_terminal` to finish. 85 | if previous_run_in_terminal_f is not None: 86 | await previous_run_in_terminal_f 87 | 88 | # Wait for all CPRs to arrive. We don't want to detach the input until 89 | # all cursor position responses have been arrived. Otherwise, the tty 90 | # will echo its input and can show stuff like ^[[39;1R. 91 | if app.input.responds_to_cpr: 92 | await app.renderer.wait_for_cpr_responses() 93 | 94 | # Draw interface in 'done' state, or erase. 95 | if render_cli_done: 96 | app._redraw(render_as_done=True) 97 | else: 98 | app.renderer.erase() 99 | 100 | # Disable rendering. 101 | app._running_in_terminal = True 102 | 103 | # Detach input. 104 | try: 105 | with app.input.detach(): 106 | with app.input.cooked_mode(): 107 | yield 108 | finally: 109 | # Redraw interface again. 110 | try: 111 | app._running_in_terminal = False 112 | app.renderer.reset() 113 | app._request_absolute_cursor_position() 114 | app._redraw() 115 | finally: 116 | new_run_in_terminal_f.set_result(None) 117 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/cache.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | from functools import wraps 3 | from typing import Any, Callable, Deque, Dict, Generic, Hashable, Tuple, TypeVar, cast 4 | 5 | __all__ = [ 6 | "SimpleCache", 7 | "FastDictCache", 8 | "memoized", 9 | ] 10 | 11 | _T = TypeVar("_T", bound=Hashable) 12 | _U = TypeVar("_U") 13 | 14 | 15 | class SimpleCache(Generic[_T, _U]): 16 | """ 17 | Very simple cache that discards the oldest item when the cache size is 18 | exceeded. 19 | 20 | :param maxsize: Maximum size of the cache. (Don't make it too big.) 21 | """ 22 | 23 | def __init__(self, maxsize: int = 8) -> None: 24 | assert maxsize > 0 25 | 26 | self._data: Dict[_T, _U] = {} 27 | self._keys: Deque[_T] = deque() 28 | self.maxsize: int = maxsize 29 | 30 | def get(self, key: _T, getter_func: Callable[[], _U]) -> _U: 31 | """ 32 | Get object from the cache. 33 | If not found, call `getter_func` to resolve it, and put that on the top 34 | of the cache instead. 35 | """ 36 | # Look in cache first. 37 | try: 38 | return self._data[key] 39 | except KeyError: 40 | # Not found? Get it. 41 | value = getter_func() 42 | self._data[key] = value 43 | self._keys.append(key) 44 | 45 | # Remove the oldest key when the size is exceeded. 46 | if len(self._data) > self.maxsize: 47 | key_to_remove = self._keys.popleft() 48 | if key_to_remove in self._data: 49 | del self._data[key_to_remove] 50 | 51 | return value 52 | 53 | def clear(self) -> None: 54 | " Clear cache. " 55 | self._data = {} 56 | self._keys = deque() 57 | 58 | 59 | _K = TypeVar("_K", bound=Tuple) 60 | _V = TypeVar("_V") 61 | 62 | 63 | class FastDictCache(Dict[_K, _V]): 64 | """ 65 | Fast, lightweight cache which keeps at most `size` items. 66 | It will discard the oldest items in the cache first. 67 | 68 | The cache is a dictionary, which doesn't keep track of access counts. 69 | It is perfect to cache little immutable objects which are not expensive to 70 | create, but where a dictionary lookup is still much faster than an object 71 | instantiation. 72 | 73 | :param get_value: Callable that's called in case of a missing key. 74 | """ 75 | 76 | # NOTE: This cache is used to cache `prompt_toolkit.layout.screen.Char` and 77 | # `prompt_toolkit.Document`. Make sure to keep this really lightweight. 78 | # Accessing the cache should stay faster than instantiating new 79 | # objects. 80 | # (Dictionary lookups are really fast.) 81 | # SimpleCache is still required for cases where the cache key is not 82 | # the same as the arguments given to the function that creates the 83 | # value.) 84 | def __init__(self, get_value: Callable[..., _V], size: int = 1000000) -> None: 85 | assert size > 0 86 | 87 | self._keys: Deque[_K] = deque() 88 | self.get_value = get_value 89 | self.size = size 90 | 91 | def __missing__(self, key: _K) -> _V: 92 | # Remove the oldest key when the size is exceeded. 93 | if len(self) > self.size: 94 | key_to_remove = self._keys.popleft() 95 | if key_to_remove in self: 96 | del self[key_to_remove] 97 | 98 | result = self.get_value(*key) 99 | self[key] = result 100 | self._keys.append(key) 101 | return result 102 | 103 | 104 | _F = TypeVar("_F", bound=Callable) 105 | 106 | 107 | def memoized(maxsize: int = 1024) -> Callable[[_F], _F]: 108 | """ 109 | Memoization decorator for immutable classes and pure functions. 110 | """ 111 | 112 | def decorator(obj: _F) -> _F: 113 | cache: SimpleCache[Hashable, Any] = SimpleCache(maxsize=maxsize) 114 | 115 | @wraps(obj) 116 | def new_callable(*a: Any, **kw: Any) -> Any: 117 | def create_new() -> Any: 118 | return obj(*a, **kw) 119 | 120 | key = (a, tuple(sorted(kw.items()))) 121 | return cache.get(key, create_new) 122 | 123 | return cast(_F, new_callable) 124 | 125 | return decorator 126 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/clipboard/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import Clipboard, ClipboardData, DummyClipboard, DynamicClipboard 2 | from .in_memory import InMemoryClipboard 3 | 4 | # We are not importing `PyperclipClipboard` here, because it would require the 5 | # `pyperclip` module to be present. 6 | 7 | # from .pyperclip import PyperclipClipboard 8 | 9 | __all__ = [ 10 | "Clipboard", 11 | "ClipboardData", 12 | "DummyClipboard", 13 | "DynamicClipboard", 14 | "InMemoryClipboard", 15 | ] 16 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/clipboard/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | Clipboard for command line interface. 3 | """ 4 | from abc import ABCMeta, abstractmethod 5 | from typing import Callable, Optional 6 | 7 | from prompt_toolkit.selection import SelectionType 8 | 9 | __all__ = [ 10 | "Clipboard", 11 | "ClipboardData", 12 | "DummyClipboard", 13 | "DynamicClipboard", 14 | ] 15 | 16 | 17 | class ClipboardData: 18 | """ 19 | Text on the clipboard. 20 | 21 | :param text: string 22 | :param type: :class:`~prompt_toolkit.selection.SelectionType` 23 | """ 24 | 25 | def __init__( 26 | self, text: str = "", type: SelectionType = SelectionType.CHARACTERS 27 | ) -> None: 28 | 29 | self.text = text 30 | self.type = type 31 | 32 | 33 | class Clipboard(metaclass=ABCMeta): 34 | """ 35 | Abstract baseclass for clipboards. 36 | (An implementation can be in memory, it can share the X11 or Windows 37 | keyboard, or can be persistent.) 38 | """ 39 | 40 | @abstractmethod 41 | def set_data(self, data: ClipboardData) -> None: 42 | """ 43 | Set data to the clipboard. 44 | 45 | :param data: :class:`~.ClipboardData` instance. 46 | """ 47 | 48 | def set_text(self, text: str) -> None: # Not abstract. 49 | """ 50 | Shortcut for setting plain text on clipboard. 51 | """ 52 | self.set_data(ClipboardData(text)) 53 | 54 | def rotate(self) -> None: 55 | """ 56 | For Emacs mode, rotate the kill ring. 57 | """ 58 | 59 | @abstractmethod 60 | def get_data(self) -> ClipboardData: 61 | """ 62 | Return clipboard data. 63 | """ 64 | 65 | 66 | class DummyClipboard(Clipboard): 67 | """ 68 | Clipboard implementation that doesn't remember anything. 69 | """ 70 | 71 | def set_data(self, data: ClipboardData) -> None: 72 | pass 73 | 74 | def set_text(self, text: str) -> None: 75 | pass 76 | 77 | def rotate(self) -> None: 78 | pass 79 | 80 | def get_data(self) -> ClipboardData: 81 | return ClipboardData() 82 | 83 | 84 | class DynamicClipboard(Clipboard): 85 | """ 86 | Clipboard class that can dynamically returns any Clipboard. 87 | 88 | :param get_clipboard: Callable that returns a :class:`.Clipboard` instance. 89 | """ 90 | 91 | def __init__(self, get_clipboard: Callable[[], Optional[Clipboard]]) -> None: 92 | self.get_clipboard = get_clipboard 93 | 94 | def _clipboard(self) -> Clipboard: 95 | return self.get_clipboard() or DummyClipboard() 96 | 97 | def set_data(self, data: ClipboardData) -> None: 98 | self._clipboard().set_data(data) 99 | 100 | def set_text(self, text: str) -> None: 101 | self._clipboard().set_text(text) 102 | 103 | def rotate(self) -> None: 104 | self._clipboard().rotate() 105 | 106 | def get_data(self) -> ClipboardData: 107 | return self._clipboard().get_data() 108 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/clipboard/in_memory.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | from typing import Deque, Optional 3 | 4 | from .base import Clipboard, ClipboardData 5 | 6 | __all__ = [ 7 | "InMemoryClipboard", 8 | ] 9 | 10 | 11 | class InMemoryClipboard(Clipboard): 12 | """ 13 | Default clipboard implementation. 14 | Just keep the data in memory. 15 | 16 | This implements a kill-ring, for Emacs mode. 17 | """ 18 | 19 | def __init__( 20 | self, data: Optional[ClipboardData] = None, max_size: int = 60 21 | ) -> None: 22 | 23 | assert max_size >= 1 24 | 25 | self.max_size = max_size 26 | self._ring: Deque[ClipboardData] = deque() 27 | 28 | if data is not None: 29 | self.set_data(data) 30 | 31 | def set_data(self, data: ClipboardData) -> None: 32 | self._ring.appendleft(data) 33 | 34 | while len(self._ring) > self.max_size: 35 | self._ring.pop() 36 | 37 | def get_data(self) -> ClipboardData: 38 | if self._ring: 39 | return self._ring[0] 40 | else: 41 | return ClipboardData() 42 | 43 | def rotate(self) -> None: 44 | if self._ring: 45 | # Add the very first item at the end. 46 | self._ring.append(self._ring.popleft()) 47 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/clipboard/pyperclip.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | import pyperclip 4 | from prompt_toolkit.selection import SelectionType 5 | 6 | from .base import Clipboard, ClipboardData 7 | 8 | __all__ = [ 9 | "PyperclipClipboard", 10 | ] 11 | 12 | 13 | class PyperclipClipboard(Clipboard): 14 | """ 15 | Clipboard that synchronizes with the Windows/Mac/Linux system clipboard, 16 | using the pyperclip module. 17 | """ 18 | 19 | def __init__(self) -> None: 20 | self._data: Optional[ClipboardData] = None 21 | 22 | def set_data(self, data: ClipboardData) -> None: 23 | self._data = data 24 | pyperclip.copy(data.text) 25 | 26 | def get_data(self) -> ClipboardData: 27 | text = pyperclip.paste() 28 | 29 | # When the clipboard data is equal to what we copied last time, reuse 30 | # the `ClipboardData` instance. That way we're sure to keep the same 31 | # `SelectionType`. 32 | if self._data and self._data.text == text: 33 | return self._data 34 | 35 | # Pyperclip returned something else. Create a new `ClipboardData` 36 | # instance. 37 | else: 38 | return ClipboardData( 39 | text=text, 40 | type=SelectionType.LINES if "\n" in text else SelectionType.LINES, 41 | ) 42 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/completion/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import ( 2 | CompleteEvent, 3 | Completer, 4 | Completion, 5 | DummyCompleter, 6 | DynamicCompleter, 7 | ThreadedCompleter, 8 | get_common_complete_suffix, 9 | merge_completers, 10 | ) 11 | from .filesystem import ExecutableCompleter, PathCompleter 12 | from .fuzzy_completer import FuzzyCompleter, FuzzyWordCompleter 13 | from .nested import NestedCompleter 14 | from .word_completer import WordCompleter 15 | 16 | __all__ = [ 17 | # Base. 18 | "Completion", 19 | "Completer", 20 | "ThreadedCompleter", 21 | "DummyCompleter", 22 | "DynamicCompleter", 23 | "CompleteEvent", 24 | "merge_completers", 25 | "get_common_complete_suffix", 26 | # Filesystem. 27 | "PathCompleter", 28 | "ExecutableCompleter", 29 | # Fuzzy 30 | "FuzzyCompleter", 31 | "FuzzyWordCompleter", 32 | # Nested. 33 | "NestedCompleter", 34 | # Word completer. 35 | "WordCompleter", 36 | ] 37 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/completion/filesystem.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Callable, Iterable, List, Optional 3 | 4 | from prompt_toolkit.completion import CompleteEvent, Completer, Completion 5 | from prompt_toolkit.document import Document 6 | 7 | __all__ = [ 8 | "PathCompleter", 9 | "ExecutableCompleter", 10 | ] 11 | 12 | 13 | class PathCompleter(Completer): 14 | """ 15 | Complete for Path variables. 16 | 17 | :param get_paths: Callable which returns a list of directories to look into 18 | when the user enters a relative path. 19 | :param file_filter: Callable which takes a filename and returns whether 20 | this file should show up in the completion. ``None`` 21 | when no filtering has to be done. 22 | :param min_input_len: Don't do autocompletion when the input string is shorter. 23 | """ 24 | 25 | def __init__( 26 | self, 27 | only_directories: bool = False, 28 | get_paths: Optional[Callable[[], List[str]]] = None, 29 | file_filter: Optional[Callable[[str], bool]] = None, 30 | min_input_len: int = 0, 31 | expanduser: bool = False, 32 | ) -> None: 33 | 34 | self.only_directories = only_directories 35 | self.get_paths = get_paths or (lambda: ["."]) 36 | self.file_filter = file_filter or (lambda _: True) 37 | self.min_input_len = min_input_len 38 | self.expanduser = expanduser 39 | 40 | def get_completions( 41 | self, document: Document, complete_event: CompleteEvent 42 | ) -> Iterable[Completion]: 43 | text = document.text_before_cursor 44 | 45 | # Complete only when we have at least the minimal input length, 46 | # otherwise, we can too many results and autocompletion will become too 47 | # heavy. 48 | if len(text) < self.min_input_len: 49 | return 50 | 51 | try: 52 | # Do tilde expansion. 53 | if self.expanduser: 54 | text = os.path.expanduser(text) 55 | 56 | # Directories where to look. 57 | dirname = os.path.dirname(text) 58 | if dirname: 59 | directories = [ 60 | os.path.dirname(os.path.join(p, text)) for p in self.get_paths() 61 | ] 62 | else: 63 | directories = self.get_paths() 64 | 65 | # Start of current file. 66 | prefix = os.path.basename(text) 67 | 68 | # Get all filenames. 69 | filenames = [] 70 | for directory in directories: 71 | # Look for matches in this directory. 72 | if os.path.isdir(directory): 73 | for filename in os.listdir(directory): 74 | if filename.startswith(prefix): 75 | filenames.append((directory, filename)) 76 | 77 | # Sort 78 | filenames = sorted(filenames, key=lambda k: k[1]) 79 | 80 | # Yield them. 81 | for directory, filename in filenames: 82 | completion = filename[len(prefix) :] 83 | full_name = os.path.join(directory, filename) 84 | 85 | if os.path.isdir(full_name): 86 | # For directories, add a slash to the filename. 87 | # (We don't add them to the `completion`. Users can type it 88 | # to trigger the autocompletion themselves.) 89 | filename += "/" 90 | elif self.only_directories: 91 | continue 92 | 93 | if not self.file_filter(full_name): 94 | continue 95 | 96 | yield Completion(completion, 0, display=filename) 97 | except OSError: 98 | pass 99 | 100 | 101 | class ExecutableCompleter(PathCompleter): 102 | """ 103 | Complete only executable files in the current path. 104 | """ 105 | 106 | def __init__(self) -> None: 107 | super().__init__( 108 | only_directories=False, 109 | min_input_len=1, 110 | get_paths=lambda: os.environ.get("PATH", "").split(os.pathsep), 111 | file_filter=lambda name: os.access(name, os.X_OK), 112 | expanduser=True, 113 | ), 114 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/completion/nested.py: -------------------------------------------------------------------------------- 1 | """ 2 | Nestedcompleter for completion of hierarchical data structures. 3 | """ 4 | from typing import Any, Dict, Iterable, Mapping, Optional, Set, Union 5 | 6 | from prompt_toolkit.completion import CompleteEvent, Completer, Completion 7 | from prompt_toolkit.completion.word_completer import WordCompleter 8 | from prompt_toolkit.document import Document 9 | 10 | __all__ = ["NestedCompleter"] 11 | 12 | # NestedDict = Mapping[str, Union['NestedDict', Set[str], None, Completer]] 13 | NestedDict = Mapping[str, Union[Any, Set[str], None, Completer]] 14 | 15 | 16 | class NestedCompleter(Completer): 17 | """ 18 | Completer which wraps around several other completers, and calls any the 19 | one that corresponds with the first word of the input. 20 | 21 | By combining multiple `NestedCompleter` instances, we can achieve multiple 22 | hierarchical levels of autocompletion. This is useful when `WordCompleter` 23 | is not sufficient. 24 | 25 | If you need multiple levels, check out the `from_nested_dict` classmethod. 26 | """ 27 | 28 | def __init__( 29 | self, options: Dict[str, Optional[Completer]], ignore_case: bool = True 30 | ) -> None: 31 | 32 | self.options = options 33 | self.ignore_case = ignore_case 34 | 35 | def __repr__(self) -> str: 36 | return "NestedCompleter(%r, ignore_case=%r)" % (self.options, self.ignore_case) 37 | 38 | @classmethod 39 | def from_nested_dict(cls, data: NestedDict) -> "NestedCompleter": 40 | """ 41 | Create a `NestedCompleter`, starting from a nested dictionary data 42 | structure, like this: 43 | 44 | .. code:: 45 | 46 | data = { 47 | 'show': { 48 | 'version': None, 49 | 'interfaces': None, 50 | 'clock': None, 51 | 'ip': {'interface': {'brief'}} 52 | }, 53 | 'exit': None 54 | 'enable': None 55 | } 56 | 57 | The value should be `None` if there is no further completion at some 58 | point. If all values in the dictionary are None, it is also possible to 59 | use a set instead. 60 | 61 | Values in this data structure can be a completers as well. 62 | """ 63 | options: Dict[str, Optional[Completer]] = {} 64 | for key, value in data.items(): 65 | if isinstance(value, Completer): 66 | options[key] = value 67 | elif isinstance(value, dict): 68 | options[key] = cls.from_nested_dict(value) 69 | elif isinstance(value, set): 70 | options[key] = cls.from_nested_dict({item: None for item in value}) 71 | else: 72 | assert value is None 73 | options[key] = None 74 | 75 | return cls(options) 76 | 77 | def get_completions( 78 | self, document: Document, complete_event: CompleteEvent 79 | ) -> Iterable[Completion]: 80 | # Split document. 81 | text = document.text_before_cursor.lstrip() 82 | stripped_len = len(document.text_before_cursor) - len(text) 83 | 84 | # If there is a space, check for the first term, and use a 85 | # subcompleter. 86 | if " " in text: 87 | first_term = text.split()[0] 88 | completer = self.options.get(first_term) 89 | 90 | # If we have a sub completer, use this for the completions. 91 | if completer is not None: 92 | remaining_text = text[len(first_term) :].lstrip() 93 | move_cursor = len(text) - len(remaining_text) + stripped_len 94 | 95 | new_document = Document( 96 | remaining_text, 97 | cursor_position=document.cursor_position - move_cursor, 98 | ) 99 | 100 | for c in completer.get_completions(new_document, complete_event): 101 | yield c 102 | 103 | # No space in the input: behave exactly like `WordCompleter`. 104 | else: 105 | completer = WordCompleter( 106 | list(self.options.keys()), ignore_case=self.ignore_case 107 | ) 108 | for c in completer.get_completions(document, complete_event): 109 | yield c 110 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/completion/word_completer.py: -------------------------------------------------------------------------------- 1 | from typing import Callable, Dict, Iterable, List, Optional, Pattern, Union 2 | 3 | from prompt_toolkit.completion import CompleteEvent, Completer, Completion 4 | from prompt_toolkit.document import Document 5 | 6 | __all__ = [ 7 | "WordCompleter", 8 | ] 9 | 10 | 11 | class WordCompleter(Completer): 12 | """ 13 | Simple autocompletion on a list of words. 14 | 15 | :param words: List of words or callable that returns a list of words. 16 | :param ignore_case: If True, case-insensitive completion. 17 | :param meta_dict: Optional dict mapping words to their meta-text. (This 18 | should map strings to strings or formatted text.) 19 | :param WORD: When True, use WORD characters. 20 | :param sentence: When True, don't complete by comparing the word before the 21 | cursor, but by comparing all the text before the cursor. In this case, 22 | the list of words is just a list of strings, where each string can 23 | contain spaces. (Can not be used together with the WORD option.) 24 | :param match_middle: When True, match not only the start, but also in the 25 | middle of the word. 26 | :param pattern: Optional regex. When given, use this regex 27 | pattern instead of default one. 28 | """ 29 | 30 | def __init__( 31 | self, 32 | words: Union[List[str], Callable[[], List[str]]], 33 | ignore_case: bool = False, 34 | meta_dict: Optional[Dict[str, str]] = None, 35 | WORD: bool = False, 36 | sentence: bool = False, 37 | match_middle: bool = False, 38 | pattern: Optional[Pattern[str]] = None, 39 | ) -> None: 40 | 41 | assert not (WORD and sentence) 42 | 43 | self.words = words 44 | self.ignore_case = ignore_case 45 | self.meta_dict = meta_dict or {} 46 | self.WORD = WORD 47 | self.sentence = sentence 48 | self.match_middle = match_middle 49 | self.pattern = pattern 50 | 51 | def get_completions( 52 | self, document: Document, complete_event: CompleteEvent 53 | ) -> Iterable[Completion]: 54 | # Get list of words. 55 | words = self.words 56 | if callable(words): 57 | words = words() 58 | 59 | # Get word/text before cursor. 60 | if self.sentence: 61 | word_before_cursor = document.text_before_cursor 62 | else: 63 | word_before_cursor = document.get_word_before_cursor( 64 | WORD=self.WORD, pattern=self.pattern 65 | ) 66 | 67 | if self.ignore_case: 68 | word_before_cursor = word_before_cursor.lower() 69 | 70 | def word_matches(word: str) -> bool: 71 | """ True when the word before the cursor matches. """ 72 | if self.ignore_case: 73 | word = word.lower() 74 | 75 | if self.match_middle: 76 | return word_before_cursor in word 77 | else: 78 | return word.startswith(word_before_cursor) 79 | 80 | for a in words: 81 | if word_matches(a): 82 | display_meta = self.meta_dict.get(a, "") 83 | yield Completion(a, -len(word_before_cursor), display_meta=display_meta) 84 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mango-tree/zsh-recall/e30cdf5b1034428ee4b944774a6369070078cf6c/lib/python3.7/site-packages/prompt_toolkit/contrib/__init__.py -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/completers/__init__.py: -------------------------------------------------------------------------------- 1 | from .system import SystemCompleter 2 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/completers/system.py: -------------------------------------------------------------------------------- 1 | from prompt_toolkit.completion.filesystem import ExecutableCompleter, PathCompleter 2 | from prompt_toolkit.contrib.regular_languages.compiler import compile 3 | from prompt_toolkit.contrib.regular_languages.completion import GrammarCompleter 4 | 5 | __all__ = [ 6 | "SystemCompleter", 7 | ] 8 | 9 | 10 | class SystemCompleter(GrammarCompleter): 11 | """ 12 | Completer for system commands. 13 | """ 14 | 15 | def __init__(self) -> None: 16 | # Compile grammar. 17 | g = compile( 18 | r""" 19 | # First we have an executable. 20 | (?P[^\s]+) 21 | 22 | # Ignore literals in between. 23 | ( 24 | \s+ 25 | ("[^"]*" | '[^']*' | [^'"]+ ) 26 | )* 27 | 28 | \s+ 29 | 30 | # Filename as parameters. 31 | ( 32 | (?P[^\s]+) | 33 | "(?P[^\s]+)" | 34 | '(?P[^\s]+)' 35 | ) 36 | """, 37 | escape_funcs={ 38 | "double_quoted_filename": (lambda string: string.replace('"', '\\"')), 39 | "single_quoted_filename": (lambda string: string.replace("'", "\\'")), 40 | }, 41 | unescape_funcs={ 42 | "double_quoted_filename": ( 43 | lambda string: string.replace('\\"', '"') 44 | ), # XXX: not entirely correct. 45 | "single_quoted_filename": (lambda string: string.replace("\\'", "'")), 46 | }, 47 | ) 48 | 49 | # Create GrammarCompleter 50 | super().__init__( 51 | g, 52 | { 53 | "executable": ExecutableCompleter(), 54 | "filename": PathCompleter(only_directories=False, expanduser=True), 55 | "double_quoted_filename": PathCompleter( 56 | only_directories=False, expanduser=True 57 | ), 58 | "single_quoted_filename": PathCompleter( 59 | only_directories=False, expanduser=True 60 | ), 61 | }, 62 | ) 63 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/regular_languages/__init__.py: -------------------------------------------------------------------------------- 1 | r""" 2 | Tool for expressing the grammar of an input as a regular language. 3 | ================================================================== 4 | 5 | The grammar for the input of many simple command line interfaces can be 6 | expressed by a regular language. Examples are PDB (the Python debugger); a 7 | simple (bash-like) shell with "pwd", "cd", "cat" and "ls" commands; arguments 8 | that you can pass to an executable; etc. It is possible to use regular 9 | expressions for validation and parsing of such a grammar. (More about regular 10 | languages: http://en.wikipedia.org/wiki/Regular_language) 11 | 12 | Example 13 | ------- 14 | 15 | Let's take the pwd/cd/cat/ls example. We want to have a shell that accepts 16 | these three commands. "cd" is followed by a quoted directory name and "cat" is 17 | followed by a quoted file name. (We allow quotes inside the filename when 18 | they're escaped with a backslash.) We could define the grammar using the 19 | following regular expression:: 20 | 21 | grammar = \s* ( 22 | pwd | 23 | ls | 24 | (cd \s+ " ([^"]|\.)+ ") | 25 | (cat \s+ " ([^"]|\.)+ ") 26 | ) \s* 27 | 28 | 29 | What can we do with this grammar? 30 | --------------------------------- 31 | 32 | - Syntax highlighting: We could use this for instance to give file names 33 | different colour. 34 | - Parse the result: .. We can extract the file names and commands by using a 35 | regular expression with named groups. 36 | - Input validation: .. Don't accept anything that does not match this grammar. 37 | When combined with a parser, we can also recursively do 38 | filename validation (and accept only existing files.) 39 | - Autocompletion: .... Each part of the grammar can have its own autocompleter. 40 | "cat" has to be completed using file names, while "cd" 41 | has to be completed using directory names. 42 | 43 | How does it work? 44 | ----------------- 45 | 46 | As a user of this library, you have to define the grammar of the input as a 47 | regular expression. The parts of this grammar where autocompletion, validation 48 | or any other processing is required need to be marked using a regex named 49 | group. Like ``(?P...)`` for instance. 50 | 51 | When the input is processed for validation (for instance), the regex will 52 | execute, the named group is captured, and the validator associated with this 53 | named group will test the captured string. 54 | 55 | There is one tricky bit: 56 | 57 | Often we operate on incomplete input (this is by definition the case for 58 | autocompletion) and we have to decide for the cursor position in which 59 | possible state the grammar it could be and in which way variables could be 60 | matched up to that point. 61 | 62 | To solve this problem, the compiler takes the original regular expression and 63 | translates it into a set of other regular expressions which each match certain 64 | prefixes of the original regular expression. We generate one prefix regular 65 | expression for every named variable (with this variable being the end of that 66 | expression). 67 | 68 | 69 | TODO: some examples of: 70 | - How to create a highlighter from this grammar. 71 | - How to create a validator from this grammar. 72 | - How to create an autocompleter from this grammar. 73 | - How to create a parser from this grammar. 74 | """ 75 | from .compiler import compile 76 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/regular_languages/completion.py: -------------------------------------------------------------------------------- 1 | """ 2 | Completer for a regular grammar. 3 | """ 4 | from typing import Dict, Iterable, List 5 | 6 | from prompt_toolkit.completion import CompleteEvent, Completer, Completion 7 | from prompt_toolkit.document import Document 8 | 9 | from .compiler import Match, _CompiledGrammar 10 | 11 | __all__ = [ 12 | "GrammarCompleter", 13 | ] 14 | 15 | 16 | class GrammarCompleter(Completer): 17 | """ 18 | Completer which can be used for autocompletion according to variables in 19 | the grammar. Each variable can have a different autocompleter. 20 | 21 | :param compiled_grammar: `GrammarCompleter` instance. 22 | :param completers: `dict` mapping variable names of the grammar to the 23 | `Completer` instances to be used for each variable. 24 | """ 25 | 26 | def __init__( 27 | self, compiled_grammar: _CompiledGrammar, completers: Dict[str, Completer] 28 | ) -> None: 29 | 30 | self.compiled_grammar = compiled_grammar 31 | self.completers = completers 32 | 33 | def get_completions( 34 | self, document: Document, complete_event: CompleteEvent 35 | ) -> Iterable[Completion]: 36 | m = self.compiled_grammar.match_prefix(document.text_before_cursor) 37 | 38 | if m: 39 | completions = self._remove_duplicates( 40 | self._get_completions_for_match(m, complete_event) 41 | ) 42 | 43 | for c in completions: 44 | yield c 45 | 46 | def _get_completions_for_match( 47 | self, match: Match, complete_event: CompleteEvent 48 | ) -> Iterable[Completion]: 49 | """ 50 | Yield all the possible completions for this input string. 51 | (The completer assumes that the cursor position was at the end of the 52 | input string.) 53 | """ 54 | for match_variable in match.end_nodes(): 55 | varname = match_variable.varname 56 | start = match_variable.start 57 | 58 | completer = self.completers.get(varname) 59 | 60 | if completer: 61 | text = match_variable.value 62 | 63 | # Unwrap text. 64 | unwrapped_text = self.compiled_grammar.unescape(varname, text) 65 | 66 | # Create a document, for the completions API (text/cursor_position) 67 | document = Document(unwrapped_text, len(unwrapped_text)) 68 | 69 | # Call completer 70 | for completion in completer.get_completions(document, complete_event): 71 | new_text = ( 72 | unwrapped_text[: len(text) + completion.start_position] 73 | + completion.text 74 | ) 75 | 76 | # Wrap again. 77 | yield Completion( 78 | text=self.compiled_grammar.escape(varname, new_text), 79 | start_position=start - len(match.string), 80 | display=completion.display, 81 | display_meta=completion.display_meta, 82 | ) 83 | 84 | def _remove_duplicates(self, items: Iterable[Completion]) -> List[Completion]: 85 | """ 86 | Remove duplicates, while keeping the order. 87 | (Sometimes we have duplicates, because the there several matches of the 88 | same grammar, each yielding similar completions.) 89 | """ 90 | result: List[Completion] = [] 91 | for i in items: 92 | if i not in result: 93 | result.append(i) 94 | return result 95 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/regular_languages/lexer.py: -------------------------------------------------------------------------------- 1 | """ 2 | `GrammarLexer` is compatible with other lexers and can be used to highlight 3 | the input using a regular grammar with annotations. 4 | """ 5 | from typing import Callable, Dict, Optional 6 | 7 | from prompt_toolkit.document import Document 8 | from prompt_toolkit.formatted_text.base import StyleAndTextTuples 9 | from prompt_toolkit.formatted_text.utils import split_lines 10 | from prompt_toolkit.lexers import Lexer 11 | 12 | from .compiler import _CompiledGrammar 13 | 14 | __all__ = [ 15 | "GrammarLexer", 16 | ] 17 | 18 | 19 | class GrammarLexer(Lexer): 20 | """ 21 | Lexer which can be used for highlighting of fragments according to variables in the grammar. 22 | 23 | (It does not actual lexing of the string, but it exposes an API, compatible 24 | with the Pygments lexer class.) 25 | 26 | :param compiled_grammar: Grammar as returned by the `compile()` function. 27 | :param lexers: Dictionary mapping variable names of the regular grammar to 28 | the lexers that should be used for this part. (This can 29 | call other lexers recursively.) If you wish a part of the 30 | grammar to just get one fragment, use a 31 | `prompt_toolkit.lexers.SimpleLexer`. 32 | """ 33 | 34 | def __init__( 35 | self, 36 | compiled_grammar: _CompiledGrammar, 37 | default_style: str = "", 38 | lexers: Optional[Dict[str, Lexer]] = None, 39 | ) -> None: 40 | 41 | self.compiled_grammar = compiled_grammar 42 | self.default_style = default_style 43 | self.lexers = lexers or {} 44 | 45 | def _get_text_fragments(self, text: str) -> StyleAndTextTuples: 46 | m = self.compiled_grammar.match_prefix(text) 47 | 48 | if m: 49 | characters: StyleAndTextTuples = [(self.default_style, c) for c in text] 50 | 51 | for v in m.variables(): 52 | # If we have a `Lexer` instance for this part of the input. 53 | # Tokenize recursively and apply tokens. 54 | lexer = self.lexers.get(v.varname) 55 | 56 | if lexer: 57 | document = Document(text[v.start : v.stop]) 58 | lexer_tokens_for_line = lexer.lex_document(document) 59 | text_fragments: StyleAndTextTuples = [] 60 | for i in range(len(document.lines)): 61 | text_fragments.extend(lexer_tokens_for_line(i)) 62 | text_fragments.append(("", "\n")) 63 | if text_fragments: 64 | text_fragments.pop() 65 | 66 | i = v.start 67 | for t, s, *_ in text_fragments: 68 | for c in s: 69 | if characters[i][0] == self.default_style: 70 | characters[i] = (t, characters[i][1]) 71 | i += 1 72 | 73 | # Highlight trailing input. 74 | trailing_input = m.trailing_input() 75 | if trailing_input: 76 | for i in range(trailing_input.start, trailing_input.stop): 77 | characters[i] = ("class:trailing-input", characters[i][1]) 78 | 79 | return characters 80 | else: 81 | return [("", text)] 82 | 83 | def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]: 84 | lines = list(split_lines(self._get_text_fragments(document.text))) 85 | 86 | def get_line(lineno: int) -> StyleAndTextTuples: 87 | try: 88 | return lines[lineno] 89 | except IndexError: 90 | return [] 91 | 92 | return get_line 93 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/regular_languages/validation.py: -------------------------------------------------------------------------------- 1 | """ 2 | Validator for a regular language. 3 | """ 4 | from typing import Dict 5 | 6 | from prompt_toolkit.document import Document 7 | from prompt_toolkit.validation import ValidationError, Validator 8 | 9 | from .compiler import _CompiledGrammar 10 | 11 | __all__ = [ 12 | "GrammarValidator", 13 | ] 14 | 15 | 16 | class GrammarValidator(Validator): 17 | """ 18 | Validator which can be used for validation according to variables in 19 | the grammar. Each variable can have its own validator. 20 | 21 | :param compiled_grammar: `GrammarCompleter` instance. 22 | :param validators: `dict` mapping variable names of the grammar to the 23 | `Validator` instances to be used for each variable. 24 | """ 25 | 26 | def __init__( 27 | self, compiled_grammar: _CompiledGrammar, validators: Dict[str, Validator] 28 | ) -> None: 29 | 30 | self.compiled_grammar = compiled_grammar 31 | self.validators = validators 32 | 33 | def validate(self, document: Document) -> None: 34 | # Parse input document. 35 | # We use `match`, not `match_prefix`, because for validation, we want 36 | # the actual, unambiguous interpretation of the input. 37 | m = self.compiled_grammar.match(document.text) 38 | 39 | if m: 40 | for v in m.variables(): 41 | validator = self.validators.get(v.varname) 42 | 43 | if validator: 44 | # Unescape text. 45 | unwrapped_text = self.compiled_grammar.unescape(v.varname, v.value) 46 | 47 | # Create a document, for the completions API (text/cursor_position) 48 | inner_document = Document(unwrapped_text, len(unwrapped_text)) 49 | 50 | try: 51 | validator.validate(inner_document) 52 | except ValidationError as e: 53 | raise ValidationError( 54 | cursor_position=v.start + e.cursor_position, 55 | message=e.message, 56 | ) 57 | else: 58 | raise ValidationError( 59 | cursor_position=len(document.text), message="Invalid command" 60 | ) 61 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/ssh/__init__.py: -------------------------------------------------------------------------------- 1 | from .server import PromptToolkitSession, PromptToolkitSSHServer 2 | 3 | __all__ = [ 4 | "PromptToolkitSession", 5 | "PromptToolkitSSHServer", 6 | ] 7 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/ssh/server.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utility for running a prompt_toolkit application in an asyncssh server. 3 | """ 4 | import asyncio 5 | import traceback 6 | from typing import Awaitable, Callable, Optional, TextIO, cast 7 | 8 | import asyncssh 9 | 10 | from prompt_toolkit.application.current import AppSession, create_app_session 11 | from prompt_toolkit.data_structures import Size 12 | from prompt_toolkit.input.posix_pipe import PosixPipeInput 13 | from prompt_toolkit.output.vt100 import Vt100_Output 14 | 15 | __all__ = [ 16 | "PromptToolkitSession", 17 | "PromptToolkitSSHServer", 18 | ] 19 | 20 | 21 | class PromptToolkitSession(asyncssh.SSHServerSession): 22 | def __init__(self, interact: Callable[[], Awaitable[None]]) -> None: 23 | self.interact = interact 24 | self._chan = None 25 | self.app_session: Optional[AppSession] = None 26 | 27 | # PipInput object, for sending input in the CLI. 28 | # (This is something that we can use in the prompt_toolkit event loop, 29 | # but still write date in manually.) 30 | self._input = PosixPipeInput() 31 | 32 | # Output object. Don't render to the real stdout, but write everything 33 | # in the SSH channel. 34 | class Stdout: 35 | def write(s, data): 36 | if self._chan is not None: 37 | self._chan.write(data.replace("\n", "\r\n")) 38 | 39 | def flush(s): 40 | pass 41 | 42 | self._output = Vt100_Output( 43 | cast(TextIO, Stdout()), self._get_size, write_binary=False 44 | ) 45 | 46 | def _get_size(self) -> Size: 47 | """ 48 | Callable that returns the current `Size`, required by Vt100_Output. 49 | """ 50 | if self._chan is None: 51 | return Size(rows=20, columns=79) 52 | else: 53 | width, height, pixwidth, pixheight = self._chan.get_terminal_size() 54 | return Size(rows=height, columns=width) 55 | 56 | def connection_made(self, chan): 57 | self._chan = chan 58 | 59 | def shell_requested(self) -> bool: 60 | return True 61 | 62 | def session_started(self) -> None: 63 | asyncio.get_event_loop().create_task(self._interact()) 64 | 65 | async def _interact(self) -> None: 66 | if self._chan is None: 67 | # Should not happen. 68 | raise Exception("`_interact` called before `connection_made`.") 69 | 70 | # Disable the line editing provided by asyncssh. Prompt_toolkit 71 | # provides the line editing. 72 | self._chan.set_line_mode(False) 73 | 74 | with create_app_session(input=self._input, output=self._output) as session: 75 | self.app_session = session 76 | try: 77 | await self.interact() 78 | except BaseException: 79 | traceback.print_exc() 80 | finally: 81 | # Close the connection. 82 | self._chan.close() 83 | 84 | def terminal_size_changed(self, width, height, pixwidth, pixheight): 85 | # Send resize event to the current application. 86 | if self.app_session and self.app_session.app: 87 | self.app_session.app._on_resize() 88 | 89 | def data_received(self, data, datatype): 90 | self._input.send_text(data) 91 | 92 | 93 | class PromptToolkitSSHServer(asyncssh.SSHServer): 94 | """ 95 | Run a prompt_toolkit application over an asyncssh server. 96 | 97 | This takes one argument, an `interact` function, which is called for each 98 | connection. This should be an asynchronous function that runs the 99 | prompt_toolkit applications. This function runs in an `AppSession`, which 100 | means that we can have multiple UI interactions concurrently. 101 | 102 | Example usage: 103 | 104 | .. code:: python 105 | 106 | async def interact() -> None: 107 | await yes_no_dialog("my title", "my text").run_async() 108 | 109 | prompt_session = PromptSession() 110 | text = await prompt_session.prompt_async("Type something: ") 111 | print_formatted_text('You said: ', text) 112 | 113 | server = PromptToolkitSSHServer(interact=interact) 114 | loop = get_event_loop() 115 | loop.run_until_complete( 116 | asyncssh.create_server( 117 | lambda: MySSHServer(interact), 118 | "", 119 | port, 120 | server_host_keys=["/etc/ssh/..."], 121 | ) 122 | ) 123 | loop.run_forever() 124 | """ 125 | 126 | def __init__(self, interact: Callable[[], Awaitable[None]]) -> None: 127 | self.interact = interact 128 | 129 | def begin_auth(self, username): 130 | # No authentication. 131 | return False 132 | 133 | def session_requested(self) -> PromptToolkitSession: 134 | return PromptToolkitSession(self.interact) 135 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/telnet/__init__.py: -------------------------------------------------------------------------------- 1 | from .server import TelnetServer 2 | 3 | __all__ = [ 4 | "TelnetServer", 5 | ] 6 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/telnet/log.py: -------------------------------------------------------------------------------- 1 | """ 2 | Python logger for the telnet server. 3 | """ 4 | import logging 5 | 6 | logger = logging.getLogger(__package__) 7 | 8 | __all__ = [ 9 | "logger", 10 | ] 11 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/contrib/telnet/protocol.py: -------------------------------------------------------------------------------- 1 | """ 2 | Parser for the Telnet protocol. (Not a complete implementation of the telnet 3 | specification, but sufficient for a command line interface.) 4 | 5 | Inspired by `Twisted.conch.telnet`. 6 | """ 7 | import struct 8 | from typing import Callable, Generator 9 | 10 | from .log import logger 11 | 12 | __all__ = [ 13 | "TelnetProtocolParser", 14 | ] 15 | 16 | 17 | def int2byte(number: int) -> bytes: 18 | return bytes((number,)) 19 | 20 | 21 | # Telnet constants. 22 | NOP = int2byte(0) 23 | SGA = int2byte(3) 24 | 25 | IAC = int2byte(255) 26 | DO = int2byte(253) 27 | DONT = int2byte(254) 28 | LINEMODE = int2byte(34) 29 | SB = int2byte(250) 30 | WILL = int2byte(251) 31 | WONT = int2byte(252) 32 | MODE = int2byte(1) 33 | SE = int2byte(240) 34 | ECHO = int2byte(1) 35 | NAWS = int2byte(31) 36 | LINEMODE = int2byte(34) 37 | SUPPRESS_GO_AHEAD = int2byte(3) 38 | 39 | DM = int2byte(242) 40 | BRK = int2byte(243) 41 | IP = int2byte(244) 42 | AO = int2byte(245) 43 | AYT = int2byte(246) 44 | EC = int2byte(247) 45 | EL = int2byte(248) 46 | GA = int2byte(249) 47 | 48 | 49 | class TelnetProtocolParser: 50 | """ 51 | Parser for the Telnet protocol. 52 | Usage:: 53 | 54 | def data_received(data): 55 | print(data) 56 | 57 | def size_received(rows, columns): 58 | print(rows, columns) 59 | 60 | p = TelnetProtocolParser(data_received, size_received) 61 | p.feed(binary_data) 62 | """ 63 | 64 | def __init__( 65 | self, 66 | data_received_callback: Callable[[bytes], None], 67 | size_received_callback: Callable[[int, int], None], 68 | ) -> None: 69 | 70 | self.data_received_callback = data_received_callback 71 | self.size_received_callback = size_received_callback 72 | 73 | self._parser = self._parse_coroutine() 74 | self._parser.send(None) # type: ignore 75 | 76 | def received_data(self, data: bytes) -> None: 77 | self.data_received_callback(data) 78 | 79 | def do_received(self, data: bytes) -> None: 80 | """ Received telnet DO command. """ 81 | logger.info("DO %r", data) 82 | 83 | def dont_received(self, data: bytes) -> None: 84 | """ Received telnet DONT command. """ 85 | logger.info("DONT %r", data) 86 | 87 | def will_received(self, data: bytes) -> None: 88 | """ Received telnet WILL command. """ 89 | logger.info("WILL %r", data) 90 | 91 | def wont_received(self, data: bytes) -> None: 92 | """ Received telnet WONT command. """ 93 | logger.info("WONT %r", data) 94 | 95 | def command_received(self, command: bytes, data: bytes) -> None: 96 | if command == DO: 97 | self.do_received(data) 98 | 99 | elif command == DONT: 100 | self.dont_received(data) 101 | 102 | elif command == WILL: 103 | self.will_received(data) 104 | 105 | elif command == WONT: 106 | self.wont_received(data) 107 | 108 | else: 109 | logger.info("command received %r %r", command, data) 110 | 111 | def naws(self, data: bytes) -> None: 112 | """ 113 | Received NAWS. (Window dimensions.) 114 | """ 115 | if len(data) == 4: 116 | # NOTE: the first parameter of struct.unpack should be 117 | # a 'str' object. Both on Py2/py3. This crashes on OSX 118 | # otherwise. 119 | columns, rows = struct.unpack(str("!HH"), data) 120 | self.size_received_callback(rows, columns) 121 | else: 122 | logger.warning("Wrong number of NAWS bytes") 123 | 124 | def negotiate(self, data: bytes) -> None: 125 | """ 126 | Got negotiate data. 127 | """ 128 | command, payload = data[0:1], data[1:] 129 | 130 | if command == NAWS: 131 | self.naws(payload) 132 | else: 133 | logger.info("Negotiate (%r got bytes)", len(data)) 134 | 135 | def _parse_coroutine(self) -> Generator[None, bytes, None]: 136 | """ 137 | Parser state machine. 138 | Every 'yield' expression returns the next byte. 139 | """ 140 | while True: 141 | d = yield 142 | 143 | if d == int2byte(0): 144 | pass # NOP 145 | 146 | # Go to state escaped. 147 | elif d == IAC: 148 | d2 = yield 149 | 150 | if d2 == IAC: 151 | self.received_data(d2) 152 | 153 | # Handle simple commands. 154 | elif d2 in (NOP, DM, BRK, IP, AO, AYT, EC, EL, GA): 155 | self.command_received(d2, b"") 156 | 157 | # Handle IAC-[DO/DONT/WILL/WONT] commands. 158 | elif d2 in (DO, DONT, WILL, WONT): 159 | d3 = yield 160 | self.command_received(d2, d3) 161 | 162 | # Subnegotiation 163 | elif d2 == SB: 164 | # Consume everything until next IAC-SE 165 | data = [] 166 | 167 | while True: 168 | d3 = yield 169 | 170 | if d3 == IAC: 171 | d4 = yield 172 | if d4 == SE: 173 | break 174 | else: 175 | data.append(d4) 176 | else: 177 | data.append(d3) 178 | 179 | self.negotiate(b"".join(data)) 180 | else: 181 | self.received_data(d) 182 | 183 | def feed(self, data: bytes) -> None: 184 | """ 185 | Feed data to the parser. 186 | """ 187 | for b in data: 188 | self._parser.send(int2byte(b)) 189 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/data_structures.py: -------------------------------------------------------------------------------- 1 | from typing import NamedTuple 2 | 3 | __all__ = [ 4 | "Point", 5 | "Size", 6 | ] 7 | 8 | 9 | Point = NamedTuple("Point", [("x", int), ("y", int)]) 10 | Size = NamedTuple("Size", [("rows", int), ("columns", int)]) 11 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/enums.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class EditingMode(Enum): 5 | # The set of key bindings that is active. 6 | VI = "VI" 7 | EMACS = "EMACS" 8 | 9 | 10 | #: Name of the search buffer. 11 | SEARCH_BUFFER = "SEARCH_BUFFER" 12 | 13 | #: Name of the default buffer. 14 | DEFAULT_BUFFER = "DEFAULT_BUFFER" 15 | 16 | #: Name of the system buffer. 17 | SYSTEM_BUFFER = "SYSTEM_BUFFER" 18 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/eventloop/__init__.py: -------------------------------------------------------------------------------- 1 | from .async_generator import generator_to_async_generator 2 | from .inputhook import ( 3 | InputHookContext, 4 | InputHookSelector, 5 | new_eventloop_with_inputhook, 6 | set_eventloop_with_inputhook, 7 | ) 8 | from .utils import ( 9 | call_soon_threadsafe, 10 | get_traceback_from_context, 11 | run_in_executor_with_context, 12 | ) 13 | 14 | __all__ = [ 15 | # Async generator 16 | "generator_to_async_generator", 17 | # Utils. 18 | "run_in_executor_with_context", 19 | "call_soon_threadsafe", 20 | "get_traceback_from_context", 21 | # Inputhooks. 22 | "new_eventloop_with_inputhook", 23 | "set_eventloop_with_inputhook", 24 | "InputHookSelector", 25 | "InputHookContext", 26 | ] 27 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/eventloop/async_context_manager.py: -------------------------------------------------------------------------------- 1 | """ 2 | @asynccontextmanager code, copied from Python 3.7's contextlib. 3 | For usage in Python 3.6. 4 | """ 5 | import _collections_abc 6 | import abc 7 | from functools import wraps 8 | 9 | __all__ = ["asynccontextmanager"] 10 | 11 | 12 | class AbstractAsyncContextManager(abc.ABC): 13 | 14 | """An abstract base class for asynchronous context managers.""" 15 | 16 | async def __aenter__(self): 17 | """Return `self` upon entering the runtime context.""" 18 | return self 19 | 20 | @abc.abstractmethod 21 | async def __aexit__(self, exc_type, exc_value, traceback): 22 | """Raise any exception triggered within the runtime context.""" 23 | return None 24 | 25 | @classmethod 26 | def __subclasshook__(cls, C): 27 | if cls is AbstractAsyncContextManager: 28 | return _collections_abc._check_methods(C, "__aenter__", "__aexit__") 29 | return NotImplemented 30 | 31 | 32 | class _GeneratorContextManagerBase: 33 | """Shared functionality for @contextmanager and @asynccontextmanager.""" 34 | 35 | def __init__(self, func, args, kwds): 36 | self.gen = func(*args, **kwds) 37 | self.func, self.args, self.kwds = func, args, kwds 38 | # Issue 19330: ensure context manager instances have good docstrings 39 | doc = getattr(func, "__doc__", None) 40 | if doc is None: 41 | doc = type(self).__doc__ 42 | self.__doc__ = doc 43 | # Unfortunately, this still doesn't provide good help output when 44 | # inspecting the created context manager instances, since pydoc 45 | # currently bypasses the instance docstring and shows the docstring 46 | # for the class instead. 47 | # See http://bugs.python.org/issue19404 for more details. 48 | 49 | 50 | class _AsyncGeneratorContextManager( 51 | _GeneratorContextManagerBase, AbstractAsyncContextManager 52 | ): 53 | """Helper for @asynccontextmanager.""" 54 | 55 | async def __aenter__(self): 56 | try: 57 | return await self.gen.__anext__() 58 | except StopAsyncIteration: 59 | raise RuntimeError("generator didn't yield") from None 60 | 61 | async def __aexit__(self, typ, value, traceback): 62 | if typ is None: 63 | try: 64 | await self.gen.__anext__() 65 | except StopAsyncIteration: 66 | return 67 | else: 68 | raise RuntimeError("generator didn't stop") 69 | else: 70 | if value is None: 71 | value = typ() 72 | # See _GeneratorContextManager.__exit__ for comments on subtleties 73 | # in this implementation 74 | try: 75 | await self.gen.athrow(typ, value, traceback) 76 | raise RuntimeError("generator didn't stop after athrow()") 77 | except StopAsyncIteration as exc: 78 | return exc is not value 79 | except RuntimeError as exc: 80 | if exc is value: 81 | return False 82 | # Avoid suppressing if a StopIteration exception 83 | # was passed to throw() and later wrapped into a RuntimeError 84 | # (see PEP 479 for sync generators; async generators also 85 | # have this behavior). But do this only if the exception wrapped 86 | # by the RuntimeError is actully Stop(Async)Iteration (see 87 | # issue29692). 88 | if isinstance(value, (StopIteration, StopAsyncIteration)): 89 | if exc.__cause__ is value: 90 | return False 91 | raise 92 | except BaseException as exc: 93 | if exc is not value: 94 | raise 95 | 96 | 97 | def asynccontextmanager(func): 98 | """@asynccontextmanager decorator. 99 | Typical usage: 100 | @asynccontextmanager 101 | async def some_async_generator(): 102 | 103 | try: 104 | yield 105 | finally: 106 | 107 | This makes this: 108 | async with some_async_generator() as : 109 | 110 | equivalent to this: 111 | 112 | try: 113 | = 114 | 115 | finally: 116 | 117 | """ 118 | 119 | @wraps(func) 120 | def helper(*args, **kwds): 121 | return _AsyncGeneratorContextManager(func, args, kwds) 122 | 123 | return helper 124 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/eventloop/async_generator.py: -------------------------------------------------------------------------------- 1 | """ 2 | Implementation for async generators. 3 | """ 4 | from asyncio import Queue, get_event_loop 5 | from typing import AsyncGenerator, Callable, Iterable, TypeVar, Union 6 | 7 | from .utils import run_in_executor_with_context 8 | 9 | __all__ = [ 10 | "generator_to_async_generator", 11 | ] 12 | 13 | 14 | _T = TypeVar("_T") 15 | 16 | 17 | class _Done: 18 | pass 19 | 20 | 21 | async def generator_to_async_generator( 22 | get_iterable: Callable[[], Iterable[_T]] 23 | ) -> AsyncGenerator[_T, None]: 24 | """ 25 | Turn a generator or iterable into an async generator. 26 | 27 | This works by running the generator in a background thread. 28 | 29 | :param get_iterable: Function that returns a generator or iterable when 30 | called. 31 | """ 32 | quitting = False 33 | _done = _Done() 34 | q: Queue[Union[_T, _Done]] = Queue() 35 | loop = get_event_loop() 36 | 37 | def runner() -> None: 38 | """ 39 | Consume the generator in background thread. 40 | When items are received, they'll be pushed to the queue. 41 | """ 42 | try: 43 | for item in get_iterable(): 44 | loop.call_soon_threadsafe(q.put_nowait, item) 45 | 46 | # When this async generator was cancelled (closed), stop this 47 | # thread. 48 | if quitting: 49 | break 50 | 51 | finally: 52 | loop.call_soon_threadsafe(q.put_nowait, _done) 53 | 54 | # Start background thread. 55 | run_in_executor_with_context(runner) 56 | 57 | try: 58 | while True: 59 | item = await q.get() 60 | if isinstance(item, _Done): 61 | break 62 | else: 63 | yield item 64 | finally: 65 | # When this async generator is closed (GeneratorExit exception, stop 66 | # the background thread as well. - we don't need that anymore.) 67 | quitting = True 68 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/eventloop/dummy_contextvars.py: -------------------------------------------------------------------------------- 1 | """ 2 | Dummy contextvars implementation, to make prompt_toolkit work on Python 3.6. 3 | 4 | As long as there is only one application running at a time, we don't need the 5 | real contextvars. So, stuff like the telnet-server and so on requires 3.7. 6 | """ 7 | from typing import Any, Callable, Generic, Optional, TypeVar 8 | 9 | 10 | def copy_context() -> "Context": 11 | return Context() 12 | 13 | 14 | _T = TypeVar("_T") 15 | 16 | 17 | class Context: 18 | def run(self, callable: Callable[..., _T], *args: Any, **kwargs: Any) -> _T: 19 | return callable(*args, **kwargs) 20 | 21 | 22 | class Token(Generic[_T]): 23 | pass 24 | 25 | 26 | class ContextVar(Generic[_T]): 27 | def __init__(self, name: str, *, default: Optional[_T] = None) -> None: 28 | self._name = name 29 | self._value = default 30 | 31 | @property 32 | def name(self) -> str: 33 | return self._name 34 | 35 | def get(self, default: Optional[_T] = None) -> _T: 36 | result = self._value or default 37 | if result is None: 38 | raise LookupError 39 | return result 40 | 41 | def set(self, value: _T) -> Token[_T]: 42 | self._value = value 43 | return Token() 44 | 45 | def reset(self, token: Token[_T]) -> None: 46 | pass 47 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/eventloop/utils.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | from asyncio import AbstractEventLoop, get_event_loop 4 | from types import TracebackType 5 | from typing import Any, Awaitable, Callable, Dict, Optional, TypeVar 6 | 7 | try: 8 | import contextvars 9 | except ImportError: 10 | from . import dummy_contextvars as contextvars # type: ignore 11 | 12 | __all__ = [ 13 | "run_in_executor_with_context", 14 | "call_soon_threadsafe", 15 | "get_traceback_from_context", 16 | ] 17 | 18 | _T = TypeVar("_T") 19 | 20 | 21 | def run_in_executor_with_context( 22 | func: Callable[..., _T], *args: Any, loop: Optional[AbstractEventLoop] = None 23 | ) -> Awaitable[_T]: 24 | """ 25 | Run a function in an executor, but make sure it uses the same contextvars. 26 | This is required so that the function will see the right application. 27 | 28 | See also: https://bugs.python.org/issue34014 29 | """ 30 | loop = loop or get_event_loop() 31 | ctx: contextvars.Context = contextvars.copy_context() 32 | 33 | return loop.run_in_executor(None, ctx.run, func, *args) 34 | 35 | 36 | def call_soon_threadsafe( 37 | func: Callable[[], None], 38 | max_postpone_time: Optional[float] = None, 39 | loop: Optional[AbstractEventLoop] = None, 40 | ) -> None: 41 | """ 42 | Wrapper around asyncio's `call_soon_threadsafe`. 43 | 44 | This takes a `max_postpone_time` which can be used to tune the urgency of 45 | the method. 46 | 47 | Asyncio runs tasks in first-in-first-out. However, this is not what we 48 | want for the render function of the prompt_toolkit UI. Rendering is 49 | expensive, but since the UI is invalidated very often, in some situations 50 | we render the UI too often, so much that the rendering CPU usage slows down 51 | the rest of the processing of the application. (Pymux is an example where 52 | we have to balance the CPU time spend on rendering the UI, and parsing 53 | process output.) 54 | However, we want to set a deadline value, for when the rendering should 55 | happen. (The UI should stay responsive). 56 | """ 57 | loop2 = loop or get_event_loop() 58 | 59 | # If no `max_postpone_time` has been given, schedule right now. 60 | if max_postpone_time is None: 61 | loop2.call_soon_threadsafe(func) 62 | return 63 | 64 | max_postpone_until = time.time() + max_postpone_time 65 | 66 | def schedule() -> None: 67 | # When there are no other tasks scheduled in the event loop. Run it 68 | # now. 69 | # Notice: uvloop doesn't have this _ready attribute. In that case, 70 | # always call immediately. 71 | if not getattr(loop2, "_ready", []): # type: ignore 72 | func() 73 | return 74 | 75 | # If the timeout expired, run this now. 76 | if time.time() > max_postpone_until: 77 | func() 78 | return 79 | 80 | # Schedule again for later. 81 | loop2.call_soon_threadsafe(schedule) 82 | 83 | loop2.call_soon_threadsafe(schedule) 84 | 85 | 86 | def get_traceback_from_context(context: Dict[str, Any]) -> Optional[TracebackType]: 87 | """ 88 | Get the traceback object from the context. 89 | """ 90 | exception = context.get("exception") 91 | if exception: 92 | if hasattr(exception, "__traceback__"): 93 | return exception.__traceback__ 94 | else: 95 | # call_exception_handler() is usually called indirectly 96 | # from an except block. If it's not the case, the traceback 97 | # is undefined... 98 | return sys.exc_info()[2] 99 | 100 | return None 101 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/eventloop/win32.py: -------------------------------------------------------------------------------- 1 | from ctypes import pointer, windll 2 | from ctypes.wintypes import BOOL, DWORD, HANDLE 3 | from typing import List, Optional 4 | 5 | from prompt_toolkit.win32_types import SECURITY_ATTRIBUTES 6 | 7 | __all__ = ["wait_for_handles", "create_win32_event"] 8 | 9 | 10 | WAIT_TIMEOUT = 0x00000102 11 | INFINITE = -1 12 | 13 | 14 | def wait_for_handles( 15 | handles: List[HANDLE], timeout: int = INFINITE 16 | ) -> Optional[HANDLE]: 17 | """ 18 | Waits for multiple handles. (Similar to 'select') Returns the handle which is ready. 19 | Returns `None` on timeout. 20 | http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx 21 | 22 | Note that handles should be a list of `HANDLE` objects, not integers. See 23 | this comment in the patch by @quark-zju for the reason why: 24 | 25 | ''' Make sure HANDLE on Windows has a correct size 26 | 27 | Previously, the type of various HANDLEs are native Python integer 28 | types. The ctypes library will treat them as 4-byte integer when used 29 | in function arguments. On 64-bit Windows, HANDLE is 8-byte and usually 30 | a small integer. Depending on whether the extra 4 bytes are zero-ed out 31 | or not, things can happen to work, or break. ''' 32 | 33 | This function returns either `None` or one of the given `HANDLE` objects. 34 | (The return value can be tested with the `is` operator.) 35 | """ 36 | arrtype = HANDLE * len(handles) 37 | handle_array = arrtype(*handles) 38 | 39 | ret = windll.kernel32.WaitForMultipleObjects( 40 | len(handle_array), handle_array, BOOL(False), DWORD(timeout) 41 | ) 42 | 43 | if ret == WAIT_TIMEOUT: 44 | return None 45 | else: 46 | return handles[ret] 47 | 48 | 49 | def create_win32_event() -> HANDLE: 50 | """ 51 | Creates a Win32 unnamed Event . 52 | http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx 53 | """ 54 | return HANDLE( 55 | windll.kernel32.CreateEventA( 56 | pointer(SECURITY_ATTRIBUTES()), 57 | BOOL(True), # Manual reset event. 58 | BOOL(False), # Initial state. 59 | None, # Unnamed event object. 60 | ) 61 | ) 62 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/filters/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Filters decide whether something is active or not (they decide about a boolean 3 | state). This is used to enable/disable features, like key bindings, parts of 4 | the layout and other stuff. For instance, we could have a `HasSearch` filter 5 | attached to some part of the layout, in order to show that part of the user 6 | interface only while the user is searching. 7 | 8 | Filters are made to avoid having to attach callbacks to all event in order to 9 | propagate state. However, they are lazy, they don't automatically propagate the 10 | state of what they are observing. Only when a filter is called (it's actually a 11 | callable), it will calculate its value. So, its not really reactive 12 | programming, but it's made to fit for this framework. 13 | 14 | Filters can be chained using ``&`` and ``|`` operations, and inverted using the 15 | ``~`` operator, for instance:: 16 | 17 | filter = has_focus('default') & ~ has_selection 18 | """ 19 | from .app import * 20 | from .base import Always, Condition, Filter, FilterOrBool, Never 21 | from .cli import * 22 | from .utils import is_true, to_filter 23 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/filters/cli.py: -------------------------------------------------------------------------------- 1 | """ 2 | For backwards-compatibility. keep this file. 3 | (Many people are going to have key bindings that rely on this file.) 4 | """ 5 | from .app import * 6 | 7 | __all__ = [ 8 | # Old names. 9 | "HasArg", 10 | "HasCompletions", 11 | "HasFocus", 12 | "HasSelection", 13 | "HasValidationError", 14 | "IsDone", 15 | "IsReadOnly", 16 | "IsMultiline", 17 | "RendererHeightIsKnown", 18 | "InEditingMode", 19 | "InPasteMode", 20 | "ViMode", 21 | "ViNavigationMode", 22 | "ViInsertMode", 23 | "ViInsertMultipleMode", 24 | "ViReplaceMode", 25 | "ViSelectionMode", 26 | "ViWaitingForTextObjectMode", 27 | "ViDigraphMode", 28 | "EmacsMode", 29 | "EmacsInsertMode", 30 | "EmacsSelectionMode", 31 | "IsSearching", 32 | "HasSearch", 33 | "ControlIsSearchable", 34 | ] 35 | 36 | # Keep the original classnames for backwards compatibility. 37 | HasValidationError = lambda: has_validation_error 38 | HasArg = lambda: has_arg 39 | IsDone = lambda: is_done 40 | RendererHeightIsKnown = lambda: renderer_height_is_known 41 | ViNavigationMode = lambda: vi_navigation_mode 42 | InPasteMode = lambda: in_paste_mode 43 | EmacsMode = lambda: emacs_mode 44 | EmacsInsertMode = lambda: emacs_insert_mode 45 | ViMode = lambda: vi_mode 46 | IsSearching = lambda: is_searching 47 | HasSearch = lambda: is_searching 48 | ControlIsSearchable = lambda: control_is_searchable 49 | EmacsSelectionMode = lambda: emacs_selection_mode 50 | ViDigraphMode = lambda: vi_digraph_mode 51 | ViWaitingForTextObjectMode = lambda: vi_waiting_for_text_object_mode 52 | ViSelectionMode = lambda: vi_selection_mode 53 | ViReplaceMode = lambda: vi_replace_mode 54 | ViInsertMultipleMode = lambda: vi_insert_multiple_mode 55 | ViInsertMode = lambda: vi_insert_mode 56 | HasSelection = lambda: has_selection 57 | HasCompletions = lambda: has_completions 58 | IsReadOnly = lambda: is_read_only 59 | IsMultiline = lambda: is_multiline 60 | 61 | HasFocus = has_focus # No lambda here! (Has_focus is callable that returns a callable.) 62 | InEditingMode = in_editing_mode 63 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/filters/utils.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | 3 | from .base import Always, Filter, FilterOrBool, Never 4 | 5 | __all__ = [ 6 | "to_filter", 7 | "is_true", 8 | ] 9 | 10 | 11 | _always = Always() 12 | _never = Never() 13 | 14 | 15 | _bool_to_filter: Dict[bool, Filter] = { 16 | True: _always, 17 | False: _never, 18 | } 19 | 20 | 21 | def to_filter(bool_or_filter: FilterOrBool) -> Filter: 22 | """ 23 | Accept both booleans and Filters as input and 24 | turn it into a Filter. 25 | """ 26 | if isinstance(bool_or_filter, bool): 27 | return _bool_to_filter[bool_or_filter] 28 | 29 | if isinstance(bool_or_filter, Filter): 30 | return bool_or_filter 31 | 32 | raise TypeError("Expecting a bool or a Filter instance. Got %r" % bool_or_filter) 33 | 34 | 35 | def is_true(value: FilterOrBool) -> bool: 36 | """ 37 | Test whether `value` is True. In case of a Filter, call it. 38 | 39 | :param value: Boolean or `Filter` instance. 40 | """ 41 | return to_filter(value)() 42 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/formatted_text/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Many places in prompt_toolkit can take either plain text, or formatted text. 3 | For instance the :func:`~prompt_toolkit.shortcuts.prompt` function takes either 4 | plain text or formatted text for the prompt. The 5 | :class:`~prompt_toolkit.layout.FormattedTextControl` can also take either plain 6 | text or formatted text. 7 | 8 | In any case, there is an input that can either be just plain text (a string), 9 | an :class:`.HTML` object, an :class:`.ANSI` object or a sequence of 10 | `(style_string, text)` tuples. The :func:`.to_formatted_text` conversion 11 | function takes any of these and turns all of them into such a tuple sequence. 12 | """ 13 | from .ansi import ANSI 14 | from .base import ( 15 | AnyFormattedText, 16 | FormattedText, 17 | StyleAndTextTuples, 18 | Template, 19 | is_formatted_text, 20 | merge_formatted_text, 21 | to_formatted_text, 22 | ) 23 | from .html import HTML 24 | from .pygments import PygmentsTokens 25 | from .utils import ( 26 | fragment_list_len, 27 | fragment_list_to_text, 28 | fragment_list_width, 29 | split_lines, 30 | ) 31 | 32 | __all__ = [ 33 | # Base. 34 | "AnyFormattedText", 35 | "to_formatted_text", 36 | "is_formatted_text", 37 | "Template", 38 | "merge_formatted_text", 39 | "FormattedText", 40 | "StyleAndTextTuples", 41 | # HTML. 42 | "HTML", 43 | # ANSI. 44 | "ANSI", 45 | # Pygments. 46 | "PygmentsTokens", 47 | # Utils. 48 | "fragment_list_len", 49 | "fragment_list_width", 50 | "fragment_list_to_text", 51 | "split_lines", 52 | ] 53 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/formatted_text/base.py: -------------------------------------------------------------------------------- 1 | from typing import TYPE_CHECKING, Any, Callable, Iterable, List, Tuple, Union, cast 2 | 3 | from prompt_toolkit.mouse_events import MouseEvent 4 | 5 | if TYPE_CHECKING: 6 | from typing_extensions import Protocol 7 | 8 | __all__ = [ 9 | "OneStyleAndTextTuple", 10 | "StyleAndTextTuples", 11 | "MagicFormattedText", 12 | "AnyFormattedText", 13 | "to_formatted_text", 14 | "is_formatted_text", 15 | "Template", 16 | "merge_formatted_text", 17 | "FormattedText", 18 | ] 19 | 20 | OneStyleAndTextTuple = Union[ 21 | Tuple[str, str], Tuple[str, str, Callable[[MouseEvent], None]], 22 | ] 23 | 24 | # List of (style, text) tuples. 25 | StyleAndTextTuples = List[OneStyleAndTextTuple] 26 | 27 | 28 | if TYPE_CHECKING: 29 | 30 | class MagicFormattedText(Protocol): 31 | """ 32 | Any object that implements ``__pt_formatted_text__`` represents formatted 33 | text. 34 | """ 35 | 36 | def __pt_formatted_text__(self) -> StyleAndTextTuples: 37 | ... 38 | 39 | 40 | AnyFormattedText = Union[ 41 | str, 42 | "MagicFormattedText", 43 | StyleAndTextTuples, 44 | # Callable[[], 'AnyFormattedText'] # Recursive definition not supported by mypy. 45 | Callable[[], Any], 46 | None, 47 | ] 48 | 49 | 50 | def to_formatted_text( 51 | value: AnyFormattedText, style: str = "", auto_convert: bool = False 52 | ) -> "FormattedText": 53 | """ 54 | Convert the given value (which can be formatted text) into a list of text 55 | fragments. (Which is the canonical form of formatted text.) The outcome is 56 | always a `FormattedText` instance, which is a list of (style, text) tuples. 57 | 58 | It can take an `HTML` object, a plain text string, or anything that 59 | implements `__pt_formatted_text__`. 60 | 61 | :param style: An additional style string which is applied to all text 62 | fragments. 63 | :param auto_convert: If `True`, also accept other types, and convert them 64 | to a string first. 65 | """ 66 | result: Union[FormattedText, StyleAndTextTuples] 67 | 68 | if value is None: 69 | result = [] 70 | elif isinstance(value, str): 71 | result = [("", value)] 72 | elif isinstance(value, list): 73 | result = cast(StyleAndTextTuples, value) 74 | elif hasattr(value, "__pt_formatted_text__"): 75 | result = cast("MagicFormattedText", value).__pt_formatted_text__() 76 | elif callable(value): 77 | return to_formatted_text(value(), style=style) 78 | elif auto_convert: 79 | result = [("", "{}".format(value))] 80 | else: 81 | raise ValueError( 82 | "No formatted text. Expecting a unicode object, " 83 | "HTML, ANSI or a FormattedText instance. Got %r" % value 84 | ) 85 | 86 | # Apply extra style. 87 | if style: 88 | result = cast( 89 | StyleAndTextTuples, 90 | [(style + " " + item_style, *rest) for item_style, *rest in result], 91 | ) 92 | 93 | # Make sure the result is wrapped in a `FormattedText`. Among other 94 | # reasons, this is important for `print_formatted_text` to work correctly 95 | # and distinguish between lists and formatted text. 96 | if isinstance(result, FormattedText): 97 | return result 98 | else: 99 | return FormattedText(result) 100 | 101 | 102 | def is_formatted_text(value: object) -> bool: 103 | """ 104 | Check whether the input is valid formatted text (for use in assert 105 | statements). 106 | In case of a callable, it doesn't check the return type. 107 | """ 108 | if callable(value): 109 | return True 110 | if isinstance(value, (str, list)): 111 | return True 112 | if hasattr(value, "__pt_formatted_text__"): 113 | return True 114 | return False 115 | 116 | 117 | class FormattedText(StyleAndTextTuples): 118 | """ 119 | A list of ``(style, text)`` tuples. 120 | 121 | (In some situations, this can also be ``(style, text, mouse_handler)`` 122 | tuples.) 123 | """ 124 | 125 | def __pt_formatted_text__(self) -> StyleAndTextTuples: 126 | return self 127 | 128 | def __repr__(self) -> str: 129 | return "FormattedText(%s)" % super().__repr__() 130 | 131 | 132 | class Template: 133 | """ 134 | Template for string interpolation with formatted text. 135 | 136 | Example:: 137 | 138 | Template(' ... {} ... ').format(HTML(...)) 139 | 140 | :param text: Plain text. 141 | """ 142 | 143 | def __init__(self, text: str) -> None: 144 | assert "{0}" not in text 145 | self.text = text 146 | 147 | def format(self, *values: AnyFormattedText) -> AnyFormattedText: 148 | def get_result(): 149 | # Split the template in parts. 150 | parts = self.text.split("{}") 151 | assert len(parts) - 1 == len(values) 152 | 153 | result = FormattedText() 154 | for part, val in zip(parts, values): 155 | result.append(("", part)) 156 | result.extend(to_formatted_text(val)) 157 | result.append(("", parts[-1])) 158 | return result 159 | 160 | return get_result 161 | 162 | 163 | def merge_formatted_text(items: Iterable[AnyFormattedText]) -> AnyFormattedText: 164 | """ 165 | Merge (Concatenate) several pieces of formatted text together. 166 | """ 167 | 168 | def _merge_formatted_text(): 169 | result = FormattedText() 170 | for i in items: 171 | result.extend(to_formatted_text(i)) 172 | return result 173 | 174 | return _merge_formatted_text 175 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/formatted_text/html.py: -------------------------------------------------------------------------------- 1 | import xml.dom.minidom as minidom 2 | from typing import Any, List, Tuple, Union 3 | 4 | from .base import FormattedText, StyleAndTextTuples 5 | 6 | __all__ = ["HTML"] 7 | 8 | 9 | class HTML: 10 | """ 11 | HTML formatted text. 12 | Take something HTML-like, for use as a formatted string. 13 | 14 | :: 15 | 16 | # Turn something into red. 17 | HTML('') 18 | 19 | # Italic, bold and underline. 20 | HTML('...') 21 | HTML('...') 22 | HTML('...') 23 | 24 | All HTML elements become available as a "class" in the style sheet. 25 | E.g. ``...`` can be styled, by setting a style for 26 | ``username``. 27 | """ 28 | 29 | def __init__(self, value: str) -> None: 30 | self.value = value 31 | document = minidom.parseString("%s" % (value,)) 32 | 33 | result: StyleAndTextTuples = [] 34 | name_stack: List[str] = [] 35 | fg_stack: List[str] = [] 36 | bg_stack: List[str] = [] 37 | 38 | def get_current_style() -> str: 39 | " Build style string for current node. " 40 | parts = [] 41 | if name_stack: 42 | parts.append("class:" + ",".join(name_stack)) 43 | 44 | if fg_stack: 45 | parts.append("fg:" + fg_stack[-1]) 46 | if bg_stack: 47 | parts.append("bg:" + bg_stack[-1]) 48 | return " ".join(parts) 49 | 50 | def process_node(node: Any) -> None: 51 | " Process node recursively. " 52 | for child in node.childNodes: 53 | if child.nodeType == child.TEXT_NODE: 54 | result.append((get_current_style(), child.data)) 55 | else: 56 | add_to_name_stack = child.nodeName not in ( 57 | "#document", 58 | "html-root", 59 | "style", 60 | ) 61 | fg = bg = "" 62 | 63 | for k, v in child.attributes.items(): 64 | if k == "fg": 65 | fg = v 66 | if k == "bg": 67 | bg = v 68 | if k == "color": 69 | fg = v # Alias for 'fg'. 70 | 71 | # Check for spaces in attributes. This would result in 72 | # invalid style strings otherwise. 73 | if " " in fg: 74 | raise ValueError('"fg" attribute contains a space.') 75 | if " " in bg: 76 | raise ValueError('"bg" attribute contains a space.') 77 | 78 | if add_to_name_stack: 79 | name_stack.append(child.nodeName) 80 | if fg: 81 | fg_stack.append(fg) 82 | if bg: 83 | bg_stack.append(bg) 84 | 85 | process_node(child) 86 | 87 | if add_to_name_stack: 88 | name_stack.pop() 89 | if fg: 90 | fg_stack.pop() 91 | if bg: 92 | bg_stack.pop() 93 | 94 | process_node(document) 95 | 96 | self.formatted_text = FormattedText(result) 97 | 98 | def __repr__(self) -> str: 99 | return "HTML(%r)" % (self.value,) 100 | 101 | def __pt_formatted_text__(self) -> StyleAndTextTuples: 102 | return self.formatted_text 103 | 104 | def format(self, *args: object, **kwargs: object) -> "HTML": 105 | """ 106 | Like `str.format`, but make sure that the arguments are properly 107 | escaped. 108 | """ 109 | # Escape all the arguments. 110 | escaped_args = [html_escape(a) for a in args] 111 | escaped_kwargs = {k: html_escape(v) for k, v in kwargs.items()} 112 | 113 | return HTML(self.value.format(*escaped_args, **escaped_kwargs)) 114 | 115 | def __mod__(self, value: Union[object, Tuple[object, ...]]) -> "HTML": 116 | """ 117 | HTML('%s') % value 118 | """ 119 | if not isinstance(value, tuple): 120 | value = (value,) 121 | 122 | value = tuple(html_escape(i) for i in value) 123 | return HTML(self.value % value) 124 | 125 | 126 | def html_escape(text: object) -> str: 127 | # The string interpolation functions also take integers and other types. 128 | # Convert to string first. 129 | if not isinstance(text, str): 130 | text = "{}".format(text) 131 | 132 | return ( 133 | text.replace("&", "&") 134 | .replace("<", "<") 135 | .replace(">", ">") 136 | .replace('"', """) 137 | ) 138 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/formatted_text/pygments.py: -------------------------------------------------------------------------------- 1 | from typing import TYPE_CHECKING, List, Tuple 2 | 3 | from prompt_toolkit.styles.pygments import pygments_token_to_classname 4 | 5 | from .base import StyleAndTextTuples 6 | 7 | if TYPE_CHECKING: 8 | from pygments.token import Token 9 | 10 | __all__ = [ 11 | "PygmentsTokens", 12 | ] 13 | 14 | 15 | class PygmentsTokens: 16 | """ 17 | Turn a pygments token list into a list of prompt_toolkit text fragments 18 | (``(style_str, text)`` tuples). 19 | """ 20 | 21 | def __init__(self, token_list: List[Tuple["Token", str]]) -> None: 22 | self.token_list = token_list 23 | 24 | def __pt_formatted_text__(self) -> StyleAndTextTuples: 25 | result: StyleAndTextTuples = [] 26 | 27 | for token, text in self.token_list: 28 | result.append(("class:" + pygments_token_to_classname(token), text)) 29 | 30 | return result 31 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/formatted_text/utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utilities for manipulating formatted text. 3 | 4 | When ``to_formatted_text`` has been called, we get a list of ``(style, text)`` 5 | tuples. This file contains functions for manipulating such a list. 6 | """ 7 | from typing import Iterable, cast 8 | 9 | from prompt_toolkit.utils import get_cwidth 10 | 11 | from .base import OneStyleAndTextTuple, StyleAndTextTuples 12 | 13 | __all__ = [ 14 | "fragment_list_len", 15 | "fragment_list_width", 16 | "fragment_list_to_text", 17 | "split_lines", 18 | ] 19 | 20 | 21 | def fragment_list_len(fragments: StyleAndTextTuples) -> int: 22 | """ 23 | Return the amount of characters in this text fragment list. 24 | 25 | :param fragments: List of ``(style_str, text)`` or 26 | ``(style_str, text, mouse_handler)`` tuples. 27 | """ 28 | ZeroWidthEscape = "[ZeroWidthEscape]" 29 | return sum(len(item[1]) for item in fragments if ZeroWidthEscape not in item[0]) 30 | 31 | 32 | def fragment_list_width(fragments: StyleAndTextTuples) -> int: 33 | """ 34 | Return the character width of this text fragment list. 35 | (Take double width characters into account.) 36 | 37 | :param fragments: List of ``(style_str, text)`` or 38 | ``(style_str, text, mouse_handler)`` tuples. 39 | """ 40 | ZeroWidthEscape = "[ZeroWidthEscape]" 41 | return sum( 42 | get_cwidth(c) 43 | for item in fragments 44 | for c in item[1] 45 | if ZeroWidthEscape not in item[0] 46 | ) 47 | 48 | 49 | def fragment_list_to_text(fragments: StyleAndTextTuples) -> str: 50 | """ 51 | Concatenate all the text parts again. 52 | 53 | :param fragments: List of ``(style_str, text)`` or 54 | ``(style_str, text, mouse_handler)`` tuples. 55 | """ 56 | ZeroWidthEscape = "[ZeroWidthEscape]" 57 | return "".join(item[1] for item in fragments if ZeroWidthEscape not in item[0]) 58 | 59 | 60 | def split_lines(fragments: StyleAndTextTuples) -> Iterable[StyleAndTextTuples]: 61 | """ 62 | Take a single list of (style_str, text) tuples and yield one such list for each 63 | line. Just like str.split, this will yield at least one item. 64 | 65 | :param fragments: List of (style_str, text) or (style_str, text, mouse_handler) 66 | tuples. 67 | """ 68 | line: StyleAndTextTuples = [] 69 | 70 | for style, string, *mouse_handler in fragments: 71 | parts = string.split("\n") 72 | 73 | for part in parts[:-1]: 74 | if part: 75 | line.append(cast(OneStyleAndTextTuple, (style, part, *mouse_handler))) 76 | yield line 77 | line = [] 78 | 79 | line.append(cast(OneStyleAndTextTuple, (style, parts[-1], *mouse_handler))) 80 | 81 | # Always yield the last line, even when this is an empty line. This ensures 82 | # that when `fragments` ends with a newline character, an additional empty 83 | # line is yielded. (Otherwise, there's no way to differentiate between the 84 | # cases where `fragments` does and doesn't end with a newline.) 85 | yield line 86 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/input/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import DummyInput, Input 2 | from .defaults import create_input, create_pipe_input 3 | 4 | __all__ = [ 5 | # Base. 6 | "Input", 7 | "DummyInput", 8 | # Defaults. 9 | "create_input", 10 | "create_pipe_input", 11 | ] 12 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/input/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | Abstraction of CLI Input. 3 | """ 4 | from abc import ABCMeta, abstractmethod, abstractproperty 5 | from contextlib import contextmanager 6 | from typing import Callable, ContextManager, Generator, List 7 | 8 | from prompt_toolkit.key_binding import KeyPress 9 | 10 | __all__ = [ 11 | "Input", 12 | "DummyInput", 13 | ] 14 | 15 | 16 | class Input(metaclass=ABCMeta): 17 | """ 18 | Abstraction for any input. 19 | 20 | An instance of this class can be given to the constructor of a 21 | :class:`~prompt_toolkit.application.Application` and will also be 22 | passed to the :class:`~prompt_toolkit.eventloop.base.EventLoop`. 23 | """ 24 | 25 | @abstractmethod 26 | def fileno(self) -> int: 27 | """ 28 | Fileno for putting this in an event loop. 29 | """ 30 | 31 | @abstractmethod 32 | def typeahead_hash(self) -> str: 33 | """ 34 | Identifier for storing type ahead key presses. 35 | """ 36 | 37 | @abstractmethod 38 | def read_keys(self) -> List[KeyPress]: 39 | """ 40 | Return a list of Key objects which are read/parsed from the input. 41 | """ 42 | 43 | def flush_keys(self) -> List[KeyPress]: 44 | """ 45 | Flush the underlying parser. and return the pending keys. 46 | (Used for vt100 input.) 47 | """ 48 | return [] 49 | 50 | def flush(self) -> None: 51 | " The event loop can call this when the input has to be flushed. " 52 | pass 53 | 54 | @property 55 | def responds_to_cpr(self) -> bool: 56 | """ 57 | `True` if the `Application` can expect to receive a CPR response from 58 | here. 59 | """ 60 | return False 61 | 62 | @abstractproperty 63 | def closed(self) -> bool: 64 | " Should be true when the input stream is closed. " 65 | return False 66 | 67 | @abstractmethod 68 | def raw_mode(self) -> ContextManager[None]: 69 | """ 70 | Context manager that turns the input into raw mode. 71 | """ 72 | 73 | @abstractmethod 74 | def cooked_mode(self) -> ContextManager[None]: 75 | """ 76 | Context manager that turns the input into cooked mode. 77 | """ 78 | 79 | @abstractmethod 80 | def attach(self, input_ready_callback: Callable[[], None]) -> ContextManager[None]: 81 | """ 82 | Return a context manager that makes this input active in the current 83 | event loop. 84 | """ 85 | 86 | @abstractmethod 87 | def detach(self) -> ContextManager[None]: 88 | """ 89 | Return a context manager that makes sure that this input is not active 90 | in the current event loop. 91 | """ 92 | 93 | def close(self) -> None: 94 | " Close input. " 95 | pass 96 | 97 | 98 | class DummyInput(Input): 99 | """ 100 | Input for use in a `DummyApplication` 101 | """ 102 | 103 | def fileno(self) -> int: 104 | raise NotImplementedError 105 | 106 | def typeahead_hash(self) -> str: 107 | return "dummy-%s" % id(self) 108 | 109 | def read_keys(self) -> List[KeyPress]: 110 | return [] 111 | 112 | @property 113 | def closed(self) -> bool: 114 | return True 115 | 116 | def raw_mode(self) -> ContextManager[None]: 117 | return _dummy_context_manager() 118 | 119 | def cooked_mode(self) -> ContextManager[None]: 120 | return _dummy_context_manager() 121 | 122 | def attach(self, input_ready_callback: Callable[[], None]) -> ContextManager[None]: 123 | return _dummy_context_manager() 124 | 125 | def detach(self) -> ContextManager[None]: 126 | return _dummy_context_manager() 127 | 128 | 129 | @contextmanager 130 | def _dummy_context_manager() -> Generator[None, None, None]: 131 | yield 132 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/input/defaults.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from typing import Optional, TextIO 3 | 4 | from prompt_toolkit.utils import is_windows 5 | 6 | from .base import Input 7 | 8 | __all__ = [ 9 | "create_input", 10 | "create_pipe_input", 11 | ] 12 | 13 | 14 | def create_input( 15 | stdin: Optional[TextIO] = None, always_prefer_tty: bool = False 16 | ) -> Input: 17 | """ 18 | Create the appropriate `Input` object for the current os/environment. 19 | 20 | :param always_prefer_tty: When set, if `sys.stdin` is connected to a Unix 21 | `pipe`, check whether `sys.stdout` or `sys.stderr` are connected to a 22 | pseudo terminal. If so, open the tty for reading instead of reading for 23 | `sys.stdin`. (We can open `stdout` or `stderr` for reading, this is how 24 | a `$PAGER` works.) 25 | """ 26 | if is_windows(): 27 | from .win32 import Win32Input 28 | 29 | return Win32Input(stdin or sys.stdin) 30 | else: 31 | from .vt100 import Vt100Input 32 | 33 | # If no input TextIO is given, use stdin/stdout. 34 | if stdin is None: 35 | stdin = sys.stdin 36 | 37 | if always_prefer_tty: 38 | for io in [sys.stdin, sys.stdout, sys.stderr]: 39 | if io.isatty(): 40 | stdin = io 41 | break 42 | 43 | return Vt100Input(stdin) 44 | 45 | 46 | def create_pipe_input() -> Input: 47 | """ 48 | Create an input pipe. 49 | This is mostly useful for unit testing. 50 | """ 51 | if is_windows(): 52 | from .win32_pipe import Win32PipeInput 53 | 54 | return Win32PipeInput() 55 | else: 56 | from .posix_pipe import PosixPipeInput 57 | 58 | return PosixPipeInput() 59 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/input/posix_pipe.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import ContextManager, TextIO, cast 3 | 4 | from ..utils import DummyContext 5 | from .vt100 import Vt100Input 6 | 7 | __all__ = [ 8 | "PosixPipeInput", 9 | ] 10 | 11 | 12 | class PosixPipeInput(Vt100Input): 13 | """ 14 | Input that is send through a pipe. 15 | This is useful if we want to send the input programmatically into the 16 | application. Mostly useful for unit testing. 17 | 18 | Usage:: 19 | 20 | input = PosixPipeInput() 21 | input.send_text('inputdata') 22 | """ 23 | 24 | _id = 0 25 | 26 | def __init__(self, text: str = "") -> None: 27 | self._r, self._w = os.pipe() 28 | 29 | class Stdin: 30 | def isatty(stdin) -> bool: 31 | return True 32 | 33 | def fileno(stdin) -> int: 34 | return self._r 35 | 36 | super().__init__(cast(TextIO, Stdin())) 37 | self.send_text(text) 38 | 39 | # Identifier for every PipeInput for the hash. 40 | self.__class__._id += 1 41 | self._id = self.__class__._id 42 | 43 | @property 44 | def responds_to_cpr(self) -> bool: 45 | return False 46 | 47 | def send_bytes(self, data: bytes) -> None: 48 | os.write(self._w, data) 49 | 50 | def send_text(self, data: str) -> None: 51 | " Send text to the input. " 52 | os.write(self._w, data.encode("utf-8")) 53 | 54 | def raw_mode(self) -> ContextManager[None]: 55 | return DummyContext() 56 | 57 | def cooked_mode(self) -> ContextManager[None]: 58 | return DummyContext() 59 | 60 | def close(self) -> None: 61 | " Close pipe fds. " 62 | os.close(self._r) 63 | os.close(self._w) 64 | 65 | # We should assign `None` to 'self._r` and 'self._w', 66 | # The event loop still needs to know the the fileno for this input in order 67 | # to properly remove it from the selectors. 68 | 69 | def typeahead_hash(self) -> str: 70 | """ 71 | This needs to be unique for every `PipeInput`. 72 | """ 73 | return "pipe-input-%s" % (self._id,) 74 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/input/posix_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import select 3 | from codecs import getincrementaldecoder 4 | 5 | __all__ = [ 6 | "PosixStdinReader", 7 | ] 8 | 9 | 10 | class PosixStdinReader: 11 | """ 12 | Wrapper around stdin which reads (nonblocking) the next available 1024 13 | bytes and decodes it. 14 | 15 | Note that you can't be sure that the input file is closed if the ``read`` 16 | function returns an empty string. When ``errors=ignore`` is passed, 17 | ``read`` can return an empty string if all malformed input was replaced by 18 | an empty string. (We can't block here and wait for more input.) So, because 19 | of that, check the ``closed`` attribute, to be sure that the file has been 20 | closed. 21 | 22 | :param stdin_fd: File descriptor from which we read. 23 | :param errors: Can be 'ignore', 'strict' or 'replace'. 24 | On Python3, this can be 'surrogateescape', which is the default. 25 | 26 | 'surrogateescape' is preferred, because this allows us to transfer 27 | unrecognised bytes to the key bindings. Some terminals, like lxterminal 28 | and Guake, use the 'Mxx' notation to send mouse events, where each 'x' 29 | can be any possible byte. 30 | """ 31 | 32 | # By default, we want to 'ignore' errors here. The input stream can be full 33 | # of junk. One occurrence of this that I had was when using iTerm2 on OS X, 34 | # with "Option as Meta" checked (You should choose "Option as +Esc".) 35 | 36 | def __init__(self, stdin_fd: int, errors: str = "surrogateescape") -> None: 37 | self.stdin_fd = stdin_fd 38 | self.errors = errors 39 | 40 | # Create incremental decoder for decoding stdin. 41 | # We can not just do `os.read(stdin.fileno(), 1024).decode('utf-8')`, because 42 | # it could be that we are in the middle of a utf-8 byte sequence. 43 | self._stdin_decoder_cls = getincrementaldecoder("utf-8") 44 | self._stdin_decoder = self._stdin_decoder_cls(errors=errors) 45 | 46 | #: True when there is nothing anymore to read. 47 | self.closed = False 48 | 49 | def read(self, count: int = 1024) -> str: 50 | # By default we choose a rather small chunk size, because reading 51 | # big amounts of input at once, causes the event loop to process 52 | # all these key bindings also at once without going back to the 53 | # loop. This will make the application feel unresponsive. 54 | """ 55 | Read the input and return it as a string. 56 | 57 | Return the text. Note that this can return an empty string, even when 58 | the input stream was not yet closed. This means that something went 59 | wrong during the decoding. 60 | """ 61 | if self.closed: 62 | return "" 63 | 64 | # Check whether there is some input to read. `os.read` would block 65 | # otherwise. 66 | # (Actually, the event loop is responsible to make sure that this 67 | # function is only called when there is something to read, but for some 68 | # reason this happens in certain situations.) 69 | try: 70 | if not select.select([self.stdin_fd], [], [], 0)[0]: 71 | return "" 72 | except IOError: 73 | # Happens for instance when the file descriptor was closed. 74 | # (We had this in ptterm, where the FD became ready, a callback was 75 | # scheduled, but in the meantime another callback closed it already.) 76 | self.closed = True 77 | 78 | # Note: the following works better than wrapping `self.stdin` like 79 | # `codecs.getreader('utf-8')(stdin)` and doing `read(1)`. 80 | # Somehow that causes some latency when the escape 81 | # character is pressed. (Especially on combination with the `select`.) 82 | try: 83 | data = os.read(self.stdin_fd, count) 84 | 85 | # Nothing more to read, stream is closed. 86 | if data == b"": 87 | self.closed = True 88 | return "" 89 | except OSError: 90 | # In case of SIGWINCH 91 | data = b"" 92 | 93 | return self._stdin_decoder.decode(data) 94 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/input/typeahead.py: -------------------------------------------------------------------------------- 1 | r""" 2 | Store input key strokes if we did read more than was required. 3 | 4 | The input classes `Vt100Input` and `Win32Input` read the input text in chunks 5 | of a few kilobytes. This means that if we read input from stdin, it could be 6 | that we read a couple of lines (with newlines in between) at once. 7 | 8 | This creates a problem: potentially, we read too much from stdin. Sometimes 9 | people paste several lines at once because they paste input in a REPL and 10 | expect each input() call to process one line. Or they rely on type ahead 11 | because the application can't keep up with the processing. 12 | 13 | However, we need to read input in bigger chunks. We need this mostly to support 14 | pasting of larger chunks of text. We don't want everything to become 15 | unresponsive because we: 16 | - read one character; 17 | - parse one character; 18 | - call the key binding, which does a string operation with one character; 19 | - and render the user interface. 20 | Doing text operations on single characters is very inefficient in Python, so we 21 | prefer to work on bigger chunks of text. This is why we have to read the input 22 | in bigger chunks. 23 | 24 | Further, line buffering is also not an option, because it doesn't work well in 25 | the architecture. We use lower level Posix APIs, that work better with the 26 | event loop and so on. In fact, there is also nothing that defines that only \n 27 | can accept the input, you could create a key binding for any key to accept the 28 | input. 29 | 30 | To support type ahead, this module will store all the key strokes that were 31 | read too early, so that they can be feed into to the next `prompt()` call or to 32 | the next prompt_toolkit `Application`. 33 | """ 34 | from collections import defaultdict 35 | from typing import Dict, List 36 | 37 | from ..key_binding import KeyPress 38 | from .base import Input 39 | 40 | __all__ = [ 41 | "store_typeahead", 42 | "get_typeahead", 43 | "clear_typeahead", 44 | ] 45 | 46 | _buffer: Dict[str, List[KeyPress]] = defaultdict(list) 47 | 48 | 49 | def store_typeahead(input_obj: Input, key_presses: List[KeyPress]) -> None: 50 | """ 51 | Insert typeahead key presses for the given input. 52 | """ 53 | global _buffer 54 | key = input_obj.typeahead_hash() 55 | _buffer[key].extend(key_presses) 56 | 57 | 58 | def get_typeahead(input_obj: Input) -> List[KeyPress]: 59 | """ 60 | Retrieve typeahead and reset the buffer for this input. 61 | """ 62 | global _buffer 63 | 64 | key = input_obj.typeahead_hash() 65 | result = _buffer[key] 66 | _buffer[key] = [] 67 | return result 68 | 69 | 70 | def clear_typeahead(input_obj: Input) -> None: 71 | """ 72 | Clear typeahead buffer. 73 | """ 74 | global _buffer 75 | key = input_obj.typeahead_hash() 76 | _buffer[key] = [] 77 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/input/win32_pipe.py: -------------------------------------------------------------------------------- 1 | from ctypes import windll 2 | from typing import Callable, ContextManager, List 3 | 4 | from prompt_toolkit.eventloop.win32 import create_win32_event 5 | 6 | from ..key_binding import KeyPress 7 | from ..utils import DummyContext 8 | from .vt100_parser import Vt100Parser 9 | from .win32 import _Win32InputBase, attach_win32_input, detach_win32_input 10 | 11 | __all__ = ["Win32PipeInput"] 12 | 13 | 14 | class Win32PipeInput(_Win32InputBase): 15 | """ 16 | This is an input pipe that works on Windows. 17 | Text or bytes can be feed into the pipe, and key strokes can be read from 18 | the pipe. This is useful if we want to send the input programmatically into 19 | the application. Mostly useful for unit testing. 20 | 21 | Notice that even though it's Windows, we use vt100 escape sequences over 22 | the pipe. 23 | 24 | Usage:: 25 | 26 | input = Win32PipeInput() 27 | input.send_text('inputdata') 28 | """ 29 | 30 | _id = 0 31 | 32 | def __init__(self) -> None: 33 | super().__init__() 34 | # Event (handle) for registering this input in the event loop. 35 | # This event is set when there is data available to read from the pipe. 36 | # Note: We use this approach instead of using a regular pipe, like 37 | # returned from `os.pipe()`, because making such a regular pipe 38 | # non-blocking is tricky and this works really well. 39 | self._event = create_win32_event() 40 | 41 | self._closed = False 42 | 43 | # Parser for incoming keys. 44 | self._buffer: List[KeyPress] = [] # Buffer to collect the Key objects. 45 | self.vt100_parser = Vt100Parser(lambda key: self._buffer.append(key)) 46 | 47 | # Identifier for every PipeInput for the hash. 48 | self.__class__._id += 1 49 | self._id = self.__class__._id 50 | 51 | @property 52 | def closed(self) -> bool: 53 | return self._closed 54 | 55 | def fileno(self): 56 | """ 57 | The windows pipe doesn't depend on the file handle. 58 | """ 59 | raise NotImplementedError 60 | 61 | @property 62 | def handle(self): 63 | " The handle used for registering this pipe in the event loop. " 64 | return self._event 65 | 66 | def attach(self, input_ready_callback: Callable) -> ContextManager[None]: 67 | """ 68 | Return a context manager that makes this input active in the current 69 | event loop. 70 | """ 71 | return attach_win32_input(self, input_ready_callback) 72 | 73 | def detach(self) -> ContextManager[None]: 74 | """ 75 | Return a context manager that makes sure that this input is not active 76 | in the current event loop. 77 | """ 78 | return detach_win32_input(self) 79 | 80 | def read_keys(self) -> List[KeyPress]: 81 | " Read list of KeyPress. " 82 | 83 | # Return result. 84 | result = self._buffer 85 | self._buffer = [] 86 | 87 | # Reset event. 88 | windll.kernel32.ResetEvent(self._event) 89 | 90 | return result 91 | 92 | def flush_keys(self) -> List[KeyPress]: 93 | """ 94 | Flush pending keys and return them. 95 | (Used for flushing the 'escape' key.) 96 | """ 97 | # Flush all pending keys. (This is most important to flush the vt100 98 | # 'Escape' key early when nothing else follows.) 99 | self.vt100_parser.flush() 100 | 101 | # Return result. 102 | result = self._buffer 103 | self._buffer = [] 104 | return result 105 | 106 | @property 107 | def responds_to_cpr(self) -> bool: 108 | return False 109 | 110 | def send_bytes(self, data: bytes) -> None: 111 | " Send bytes to the input. " 112 | self.send_text(data.decode("utf-8", "ignore")) 113 | 114 | def send_text(self, text: str) -> None: 115 | " Send text to the input. " 116 | # Pass it through our vt100 parser. 117 | self.vt100_parser.feed(text) 118 | 119 | # Set event. 120 | windll.kernel32.SetEvent(self._event) 121 | 122 | def raw_mode(self) -> ContextManager[None]: 123 | return DummyContext() 124 | 125 | def cooked_mode(self) -> ContextManager[None]: 126 | return DummyContext() 127 | 128 | def close(self) -> None: 129 | " Close pipe handles. " 130 | windll.kernel32.CloseHandle(self._event) 131 | self._closed = True 132 | 133 | def typeahead_hash(self) -> str: 134 | """ 135 | This needs to be unique for every `PipeInput`. 136 | """ 137 | return "pipe-input-%s" % (self._id,) 138 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/__init__.py: -------------------------------------------------------------------------------- 1 | from .key_bindings import ( 2 | ConditionalKeyBindings, 3 | DynamicKeyBindings, 4 | KeyBindings, 5 | KeyBindingsBase, 6 | merge_key_bindings, 7 | ) 8 | from .key_processor import KeyPress 9 | 10 | __all__ = [ 11 | "ConditionalKeyBindings", 12 | "DynamicKeyBindings", 13 | "KeyBindings", 14 | "KeyBindingsBase", 15 | "merge_key_bindings", 16 | "KeyPress", 17 | ] 18 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/bindings/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mango-tree/zsh-recall/e30cdf5b1034428ee4b944774a6369070078cf6c/lib/python3.7/site-packages/prompt_toolkit/key_binding/bindings/__init__.py -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/bindings/auto_suggest.py: -------------------------------------------------------------------------------- 1 | """ 2 | Key bindings for auto suggestion (for fish-style auto suggestion). 3 | """ 4 | import re 5 | 6 | from prompt_toolkit.application.current import get_app 7 | from prompt_toolkit.filters import Condition, emacs_mode 8 | from prompt_toolkit.key_binding.key_bindings import KeyBindings 9 | from prompt_toolkit.key_binding.key_processor import KeyPressEvent 10 | 11 | __all__ = [ 12 | "load_auto_suggest_bindings", 13 | ] 14 | 15 | E = KeyPressEvent 16 | 17 | 18 | def load_auto_suggest_bindings() -> KeyBindings: 19 | """ 20 | Key bindings for accepting auto suggestion text. 21 | 22 | (This has to come after the Vi bindings, because they also have an 23 | implementation for the "right arrow", but we really want the suggestion 24 | binding when a suggestion is available.) 25 | """ 26 | key_bindings = KeyBindings() 27 | handle = key_bindings.add 28 | 29 | @Condition 30 | def suggestion_available() -> bool: 31 | app = get_app() 32 | return ( 33 | app.current_buffer.suggestion is not None 34 | and app.current_buffer.document.is_cursor_at_the_end 35 | ) 36 | 37 | @handle("c-f", filter=suggestion_available) 38 | @handle("c-e", filter=suggestion_available) 39 | @handle("right", filter=suggestion_available) 40 | def _accept(event: E) -> None: 41 | """ 42 | Accept suggestion. 43 | """ 44 | b = event.current_buffer 45 | suggestion = b.suggestion 46 | 47 | if suggestion: 48 | b.insert_text(suggestion.text) 49 | 50 | @handle("escape", "f", filter=suggestion_available & emacs_mode) 51 | def _fill(event: E) -> None: 52 | """ 53 | Fill partial suggestion. 54 | """ 55 | b = event.current_buffer 56 | suggestion = b.suggestion 57 | 58 | if suggestion: 59 | t = re.split(r"(\S+\s+)", suggestion.text) 60 | b.insert_text(next(x for x in t if x)) 61 | 62 | return key_bindings 63 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/bindings/cpr.py: -------------------------------------------------------------------------------- 1 | from prompt_toolkit.key_binding.key_processor import KeyPressEvent 2 | from prompt_toolkit.keys import Keys 3 | 4 | from ..key_bindings import KeyBindings 5 | 6 | __all__ = [ 7 | "load_cpr_bindings", 8 | ] 9 | 10 | E = KeyPressEvent 11 | 12 | 13 | def load_cpr_bindings() -> KeyBindings: 14 | key_bindings = KeyBindings() 15 | 16 | @key_bindings.add(Keys.CPRResponse, save_before=lambda e: False) 17 | def _(event: E) -> None: 18 | """ 19 | Handle incoming Cursor-Position-Request response. 20 | """ 21 | # The incoming data looks like u'\x1b[35;1R' 22 | # Parse row/col information. 23 | row, col = map(int, event.data[2:-1].split(";")) 24 | 25 | # Report absolute cursor position to the renderer. 26 | event.app.renderer.report_absolute_cursor_row(row) 27 | 28 | return key_bindings 29 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/bindings/focus.py: -------------------------------------------------------------------------------- 1 | from prompt_toolkit.key_binding.key_processor import KeyPressEvent 2 | 3 | __all__ = [ 4 | "focus_next", 5 | "focus_previous", 6 | ] 7 | 8 | E = KeyPressEvent 9 | 10 | 11 | def focus_next(event: E) -> None: 12 | """ 13 | Focus the next visible Window. 14 | (Often bound to the `Tab` key.) 15 | """ 16 | event.app.layout.focus_next() 17 | 18 | 19 | def focus_previous(event: E) -> None: 20 | """ 21 | Focus the previous visible Window. 22 | (Often bound to the `BackTab` key.) 23 | """ 24 | event.app.layout.focus_previous() 25 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/bindings/mouse.py: -------------------------------------------------------------------------------- 1 | from prompt_toolkit.data_structures import Point 2 | from prompt_toolkit.key_binding.key_processor import KeyPress, KeyPressEvent 3 | from prompt_toolkit.keys import Keys 4 | from prompt_toolkit.mouse_events import MouseEvent, MouseEventType 5 | from prompt_toolkit.utils import is_windows 6 | 7 | from ..key_bindings import KeyBindings 8 | 9 | __all__ = [ 10 | "load_mouse_bindings", 11 | ] 12 | 13 | E = KeyPressEvent 14 | 15 | 16 | def load_mouse_bindings() -> KeyBindings: 17 | """ 18 | Key bindings, required for mouse support. 19 | (Mouse events enter through the key binding system.) 20 | """ 21 | key_bindings = KeyBindings() 22 | 23 | @key_bindings.add(Keys.Vt100MouseEvent) 24 | def _(event: E) -> None: 25 | """ 26 | Handling of incoming mouse event. 27 | """ 28 | # TypicaL: "eSC[MaB*" 29 | # Urxvt: "Esc[96;14;13M" 30 | # Xterm SGR: "Esc[<64;85;12M" 31 | 32 | # Parse incoming packet. 33 | if event.data[2] == "M": 34 | # Typical. 35 | mouse_event, x, y = map(ord, event.data[3:]) 36 | mouse_event_type = { 37 | 32: MouseEventType.MOUSE_DOWN, 38 | 35: MouseEventType.MOUSE_UP, 39 | 96: MouseEventType.SCROLL_UP, 40 | 97: MouseEventType.SCROLL_DOWN, 41 | }.get(mouse_event) 42 | 43 | # Handle situations where `PosixStdinReader` used surrogateescapes. 44 | if x >= 0xDC00: 45 | x -= 0xDC00 46 | if y >= 0xDC00: 47 | y -= 0xDC00 48 | 49 | x -= 32 50 | y -= 32 51 | else: 52 | # Urxvt and Xterm SGR. 53 | # When the '<' is not present, we are not using the Xterm SGR mode, 54 | # but Urxvt instead. 55 | data = event.data[2:] 56 | if data[:1] == "<": 57 | sgr = True 58 | data = data[1:] 59 | else: 60 | sgr = False 61 | 62 | # Extract coordinates. 63 | mouse_event, x, y = map(int, data[:-1].split(";")) 64 | m = data[-1] 65 | 66 | # Parse event type. 67 | if sgr: 68 | mouse_event_type = { 69 | (0, "M"): MouseEventType.MOUSE_DOWN, 70 | (0, "m"): MouseEventType.MOUSE_UP, 71 | (64, "M"): MouseEventType.SCROLL_UP, 72 | (65, "M"): MouseEventType.SCROLL_DOWN, 73 | }.get((mouse_event, m)) 74 | else: 75 | mouse_event_type = { 76 | 32: MouseEventType.MOUSE_DOWN, 77 | 35: MouseEventType.MOUSE_UP, 78 | 96: MouseEventType.SCROLL_UP, 79 | 97: MouseEventType.SCROLL_DOWN, 80 | }.get(mouse_event) 81 | 82 | x -= 1 83 | y -= 1 84 | 85 | # Only handle mouse events when we know the window height. 86 | if event.app.renderer.height_is_known and mouse_event_type is not None: 87 | # Take region above the layout into account. The reported 88 | # coordinates are absolute to the visible part of the terminal. 89 | from prompt_toolkit.renderer import HeightIsUnknownError 90 | 91 | try: 92 | y -= event.app.renderer.rows_above_layout 93 | except HeightIsUnknownError: 94 | return 95 | 96 | # Call the mouse handler from the renderer. 97 | handler = event.app.renderer.mouse_handlers.mouse_handlers[x, y] 98 | handler(MouseEvent(position=Point(x=x, y=y), event_type=mouse_event_type)) 99 | 100 | @key_bindings.add(Keys.ScrollUp) 101 | def _scroll_up(event: E) -> None: 102 | """ 103 | Scroll up event without cursor position. 104 | """ 105 | # We don't receive a cursor position, so we don't know which window to 106 | # scroll. Just send an 'up' key press instead. 107 | event.key_processor.feed(KeyPress(Keys.Up), first=True) 108 | 109 | @key_bindings.add(Keys.ScrollDown) 110 | def _scroll_down(event: E) -> None: 111 | """ 112 | Scroll down event without cursor position. 113 | """ 114 | event.key_processor.feed(KeyPress(Keys.Down), first=True) 115 | 116 | @key_bindings.add(Keys.WindowsMouseEvent) 117 | def _mouse(event: E) -> None: 118 | """ 119 | Handling of mouse events for Windows. 120 | """ 121 | assert is_windows() # This key binding should only exist for Windows. 122 | 123 | # Parse data. 124 | pieces = event.data.split(";") 125 | 126 | event_type = MouseEventType(pieces[0]) 127 | x = int(pieces[1]) 128 | y = int(pieces[2]) 129 | 130 | # Make coordinates absolute to the visible part of the terminal. 131 | output = event.app.renderer.output 132 | 133 | from prompt_toolkit.output.win32 import Win32Output 134 | 135 | if isinstance(output, Win32Output): 136 | screen_buffer_info = output.get_win32_screen_buffer_info() 137 | rows_above_cursor = ( 138 | screen_buffer_info.dwCursorPosition.Y - event.app.renderer._cursor_pos.y 139 | ) 140 | y -= rows_above_cursor 141 | 142 | # Call the mouse event handler. 143 | handler = event.app.renderer.mouse_handlers.mouse_handlers[x, y] 144 | handler(MouseEvent(position=Point(x=x, y=y), event_type=event_type)) 145 | 146 | return key_bindings 147 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/bindings/open_in_editor.py: -------------------------------------------------------------------------------- 1 | """ 2 | Open in editor key bindings. 3 | """ 4 | from prompt_toolkit.filters import emacs_mode, has_selection, vi_navigation_mode 5 | 6 | from ..key_bindings import KeyBindings, KeyBindingsBase, merge_key_bindings 7 | from .named_commands import get_by_name 8 | 9 | __all__ = [ 10 | "load_open_in_editor_bindings", 11 | "load_emacs_open_in_editor_bindings", 12 | "load_vi_open_in_editor_bindings", 13 | ] 14 | 15 | 16 | def load_open_in_editor_bindings() -> KeyBindingsBase: 17 | """ 18 | Load both the Vi and emacs key bindings for handling edit-and-execute-command. 19 | """ 20 | return merge_key_bindings( 21 | [load_emacs_open_in_editor_bindings(), load_vi_open_in_editor_bindings(),] 22 | ) 23 | 24 | 25 | def load_emacs_open_in_editor_bindings() -> KeyBindings: 26 | """ 27 | Pressing C-X C-E will open the buffer in an external editor. 28 | """ 29 | key_bindings = KeyBindings() 30 | 31 | key_bindings.add("c-x", "c-e", filter=emacs_mode & ~has_selection)( 32 | get_by_name("edit-and-execute-command") 33 | ) 34 | 35 | return key_bindings 36 | 37 | 38 | def load_vi_open_in_editor_bindings() -> KeyBindings: 39 | """ 40 | Pressing 'v' in navigation mode will open the buffer in an external editor. 41 | """ 42 | key_bindings = KeyBindings() 43 | key_bindings.add("v", filter=vi_navigation_mode)( 44 | get_by_name("edit-and-execute-command") 45 | ) 46 | return key_bindings 47 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/bindings/page_navigation.py: -------------------------------------------------------------------------------- 1 | """ 2 | Key bindings for extra page navigation: bindings for up/down scrolling through 3 | long pages, like in Emacs or Vi. 4 | """ 5 | from prompt_toolkit.filters import buffer_has_focus, emacs_mode, vi_mode 6 | from prompt_toolkit.key_binding.key_bindings import ( 7 | ConditionalKeyBindings, 8 | KeyBindings, 9 | KeyBindingsBase, 10 | merge_key_bindings, 11 | ) 12 | 13 | from .scroll import ( 14 | scroll_backward, 15 | scroll_forward, 16 | scroll_half_page_down, 17 | scroll_half_page_up, 18 | scroll_one_line_down, 19 | scroll_one_line_up, 20 | scroll_page_down, 21 | scroll_page_up, 22 | ) 23 | 24 | __all__ = [ 25 | "load_page_navigation_bindings", 26 | "load_emacs_page_navigation_bindings", 27 | "load_vi_page_navigation_bindings", 28 | ] 29 | 30 | 31 | def load_page_navigation_bindings() -> KeyBindingsBase: 32 | """ 33 | Load both the Vi and Emacs bindings for page navigation. 34 | """ 35 | # Only enable when a `Buffer` is focused, otherwise, we would catch keys 36 | # when another widget is focused (like for instance `c-d` in a 37 | # ptterm.Terminal). 38 | return ConditionalKeyBindings( 39 | merge_key_bindings( 40 | [load_emacs_page_navigation_bindings(), load_vi_page_navigation_bindings(),] 41 | ), 42 | buffer_has_focus, 43 | ) 44 | 45 | 46 | def load_emacs_page_navigation_bindings() -> KeyBindingsBase: 47 | """ 48 | Key bindings, for scrolling up and down through pages. 49 | This are separate bindings, because GNU readline doesn't have them. 50 | """ 51 | key_bindings = KeyBindings() 52 | handle = key_bindings.add 53 | 54 | handle("c-v")(scroll_page_down) 55 | handle("pagedown")(scroll_page_down) 56 | handle("escape", "v")(scroll_page_up) 57 | handle("pageup")(scroll_page_up) 58 | 59 | return ConditionalKeyBindings(key_bindings, emacs_mode) 60 | 61 | 62 | def load_vi_page_navigation_bindings() -> KeyBindingsBase: 63 | """ 64 | Key bindings, for scrolling up and down through pages. 65 | This are separate bindings, because GNU readline doesn't have them. 66 | """ 67 | key_bindings = KeyBindings() 68 | handle = key_bindings.add 69 | 70 | handle("c-f")(scroll_forward) 71 | handle("c-b")(scroll_backward) 72 | handle("c-d")(scroll_half_page_down) 73 | handle("c-u")(scroll_half_page_up) 74 | handle("c-e")(scroll_one_line_down) 75 | handle("c-y")(scroll_one_line_up) 76 | handle("pagedown")(scroll_page_down) 77 | handle("pageup")(scroll_page_up) 78 | 79 | return ConditionalKeyBindings(key_bindings, vi_mode) 80 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/bindings/search.py: -------------------------------------------------------------------------------- 1 | """ 2 | Search related key bindings. 3 | """ 4 | from prompt_toolkit import search 5 | from prompt_toolkit.application.current import get_app 6 | from prompt_toolkit.filters import Condition, control_is_searchable, is_searching 7 | from prompt_toolkit.key_binding.key_processor import KeyPressEvent 8 | 9 | from ..key_bindings import key_binding 10 | 11 | __all__ = [ 12 | "abort_search", 13 | "accept_search", 14 | "start_reverse_incremental_search", 15 | "start_forward_incremental_search", 16 | "reverse_incremental_search", 17 | "forward_incremental_search", 18 | "accept_search_and_accept_input", 19 | ] 20 | 21 | E = KeyPressEvent 22 | 23 | 24 | @key_binding(filter=is_searching) 25 | def abort_search(event: E) -> None: 26 | """ 27 | Abort an incremental search and restore the original 28 | line. 29 | (Usually bound to ControlG/ControlC.) 30 | """ 31 | search.stop_search() 32 | 33 | 34 | @key_binding(filter=is_searching) 35 | def accept_search(event: E) -> None: 36 | """ 37 | When enter pressed in isearch, quit isearch mode. (Multiline 38 | isearch would be too complicated.) 39 | (Usually bound to Enter.) 40 | """ 41 | search.accept_search() 42 | 43 | 44 | @key_binding(filter=control_is_searchable) 45 | def start_reverse_incremental_search(event: E) -> None: 46 | """ 47 | Enter reverse incremental search. 48 | (Usually ControlR.) 49 | """ 50 | search.start_search(direction=search.SearchDirection.BACKWARD) 51 | 52 | 53 | @key_binding(filter=control_is_searchable) 54 | def start_forward_incremental_search(event: E) -> None: 55 | """ 56 | Enter forward incremental search. 57 | (Usually ControlS.) 58 | """ 59 | search.start_search(direction=search.SearchDirection.FORWARD) 60 | 61 | 62 | @key_binding(filter=is_searching) 63 | def reverse_incremental_search(event: E) -> None: 64 | """ 65 | Apply reverse incremental search, but keep search buffer focused. 66 | """ 67 | search.do_incremental_search(search.SearchDirection.BACKWARD, count=event.arg) 68 | 69 | 70 | @key_binding(filter=is_searching) 71 | def forward_incremental_search(event: E) -> None: 72 | """ 73 | Apply forward incremental search, but keep search buffer focused. 74 | """ 75 | search.do_incremental_search(search.SearchDirection.FORWARD, count=event.arg) 76 | 77 | 78 | @Condition 79 | def _previous_buffer_is_returnable() -> bool: 80 | """ 81 | True if the previously focused buffer has a return handler. 82 | """ 83 | prev_control = get_app().layout.search_target_buffer_control 84 | return bool(prev_control and prev_control.buffer.is_returnable) 85 | 86 | 87 | @key_binding(filter=is_searching & _previous_buffer_is_returnable) 88 | def accept_search_and_accept_input(event: E) -> None: 89 | """ 90 | Accept the search operation first, then accept the input. 91 | """ 92 | search.accept_search() 93 | event.current_buffer.validate_and_handle() 94 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/defaults.py: -------------------------------------------------------------------------------- 1 | """ 2 | Default key bindings.:: 3 | 4 | key_bindings = load_key_bindings() 5 | app = Application(key_bindings=key_bindings) 6 | """ 7 | from prompt_toolkit.filters import buffer_has_focus 8 | from prompt_toolkit.key_binding.bindings.basic import load_basic_bindings 9 | from prompt_toolkit.key_binding.bindings.cpr import load_cpr_bindings 10 | from prompt_toolkit.key_binding.bindings.emacs import ( 11 | load_emacs_bindings, 12 | load_emacs_search_bindings, 13 | load_emacs_shift_selection_bindings, 14 | ) 15 | from prompt_toolkit.key_binding.bindings.mouse import load_mouse_bindings 16 | from prompt_toolkit.key_binding.bindings.vi import ( 17 | load_vi_bindings, 18 | load_vi_search_bindings, 19 | ) 20 | from prompt_toolkit.key_binding.key_bindings import ( 21 | ConditionalKeyBindings, 22 | KeyBindingsBase, 23 | merge_key_bindings, 24 | ) 25 | 26 | __all__ = [ 27 | "load_key_bindings", 28 | ] 29 | 30 | 31 | def load_key_bindings() -> KeyBindingsBase: 32 | """ 33 | Create a KeyBindings object that contains the default key bindings. 34 | """ 35 | all_bindings = merge_key_bindings( 36 | [ 37 | # Load basic bindings. 38 | load_basic_bindings(), 39 | # Load emacs bindings. 40 | load_emacs_bindings(), 41 | load_emacs_search_bindings(), 42 | load_emacs_shift_selection_bindings(), 43 | # Load Vi bindings. 44 | load_vi_bindings(), 45 | load_vi_search_bindings(), 46 | ] 47 | ) 48 | 49 | return merge_key_bindings( 50 | [ 51 | # Make sure that the above key bindings are only active if the 52 | # currently focused control is a `BufferControl`. For other controls, we 53 | # don't want these key bindings to intervene. (This would break "ptterm" 54 | # for instance, which handles 'Keys.Any' in the user control itself.) 55 | ConditionalKeyBindings(all_bindings, buffer_has_focus), 56 | # Active, even when no buffer has been focused. 57 | load_mouse_bindings(), 58 | load_cpr_bindings(), 59 | ] 60 | ) 61 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/emacs_state.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | 3 | from .key_processor import KeyPress 4 | 5 | __all__ = [ 6 | "EmacsState", 7 | ] 8 | 9 | 10 | class EmacsState: 11 | """ 12 | Mutable class to hold Emacs specific state. 13 | """ 14 | 15 | def __init__(self) -> None: 16 | # Simple macro recording. (Like Readline does.) 17 | # (For Emacs mode.) 18 | self.macro: Optional[List[KeyPress]] = [] 19 | self.current_recording: Optional[List[KeyPress]] = None 20 | 21 | def reset(self) -> None: 22 | self.current_recording = None 23 | 24 | @property 25 | def is_recording(self) -> bool: 26 | " Tell whether we are recording a macro. " 27 | return self.current_recording is not None 28 | 29 | def start_macro(self) -> None: 30 | " Start recording macro. " 31 | self.current_recording = [] 32 | 33 | def end_macro(self) -> None: 34 | " End recording macro. " 35 | self.macro = self.current_recording 36 | self.current_recording = None 37 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/key_binding/vi_state.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from typing import TYPE_CHECKING, Callable, Dict, Optional 3 | 4 | from prompt_toolkit.clipboard import ClipboardData 5 | 6 | if TYPE_CHECKING: 7 | from .key_processor import KeyPressEvent 8 | from .key_bindings.vi import TextObject 9 | 10 | __all__ = [ 11 | "InputMode", 12 | "CharacterFind", 13 | "ViState", 14 | ] 15 | 16 | 17 | class InputMode(str, Enum): 18 | value: str 19 | 20 | INSERT = "vi-insert" 21 | INSERT_MULTIPLE = "vi-insert-multiple" 22 | NAVIGATION = "vi-navigation" # Normal mode. 23 | REPLACE = "vi-replace" 24 | 25 | 26 | class CharacterFind: 27 | def __init__(self, character: str, backwards: bool = False) -> None: 28 | self.character = character 29 | self.backwards = backwards 30 | 31 | 32 | class ViState: 33 | """ 34 | Mutable class to hold the state of the Vi navigation. 35 | """ 36 | 37 | def __init__(self) -> None: 38 | #: None or CharacterFind instance. (This is used to repeat the last 39 | #: search in Vi mode, by pressing the 'n' or 'N' in navigation mode.) 40 | self.last_character_find: Optional[CharacterFind] = None 41 | 42 | # When an operator is given and we are waiting for text object, 43 | # -- e.g. in the case of 'dw', after the 'd' --, an operator callback 44 | # is set here. 45 | self.operator_func: Optional[ 46 | Callable[["KeyPressEvent", "TextObject"], None] 47 | ] = None 48 | self.operator_arg: Optional[int] = None 49 | 50 | #: Named registers. Maps register name (e.g. 'a') to 51 | #: :class:`ClipboardData` instances. 52 | self.named_registers: Dict[str, ClipboardData] = {} 53 | 54 | #: The Vi mode we're currently in to. 55 | self.__input_mode = InputMode.INSERT 56 | 57 | #: Waiting for digraph. 58 | self.waiting_for_digraph = False 59 | self.digraph_symbol1: Optional[str] = None # (None or a symbol.) 60 | 61 | #: When true, make ~ act as an operator. 62 | self.tilde_operator = False 63 | 64 | #: Register in which we are recording a macro. 65 | #: `None` when not recording anything. 66 | # Note that the recording is only stored in the register after the 67 | # recording is stopped. So we record in a separate `current_recording` 68 | # variable. 69 | self.recording_register: Optional[str] = None 70 | self.current_recording: str = "" 71 | 72 | # Temporary navigation (normal) mode. 73 | # This happens when control-o has been pressed in insert or replace 74 | # mode. The user can now do one navigation action and we'll return back 75 | # to insert/replace. 76 | self.temporary_navigation_mode = False 77 | 78 | @property 79 | def input_mode(self) -> InputMode: 80 | " Get `InputMode`. " 81 | return self.__input_mode 82 | 83 | @input_mode.setter 84 | def input_mode(self, value: InputMode) -> None: 85 | " Set `InputMode`. " 86 | if value == InputMode.NAVIGATION: 87 | self.waiting_for_digraph = False 88 | self.operator_func = None 89 | self.operator_arg = None 90 | 91 | self.__input_mode = value 92 | 93 | def reset(self) -> None: 94 | """ 95 | Reset state, go back to the given mode. INSERT by default. 96 | """ 97 | # Go back to insert mode. 98 | self.input_mode = InputMode.INSERT 99 | 100 | self.waiting_for_digraph = False 101 | self.operator_func = None 102 | self.operator_arg = None 103 | 104 | # Reset recording state. 105 | self.recording_register = None 106 | self.current_recording = "" 107 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/keys.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from typing import Dict, List 3 | 4 | __all__ = [ 5 | "Keys", 6 | "ALL_KEYS", 7 | ] 8 | 9 | 10 | class Keys(str, Enum): 11 | """ 12 | List of keys for use in key bindings. 13 | 14 | Note that this is an "StrEnum", all values can be compared against 15 | strings. 16 | """ 17 | 18 | value: str 19 | 20 | Escape = "escape" # Also Control-[ 21 | ShiftEscape = "s-escape" 22 | 23 | ControlAt = "c-@" # Also Control-Space. 24 | 25 | ControlA = "c-a" 26 | ControlB = "c-b" 27 | ControlC = "c-c" 28 | ControlD = "c-d" 29 | ControlE = "c-e" 30 | ControlF = "c-f" 31 | ControlG = "c-g" 32 | ControlH = "c-h" 33 | ControlI = "c-i" # Tab 34 | ControlJ = "c-j" # Newline 35 | ControlK = "c-k" 36 | ControlL = "c-l" 37 | ControlM = "c-m" # Carriage return 38 | ControlN = "c-n" 39 | ControlO = "c-o" 40 | ControlP = "c-p" 41 | ControlQ = "c-q" 42 | ControlR = "c-r" 43 | ControlS = "c-s" 44 | ControlT = "c-t" 45 | ControlU = "c-u" 46 | ControlV = "c-v" 47 | ControlW = "c-w" 48 | ControlX = "c-x" 49 | ControlY = "c-y" 50 | ControlZ = "c-z" 51 | 52 | Control1 = "c-1" 53 | Control2 = "c-2" 54 | Control3 = "c-3" 55 | Control4 = "c-4" 56 | Control5 = "c-5" 57 | Control6 = "c-6" 58 | Control7 = "c-7" 59 | Control8 = "c-8" 60 | Control9 = "c-9" 61 | Control0 = "c-0" 62 | 63 | ControlShift1 = "c-s-1" 64 | ControlShift2 = "c-s-2" 65 | ControlShift3 = "c-s-3" 66 | ControlShift4 = "c-s-4" 67 | ControlShift5 = "c-s-5" 68 | ControlShift6 = "c-s-6" 69 | ControlShift7 = "c-s-7" 70 | ControlShift8 = "c-s-8" 71 | ControlShift9 = "c-s-9" 72 | ControlShift0 = "c-s-0" 73 | 74 | ControlBackslash = "c-\\" 75 | ControlSquareClose = "c-]" 76 | ControlCircumflex = "c-^" 77 | ControlUnderscore = "c-_" 78 | 79 | Left = "left" 80 | Right = "right" 81 | Up = "up" 82 | Down = "down" 83 | Home = "home" 84 | End = "end" 85 | Insert = "insert" 86 | Delete = "delete" 87 | PageUp = "pageup" 88 | PageDown = "pagedown" 89 | 90 | ControlLeft = "c-left" 91 | ControlRight = "c-right" 92 | ControlUp = "c-up" 93 | ControlDown = "c-down" 94 | ControlHome = "c-home" 95 | ControlEnd = "c-end" 96 | ControlInsert = "c-insert" 97 | ControlDelete = "c-delete" 98 | ControlPageUp = "c-pageup" 99 | ControlPageDown = "c-pagedown" 100 | 101 | ShiftLeft = "s-left" 102 | ShiftRight = "s-right" 103 | ShiftUp = "s-up" 104 | ShiftDown = "s-down" 105 | ShiftHome = "s-home" 106 | ShiftEnd = "s-end" 107 | ShiftInsert = "s-insert" 108 | ShiftDelete = "s-delete" 109 | ShiftPageUp = "s-pageup" 110 | ShiftPageDown = "s-pagedown" 111 | 112 | ControlShiftLeft = "c-s-left" 113 | ControlShiftRight = "c-s-right" 114 | ControlShiftUp = "c-s-up" 115 | ControlShiftDown = "c-s-down" 116 | ControlShiftHome = "c-s-home" 117 | ControlShiftEnd = "c-s-end" 118 | ControlShiftInsert = "c-s-insert" 119 | ControlShiftDelete = "c-s-delete" 120 | ControlShiftPageUp = "c-s-pageup" 121 | ControlShiftPageDown = "c-s-pagedown" 122 | 123 | BackTab = "s-tab" # shift + tab 124 | 125 | F1 = "f1" 126 | F2 = "f2" 127 | F3 = "f3" 128 | F4 = "f4" 129 | F5 = "f5" 130 | F6 = "f6" 131 | F7 = "f7" 132 | F8 = "f8" 133 | F9 = "f9" 134 | F10 = "f10" 135 | F11 = "f11" 136 | F12 = "f12" 137 | F13 = "f13" 138 | F14 = "f14" 139 | F15 = "f15" 140 | F16 = "f16" 141 | F17 = "f17" 142 | F18 = "f18" 143 | F19 = "f19" 144 | F20 = "f20" 145 | F21 = "f21" 146 | F22 = "f22" 147 | F23 = "f23" 148 | F24 = "f24" 149 | 150 | ControlF1 = "c-f1" 151 | ControlF2 = "c-f2" 152 | ControlF3 = "c-f3" 153 | ControlF4 = "c-f4" 154 | ControlF5 = "c-f5" 155 | ControlF6 = "c-f6" 156 | ControlF7 = "c-f7" 157 | ControlF8 = "c-f8" 158 | ControlF9 = "c-f9" 159 | ControlF10 = "c-f10" 160 | ControlF11 = "c-f11" 161 | ControlF12 = "c-f12" 162 | ControlF13 = "c-f13" 163 | ControlF14 = "c-f14" 164 | ControlF15 = "c-f15" 165 | ControlF16 = "c-f16" 166 | ControlF17 = "c-f17" 167 | ControlF18 = "c-f18" 168 | ControlF19 = "c-f19" 169 | ControlF20 = "c-f20" 170 | ControlF21 = "c-f21" 171 | ControlF22 = "c-f22" 172 | ControlF23 = "c-f23" 173 | ControlF24 = "c-f24" 174 | 175 | # Matches any key. 176 | Any = "" 177 | 178 | # Special. 179 | ScrollUp = "" 180 | ScrollDown = "" 181 | 182 | CPRResponse = "" 183 | Vt100MouseEvent = "" 184 | WindowsMouseEvent = "" 185 | BracketedPaste = "" 186 | 187 | # For internal use: key which is ignored. 188 | # (The key binding for this key should not do anything.) 189 | Ignore = "" 190 | 191 | # Some 'Key' aliases (for backwards-compatibility). 192 | ControlSpace = ControlAt 193 | Tab = ControlI 194 | Enter = ControlM 195 | Backspace = ControlH 196 | 197 | # ShiftControl was renamed to ControlShift in 198 | # 888fcb6fa4efea0de8333177e1bbc792f3ff3c24 (20 Feb 2020). 199 | ShiftControlLeft = ControlShiftLeft 200 | ShiftControlRight = ControlShiftRight 201 | ShiftControlHome = ControlShiftHome 202 | ShiftControlEnd = ControlShiftEnd 203 | 204 | 205 | ALL_KEYS: List[str] = [k.value for k in Keys] 206 | 207 | 208 | # Aliases. 209 | KEY_ALIASES: Dict[str, str] = { 210 | "backspace": "c-h", 211 | "c-space": "c-@", 212 | "enter": "c-m", 213 | "tab": "c-i", 214 | # ShiftControl was renamed to ControlShift. 215 | "s-c-left": "c-s-left", 216 | "s-c-right": "c-s-right", 217 | "s-c-home": "c-s-home", 218 | "s-c-end": "c-s-end", 219 | } 220 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/layout/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Command line layout definitions 3 | ------------------------------- 4 | 5 | The layout of a command line interface is defined by a Container instance. 6 | There are two main groups of classes here. Containers and controls: 7 | 8 | - A container can contain other containers or controls, it can have multiple 9 | children and it decides about the dimensions. 10 | - A control is responsible for rendering the actual content to a screen. 11 | A control can propose some dimensions, but it's the container who decides 12 | about the dimensions -- or when the control consumes more space -- which part 13 | of the control will be visible. 14 | 15 | 16 | Container classes:: 17 | 18 | - Container (Abstract base class) 19 | |- HSplit (Horizontal split) 20 | |- VSplit (Vertical split) 21 | |- FloatContainer (Container which can also contain menus and other floats) 22 | `- Window (Container which contains one actual control 23 | 24 | Control classes:: 25 | 26 | - UIControl (Abstract base class) 27 | |- FormattedTextControl (Renders formatted text, or a simple list of text fragments) 28 | `- BufferControl (Renders an input buffer.) 29 | 30 | 31 | Usually, you end up wrapping every control inside a `Window` object, because 32 | that's the only way to render it in a layout. 33 | 34 | There are some prepared toolbars which are ready to use:: 35 | 36 | - SystemToolbar (Shows the 'system' input buffer, for entering system commands.) 37 | - ArgToolbar (Shows the input 'arg', for repetition of input commands.) 38 | - SearchToolbar (Shows the 'search' input buffer, for incremental search.) 39 | - CompletionsToolbar (Shows the completions of the current buffer.) 40 | - ValidationToolbar (Shows validation errors of the current buffer.) 41 | 42 | And one prepared menu: 43 | 44 | - CompletionsMenu 45 | 46 | """ 47 | from .containers import ( 48 | ColorColumn, 49 | ConditionalContainer, 50 | Container, 51 | DynamicContainer, 52 | Float, 53 | FloatContainer, 54 | HorizontalAlign, 55 | HSplit, 56 | ScrollOffsets, 57 | VerticalAlign, 58 | VSplit, 59 | Window, 60 | WindowAlign, 61 | WindowRenderInfo, 62 | is_container, 63 | to_container, 64 | to_window, 65 | ) 66 | from .controls import ( 67 | BufferControl, 68 | DummyControl, 69 | FormattedTextControl, 70 | SearchBufferControl, 71 | UIContent, 72 | UIControl, 73 | ) 74 | from .dimension import ( 75 | AnyDimension, 76 | D, 77 | Dimension, 78 | is_dimension, 79 | max_layout_dimensions, 80 | sum_layout_dimensions, 81 | to_dimension, 82 | ) 83 | from .layout import InvalidLayoutError, Layout, walk 84 | from .margins import ( 85 | ConditionalMargin, 86 | Margin, 87 | NumberedMargin, 88 | PromptMargin, 89 | ScrollbarMargin, 90 | ) 91 | from .menus import CompletionsMenu, MultiColumnCompletionsMenu 92 | 93 | __all__ = [ 94 | # Layout. 95 | "Layout", 96 | "InvalidLayoutError", 97 | "walk", 98 | # Dimensions. 99 | "AnyDimension", 100 | "Dimension", 101 | "D", 102 | "sum_layout_dimensions", 103 | "max_layout_dimensions", 104 | "to_dimension", 105 | "is_dimension", 106 | # Containers. 107 | "Container", 108 | "HorizontalAlign", 109 | "VerticalAlign", 110 | "HSplit", 111 | "VSplit", 112 | "FloatContainer", 113 | "Float", 114 | "WindowAlign", 115 | "Window", 116 | "WindowRenderInfo", 117 | "ConditionalContainer", 118 | "ScrollOffsets", 119 | "ColorColumn", 120 | "to_container", 121 | "to_window", 122 | "is_container", 123 | "DynamicContainer", 124 | # Controls. 125 | "BufferControl", 126 | "SearchBufferControl", 127 | "DummyControl", 128 | "FormattedTextControl", 129 | "UIControl", 130 | "UIContent", 131 | # Margins. 132 | "Margin", 133 | "NumberedMargin", 134 | "ScrollbarMargin", 135 | "ConditionalMargin", 136 | "PromptMargin", 137 | # Menus. 138 | "CompletionsMenu", 139 | "MultiColumnCompletionsMenu", 140 | ] 141 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/layout/dummy.py: -------------------------------------------------------------------------------- 1 | """ 2 | Dummy layout. Used when somebody creates an `Application` without specifying a 3 | `Layout`. 4 | """ 5 | from prompt_toolkit.formatted_text import HTML 6 | from prompt_toolkit.key_binding import KeyBindings 7 | from prompt_toolkit.key_binding.key_processor import KeyPressEvent 8 | 9 | from .containers import Window 10 | from .controls import FormattedTextControl 11 | from .dimension import D 12 | from .layout import Layout 13 | 14 | __all__ = [ 15 | "create_dummy_layout", 16 | ] 17 | 18 | E = KeyPressEvent 19 | 20 | 21 | def create_dummy_layout() -> Layout: 22 | """ 23 | Create a dummy layout for use in an 'Application' that doesn't have a 24 | layout specified. When ENTER is pressed, the application quits. 25 | """ 26 | kb = KeyBindings() 27 | 28 | @kb.add("enter") 29 | def enter(event: E) -> None: 30 | event.app.exit() 31 | 32 | control = FormattedTextControl( 33 | HTML("No layout specified. Press ENTER to quit."), 34 | key_bindings=kb, 35 | ) 36 | window = Window(content=control, height=D(min=1)) 37 | return Layout(container=window, focused_element=window) 38 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/layout/mouse_handlers.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | from itertools import product 3 | from typing import Callable, DefaultDict, Tuple 4 | 5 | from prompt_toolkit.mouse_events import MouseEvent 6 | 7 | __all__ = [ 8 | "MouseHandlers", 9 | ] 10 | 11 | 12 | class MouseHandlers: 13 | """ 14 | Two dimensional raster of callbacks for mouse events. 15 | """ 16 | 17 | def __init__(self) -> None: 18 | def dummy_callback(mouse_event: MouseEvent) -> None: 19 | """ 20 | :param mouse_event: `MouseEvent` instance. 21 | """ 22 | 23 | # Map (x,y) tuples to handlers. 24 | self.mouse_handlers: DefaultDict[ 25 | Tuple[int, int], Callable[[MouseEvent], None] 26 | ] = defaultdict(lambda: dummy_callback) 27 | 28 | def set_mouse_handler_for_range( 29 | self, 30 | x_min: int, 31 | x_max: int, 32 | y_min: int, 33 | y_max: int, 34 | handler: Callable[[MouseEvent], None], 35 | ) -> None: 36 | """ 37 | Set mouse handler for a region. 38 | """ 39 | for x, y in product(range(x_min, x_max), range(y_min, y_max)): 40 | self.mouse_handlers[x, y] = handler 41 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/layout/utils.py: -------------------------------------------------------------------------------- 1 | from typing import Iterable, List, TypeVar, Union, cast, overload 2 | 3 | from prompt_toolkit.formatted_text.base import OneStyleAndTextTuple 4 | 5 | __all__ = [ 6 | "explode_text_fragments", 7 | ] 8 | 9 | _T = TypeVar("_T", bound=OneStyleAndTextTuple) 10 | 11 | 12 | class _ExplodedList(List[_T]): 13 | """ 14 | Wrapper around a list, that marks it as 'exploded'. 15 | 16 | As soon as items are added or the list is extended, the new items are 17 | automatically exploded as well. 18 | """ 19 | 20 | exploded = True 21 | 22 | def append(self, item: _T) -> None: 23 | self.extend([item]) 24 | 25 | def extend(self, lst: Iterable[_T]) -> None: 26 | super().extend(explode_text_fragments(lst)) 27 | 28 | def insert(self, index: int, item: _T) -> None: 29 | raise NotImplementedError # TODO 30 | 31 | # TODO: When creating a copy() or [:], return also an _ExplodedList. 32 | 33 | @overload 34 | def __setitem__(self, index: int, value: _T) -> None: 35 | ... 36 | 37 | @overload 38 | def __setitem__(self, index: slice, value: Iterable[_T]) -> None: 39 | ... 40 | 41 | def __setitem__( 42 | self, index: Union[int, slice], value: Union[_T, Iterable[_T]] 43 | ) -> None: 44 | """ 45 | Ensure that when `(style_str, 'long string')` is set, the string will be 46 | exploded. 47 | """ 48 | if not isinstance(index, slice): 49 | index = slice(index, index + 1) 50 | if isinstance(value, tuple): # In case of `OneStyleAndTextTuple`. 51 | value = cast("List[_T]", [value]) 52 | 53 | super().__setitem__(index, explode_text_fragments(cast("Iterable[_T]", value))) 54 | 55 | 56 | def explode_text_fragments(fragments: Iterable[_T]) -> _ExplodedList[_T]: 57 | """ 58 | Turn a list of (style_str, text) tuples into another list where each string is 59 | exactly one character. 60 | 61 | It should be fine to call this function several times. Calling this on a 62 | list that is already exploded, is a null operation. 63 | 64 | :param fragments: List of (style, text) tuples. 65 | """ 66 | # When the fragments is already exploded, don't explode again. 67 | if isinstance(fragments, _ExplodedList): 68 | return fragments 69 | 70 | result: List[_T] = [] 71 | 72 | for style, string, *rest in fragments: # type: ignore 73 | for c in string: # type: ignore 74 | result.append((style, c, *rest)) # type: ignore 75 | 76 | return _ExplodedList(result) 77 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/lexers/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Lexer interface and implementations. 3 | Used for syntax highlighting. 4 | """ 5 | from .base import DynamicLexer, Lexer, SimpleLexer 6 | from .pygments import PygmentsLexer, RegexSync, SyncFromStart, SyntaxSync 7 | 8 | __all__ = [ 9 | # Base. 10 | "Lexer", 11 | "SimpleLexer", 12 | "DynamicLexer", 13 | # Pygments. 14 | "PygmentsLexer", 15 | "RegexSync", 16 | "SyncFromStart", 17 | "SyntaxSync", 18 | ] 19 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/lexers/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | Base classes for prompt_toolkit lexers. 3 | """ 4 | from abc import ABCMeta, abstractmethod 5 | from typing import Callable, Hashable, Optional 6 | 7 | from prompt_toolkit.document import Document 8 | from prompt_toolkit.formatted_text.base import StyleAndTextTuples 9 | 10 | __all__ = [ 11 | "Lexer", 12 | "SimpleLexer", 13 | "DynamicLexer", 14 | ] 15 | 16 | 17 | class Lexer(metaclass=ABCMeta): 18 | """ 19 | Base class for all lexers. 20 | """ 21 | 22 | @abstractmethod 23 | def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]: 24 | """ 25 | Takes a :class:`~prompt_toolkit.document.Document` and returns a 26 | callable that takes a line number and returns a list of 27 | ``(style_str, text)`` tuples for that line. 28 | 29 | XXX: Note that in the past, this was supposed to return a list 30 | of ``(Token, text)`` tuples, just like a Pygments lexer. 31 | """ 32 | 33 | def invalidation_hash(self) -> Hashable: 34 | """ 35 | When this changes, `lex_document` could give a different output. 36 | (Only used for `DynamicLexer`.) 37 | """ 38 | return id(self) 39 | 40 | 41 | class SimpleLexer(Lexer): 42 | """ 43 | Lexer that doesn't do any tokenizing and returns the whole input as one 44 | token. 45 | 46 | :param style: The style string for this lexer. 47 | """ 48 | 49 | def __init__(self, style: str = "") -> None: 50 | self.style = style 51 | 52 | def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]: 53 | lines = document.lines 54 | 55 | def get_line(lineno: int) -> StyleAndTextTuples: 56 | " Return the tokens for the given line. " 57 | try: 58 | return [(self.style, lines[lineno])] 59 | except IndexError: 60 | return [] 61 | 62 | return get_line 63 | 64 | 65 | class DynamicLexer(Lexer): 66 | """ 67 | Lexer class that can dynamically returns any Lexer. 68 | 69 | :param get_lexer: Callable that returns a :class:`.Lexer` instance. 70 | """ 71 | 72 | def __init__(self, get_lexer: Callable[[], Optional[Lexer]]) -> None: 73 | self.get_lexer = get_lexer 74 | self._dummy = SimpleLexer() 75 | 76 | def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]: 77 | lexer = self.get_lexer() or self._dummy 78 | return lexer.lex_document(document) 79 | 80 | def invalidation_hash(self) -> Hashable: 81 | lexer = self.get_lexer() or self._dummy 82 | return id(lexer) 83 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/log.py: -------------------------------------------------------------------------------- 1 | """ 2 | Logging configuration. 3 | """ 4 | import logging 5 | 6 | __all__ = [ 7 | "logger", 8 | ] 9 | 10 | logger = logging.getLogger(__package__) 11 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/mouse_events.py: -------------------------------------------------------------------------------- 1 | """ 2 | Mouse events. 3 | 4 | 5 | How it works 6 | ------------ 7 | 8 | The renderer has a 2 dimensional grid of mouse event handlers. 9 | (`prompt_toolkit.layout.MouseHandlers`.) When the layout is rendered, the 10 | `Window` class will make sure that this grid will also be filled with 11 | callbacks. For vt100 terminals, mouse events are received through stdin, just 12 | like any other key press. There is a handler among the key bindings that 13 | catches these events and forwards them to such a mouse event handler. It passes 14 | through the `Window` class where the coordinates are translated from absolute 15 | coordinates to coordinates relative to the user control, and there 16 | `UIControl.mouse_handler` is called. 17 | """ 18 | from enum import Enum 19 | 20 | from .data_structures import Point 21 | 22 | __all__ = ["MouseEventType", "MouseEvent"] 23 | 24 | 25 | class MouseEventType(Enum): 26 | MOUSE_UP = "MOUSE_UP" 27 | MOUSE_DOWN = "MOUSE_DOWN" 28 | SCROLL_UP = "SCROLL_UP" 29 | SCROLL_DOWN = "SCROLL_DOWN" 30 | 31 | 32 | class MouseEvent: 33 | """ 34 | Mouse event, sent to `UIControl.mouse_handler`. 35 | 36 | :param position: `Point` instance. 37 | :param event_type: `MouseEventType`. 38 | """ 39 | 40 | def __init__(self, position: Point, event_type: MouseEventType) -> None: 41 | self.position = position 42 | self.event_type = event_type 43 | 44 | def __repr__(self) -> str: 45 | return "MouseEvent(%r, %r)" % (self.position, self.event_type) 46 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/output/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import DummyOutput, Output 2 | from .color_depth import ColorDepth 3 | from .defaults import create_output 4 | 5 | __all__ = [ 6 | # Base. 7 | "Output", 8 | "DummyOutput", 9 | # Color depth. 10 | "ColorDepth", 11 | # Defaults. 12 | "create_output", 13 | ] 14 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/output/color_depth.py: -------------------------------------------------------------------------------- 1 | import os 2 | from enum import Enum 3 | from typing import Optional 4 | 5 | from prompt_toolkit.utils import is_dumb_terminal, is_windows 6 | 7 | __all__ = [ 8 | "ColorDepth", 9 | ] 10 | 11 | 12 | class ColorDepth(str, Enum): 13 | """ 14 | Possible color depth values for the output. 15 | """ 16 | 17 | value: str 18 | 19 | #: One color only. 20 | DEPTH_1_BIT = "DEPTH_1_BIT" 21 | 22 | #: ANSI Colors. 23 | DEPTH_4_BIT = "DEPTH_4_BIT" 24 | 25 | #: The default. 26 | DEPTH_8_BIT = "DEPTH_8_BIT" 27 | 28 | #: 24 bit True color. 29 | DEPTH_24_BIT = "DEPTH_24_BIT" 30 | 31 | # Aliases. 32 | MONOCHROME = DEPTH_1_BIT 33 | ANSI_COLORS_ONLY = DEPTH_4_BIT 34 | DEFAULT = DEPTH_8_BIT 35 | TRUE_COLOR = DEPTH_24_BIT 36 | 37 | @classmethod 38 | def default(cls, term: Optional[str] = None) -> "ColorDepth": 39 | """ 40 | Return the default color depth, according to the $TERM value. 41 | 42 | We prefer 256 colors almost always, because this is what most terminals 43 | support these days, and is a good default. 44 | 45 | The $PROMPT_TOOLKIT_COLOR_DEPTH environment variable can be used to 46 | override this outcome. This is a way to enforce a certain color depth 47 | in all prompt_toolkit applications. 48 | 49 | If no `term` parameter is given, we use the $TERM environment variable. 50 | """ 51 | # Take `TERM` value from environment variable if nothing was passed. 52 | if term is None: 53 | term = os.environ.get("TERM", "") 54 | 55 | if is_dumb_terminal(term): 56 | return cls.DEPTH_1_BIT 57 | 58 | if term in ("linux", "eterm-color"): 59 | return cls.DEPTH_4_BIT 60 | 61 | # For now, always use 4 bit color on Windows 10 by default, even when 62 | # vt100 escape sequences with ENABLE_VIRTUAL_TERMINAL_PROCESSING are 63 | # supported. We don't have a reliable way yet to know whether our 64 | # console supports true color or only 4-bit. 65 | if is_windows() and "PROMPT_TOOLKIT_COLOR_DEPTH" not in os.environ: 66 | return cls.DEPTH_4_BIT 67 | 68 | # Check the `PROMPT_TOOLKIT_COLOR_DEPTH` environment variable. 69 | all_values = [i.value for i in ColorDepth] 70 | 71 | if os.environ.get("PROMPT_TOOLKIT_COLOR_DEPTH") in all_values: 72 | return cls(os.environ["PROMPT_TOOLKIT_COLOR_DEPTH"]) 73 | 74 | return cls.DEPTH_8_BIT 75 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/output/conemu.py: -------------------------------------------------------------------------------- 1 | from typing import Any, TextIO 2 | 3 | from prompt_toolkit.data_structures import Size 4 | from prompt_toolkit.renderer import Output 5 | 6 | from .vt100 import Vt100_Output 7 | from .win32 import Win32Output 8 | 9 | __all__ = [ 10 | "ConEmuOutput", 11 | ] 12 | 13 | 14 | class ConEmuOutput: 15 | """ 16 | ConEmu (Windows) output abstraction. 17 | 18 | ConEmu is a Windows console application, but it also supports ANSI escape 19 | sequences. This output class is actually a proxy to both `Win32Output` and 20 | `Vt100_Output`. It uses `Win32Output` for console sizing and scrolling, but 21 | all cursor movements and scrolling happens through the `Vt100_Output`. 22 | 23 | This way, we can have 256 colors in ConEmu and Cmder. Rendering will be 24 | even a little faster as well. 25 | 26 | http://conemu.github.io/ 27 | http://gooseberrycreative.com/cmder/ 28 | """ 29 | 30 | def __init__(self, stdout: TextIO) -> None: 31 | self.win32_output = Win32Output(stdout) 32 | self.vt100_output = Vt100_Output(stdout, lambda: Size(0, 0)) 33 | 34 | def __getattr__(self, name: str) -> Any: 35 | if name in ( 36 | "get_size", 37 | "get_rows_below_cursor_position", 38 | "enable_mouse_support", 39 | "disable_mouse_support", 40 | "scroll_buffer_to_prompt", 41 | "get_win32_screen_buffer_info", 42 | "enable_bracketed_paste", 43 | "disable_bracketed_paste", 44 | ): 45 | return getattr(self.win32_output, name) 46 | else: 47 | return getattr(self.vt100_output, name) 48 | 49 | 50 | Output.register(ConEmuOutput) 51 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/output/defaults.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from typing import Optional, TextIO, cast 3 | 4 | from prompt_toolkit.patch_stdout import StdoutProxy 5 | from prompt_toolkit.utils import ( 6 | get_term_environment_variable, 7 | is_conemu_ansi, 8 | is_windows, 9 | ) 10 | 11 | from .base import Output 12 | 13 | __all__ = [ 14 | "create_output", 15 | ] 16 | 17 | 18 | def create_output( 19 | stdout: Optional[TextIO] = None, always_prefer_tty: bool = True 20 | ) -> Output: 21 | """ 22 | Return an :class:`~prompt_toolkit.output.Output` instance for the command 23 | line. 24 | 25 | :param stdout: The stdout object 26 | :param always_prefer_tty: When set, look for `sys.stderr` if `sys.stdout` 27 | is not a TTY. (The prompt_toolkit render output is not meant to be 28 | consumed by something other then a terminal, so this is a reasonable 29 | default.) 30 | """ 31 | if stdout is None: 32 | # By default, render to stdout. If the output is piped somewhere else, 33 | # render to stderr. 34 | stdout = sys.stdout 35 | 36 | if always_prefer_tty: 37 | for io in [sys.stdout, sys.stderr]: 38 | if io.isatty(): 39 | stdout = io 40 | break 41 | 42 | # If the patch_stdout context manager has been used, then sys.stdout is 43 | # replaced by this proxy. For prompt_toolkit applications, we want to use 44 | # the real stdout. 45 | while isinstance(stdout, StdoutProxy): 46 | stdout = stdout.original_stdout 47 | 48 | if is_windows(): 49 | from .conemu import ConEmuOutput 50 | from .win32 import Win32Output 51 | from .windows10 import is_win_vt100_enabled, Windows10_Output 52 | 53 | if is_win_vt100_enabled(): 54 | return cast(Output, Windows10_Output(stdout)) 55 | if is_conemu_ansi(): 56 | return cast(Output, ConEmuOutput(stdout)) 57 | else: 58 | return Win32Output(stdout) 59 | else: 60 | from .vt100 import Vt100_Output 61 | 62 | return Vt100_Output.from_pty(stdout, term=get_term_environment_variable()) 63 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/output/windows10.py: -------------------------------------------------------------------------------- 1 | from ctypes import byref, windll 2 | from ctypes.wintypes import DWORD, HANDLE 3 | from typing import Any, TextIO 4 | 5 | from prompt_toolkit.data_structures import Size 6 | from prompt_toolkit.renderer import Output 7 | from prompt_toolkit.utils import is_windows 8 | from prompt_toolkit.win32_types import STD_OUTPUT_HANDLE 9 | 10 | from .vt100 import Vt100_Output 11 | from .win32 import Win32Output 12 | 13 | __all__ = [ 14 | "Windows10_Output", 15 | ] 16 | 17 | # See: https://msdn.microsoft.com/pl-pl/library/windows/desktop/ms686033(v=vs.85).aspx 18 | ENABLE_PROCESSED_INPUT = 0x0001 19 | ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 20 | 21 | 22 | class Windows10_Output: 23 | """ 24 | Windows 10 output abstraction. This enables and uses vt100 escape sequences. 25 | """ 26 | 27 | def __init__(self, stdout: TextIO) -> None: 28 | self.win32_output = Win32Output(stdout) 29 | self.vt100_output = Vt100_Output(stdout, lambda: Size(0, 0)) 30 | self._hconsole = HANDLE(windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)) 31 | 32 | def flush(self) -> None: 33 | """ 34 | Write to output stream and flush. 35 | """ 36 | original_mode = DWORD(0) 37 | 38 | # Remember the previous console mode. 39 | windll.kernel32.GetConsoleMode(self._hconsole, byref(original_mode)) 40 | 41 | # Enable processing of vt100 sequences. 42 | windll.kernel32.SetConsoleMode( 43 | self._hconsole, 44 | DWORD(ENABLE_PROCESSED_INPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING), 45 | ) 46 | 47 | try: 48 | self.vt100_output.flush() 49 | finally: 50 | # Restore console mode. 51 | windll.kernel32.SetConsoleMode(self._hconsole, original_mode) 52 | 53 | def __getattr__(self, name: str) -> Any: 54 | if name in ( 55 | "get_size", 56 | "get_rows_below_cursor_position", 57 | "enable_mouse_support", 58 | "disable_mouse_support", 59 | "scroll_buffer_to_prompt", 60 | "get_win32_screen_buffer_info", 61 | "enable_bracketed_paste", 62 | "disable_bracketed_paste", 63 | ): 64 | return getattr(self.win32_output, name) 65 | else: 66 | return getattr(self.vt100_output, name) 67 | 68 | 69 | Output.register(Windows10_Output) 70 | 71 | 72 | def is_win_vt100_enabled() -> bool: 73 | """ 74 | Returns True when we're running Windows and VT100 escape sequences are 75 | supported. 76 | """ 77 | if not is_windows(): 78 | return False 79 | 80 | hconsole = HANDLE(windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)) 81 | 82 | # Get original console mode. 83 | original_mode = DWORD(0) 84 | windll.kernel32.GetConsoleMode(hconsole, byref(original_mode)) 85 | 86 | try: 87 | # Try to enable VT100 sequences. 88 | result = windll.kernel32.SetConsoleMode( 89 | hconsole, DWORD(ENABLE_PROCESSED_INPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING) 90 | ) 91 | 92 | return result == 1 93 | finally: 94 | windll.kernel32.SetConsoleMode(hconsole, original_mode) 95 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/patch_stdout.py: -------------------------------------------------------------------------------- 1 | """ 2 | patch_stdout 3 | ============ 4 | 5 | This implements a context manager that ensures that print statements within 6 | it won't destroy the user interface. The context manager will replace 7 | `sys.stdout` by something that draws the output above the current prompt, 8 | rather than overwriting the UI. 9 | 10 | Usage:: 11 | 12 | with patch_stdout(application): 13 | ... 14 | application.run() 15 | ... 16 | 17 | Multiple applications can run in the body of the context manager, one after the 18 | other. 19 | """ 20 | import sys 21 | import threading 22 | from asyncio import get_event_loop 23 | from contextlib import contextmanager 24 | from typing import Generator, List, Optional, TextIO, cast 25 | 26 | from .application import run_in_terminal 27 | 28 | __all__ = [ 29 | "patch_stdout", 30 | "StdoutProxy", 31 | ] 32 | 33 | 34 | @contextmanager 35 | def patch_stdout(raw: bool = False) -> Generator[None, None, None]: 36 | """ 37 | Replace `sys.stdout` by an :class:`_StdoutProxy` instance. 38 | 39 | Writing to this proxy will make sure that the text appears above the 40 | prompt, and that it doesn't destroy the output from the renderer. If no 41 | application is curring, the behaviour should be identical to writing to 42 | `sys.stdout` directly. 43 | 44 | Warning: If a new event loop is installed using `asyncio.set_event_loop()`, 45 | then make sure that the context manager is applied after the event loop 46 | is changed. Printing to stdout will be scheduled in the event loop 47 | that's active when the context manager is created. 48 | 49 | :param raw: (`bool`) When True, vt100 terminal escape sequences are not 50 | removed/escaped. 51 | """ 52 | proxy = cast(TextIO, StdoutProxy(raw=raw)) 53 | 54 | original_stdout = sys.stdout 55 | original_stderr = sys.stderr 56 | 57 | # Enter. 58 | sys.stdout = proxy 59 | sys.stderr = proxy 60 | 61 | try: 62 | yield 63 | finally: 64 | # Exit. 65 | proxy.flush() 66 | 67 | sys.stdout = original_stdout 68 | sys.stderr = original_stderr 69 | 70 | 71 | class StdoutProxy: 72 | """ 73 | Proxy object for stdout which captures everything and prints output above 74 | the current application. 75 | """ 76 | 77 | def __init__( 78 | self, raw: bool = False, original_stdout: Optional[TextIO] = None 79 | ) -> None: 80 | 81 | original_stdout = original_stdout or sys.__stdout__ 82 | 83 | self.original_stdout = original_stdout 84 | 85 | self._lock = threading.RLock() 86 | self._raw = raw 87 | self._buffer: List[str] = [] 88 | 89 | # errors/encoding attribute for compatibility with sys.__stdout__. 90 | self.errors = original_stdout.errors 91 | self.encoding = original_stdout.encoding 92 | 93 | self.loop = get_event_loop() 94 | 95 | def _write_and_flush(self, text: str) -> None: 96 | """ 97 | Write the given text to stdout and flush. 98 | If an application is running, use `run_in_terminal`. 99 | """ 100 | if not text: 101 | # Don't bother calling `run_in_terminal` when there is nothing to 102 | # display. 103 | return 104 | 105 | def write_and_flush() -> None: 106 | self.original_stdout.write(text) 107 | self.original_stdout.flush() 108 | 109 | def write_and_flush_in_loop() -> None: 110 | # If an application is running, use `run_in_terminal`, otherwise 111 | # call it directly. 112 | run_in_terminal.run_in_terminal(write_and_flush, in_executor=False) 113 | 114 | # Make sure `write_and_flush` is executed *in* the event loop, not in 115 | # another thread. 116 | self.loop.call_soon_threadsafe(write_and_flush_in_loop) 117 | 118 | def _write(self, data: str) -> None: 119 | """ 120 | Note: print()-statements cause to multiple write calls. 121 | (write('line') and write('\n')). Of course we don't want to call 122 | `run_in_terminal` for every individual call, because that's too 123 | expensive, and as long as the newline hasn't been written, the 124 | text itself is again overwritten by the rendering of the input 125 | command line. Therefor, we have a little buffer which holds the 126 | text until a newline is written to stdout. 127 | """ 128 | if "\n" in data: 129 | # When there is a newline in the data, write everything before the 130 | # newline, including the newline itself. 131 | before, after = data.rsplit("\n", 1) 132 | to_write = self._buffer + [before, "\n"] 133 | self._buffer = [after] 134 | 135 | text = "".join(to_write) 136 | self._write_and_flush(text) 137 | else: 138 | # Otherwise, cache in buffer. 139 | self._buffer.append(data) 140 | 141 | def _flush(self) -> None: 142 | text = "".join(self._buffer) 143 | self._buffer = [] 144 | self._write_and_flush(text) 145 | 146 | def write(self, data: str) -> int: 147 | with self._lock: 148 | self._write(data) 149 | 150 | return len(data) # Pretend everything was written. 151 | 152 | def flush(self) -> None: 153 | """ 154 | Flush buffered output. 155 | """ 156 | with self._lock: 157 | self._flush() 158 | 159 | def fileno(self) -> int: 160 | """ 161 | Return file descriptor. 162 | """ 163 | # This is important for code that expects sys.stdout.fileno() to work. 164 | return self.original_stdout.fileno() 165 | 166 | def isatty(self) -> bool: 167 | return self.original_stdout.isatty() 168 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/selection.py: -------------------------------------------------------------------------------- 1 | """ 2 | Data structures for the selection. 3 | """ 4 | from enum import Enum 5 | 6 | __all__ = [ 7 | "SelectionType", 8 | "PasteMode", 9 | "SelectionState", 10 | ] 11 | 12 | 13 | class SelectionType(Enum): 14 | """ 15 | Type of selection. 16 | """ 17 | 18 | #: Characters. (Visual in Vi.) 19 | CHARACTERS = "CHARACTERS" 20 | 21 | #: Whole lines. (Visual-Line in Vi.) 22 | LINES = "LINES" 23 | 24 | #: A block selection. (Visual-Block in Vi.) 25 | BLOCK = "BLOCK" 26 | 27 | 28 | class PasteMode(Enum): 29 | EMACS = "EMACS" # Yank like emacs. 30 | VI_AFTER = "VI_AFTER" # When pressing 'p' in Vi. 31 | VI_BEFORE = "VI_BEFORE" # When pressing 'P' in Vi. 32 | 33 | 34 | class SelectionState: 35 | """ 36 | State of the current selection. 37 | 38 | :param original_cursor_position: int 39 | :param type: :class:`~.SelectionType` 40 | """ 41 | 42 | def __init__( 43 | self, 44 | original_cursor_position: int = 0, 45 | type: SelectionType = SelectionType.CHARACTERS, 46 | ) -> None: 47 | 48 | self.original_cursor_position = original_cursor_position 49 | self.type = type 50 | self.shift_mode = False 51 | 52 | def enter_shift_mode(self) -> None: 53 | self.shift_mode = True 54 | 55 | def __repr__(self) -> str: 56 | return "%s(original_cursor_position=%r, type=%r)" % ( 57 | self.__class__.__name__, 58 | self.original_cursor_position, 59 | self.type, 60 | ) 61 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/shortcuts/__init__.py: -------------------------------------------------------------------------------- 1 | from .dialogs import ( 2 | button_dialog, 3 | checkboxlist_dialog, 4 | input_dialog, 5 | message_dialog, 6 | progress_dialog, 7 | radiolist_dialog, 8 | yes_no_dialog, 9 | ) 10 | from .progress_bar import ProgressBar 11 | from .prompt import ( 12 | CompleteStyle, 13 | PromptSession, 14 | confirm, 15 | create_confirm_session, 16 | prompt, 17 | ) 18 | from .utils import clear, clear_title, print_container, print_formatted_text, set_title 19 | 20 | __all__ = [ 21 | # Dialogs. 22 | "input_dialog", 23 | "message_dialog", 24 | "progress_dialog", 25 | "checkboxlist_dialog", 26 | "radiolist_dialog", 27 | "yes_no_dialog", 28 | "button_dialog", 29 | # Prompts. 30 | "PromptSession", 31 | "prompt", 32 | "confirm", 33 | "create_confirm_session", 34 | "CompleteStyle", 35 | # Progress bars. 36 | "ProgressBar", 37 | # Utils. 38 | "clear", 39 | "clear_title", 40 | "print_formatted_text", 41 | "set_title", 42 | ] 43 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/shortcuts/progress_bar/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import ProgressBar 2 | from .formatters import ( 3 | Bar, 4 | Formatter, 5 | IterationsPerSecond, 6 | Label, 7 | Percentage, 8 | Progress, 9 | Rainbow, 10 | SpinningWheel, 11 | Text, 12 | TimeElapsed, 13 | TimeLeft, 14 | ) 15 | 16 | __all__ = [ 17 | "ProgressBar", 18 | # Formatters. 19 | "Formatter", 20 | "Text", 21 | "Label", 22 | "Percentage", 23 | "Bar", 24 | "Progress", 25 | "TimeElapsed", 26 | "TimeLeft", 27 | "IterationsPerSecond", 28 | "SpinningWheel", 29 | "Rainbow", 30 | ] 31 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/styles/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Styling for prompt_toolkit applications. 3 | """ 4 | from .base import ( 5 | ANSI_COLOR_NAMES, 6 | DEFAULT_ATTRS, 7 | Attrs, 8 | BaseStyle, 9 | DummyStyle, 10 | DynamicStyle, 11 | ) 12 | from .defaults import default_pygments_style, default_ui_style 13 | from .named_colors import NAMED_COLORS 14 | from .pygments import ( 15 | pygments_token_to_classname, 16 | style_from_pygments_cls, 17 | style_from_pygments_dict, 18 | ) 19 | from .style import Priority, Style, merge_styles, parse_color 20 | from .style_transformation import ( 21 | AdjustBrightnessStyleTransformation, 22 | ConditionalStyleTransformation, 23 | DummyStyleTransformation, 24 | DynamicStyleTransformation, 25 | ReverseStyleTransformation, 26 | SetDefaultColorStyleTransformation, 27 | StyleTransformation, 28 | SwapLightAndDarkStyleTransformation, 29 | merge_style_transformations, 30 | ) 31 | 32 | __all__ = [ 33 | # Base. 34 | "Attrs", 35 | "DEFAULT_ATTRS", 36 | "ANSI_COLOR_NAMES", 37 | "BaseStyle", 38 | "DummyStyle", 39 | "DynamicStyle", 40 | # Defaults. 41 | "default_ui_style", 42 | "default_pygments_style", 43 | # Style. 44 | "Style", 45 | "Priority", 46 | "merge_styles", 47 | "parse_color", 48 | # Style transformation. 49 | "StyleTransformation", 50 | "SwapLightAndDarkStyleTransformation", 51 | "ReverseStyleTransformation", 52 | "SetDefaultColorStyleTransformation", 53 | "AdjustBrightnessStyleTransformation", 54 | "DummyStyleTransformation", 55 | "ConditionalStyleTransformation", 56 | "DynamicStyleTransformation", 57 | "merge_style_transformations", 58 | # Pygments. 59 | "style_from_pygments_cls", 60 | "style_from_pygments_dict", 61 | "pygments_token_to_classname", 62 | # Named colors. 63 | "NAMED_COLORS", 64 | ] 65 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/styles/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | The base classes for the styling. 3 | """ 4 | from abc import ABCMeta, abstractmethod, abstractproperty 5 | from typing import Callable, Dict, Hashable, List, NamedTuple, Optional, Tuple 6 | 7 | __all__ = [ 8 | "Attrs", 9 | "DEFAULT_ATTRS", 10 | "ANSI_COLOR_NAMES", 11 | "ANSI_COLOR_NAMES_ALIASES", 12 | "BaseStyle", 13 | "DummyStyle", 14 | "DynamicStyle", 15 | ] 16 | 17 | 18 | #: Style attributes. 19 | Attrs = NamedTuple( 20 | "Attrs", 21 | [ 22 | ("color", Optional[str]), 23 | ("bgcolor", Optional[str]), 24 | ("bold", Optional[bool]), 25 | ("underline", Optional[bool]), 26 | ("italic", Optional[bool]), 27 | ("blink", Optional[bool]), 28 | ("reverse", Optional[bool]), 29 | ("hidden", Optional[bool]), 30 | ], 31 | ) 32 | 33 | """ 34 | :param color: Hexadecimal string. E.g. '000000' or Ansi color name: e.g. 'ansiblue' 35 | :param bgcolor: Hexadecimal string. E.g. 'ffffff' or Ansi color name: e.g. 'ansired' 36 | :param bold: Boolean 37 | :param underline: Boolean 38 | :param italic: Boolean 39 | :param blink: Boolean 40 | :param reverse: Boolean 41 | :param hidden: Boolean 42 | """ 43 | 44 | #: The default `Attrs`. 45 | DEFAULT_ATTRS = Attrs( 46 | color="", 47 | bgcolor="", 48 | bold=False, 49 | underline=False, 50 | italic=False, 51 | blink=False, 52 | reverse=False, 53 | hidden=False, 54 | ) 55 | 56 | 57 | #: ``Attrs.bgcolor/fgcolor`` can be in either 'ffffff' format, or can be any of 58 | #: the following in case we want to take colors from the 8/16 color palette. 59 | #: Usually, in that case, the terminal application allows to configure the RGB 60 | #: values for these names. 61 | #: ISO 6429 colors 62 | ANSI_COLOR_NAMES = [ 63 | "ansidefault", 64 | # Low intensity, dark. (One or two components 0x80, the other 0x00.) 65 | "ansiblack", 66 | "ansired", 67 | "ansigreen", 68 | "ansiyellow", 69 | "ansiblue", 70 | "ansimagenta", 71 | "ansicyan", 72 | "ansigray", 73 | # High intensity, bright. (One or two components 0xff, the other 0x00. Not supported everywhere.) 74 | "ansibrightblack", 75 | "ansibrightred", 76 | "ansibrightgreen", 77 | "ansibrightyellow", 78 | "ansibrightblue", 79 | "ansibrightmagenta", 80 | "ansibrightcyan", 81 | "ansiwhite", 82 | ] 83 | 84 | 85 | # People don't use the same ANSI color names everywhere. In prompt_toolkit 1.0 86 | # we used some unconventional names (which were contributed like that to 87 | # Pygments). This is fixed now, but we still support the old names. 88 | 89 | # The table below maps the old aliases to the current names. 90 | ANSI_COLOR_NAMES_ALIASES: Dict[str, str] = { 91 | "ansidarkgray": "ansibrightblack", 92 | "ansiteal": "ansicyan", 93 | "ansiturquoise": "ansibrightcyan", 94 | "ansibrown": "ansiyellow", 95 | "ansipurple": "ansimagenta", 96 | "ansifuchsia": "ansibrightmagenta", 97 | "ansilightgray": "ansigray", 98 | "ansidarkred": "ansired", 99 | "ansidarkgreen": "ansigreen", 100 | "ansidarkblue": "ansiblue", 101 | } 102 | assert set(ANSI_COLOR_NAMES_ALIASES.values()).issubset(set(ANSI_COLOR_NAMES)) 103 | assert not (set(ANSI_COLOR_NAMES_ALIASES.keys()) & set(ANSI_COLOR_NAMES)) 104 | 105 | 106 | class BaseStyle(metaclass=ABCMeta): 107 | """ 108 | Abstract base class for prompt_toolkit styles. 109 | """ 110 | 111 | @abstractmethod 112 | def get_attrs_for_style_str( 113 | self, style_str: str, default: Attrs = DEFAULT_ATTRS 114 | ) -> Attrs: 115 | """ 116 | Return :class:`.Attrs` for the given style string. 117 | 118 | :param style_str: The style string. This can contain inline styling as 119 | well as classnames (e.g. "class:title"). 120 | :param default: `Attrs` to be used if no styling was defined. 121 | """ 122 | 123 | @abstractproperty 124 | def style_rules(self) -> List[Tuple[str, str]]: 125 | """ 126 | The list of style rules, used to create this style. 127 | (Required for `DynamicStyle` and `_MergedStyle` to work.) 128 | """ 129 | return [] 130 | 131 | @abstractmethod 132 | def invalidation_hash(self) -> Hashable: 133 | """ 134 | Invalidation hash for the style. When this changes over time, the 135 | renderer knows that something in the style changed, and that everything 136 | has to be redrawn. 137 | """ 138 | 139 | 140 | class DummyStyle(BaseStyle): 141 | """ 142 | A style that doesn't style anything. 143 | """ 144 | 145 | def get_attrs_for_style_str( 146 | self, style_str: str, default: Attrs = DEFAULT_ATTRS 147 | ) -> Attrs: 148 | return default 149 | 150 | def invalidation_hash(self) -> Hashable: 151 | return 1 # Always the same value. 152 | 153 | @property 154 | def style_rules(self) -> List[Tuple[str, str]]: 155 | return [] 156 | 157 | 158 | class DynamicStyle(BaseStyle): 159 | """ 160 | Style class that can dynamically returns an other Style. 161 | 162 | :param get_style: Callable that returns a :class:`.Style` instance. 163 | """ 164 | 165 | def __init__(self, get_style: Callable[[], Optional[BaseStyle]]): 166 | self.get_style = get_style 167 | self._dummy = DummyStyle() 168 | 169 | def get_attrs_for_style_str( 170 | self, style_str: str, default: Attrs = DEFAULT_ATTRS 171 | ) -> Attrs: 172 | style = self.get_style() or self._dummy 173 | 174 | return style.get_attrs_for_style_str(style_str, default) 175 | 176 | def invalidation_hash(self) -> Hashable: 177 | return (self.get_style() or self._dummy).invalidation_hash() 178 | 179 | @property 180 | def style_rules(self) -> List[Tuple[str, str]]: 181 | return (self.get_style() or self._dummy).style_rules 182 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/styles/named_colors.py: -------------------------------------------------------------------------------- 1 | """ 2 | All modern web browsers support these 140 color names. 3 | Taken from: https://www.w3schools.com/colors/colors_names.asp 4 | """ 5 | from typing import Dict 6 | 7 | __all__ = [ 8 | "NAMED_COLORS", 9 | ] 10 | 11 | 12 | NAMED_COLORS: Dict[str, str] = { 13 | "AliceBlue": "#f0f8ff", 14 | "AntiqueWhite": "#faebd7", 15 | "Aqua": "#00ffff", 16 | "Aquamarine": "#7fffd4", 17 | "Azure": "#f0ffff", 18 | "Beige": "#f5f5dc", 19 | "Bisque": "#ffe4c4", 20 | "Black": "#000000", 21 | "BlanchedAlmond": "#ffebcd", 22 | "Blue": "#0000ff", 23 | "BlueViolet": "#8a2be2", 24 | "Brown": "#a52a2a", 25 | "BurlyWood": "#deb887", 26 | "CadetBlue": "#5f9ea0", 27 | "Chartreuse": "#7fff00", 28 | "Chocolate": "#d2691e", 29 | "Coral": "#ff7f50", 30 | "CornflowerBlue": "#6495ed", 31 | "Cornsilk": "#fff8dc", 32 | "Crimson": "#dc143c", 33 | "Cyan": "#00ffff", 34 | "DarkBlue": "#00008b", 35 | "DarkCyan": "#008b8b", 36 | "DarkGoldenRod": "#b8860b", 37 | "DarkGray": "#a9a9a9", 38 | "DarkGreen": "#006400", 39 | "DarkGrey": "#a9a9a9", 40 | "DarkKhaki": "#bdb76b", 41 | "DarkMagenta": "#8b008b", 42 | "DarkOliveGreen": "#556b2f", 43 | "DarkOrange": "#ff8c00", 44 | "DarkOrchid": "#9932cc", 45 | "DarkRed": "#8b0000", 46 | "DarkSalmon": "#e9967a", 47 | "DarkSeaGreen": "#8fbc8f", 48 | "DarkSlateBlue": "#483d8b", 49 | "DarkSlateGray": "#2f4f4f", 50 | "DarkSlateGrey": "#2f4f4f", 51 | "DarkTurquoise": "#00ced1", 52 | "DarkViolet": "#9400d3", 53 | "DeepPink": "#ff1493", 54 | "DeepSkyBlue": "#00bfff", 55 | "DimGray": "#696969", 56 | "DimGrey": "#696969", 57 | "DodgerBlue": "#1e90ff", 58 | "FireBrick": "#b22222", 59 | "FloralWhite": "#fffaf0", 60 | "ForestGreen": "#228b22", 61 | "Fuchsia": "#ff00ff", 62 | "Gainsboro": "#dcdcdc", 63 | "GhostWhite": "#f8f8ff", 64 | "Gold": "#ffd700", 65 | "GoldenRod": "#daa520", 66 | "Gray": "#808080", 67 | "Green": "#008000", 68 | "GreenYellow": "#adff2f", 69 | "Grey": "#808080", 70 | "HoneyDew": "#f0fff0", 71 | "HotPink": "#ff69b4", 72 | "IndianRed": "#cd5c5c", 73 | "Indigo": "#4b0082", 74 | "Ivory": "#fffff0", 75 | "Khaki": "#f0e68c", 76 | "Lavender": "#e6e6fa", 77 | "LavenderBlush": "#fff0f5", 78 | "LawnGreen": "#7cfc00", 79 | "LemonChiffon": "#fffacd", 80 | "LightBlue": "#add8e6", 81 | "LightCoral": "#f08080", 82 | "LightCyan": "#e0ffff", 83 | "LightGoldenRodYellow": "#fafad2", 84 | "LightGray": "#d3d3d3", 85 | "LightGreen": "#90ee90", 86 | "LightGrey": "#d3d3d3", 87 | "LightPink": "#ffb6c1", 88 | "LightSalmon": "#ffa07a", 89 | "LightSeaGreen": "#20b2aa", 90 | "LightSkyBlue": "#87cefa", 91 | "LightSlateGray": "#778899", 92 | "LightSlateGrey": "#778899", 93 | "LightSteelBlue": "#b0c4de", 94 | "LightYellow": "#ffffe0", 95 | "Lime": "#00ff00", 96 | "LimeGreen": "#32cd32", 97 | "Linen": "#faf0e6", 98 | "Magenta": "#ff00ff", 99 | "Maroon": "#800000", 100 | "MediumAquaMarine": "#66cdaa", 101 | "MediumBlue": "#0000cd", 102 | "MediumOrchid": "#ba55d3", 103 | "MediumPurple": "#9370db", 104 | "MediumSeaGreen": "#3cb371", 105 | "MediumSlateBlue": "#7b68ee", 106 | "MediumSpringGreen": "#00fa9a", 107 | "MediumTurquoise": "#48d1cc", 108 | "MediumVioletRed": "#c71585", 109 | "MidnightBlue": "#191970", 110 | "MintCream": "#f5fffa", 111 | "MistyRose": "#ffe4e1", 112 | "Moccasin": "#ffe4b5", 113 | "NavajoWhite": "#ffdead", 114 | "Navy": "#000080", 115 | "OldLace": "#fdf5e6", 116 | "Olive": "#808000", 117 | "OliveDrab": "#6b8e23", 118 | "Orange": "#ffa500", 119 | "OrangeRed": "#ff4500", 120 | "Orchid": "#da70d6", 121 | "PaleGoldenRod": "#eee8aa", 122 | "PaleGreen": "#98fb98", 123 | "PaleTurquoise": "#afeeee", 124 | "PaleVioletRed": "#db7093", 125 | "PapayaWhip": "#ffefd5", 126 | "PeachPuff": "#ffdab9", 127 | "Peru": "#cd853f", 128 | "Pink": "#ffc0cb", 129 | "Plum": "#dda0dd", 130 | "PowderBlue": "#b0e0e6", 131 | "Purple": "#800080", 132 | "RebeccaPurple": "#663399", 133 | "Red": "#ff0000", 134 | "RosyBrown": "#bc8f8f", 135 | "RoyalBlue": "#4169e1", 136 | "SaddleBrown": "#8b4513", 137 | "Salmon": "#fa8072", 138 | "SandyBrown": "#f4a460", 139 | "SeaGreen": "#2e8b57", 140 | "SeaShell": "#fff5ee", 141 | "Sienna": "#a0522d", 142 | "Silver": "#c0c0c0", 143 | "SkyBlue": "#87ceeb", 144 | "SlateBlue": "#6a5acd", 145 | "SlateGray": "#708090", 146 | "SlateGrey": "#708090", 147 | "Snow": "#fffafa", 148 | "SpringGreen": "#00ff7f", 149 | "SteelBlue": "#4682b4", 150 | "Tan": "#d2b48c", 151 | "Teal": "#008080", 152 | "Thistle": "#d8bfd8", 153 | "Tomato": "#ff6347", 154 | "Turquoise": "#40e0d0", 155 | "Violet": "#ee82ee", 156 | "Wheat": "#f5deb3", 157 | "White": "#ffffff", 158 | "WhiteSmoke": "#f5f5f5", 159 | "Yellow": "#ffff00", 160 | "YellowGreen": "#9acd32", 161 | } 162 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/styles/pygments.py: -------------------------------------------------------------------------------- 1 | """ 2 | Adaptor for building prompt_toolkit styles, starting from a Pygments style. 3 | 4 | Usage:: 5 | 6 | from pygments.styles.tango import TangoStyle 7 | style = style_from_pygments_cls(pygments_style_cls=TangoStyle) 8 | """ 9 | from typing import TYPE_CHECKING, Dict, Type 10 | 11 | from .style import Style 12 | 13 | if TYPE_CHECKING: 14 | from pygments.token import Token 15 | from pygments.style import Style as PygmentsStyle 16 | 17 | 18 | __all__ = [ 19 | "style_from_pygments_cls", 20 | "style_from_pygments_dict", 21 | "pygments_token_to_classname", 22 | ] 23 | 24 | 25 | def style_from_pygments_cls(pygments_style_cls: Type["PygmentsStyle"]) -> Style: 26 | """ 27 | Shortcut to create a :class:`.Style` instance from a Pygments style class 28 | and a style dictionary. 29 | 30 | Example:: 31 | 32 | from prompt_toolkit.styles.from_pygments import style_from_pygments_cls 33 | from pygments.styles import get_style_by_name 34 | style = style_from_pygments_cls(get_style_by_name('monokai')) 35 | 36 | :param pygments_style_cls: Pygments style class to start from. 37 | """ 38 | # Import inline. 39 | from pygments.style import Style as PygmentsStyle 40 | 41 | assert issubclass(pygments_style_cls, PygmentsStyle) 42 | 43 | return style_from_pygments_dict(pygments_style_cls.styles) 44 | 45 | 46 | def style_from_pygments_dict(pygments_dict: Dict["Token", str]) -> Style: 47 | """ 48 | Create a :class:`.Style` instance from a Pygments style dictionary. 49 | (One that maps Token objects to style strings.) 50 | """ 51 | pygments_style = [] 52 | 53 | for token, style in pygments_dict.items(): 54 | pygments_style.append((pygments_token_to_classname(token), style)) 55 | 56 | return Style(pygments_style) 57 | 58 | 59 | def pygments_token_to_classname(token: "Token") -> str: 60 | """ 61 | Turn e.g. `Token.Name.Exception` into `'pygments.name.exception'`. 62 | 63 | (Our Pygments lexer will also turn the tokens that pygments produces in a 64 | prompt_toolkit list of fragments that match these styling rules.) 65 | """ 66 | parts = ("pygments",) + token 67 | return ".".join(parts).lower() 68 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/token.py: -------------------------------------------------------------------------------- 1 | """ 2 | """ 3 | 4 | __all__ = [ 5 | "ZeroWidthEscape", 6 | ] 7 | 8 | ZeroWidthEscape = "[ZeroWidthEscape]" 9 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/widgets/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Collection of reusable components for building full screen applications. 3 | These are higher level abstractions on top of the `prompt_toolkit.layout` 4 | module. 5 | 6 | Most of these widgets implement the ``__pt_container__`` method, which makes it 7 | possible to embed these in the layout like any other container. 8 | """ 9 | from .base import ( 10 | Box, 11 | Button, 12 | Checkbox, 13 | CheckboxList, 14 | Frame, 15 | HorizontalLine, 16 | Label, 17 | ProgressBar, 18 | RadioList, 19 | Shadow, 20 | TextArea, 21 | VerticalLine, 22 | ) 23 | from .dialogs import Dialog 24 | from .menus import MenuContainer, MenuItem 25 | from .toolbars import ( 26 | ArgToolbar, 27 | CompletionsToolbar, 28 | FormattedTextToolbar, 29 | SearchToolbar, 30 | SystemToolbar, 31 | ValidationToolbar, 32 | ) 33 | 34 | __all__ = [ 35 | # Base. 36 | "TextArea", 37 | "Label", 38 | "Button", 39 | "Frame", 40 | "Shadow", 41 | "Box", 42 | "VerticalLine", 43 | "HorizontalLine", 44 | "CheckboxList", 45 | "RadioList", 46 | "Checkbox", 47 | "ProgressBar", 48 | # Toolbars. 49 | "ArgToolbar", 50 | "CompletionsToolbar", 51 | "FormattedTextToolbar", 52 | "SearchToolbar", 53 | "SystemToolbar", 54 | "ValidationToolbar", 55 | # Dialogs. 56 | "Dialog", 57 | # Menus. 58 | "MenuContainer", 59 | "MenuItem", 60 | ] 61 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/widgets/dialogs.py: -------------------------------------------------------------------------------- 1 | """ 2 | Collection of reusable components for building full screen applications. 3 | """ 4 | from typing import Optional, Sequence, Union 5 | 6 | from prompt_toolkit.filters import has_completions, has_focus 7 | from prompt_toolkit.formatted_text import AnyFormattedText 8 | from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous 9 | from prompt_toolkit.key_binding.key_bindings import KeyBindings 10 | from prompt_toolkit.layout.containers import ( 11 | AnyContainer, 12 | DynamicContainer, 13 | HSplit, 14 | VSplit, 15 | ) 16 | from prompt_toolkit.layout.dimension import AnyDimension 17 | from prompt_toolkit.layout.dimension import Dimension as D 18 | 19 | from .base import Box, Button, Frame, Shadow 20 | 21 | __all__ = [ 22 | "Dialog", 23 | ] 24 | 25 | 26 | class Dialog: 27 | """ 28 | Simple dialog window. This is the base for input dialogs, message dialogs 29 | and confirmation dialogs. 30 | 31 | Changing the title and body of the dialog is possible at runtime by 32 | assigning to the `body` and `title` attributes of this class. 33 | 34 | :param body: Child container object. 35 | :param title: Text to be displayed in the heading of the dialog. 36 | :param buttons: A list of `Button` widgets, displayed at the bottom. 37 | """ 38 | 39 | def __init__( 40 | self, 41 | body: AnyContainer, 42 | title: AnyFormattedText = "", 43 | buttons: Optional[Sequence[Button]] = None, 44 | modal: bool = True, 45 | width: AnyDimension = None, 46 | with_background: bool = False, 47 | ) -> None: 48 | 49 | self.body = body 50 | self.title = title 51 | 52 | buttons = buttons or [] 53 | 54 | # When a button is selected, handle left/right key bindings. 55 | buttons_kb = KeyBindings() 56 | if len(buttons) > 1: 57 | first_selected = has_focus(buttons[0]) 58 | last_selected = has_focus(buttons[-1]) 59 | 60 | buttons_kb.add("left", filter=~first_selected)(focus_previous) 61 | buttons_kb.add("right", filter=~last_selected)(focus_next) 62 | 63 | frame_body: AnyContainer 64 | if buttons: 65 | frame_body = HSplit( 66 | [ 67 | # Add optional padding around the body. 68 | Box( 69 | body=DynamicContainer(lambda: self.body), 70 | padding=D(preferred=1, max=1), 71 | padding_bottom=0, 72 | ), 73 | # The buttons. 74 | Box( 75 | body=VSplit(buttons, padding=1, key_bindings=buttons_kb), 76 | height=D(min=1, max=3, preferred=3), 77 | ), 78 | ] 79 | ) 80 | else: 81 | frame_body = body 82 | 83 | # Key bindings for whole dialog. 84 | kb = KeyBindings() 85 | kb.add("tab", filter=~has_completions)(focus_next) 86 | kb.add("s-tab", filter=~has_completions)(focus_previous) 87 | 88 | frame = Shadow( 89 | body=Frame( 90 | title=lambda: self.title, 91 | body=frame_body, 92 | style="class:dialog.body", 93 | width=(None if with_background is None else width), 94 | key_bindings=kb, 95 | modal=modal, 96 | ) 97 | ) 98 | 99 | self.container: Union[Box, Shadow] 100 | if with_background: 101 | self.container = Box(body=frame, style="class:dialog", width=width) 102 | else: 103 | self.container = frame 104 | 105 | def __pt_container__(self) -> AnyContainer: 106 | return self.container 107 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/prompt_toolkit/win32_types.py: -------------------------------------------------------------------------------- 1 | from ctypes import Structure, Union, c_char, c_long, c_short, c_ulong 2 | from ctypes.wintypes import BOOL, DWORD, LPVOID, WCHAR, WORD 3 | 4 | # Input/Output standard device numbers. Note that these are not handle objects. 5 | # It's the `windll.kernel32.GetStdHandle` system call that turns them into a 6 | # real handle object. 7 | STD_INPUT_HANDLE = c_ulong(-10) 8 | STD_OUTPUT_HANDLE = c_ulong(-11) 9 | STD_ERROR_HANDLE = c_ulong(-12) 10 | 11 | 12 | class COORD(Structure): 13 | """ 14 | Struct in wincon.h 15 | http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119(v=vs.85).aspx 16 | """ 17 | 18 | _fields_ = [ 19 | ("X", c_short), # Short 20 | ("Y", c_short), # Short 21 | ] 22 | 23 | def __repr__(self) -> str: 24 | return "%s(X=%r, Y=%r, type_x=%r, type_y=%r)" % ( 25 | self.__class__.__name__, 26 | self.X, 27 | self.Y, 28 | type(self.X), 29 | type(self.Y), 30 | ) 31 | 32 | 33 | class UNICODE_OR_ASCII(Union): 34 | _fields_ = [ 35 | ("AsciiChar", c_char), 36 | ("UnicodeChar", WCHAR), 37 | ] 38 | 39 | 40 | class KEY_EVENT_RECORD(Structure): 41 | """ 42 | http://msdn.microsoft.com/en-us/library/windows/desktop/ms684166(v=vs.85).aspx 43 | """ 44 | 45 | _fields_ = [ 46 | ("KeyDown", c_long), # bool 47 | ("RepeatCount", c_short), # word 48 | ("VirtualKeyCode", c_short), # word 49 | ("VirtualScanCode", c_short), # word 50 | ("uChar", UNICODE_OR_ASCII), # Unicode or ASCII. 51 | ("ControlKeyState", c_long), # double word 52 | ] 53 | 54 | 55 | class MOUSE_EVENT_RECORD(Structure): 56 | """ 57 | http://msdn.microsoft.com/en-us/library/windows/desktop/ms684239(v=vs.85).aspx 58 | """ 59 | 60 | _fields_ = [ 61 | ("MousePosition", COORD), 62 | ("ButtonState", c_long), # dword 63 | ("ControlKeyState", c_long), # dword 64 | ("EventFlags", c_long), # dword 65 | ] 66 | 67 | 68 | class WINDOW_BUFFER_SIZE_RECORD(Structure): 69 | """ 70 | http://msdn.microsoft.com/en-us/library/windows/desktop/ms687093(v=vs.85).aspx 71 | """ 72 | 73 | _fields_ = [("Size", COORD)] 74 | 75 | 76 | class MENU_EVENT_RECORD(Structure): 77 | """ 78 | http://msdn.microsoft.com/en-us/library/windows/desktop/ms684213(v=vs.85).aspx 79 | """ 80 | 81 | _fields_ = [("CommandId", c_long)] # uint 82 | 83 | 84 | class FOCUS_EVENT_RECORD(Structure): 85 | """ 86 | http://msdn.microsoft.com/en-us/library/windows/desktop/ms683149(v=vs.85).aspx 87 | """ 88 | 89 | _fields_ = [("SetFocus", c_long)] # bool 90 | 91 | 92 | class EVENT_RECORD(Union): 93 | _fields_ = [ 94 | ("KeyEvent", KEY_EVENT_RECORD), 95 | ("MouseEvent", MOUSE_EVENT_RECORD), 96 | ("WindowBufferSizeEvent", WINDOW_BUFFER_SIZE_RECORD), 97 | ("MenuEvent", MENU_EVENT_RECORD), 98 | ("FocusEvent", FOCUS_EVENT_RECORD), 99 | ] 100 | 101 | 102 | class INPUT_RECORD(Structure): 103 | """ 104 | http://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx 105 | """ 106 | 107 | _fields_ = [("EventType", c_short), ("Event", EVENT_RECORD)] # word # Union. 108 | 109 | 110 | EventTypes = { 111 | 1: "KeyEvent", 112 | 2: "MouseEvent", 113 | 4: "WindowBufferSizeEvent", 114 | 8: "MenuEvent", 115 | 16: "FocusEvent", 116 | } 117 | 118 | 119 | class SMALL_RECT(Structure): 120 | """struct in wincon.h.""" 121 | 122 | _fields_ = [ 123 | ("Left", c_short), 124 | ("Top", c_short), 125 | ("Right", c_short), 126 | ("Bottom", c_short), 127 | ] 128 | 129 | 130 | class CONSOLE_SCREEN_BUFFER_INFO(Structure): 131 | """struct in wincon.h.""" 132 | 133 | _fields_ = [ 134 | ("dwSize", COORD), 135 | ("dwCursorPosition", COORD), 136 | ("wAttributes", WORD), 137 | ("srWindow", SMALL_RECT), 138 | ("dwMaximumWindowSize", COORD), 139 | ] 140 | 141 | def __str__(self) -> str: 142 | return "(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)" % ( 143 | self.dwSize.Y, 144 | self.dwSize.X, 145 | self.dwCursorPosition.Y, 146 | self.dwCursorPosition.X, 147 | self.wAttributes, 148 | self.srWindow.Top, 149 | self.srWindow.Left, 150 | self.srWindow.Bottom, 151 | self.srWindow.Right, 152 | self.dwMaximumWindowSize.Y, 153 | self.dwMaximumWindowSize.X, 154 | ) 155 | 156 | 157 | class SECURITY_ATTRIBUTES(Structure): 158 | """ 159 | http://msdn.microsoft.com/en-us/library/windows/desktop/aa379560(v=vs.85).aspx 160 | """ 161 | 162 | _fields_ = [ 163 | ("nLength", DWORD), 164 | ("lpSecurityDescriptor", LPVOID), 165 | ("bInheritHandle", BOOL), 166 | ] 167 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/wcwidth/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | wcwidth module. 3 | 4 | https://github.com/jquast/wcwidth 5 | """ 6 | # re-export all functions & definitions, even private ones, from top-level 7 | # module path, to allow for 'from wcwidth import _private_func'. Of course, 8 | # user beware that any _private function may disappear or change signature at 9 | # any future version. 10 | 11 | # local 12 | from .wcwidth import ZERO_WIDTH # noqa 13 | from .wcwidth import (WIDE_EASTASIAN, 14 | wcwidth, 15 | wcswidth, 16 | _bisearch, 17 | list_versions, 18 | _wcmatch_version, 19 | _wcversion_value, 20 | _get_package_version) 21 | 22 | # The __all__ attribute defines the items exported from statement, 23 | # 'from wcwidth import *', but also to say, "This is the public API". 24 | __all__ = ('wcwidth', 'wcswidth', 'list_versions') 25 | __version__ = _get_package_version() 26 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/wcwidth/tests/__init__.py: -------------------------------------------------------------------------------- 1 | """This file intentionally left blank.""" 2 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/wcwidth/tests/test_core.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | """Core tests module for wcwidth.""" 3 | import wcwidth 4 | 5 | 6 | def test_hello_jp(): 7 | u""" 8 | Width of Japanese phrase: コンニチハ, セカイ! 9 | 10 | Given a phrase of 5 and 3 Katakana ideographs, joined with 11 | 3 English-ASCII punctuation characters, totaling 11, this 12 | phrase consumes 19 cells of a terminal emulator. 13 | """ 14 | # given, 15 | phrase = u'コンニチハ, セカイ!' 16 | expect_length_each = (2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1) 17 | expect_length_phrase = sum(expect_length_each) 18 | 19 | # exercise, 20 | length_each = tuple(map(wcwidth.wcwidth, phrase)) 21 | length_phrase = wcwidth.wcswidth(phrase) 22 | 23 | # verify, 24 | assert length_each == expect_length_each 25 | assert length_phrase == expect_length_phrase 26 | 27 | 28 | def test_wcswidth_substr(): 29 | """ 30 | Test wcswidth() optional 2nd parameter, ``n``. 31 | 32 | ``n`` determines at which position of the string 33 | to stop counting length. 34 | """ 35 | # given, 36 | phrase = u'コンニチハ, セカイ!' 37 | end = 7 38 | expect_length_each = (2, 2, 2, 2, 2, 1, 1,) 39 | expect_length_phrase = sum(expect_length_each) 40 | 41 | # exercise, 42 | length_phrase = wcwidth.wcswidth(phrase, end) 43 | 44 | # verify, 45 | assert length_phrase == expect_length_phrase 46 | 47 | 48 | def test_null_width_0(): 49 | """NULL (0) reports width 0.""" 50 | # given, 51 | phrase = u'abc\x00def' 52 | expect_length_each = (1, 1, 1, 0, 1, 1, 1) 53 | expect_length_phrase = sum(expect_length_each) 54 | 55 | # exercise, 56 | length_each = tuple(map(wcwidth.wcwidth, phrase)) 57 | length_phrase = wcwidth.wcswidth(phrase, len(phrase)) 58 | 59 | # verify, 60 | assert length_each == expect_length_each 61 | assert length_phrase == expect_length_phrase 62 | 63 | 64 | def test_control_c0_width_negative_1(): 65 | """CSI (Control sequence initiate) reports width -1.""" 66 | # given, 67 | phrase = u'\x1b[0m' 68 | expect_length_each = (-1, 1, 1, 1) 69 | expect_length_phrase = -1 70 | 71 | # exercise, 72 | length_each = tuple(map(wcwidth.wcwidth, phrase)) 73 | length_phrase = wcwidth.wcswidth(phrase, len(phrase)) 74 | 75 | # verify, 76 | assert length_each == expect_length_each 77 | assert length_phrase == expect_length_phrase 78 | 79 | 80 | def test_combining_width_negative_1(): 81 | """Simple test combining reports total width of 4.""" 82 | # given, 83 | phrase = u'--\u05bf--' 84 | expect_length_each = (1, 1, 0, 1, 1) 85 | expect_length_phrase = 4 86 | 87 | # exercise, 88 | length_each = tuple(map(wcwidth.wcwidth, phrase)) 89 | length_phrase = wcwidth.wcswidth(phrase, len(phrase)) 90 | 91 | # verify, 92 | assert length_each == expect_length_each 93 | assert length_phrase == expect_length_phrase 94 | 95 | 96 | def test_combining_cafe(): 97 | u"""Phrase cafe + COMBINING ACUTE ACCENT is café of length 4.""" 98 | phrase = u"cafe\u0301" 99 | expect_length_each = (1, 1, 1, 1, 0) 100 | expect_length_phrase = 4 101 | 102 | # exercise, 103 | length_each = tuple(map(wcwidth.wcwidth, phrase)) 104 | length_phrase = wcwidth.wcswidth(phrase, len(phrase)) 105 | 106 | # verify, 107 | assert length_each == expect_length_each 108 | assert length_phrase == expect_length_phrase 109 | 110 | 111 | def test_combining_enclosing(): 112 | u"""CYRILLIC CAPITAL LETTER A + COMBINING CYRILLIC HUNDRED THOUSANDS SIGN is А҈ of length 1.""" 113 | phrase = u"\u0410\u0488" 114 | expect_length_each = (1, 0) 115 | expect_length_phrase = 1 116 | 117 | # exercise, 118 | length_each = tuple(map(wcwidth.wcwidth, phrase)) 119 | length_phrase = wcwidth.wcswidth(phrase, len(phrase)) 120 | 121 | # verify, 122 | assert length_each == expect_length_each 123 | assert length_phrase == expect_length_phrase 124 | 125 | 126 | def test_combining_spacing(): 127 | u"""Balinese kapal (ship) is ᬓᬨᬮ᭄ of length 4.""" 128 | phrase = u"\u1B13\u1B28\u1B2E\u1B44" 129 | expect_length_each = (1, 1, 1, 1) 130 | expect_length_phrase = 4 131 | 132 | # exercise, 133 | length_each = tuple(map(wcwidth.wcwidth, phrase)) 134 | length_phrase = wcwidth.wcswidth(phrase, len(phrase)) 135 | 136 | # verify, 137 | assert length_each == expect_length_each 138 | assert length_phrase == expect_length_phrase 139 | -------------------------------------------------------------------------------- /lib/python3.7/site-packages/wcwidth/version.json: -------------------------------------------------------------------------------- 1 | {"tables": ["4.1.0", "5.0.0", "5.1.0", "5.2.0", "6.0.0", "6.1.0", "6.2.0", "6.3.0", "7.0.0", "8.0.0", "9.0.0", "10.0.0", "11.0.0", "12.0.0", "12.1.0", "13.0.0"], "package": "0.2.3", "default": "8.0.0"} 2 | -------------------------------------------------------------------------------- /zsh-recall.plugin.zsh: -------------------------------------------------------------------------------- 1 | DIR="$( cd "$( dirname "$0" )" && pwd )" 2 | 3 | recall () { 4 | PYTHONPATH="$DIR/lib/python3.7/site-packages/" \ 5 | python3 "$DIR/recall.py" "$@" 6 | 7 | tput cnorm # show cursor 8 | if [[ -a "$HOME/.zsh_next_cmd" ]]; then 9 | CMD="$(cat $HOME/.zsh_next_cmd)" 10 | rm $HOME/.zsh_next_cmd 11 | print -z "$CMD" 12 | fi 13 | } 14 | 15 | alias rec="recall" 16 | --------------------------------------------------------------------------------