Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/prompt_toolkit/completion/filesystem.py: 23%
47 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1from __future__ import annotations
3import os
4from typing import Callable, Iterable
6from prompt_toolkit.completion import CompleteEvent, Completer, Completion
7from prompt_toolkit.document import Document
9__all__ = [
10 "PathCompleter",
11 "ExecutableCompleter",
12]
15class PathCompleter(Completer):
16 """
17 Complete for Path variables.
19 :param get_paths: Callable which returns a list of directories to look into
20 when the user enters a relative path.
21 :param file_filter: Callable which takes a filename and returns whether
22 this file should show up in the completion. ``None``
23 when no filtering has to be done.
24 :param min_input_len: Don't do autocompletion when the input string is shorter.
25 """
27 def __init__(
28 self,
29 only_directories: bool = False,
30 get_paths: Callable[[], list[str]] | None = None,
31 file_filter: Callable[[str], bool] | None = None,
32 min_input_len: int = 0,
33 expanduser: bool = False,
34 ) -> None:
35 self.only_directories = only_directories
36 self.get_paths = get_paths or (lambda: ["."])
37 self.file_filter = file_filter or (lambda _: True)
38 self.min_input_len = min_input_len
39 self.expanduser = expanduser
41 def get_completions(
42 self, document: Document, complete_event: CompleteEvent
43 ) -> Iterable[Completion]:
44 text = document.text_before_cursor
46 # Complete only when we have at least the minimal input length,
47 # otherwise, we can too many results and autocompletion will become too
48 # heavy.
49 if len(text) < self.min_input_len:
50 return
52 try:
53 # Do tilde expansion.
54 if self.expanduser:
55 text = os.path.expanduser(text)
57 # Directories where to look.
58 dirname = os.path.dirname(text)
59 if dirname:
60 directories = [
61 os.path.dirname(os.path.join(p, text)) for p in self.get_paths()
62 ]
63 else:
64 directories = self.get_paths()
66 # Start of current file.
67 prefix = os.path.basename(text)
69 # Get all filenames.
70 filenames = []
71 for directory in directories:
72 # Look for matches in this directory.
73 if os.path.isdir(directory):
74 for filename in os.listdir(directory):
75 if filename.startswith(prefix):
76 filenames.append((directory, filename))
78 # Sort
79 filenames = sorted(filenames, key=lambda k: k[1])
81 # Yield them.
82 for directory, filename in filenames:
83 completion = filename[len(prefix) :]
84 full_name = os.path.join(directory, filename)
86 if os.path.isdir(full_name):
87 # For directories, add a slash to the filename.
88 # (We don't add them to the `completion`. Users can type it
89 # to trigger the autocompletion themselves.)
90 filename += "/"
91 elif self.only_directories:
92 continue
94 if not self.file_filter(full_name):
95 continue
97 yield Completion(
98 text=completion,
99 start_position=0,
100 display=filename,
101 )
102 except OSError:
103 pass
106class ExecutableCompleter(PathCompleter):
107 """
108 Complete only executable files in the current path.
109 """
111 def __init__(self) -> None:
112 super().__init__(
113 only_directories=False,
114 min_input_len=1,
115 get_paths=lambda: os.environ.get("PATH", "").split(os.pathsep),
116 file_filter=lambda name: os.access(name, os.X_OK),
117 expanduser=True,
118 )