3131
3232from glob import glob
3333
34+ import jedi
35+
3436from bpython import inspection
3537from bpython import importcompletion
3638from 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
312352def 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)
0 commit comments