diff --git a/examples/prompts/auto-completion/autocomplete-file-path.py b/examples/prompts/auto-completion/autocomplete-file-path.py new file mode 100644 index 000000000..1af8113cb --- /dev/null +++ b/examples/prompts/auto-completion/autocomplete-file-path.py @@ -0,0 +1,15 @@ +from prompt_toolkit import prompt +from prompt_toolkit.completion import PathCompleter + + +def main(): + text = prompt( + "shell: ", + completer=PathCompleter(use_word=True), + complete_while_typing=False, + ) + print("You said: %s" % text) + + +if __name__ == "__main__": + main() diff --git a/prompt_toolkit/completion/filesystem.py b/prompt_toolkit/completion/filesystem.py index 17eb173bf..a5b28bf8c 100644 --- a/prompt_toolkit/completion/filesystem.py +++ b/prompt_toolkit/completion/filesystem.py @@ -1,4 +1,5 @@ import os +import re from typing import Callable, Iterable, List, Optional from prompt_toolkit.completion import CompleteEvent, Completer, Completion @@ -9,6 +10,8 @@ "ExecutableCompleter", ] +_FILE_PATH_RE = re.compile(r"[^\s\"'\t]+") + class PathCompleter(Completer): """ @@ -20,6 +23,7 @@ class PathCompleter(Completer): this file should show up in the completion. ``None`` when no filtering has to be done. :param min_input_len: Don't do autocompletion when the input string is shorter. + :param use_word: Search up to the last white space instead of the whole input. """ def __init__( @@ -29,6 +33,7 @@ def __init__( file_filter: Optional[Callable[[str], bool]] = None, min_input_len: int = 0, expanduser: bool = False, + use_word: bool = False, ) -> None: self.only_directories = only_directories @@ -36,11 +41,17 @@ def __init__( self.file_filter = file_filter or (lambda _: True) self.min_input_len = min_input_len self.expanduser = expanduser + self.use_word = use_word def get_completions( self, document: Document, complete_event: CompleteEvent ) -> Iterable[Completion]: - text = document.text_before_cursor + + text = ( + document.text_before_cursor + if not self.use_word + else document.get_word_before_cursor(pattern=_FILE_PATH_RE) + ) # Complete only when we have at least the minimal input length, # otherwise, we can too many results and autocompletion will become too @@ -93,7 +104,11 @@ def get_completions( if not self.file_filter(full_name): continue - yield Completion(completion, 0, display=filename) + yield Completion( + completion, + 0, + display=filename, + ) except OSError: pass