Skip to content

Commit 2cfa83b

Browse files
committed
Re-introduce autocompletion modes
Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
1 parent 4d26621 commit 2cfa83b

File tree

2 files changed

+53
-26
lines changed

2 files changed

+53
-26
lines changed

bpython/autocomplete.py

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,32 @@ def after_last_dot(name):
6868
return name.rstrip('.').rsplit('.')[-1]
6969

7070

71+
def method_match_simple(word, size, text):
72+
return word[:size] == text
73+
74+
75+
def method_match_substring(word, size, text):
76+
return text in word
77+
78+
79+
def method_match_fuzzy(word, size, text):
80+
s = r'.*%s.*' % '.*'.join(list(text))
81+
return re.search(s, word)
82+
83+
84+
MODES_MAP = {
85+
SIMPLE: method_match_simple,
86+
SUBSTRING: method_match_substring,
87+
FUZZY: method_match_fuzzy
88+
}
89+
90+
7191
class BaseCompletionType(object):
7292
"""Describes different completion types"""
7393

74-
def __init__(self, shown_before_tab=True):
94+
def __init__(self, shown_before_tab=True, mode=SIMPLE):
7595
self._shown_before_tab = shown_before_tab
96+
self.method_match = MODES_MAP[mode]
7697

7798
def matches(self, cursor_offset, line, **kwargs):
7899
"""Returns a list of possible matches given a line and cursor, or None
@@ -112,17 +133,20 @@ def shown_before_tab(self):
112133
once that has happened."""
113134
return self._shown_before_tab
114135

136+
def method_match(self, word, size, text):
137+
return word[:size] == text
138+
115139

116140
class CumulativeCompleter(BaseCompletionType):
117141
"""Returns combined matches from several completers"""
118142

119-
def __init__(self, completers):
143+
def __init__(self, completers, mode=SIMPLE):
120144
if not completers:
121145
raise ValueError(
122146
"CumulativeCompleter requires at least one completer")
123147
self._completers = completers
124148

125-
super(CumulativeCompleter, self).__init__(True)
149+
super(CumulativeCompleter, self).__init__(True, mode)
126150

127151
def locate(self, current_offset, line):
128152
return self._completers[0].locate(current_offset, line)
@@ -158,8 +182,8 @@ def format(self, word):
158182

159183
class FilenameCompletion(BaseCompletionType):
160184

161-
def __init__(self):
162-
super(FilenameCompletion, self).__init__(False)
185+
def __init__(self, mode=SIMPLE):
186+
super(FilenameCompletion, self).__init__(False, mode)
163187

164188
if sys.version_info[:2] >= (3, 4):
165189
def safe_glob(self, pathname):
@@ -282,7 +306,7 @@ def attr_lookup(self, obj, expr, attr):
282306
matches = []
283307
n = len(attr)
284308
for word in words:
285-
if method_match(word, n, attr) and word != "__builtins__":
309+
if self.method_match(word, n, attr) and word != "__builtins__":
286310
matches.append("%s.%s" % (expr, word))
287311
return matches
288312

@@ -354,11 +378,11 @@ def matches(self, cursor_offset, line, **kwargs):
354378
matches = set()
355379
n = len(text)
356380
for word in KEYWORDS:
357-
if method_match(word, n, text):
381+
if self.method_match(word, n, text):
358382
matches.add(word)
359383
for nspace in (builtins.__dict__, locals_):
360384
for word, val in iteritems(nspace):
361-
if method_match(word, n, text) and word != "__builtins__":
385+
if self.method_match(word, n, text) and word != "__builtins__":
362386
word = try_decode(word, 'ascii')
363387
# if identifier isn't ascii, don't complete (syntax error)
364388
if word is None:
@@ -508,28 +532,31 @@ def get_completer(completers, cursor_offset, line, **kwargs):
508532
"""
509533

510534
for completer in completers:
511-
matches = completer.matches(
512-
cursor_offset, line, **kwargs)
535+
matches = completer.matches(cursor_offset, line, **kwargs)
513536
if matches is not None:
514537
return sorted(matches), (completer if matches else None)
515538
return [], None
516539

517540

518-
BPYTHON_COMPLETER = (
519-
DictKeyCompletion(),
520-
StringLiteralAttrCompletion(),
521-
ImportCompletion(),
522-
FilenameCompletion(),
523-
MagicMethodCompletion(),
524-
MultilineJediCompletion(),
525-
GlobalCompletion(),
526-
CumulativeCompleter((AttrCompletion(), ParameterNameCompletion()))
527-
)
541+
def get_default_completer(mode=SIMPLE):
542+
return (
543+
DictKeyCompletion(mode=mode),
544+
StringLiteralAttrCompletion(mode=mode),
545+
ImportCompletion(mode=mode),
546+
FilenameCompletion(mode=mode),
547+
MagicMethodCompletion(mode=mode),
548+
MultilineJediCompletion(mode=mode),
549+
GlobalCompletion(mode=mode),
550+
CumulativeCompleter((AttrCompletion(mode=mode),
551+
ParameterNameCompletion(mode=mode)),
552+
mode=mode)
553+
)
528554

529555

530556
def get_completer_bpython(cursor_offset, line, **kwargs):
531557
""""""
532-
return get_completer(BPYTHON_COMPLETER, cursor_offset, line, **kwargs)
558+
return get_completer(get_default_completer(),
559+
cursor_offset, line, **kwargs)
533560

534561

535562
class EvaluationError(Exception):
@@ -552,7 +579,3 @@ def _callable_postfix(value, word):
552579
if inspection.is_callable(value):
553580
word += '('
554581
return word
555-
556-
557-
def method_match(word, size, text):
558-
return word[:size] == text

bpython/repl.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ def __init__(self, interp, config):
384384
except EnvironmentError:
385385
pass
386386

387+
self.completers = autocomplete.get_default_completer(
388+
config.autocomplete_mode)
389+
387390
@property
388391
def ps1(self):
389392
try:
@@ -595,7 +598,8 @@ def complete(self, tab=False):
595598

596599
self.set_docstring()
597600

598-
matches, completer = autocomplete.get_completer_bpython(
601+
matches, completer = autocomplete.get_completer(
602+
self.completers,
599603
cursor_offset=self.cursor_offset,
600604
line=self.current_line,
601605
locals_=self.interp.locals,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy