@@ -68,11 +68,32 @@ def after_last_dot(name):
68
68
return name .rstrip ('.' ).rsplit ('.' )[- 1 ]
69
69
70
70
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
+
71
91
class BaseCompletionType (object ):
72
92
"""Describes different completion types"""
73
93
74
- def __init__ (self , shown_before_tab = True ):
94
+ def __init__ (self , shown_before_tab = True , mode = SIMPLE ):
75
95
self ._shown_before_tab = shown_before_tab
96
+ self .method_match = MODES_MAP [mode ]
76
97
77
98
def matches (self , cursor_offset , line , ** kwargs ):
78
99
"""Returns a list of possible matches given a line and cursor, or None
@@ -112,17 +133,20 @@ def shown_before_tab(self):
112
133
once that has happened."""
113
134
return self ._shown_before_tab
114
135
136
+ def method_match (self , word , size , text ):
137
+ return word [:size ] == text
138
+
115
139
116
140
class CumulativeCompleter (BaseCompletionType ):
117
141
"""Returns combined matches from several completers"""
118
142
119
- def __init__ (self , completers ):
143
+ def __init__ (self , completers , mode = SIMPLE ):
120
144
if not completers :
121
145
raise ValueError (
122
146
"CumulativeCompleter requires at least one completer" )
123
147
self ._completers = completers
124
148
125
- super (CumulativeCompleter , self ).__init__ (True )
149
+ super (CumulativeCompleter , self ).__init__ (True , mode )
126
150
127
151
def locate (self , current_offset , line ):
128
152
return self ._completers [0 ].locate (current_offset , line )
@@ -158,8 +182,8 @@ def format(self, word):
158
182
159
183
class FilenameCompletion (BaseCompletionType ):
160
184
161
- def __init__ (self ):
162
- super (FilenameCompletion , self ).__init__ (False )
185
+ def __init__ (self , mode = SIMPLE ):
186
+ super (FilenameCompletion , self ).__init__ (False , mode )
163
187
164
188
if sys .version_info [:2 ] >= (3 , 4 ):
165
189
def safe_glob (self , pathname ):
@@ -282,7 +306,7 @@ def attr_lookup(self, obj, expr, attr):
282
306
matches = []
283
307
n = len (attr )
284
308
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__" :
286
310
matches .append ("%s.%s" % (expr , word ))
287
311
return matches
288
312
@@ -354,11 +378,11 @@ def matches(self, cursor_offset, line, **kwargs):
354
378
matches = set ()
355
379
n = len (text )
356
380
for word in KEYWORDS :
357
- if method_match (word , n , text ):
381
+ if self . method_match (word , n , text ):
358
382
matches .add (word )
359
383
for nspace in (builtins .__dict__ , locals_ ):
360
384
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__" :
362
386
word = try_decode (word , 'ascii' )
363
387
# if identifier isn't ascii, don't complete (syntax error)
364
388
if word is None :
@@ -508,28 +532,31 @@ def get_completer(completers, cursor_offset, line, **kwargs):
508
532
"""
509
533
510
534
for completer in completers :
511
- matches = completer .matches (
512
- cursor_offset , line , ** kwargs )
535
+ matches = completer .matches (cursor_offset , line , ** kwargs )
513
536
if matches is not None :
514
537
return sorted (matches ), (completer if matches else None )
515
538
return [], None
516
539
517
540
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
+ )
528
554
529
555
530
556
def get_completer_bpython (cursor_offset , line , ** kwargs ):
531
557
""""""
532
- return get_completer (BPYTHON_COMPLETER , cursor_offset , line , ** kwargs )
558
+ return get_completer (get_default_completer (),
559
+ cursor_offset , line , ** kwargs )
533
560
534
561
535
562
class EvaluationError (Exception ):
@@ -552,7 +579,3 @@ def _callable_postfix(value, word):
552
579
if inspection .is_callable (value ):
553
580
word += '('
554
581
return word
555
-
556
-
557
- def method_match (word , size , text ):
558
- return word [:size ] == text
0 commit comments