Skip to content

Commit 57b94b0

Browse files
Jedi completion only for multiline blocks
1 parent e3311cd commit 57b94b0

File tree

5 files changed

+54
-10
lines changed

5 files changed

+54
-10
lines changed

bpython/autocomplete.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131

3232
from glob import glob
3333

34+
import jedi
35+
3436
from bpython import inspection
3537
from bpython import importcompletion
3638
from bpython import line as lineparts
@@ -114,7 +116,7 @@ def locate(self, current_offset, line):
114116
def format(self, word):
115117
return self._completers[0].format(word)
116118

117-
def matches(self, cursor_offset, line, locals_, argspec, current_block, complete_magic_methods):
119+
def matches(self, cursor_offset, line, locals_, argspec, current_block, complete_magic_methods, history):
118120
all_matches = set()
119121
for completer in self._completers:
120122
# these have to be explicitely listed to deal with the different
@@ -124,7 +126,8 @@ def matches(self, cursor_offset, line, locals_, argspec, current_block, complete
124126
locals_=locals_,
125127
argspec=argspec,
126128
current_block=current_block,
127-
complete_magic_methods=complete_magic_methods)
129+
complete_magic_methods=complete_magic_methods,
130+
history=history)
128131
if matches is not None:
129132
all_matches.update(matches)
130133

@@ -308,6 +311,43 @@ def matches(self, cursor_offset, line, **kwargs):
308311
def locate(self, current_offset, line):
309312
return lineparts.current_string_literal_attr(current_offset, line)
310313

314+
class JediCompletion(BaseCompletionType):
315+
@classmethod
316+
def matches(self, cursor_offset, line, history, **kwargs):
317+
if not lineparts.current_word(cursor_offset, line):
318+
return None
319+
history = '\n'.join(history) + '\n' + line
320+
script = jedi.Script(history, len(history.splitlines()), cursor_offset, 'fake.py')
321+
completions = script.completions()
322+
if completions:
323+
self._original = completions[0]
324+
else:
325+
self._original = None
326+
327+
matches = [c.name for c in completions]
328+
if all(m.startswith('_') for m in matches):
329+
return matches
330+
elif any(not m.startswith(matches[0][0]) for m in matches):
331+
return matches
332+
else:
333+
return [m for m in matches if not m.startswith('_')]
334+
335+
def locate(self, cursor_offset, line):
336+
start = cursor_offset - (len(self._original.name) - len(self._original.complete))
337+
end = cursor_offset
338+
return start, end, line[start:end]
339+
340+
341+
class MultilineJediCompletion(JediCompletion):
342+
@classmethod
343+
def matches(cls, cursor_offset, line, current_block, history, **kwargs):
344+
if '\n' in current_block:
345+
assert cursor_offset <= len(line), "%r %r" % (cursor_offset, line)
346+
results = JediCompletion.matches(cursor_offset, line, history)
347+
return results
348+
else:
349+
return None
350+
311351

312352
def get_completer(completers, cursor_offset, line, **kwargs):
313353
"""Returns a list of matches and an applicable completer
@@ -338,6 +378,7 @@ def get_completer(completers, cursor_offset, line, **kwargs):
338378
ImportCompletion(),
339379
FilenameCompletion(),
340380
MagicMethodCompletion(),
381+
MultilineJediCompletion(),
341382
GlobalCompletion(),
342383
CumulativeCompleter((AttrCompletion(), ParameterNameCompletion()))
343384
)

bpython/curtsiesfrontend/repl.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -607,9 +607,7 @@ def readline_kill(self, e):
607607
self.cut_buffer = cut
608608

609609
def on_enter(self, insert_into_history=True):
610-
self.cursor_offset = -1 # so the cursor isn't touching a paren
611-
self.unhighlight_paren() # in unhighlight_paren
612-
self.highlighted_paren = None
610+
self._set_cursor_offset(-1, update_completion=False) # so the cursor isn't touching a paren
613611

614612
self.history.append(self.current_line)
615613
self.push(self.current_line, insert_into_history=insert_into_history)
@@ -866,7 +864,7 @@ def run_code_and_maybe_finish(self, for_code=None):
866864
self.display_lines.extend(paint.display_linize(self.current_stdouterr_line, self.width))
867865
self.current_stdouterr_line = ''
868866

869-
self.current_line = ' '*indent
867+
self._set_current_line(' '*indent, update_completion=True)
870868
self.cursor_offset = len(self.current_line)
871869

872870
def keyboard_interrupt(self):

bpython/repl.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,8 @@ def complete(self, tab=False):
534534
locals_=self.interp.locals,
535535
argspec=self.argspec,
536536
current_block='\n'.join(self.buffer + [self.current_line]),
537-
complete_magic_methods=self.config.complete_magic_methods)
537+
complete_magic_methods=self.config.complete_magic_methods,
538+
history=self.history)
538539
#TODO implement completer.shown_before_tab == False (filenames shouldn't fill screen)
539540

540541
if len(matches) == 0:

bpython/test/test_autocomplete.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,18 +83,18 @@ def test_no_completers_fails(self):
8383
def test_one_empty_completer_returns_empty(self):
8484
a = self.completer([])
8585
cumulative = autocomplete.CumulativeCompleter([a])
86-
self.assertEqual(cumulative.matches(3, 'abc', 1, 1, 1, 1), [])
86+
self.assertEqual(cumulative.matches(3, 'abc', 1, 1, 1, 1, 1), [])
8787

8888
def test_one_none_completer_returns_empty(self):
8989
a = self.completer(None)
9090
cumulative = autocomplete.CumulativeCompleter([a])
91-
self.assertEqual(cumulative.matches(3, 'abc', 1, 1, 1, 1), [])
91+
self.assertEqual(cumulative.matches(3, 'abc', 1, 1, 1, 1, 1), [])
9292

9393
def test_two_completers_get_both(self):
9494
a = self.completer(['a'])
9595
b = self.completer(['b'])
9696
cumulative = autocomplete.CumulativeCompleter([a, b])
97-
self.assertEqual(cumulative.matches(3, 'abc', 1, 1, 1, 1), (['a', 'b']))
97+
self.assertEqual(cumulative.matches(3, 'abc', 1, 1, 1, 1, 1), (['a', 'b']))
9898

9999

100100
class TestFilenameCompletion(unittest.TestCase):

bpython/test/test_line_properties.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ def test_dots(self):
124124
self.assertAccess('stuff[<asd|fg>]')
125125
self.assertAccess('stuff[asdf[<asd|fg>]')
126126

127+
def test_open_paren(self):
128+
self.assertAccess('<foo(|>')
129+
# documenting current behavior - TODO is this intended?
130+
127131
class TestCurrentDictKey(LineTestCase):
128132
def setUp(self):
129133
self.func = current_dict_key

0 commit comments

Comments
 (0)