init
This commit is contained in:
commit
38355d2442
9083 changed files with 1225834 additions and 0 deletions
187
.venv/lib/python3.8/site-packages/prompt_toolkit/auto_suggest.py
Normal file
187
.venv/lib/python3.8/site-packages/prompt_toolkit/auto_suggest.py
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
"""
|
||||
`Fish-style <http://fishshell.com/>`_ like auto-suggestion.
|
||||
|
||||
While a user types input in a certain buffer, suggestions are generated
|
||||
(asynchronously.) Usually, they are displayed after the input. When the cursor
|
||||
presses the right arrow and the cursor is at the end of the input, the
|
||||
suggestion will be inserted.
|
||||
|
||||
If you want the auto suggestions to be asynchronous (in a background thread),
|
||||
because they take too much time, and could potentially block the event loop,
|
||||
then wrap the :class:`.AutoSuggest` instance into a
|
||||
:class:`.ThreadedAutoSuggest`.
|
||||
"""
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from typing import TYPE_CHECKING, Callable, Optional, Union
|
||||
|
||||
from prompt_toolkit.eventloop import run_in_executor_with_context
|
||||
|
||||
from .document import Document
|
||||
from .filters import Filter, to_filter
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .buffer import Buffer
|
||||
|
||||
__all__ = [
|
||||
"Suggestion",
|
||||
"AutoSuggest",
|
||||
"ThreadedAutoSuggest",
|
||||
"DummyAutoSuggest",
|
||||
"AutoSuggestFromHistory",
|
||||
"ConditionalAutoSuggest",
|
||||
"DynamicAutoSuggest",
|
||||
]
|
||||
|
||||
|
||||
class Suggestion:
|
||||
"""
|
||||
Suggestion returned by an auto-suggest algorithm.
|
||||
|
||||
:param text: The suggestion text.
|
||||
"""
|
||||
|
||||
def __init__(self, text: str) -> None:
|
||||
self.text = text
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "Suggestion(%s)" % self.text
|
||||
|
||||
|
||||
class AutoSuggest(metaclass=ABCMeta):
|
||||
"""
|
||||
Base class for auto suggestion implementations.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def get_suggestion(
|
||||
self, buffer: "Buffer", document: Document
|
||||
) -> Optional[Suggestion]:
|
||||
"""
|
||||
Return `None` or a :class:`.Suggestion` instance.
|
||||
|
||||
We receive both :class:`~prompt_toolkit.buffer.Buffer` and
|
||||
:class:`~prompt_toolkit.document.Document`. The reason is that auto
|
||||
suggestions are retrieved asynchronously. (Like completions.) The
|
||||
buffer text could be changed in the meantime, but ``document`` contains
|
||||
the buffer document like it was at the start of the auto suggestion
|
||||
call. So, from here, don't access ``buffer.text``, but use
|
||||
``document.text`` instead.
|
||||
|
||||
:param buffer: The :class:`~prompt_toolkit.buffer.Buffer` instance.
|
||||
:param document: The :class:`~prompt_toolkit.document.Document` instance.
|
||||
"""
|
||||
|
||||
async def get_suggestion_async(
|
||||
self, buff: "Buffer", document: Document
|
||||
) -> Optional[Suggestion]:
|
||||
"""
|
||||
Return a :class:`.Future` which is set when the suggestions are ready.
|
||||
This function can be overloaded in order to provide an asynchronous
|
||||
implementation.
|
||||
"""
|
||||
return self.get_suggestion(buff, document)
|
||||
|
||||
|
||||
class ThreadedAutoSuggest(AutoSuggest):
|
||||
"""
|
||||
Wrapper that runs auto suggestions in a thread.
|
||||
(Use this to prevent the user interface from becoming unresponsive if the
|
||||
generation of suggestions takes too much time.)
|
||||
"""
|
||||
|
||||
def __init__(self, auto_suggest: AutoSuggest) -> None:
|
||||
self.auto_suggest = auto_suggest
|
||||
|
||||
def get_suggestion(
|
||||
self, buff: "Buffer", document: Document
|
||||
) -> Optional[Suggestion]:
|
||||
return self.auto_suggest.get_suggestion(buff, document)
|
||||
|
||||
async def get_suggestion_async(
|
||||
self, buff: "Buffer", document: Document
|
||||
) -> Optional[Suggestion]:
|
||||
"""
|
||||
Run the `get_suggestion` function in a thread.
|
||||
"""
|
||||
|
||||
def run_get_suggestion_thread() -> Optional[Suggestion]:
|
||||
return self.get_suggestion(buff, document)
|
||||
|
||||
return await run_in_executor_with_context(run_get_suggestion_thread)
|
||||
|
||||
|
||||
class DummyAutoSuggest(AutoSuggest):
|
||||
"""
|
||||
AutoSuggest class that doesn't return any suggestion.
|
||||
"""
|
||||
|
||||
def get_suggestion(
|
||||
self, buffer: "Buffer", document: Document
|
||||
) -> Optional[Suggestion]:
|
||||
return None # No suggestion
|
||||
|
||||
|
||||
class AutoSuggestFromHistory(AutoSuggest):
|
||||
"""
|
||||
Give suggestions based on the lines in the history.
|
||||
"""
|
||||
|
||||
def get_suggestion(
|
||||
self, buffer: "Buffer", document: Document
|
||||
) -> Optional[Suggestion]:
|
||||
history = buffer.history
|
||||
|
||||
# Consider only the last line for the suggestion.
|
||||
text = document.text.rsplit("\n", 1)[-1]
|
||||
|
||||
# Only create a suggestion when this is not an empty line.
|
||||
if text.strip():
|
||||
# Find first matching line in history.
|
||||
for string in reversed(list(history.get_strings())):
|
||||
for line in reversed(string.splitlines()):
|
||||
if line.startswith(text):
|
||||
return Suggestion(line[len(text) :])
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class ConditionalAutoSuggest(AutoSuggest):
|
||||
"""
|
||||
Auto suggest that can be turned on and of according to a certain condition.
|
||||
"""
|
||||
|
||||
def __init__(self, auto_suggest: AutoSuggest, filter: Union[bool, Filter]) -> None:
|
||||
|
||||
self.auto_suggest = auto_suggest
|
||||
self.filter = to_filter(filter)
|
||||
|
||||
def get_suggestion(
|
||||
self, buffer: "Buffer", document: Document
|
||||
) -> Optional[Suggestion]:
|
||||
if self.filter():
|
||||
return self.auto_suggest.get_suggestion(buffer, document)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class DynamicAutoSuggest(AutoSuggest):
|
||||
"""
|
||||
Validator class that can dynamically returns any Validator.
|
||||
|
||||
:param get_validator: Callable that returns a :class:`.Validator` instance.
|
||||
"""
|
||||
|
||||
def __init__(self, get_auto_suggest: Callable[[], Optional[AutoSuggest]]) -> None:
|
||||
self.get_auto_suggest = get_auto_suggest
|
||||
|
||||
def get_suggestion(
|
||||
self, buff: "Buffer", document: Document
|
||||
) -> Optional[Suggestion]:
|
||||
auto_suggest = self.get_auto_suggest() or DummyAutoSuggest()
|
||||
return auto_suggest.get_suggestion(buff, document)
|
||||
|
||||
async def get_suggestion_async(
|
||||
self, buff: "Buffer", document: Document
|
||||
) -> Optional[Suggestion]:
|
||||
auto_suggest = self.get_auto_suggest() or DummyAutoSuggest()
|
||||
return await auto_suggest.get_suggestion_async(buff, document)
|
||||
Loading…
Add table
Add a link
Reference in a new issue