Spaces:
Sleeping
Sleeping
"""Module contains the class to create filepath prompt and filepath completer class.""" | |
import os | |
from pathlib import Path | |
from typing import TYPE_CHECKING, Any, Callable, Generator, Optional | |
from prompt_toolkit.completion import Completer, Completion | |
from prompt_toolkit.completion.base import ThreadedCompleter | |
from InquirerPy.prompts.input import InputPrompt | |
from InquirerPy.utils import ( | |
InquirerPyDefault, | |
InquirerPyKeybindings, | |
InquirerPyMessage, | |
InquirerPySessionResult, | |
InquirerPyStyle, | |
InquirerPyValidate, | |
) | |
if TYPE_CHECKING: | |
from prompt_toolkit.input.base import Input | |
from prompt_toolkit.output.base import Output | |
__all__ = ["FilePathPrompt", "FilePathCompleter"] | |
class FilePathCompleter(Completer): | |
"""An auto completion class which generates system filepath. | |
See Also: | |
:class:`~prompt_toolkit.completion.Completer` | |
Args: | |
only_directories: Only complete directories. | |
only_files: Only complete files. | |
""" | |
def __init__(self, only_directories: bool = False, only_files: bool = False): | |
self._only_directories = only_directories | |
self._only_files = only_files | |
self._delimiter = "/" if os.name == "posix" else "\\" | |
def get_completions( | |
self, document, complete_event | |
) -> Generator[Completion, None, None]: | |
"""Get a list of valid system paths.""" | |
if document.text == "~": | |
return | |
validation = lambda file, doc_text: str(file).startswith(doc_text) | |
if document.cursor_position == 0: | |
dirname = Path.cwd() | |
validation = lambda file, doc_text: True | |
elif document.text.startswith("~"): | |
dirname = Path(os.path.dirname(f"{Path.home()}{document.text[1:]}")) | |
validation = lambda file, doc_text: str(file).startswith( | |
f"{Path.home()}{doc_text[1:]}" | |
) | |
elif document.text.startswith(f".{self._delimiter}"): | |
dirname = Path(os.path.dirname(document.text)) | |
validation = lambda file, doc_text: str(file).startswith(doc_text[2:]) | |
else: | |
dirname = Path(os.path.dirname(document.text)) | |
for item in self._get_completion(document, dirname, validation): | |
yield item | |
def _get_completion( | |
self, document, path, validation | |
) -> Generator[Completion, None, None]: | |
if not path.is_dir(): | |
return | |
for file in path.iterdir(): | |
if self._only_directories and not file.is_dir(): | |
continue | |
if self._only_files and not file.is_file(): | |
continue | |
if validation(file, document.text): | |
file_name = file.name | |
display_name = file_name | |
if file.is_dir(): | |
display_name = f"{file_name}{self._delimiter}" | |
yield Completion( | |
file.name, | |
start_position=-1 * len(os.path.basename(document.text)), | |
display=display_name, | |
) | |
class FilePathPrompt(InputPrompt): | |
"""Create a prompt that provides auto completion for system filepaths. | |
A wrapper class around :class:`~prompt_toolkit.shortcuts.PromptSession`. | |
Args: | |
message: The question to ask the user. | |
Refer to :ref:`pages/dynamic:message` documentation for more details. | |
style: An :class:`InquirerPyStyle` instance. | |
Refer to :ref:`Style <pages/style:Alternate Syntax>` documentation for more details. | |
vi_mode: Use vim keybinding for the prompt. | |
Refer to :ref:`pages/kb:Keybindings` documentation for more details. | |
default: Set the default text value of the prompt. | |
Refer to :ref:`pages/dynamic:default` documentation for more details. | |
qmark: Question mark symbol. Custom symbol that will be displayed infront of the question before its answered. | |
amark: Answer mark symbol. Custom symbol that will be displayed infront of the question after its answered. | |
instruction: Short instruction to display next to the question. | |
long_instruction: Long instructions to display at the bottom of the prompt. | |
multicolumn_complete: Change the auto-completion UI to a multi column display. | |
validate: Add validation to user input. | |
Refer to :ref:`pages/validator:Validator` documentation for more details. | |
invalid_message: Error message to display when user input is invalid. | |
Refer to :ref:`pages/validator:Validator` documentation for more details. | |
transformer: A function which performs additional transformation on the value that gets printed to the terminal. | |
Different than `filter` parameter, this is only visual effect and won’t affect the actual value returned by :meth:`~InquirerPy.base.simple.BaseSimplePrompt.execute`. | |
Refer to :ref:`pages/dynamic:transformer` documentation for more details. | |
filter: A function which performs additional transformation on the result. | |
This affects the actual value returned by :meth:`~InquirerPy.base.simple.BaseSimplePrompt.execute`. | |
Refer to :ref:`pages/dynamic:filter` documentation for more details. | |
keybindings: Customise the builtin keybindings. | |
Refer to :ref:`pages/kb:Keybindings` for more details. | |
wrap_lines: Soft wrap question lines when question exceeds the terminal width. | |
only_directories: Only complete directories. | |
only_files: Only complete files. | |
raise_keyboard_interrupt: Raise the :class:`KeyboardInterrupt` exception when `ctrl-c` is pressed. If false, the result | |
will be `None` and the question is skiped. | |
mandatory: Indicate if the prompt is mandatory. If True, then the question cannot be skipped. | |
mandatory_message: Error message to show when user attempts to skip mandatory prompt. | |
session_result: Used internally for :ref:`index:Classic Syntax (PyInquirer)`. | |
input: Used internally and will be removed in future updates. | |
output: Used internally and will be removed in future updates. | |
Examples: | |
>>> from InquirerPy import inquirer | |
>>> result = inquirer.filepath(message="Enter a path:").execute() | |
>>> print(result) | |
/home/ubuntu/README.md | |
""" | |
def __init__( | |
self, | |
message: InquirerPyMessage, | |
style: Optional[InquirerPyStyle] = None, | |
vi_mode: bool = False, | |
default: InquirerPyDefault = "", | |
qmark: str = "?", | |
amark: str = "?", | |
instruction: str = "", | |
long_instruction: str = "", | |
multicolumn_complete: bool = False, | |
validate: Optional[InquirerPyValidate] = None, | |
invalid_message: str = "Invalid input", | |
only_directories: bool = False, | |
only_files: bool = False, | |
transformer: Optional[Callable[[str], Any]] = None, | |
filter: Optional[Callable[[str], Any]] = None, | |
keybindings: Optional[InquirerPyKeybindings] = None, | |
wrap_lines: bool = True, | |
raise_keyboard_interrupt: bool = True, | |
mandatory: bool = True, | |
mandatory_message: str = "Mandatory prompt", | |
session_result: Optional[InquirerPySessionResult] = None, | |
input: Optional["Input"] = None, | |
output: Optional["Output"] = None, | |
) -> None: | |
super().__init__( | |
message=message, | |
style=style, | |
vi_mode=vi_mode, | |
default=default, | |
qmark=qmark, | |
amark=amark, | |
instruction=instruction, | |
long_instruction=long_instruction, | |
completer=ThreadedCompleter( | |
FilePathCompleter( | |
only_directories=only_directories, only_files=only_files | |
) | |
), | |
multicolumn_complete=multicolumn_complete, | |
validate=validate, | |
invalid_message=invalid_message, | |
transformer=transformer, | |
filter=filter, | |
keybindings=keybindings, | |
wrap_lines=wrap_lines, | |
raise_keyboard_interrupt=raise_keyboard_interrupt, | |
mandatory=mandatory, | |
mandatory_message=mandatory_message, | |
session_result=session_result, | |
input=input, | |
output=output, | |
) | |