@@ -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+
7191class 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
116140class 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
159183class 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
530556def 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
535562class 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
0 commit comments