1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
"""
"""
from __future__ import unicode_literals
from abc import ABCMeta, abstractmethod
from six import with_metaclass
__all__ = (
'Completion',
'Completer',
'CompleteEvent',
'get_common_complete_suffix',
)
class Completion(object):
"""
:param text: The new string that will be inserted into the document.
:param start_position: Position relative to the cursor_position where the
new text will start. The text will be inserted between the
start_position and the original cursor position.
:param display: (optional string) If the completion has to be displayed
differently in the completion menu.
:param display_meta: (Optional string) Meta information about the
completion, e.g. the path or source where it's coming from.
:param get_display_meta: Lazy `display_meta`. Retrieve meta information
only when meta is displayed.
"""
def __init__(self, text, start_position=0, display=None, display_meta=None,
get_display_meta=None):
self.text = text
self.start_position = start_position
self._display_meta = display_meta
self._get_display_meta = get_display_meta
if display is None:
self.display = text
else:
self.display = display
assert self.start_position <= 0
def __repr__(self):
if self.display == self.text:
return '%s(text=%r, start_position=%r)' % (
self.__class__.__name__, self.text, self.start_position)
else:
return '%s(text=%r, start_position=%r, display=%r)' % (
self.__class__.__name__, self.text, self.start_position,
self.display)
def __eq__(self, other):
return (
self.text == other.text and
self.start_position == other.start_position and
self.display == other.display and
self.display_meta == other.display_meta)
def __hash__(self):
return hash((self.text, self.start_position, self.display, self.display_meta))
@property
def display_meta(self):
# Return meta-text. (This is lazy when using "get_display_meta".)
if self._display_meta is not None:
return self._display_meta
elif self._get_display_meta:
self._display_meta = self._get_display_meta()
return self._display_meta
else:
return ''
def new_completion_from_position(self, position):
"""
(Only for internal use!)
Get a new completion by splitting this one. Used by
`CommandLineInterface` when it needs to have a list of new completions
after inserting the common prefix.
"""
assert isinstance(position, int) and position - self.start_position >= 0
return Completion(
text=self.text[position - self.start_position:],
display=self.display,
display_meta=self._display_meta,
get_display_meta=self._get_display_meta)
class CompleteEvent(object):
"""
Event that called the completer.
:param text_inserted: When True, it means that completions are requested
because of a text insert. (`Buffer.complete_while_typing`.)
:param completion_requested: When True, it means that the user explicitely
pressed the `Tab` key in order to view the completions.
These two flags can be used for instance to implemented a completer that
shows some completions when ``Tab`` has been pressed, but not
automatically when the user presses a space. (Because of
`complete_while_typing`.)
"""
def __init__(self, text_inserted=False, completion_requested=False):
assert not (text_inserted and completion_requested)
#: Automatic completion while typing.
self.text_inserted = text_inserted
#: Used explicitely requested completion by pressing 'tab'.
self.completion_requested = completion_requested
def __repr__(self):
return '%s(text_inserted=%r, completion_requested=%r)' % (
self.__class__.__name__, self.text_inserted, self.completion_requested)
class Completer(with_metaclass(ABCMeta, object)):
"""
Base class for completer implementations.
"""
@abstractmethod
def get_completions(self, document, complete_event):
"""
Yield :class:`.Completion` instances.
:param document: :class:`~prompt_toolkit.document.Document` instance.
:param complete_event: :class:`.CompleteEvent` instance.
"""
while False:
yield
def get_common_complete_suffix(document, completions):
"""
Return the common prefix for all completions.
"""
# Take only completions that don't change the text before the cursor.
def doesnt_change_before_cursor(completion):
end = completion.text[:-completion.start_position]
return document.text_before_cursor.endswith(end)
completions2 = [c for c in completions if doesnt_change_before_cursor(c)]
# When there is at least one completion that changes the text before the
# cursor, don't return any common part.
if len(completions2) != len(completions):
return ''
# Return the common prefix.
def get_suffix(completion):
return completion.text[-completion.start_position:]
return _commonprefix([get_suffix(c) for c in completions2])
def _commonprefix(strings):
# Similar to os.path.commonprefix
if not strings:
return ''
else:
s1 = min(strings)
s2 = max(strings)
for i, c in enumerate(s1):
if c != s2[i]:
return s1[:i]
return s1
|