@@ -193,7 +193,7 @@ def flag_based_complete(text, line, begidx, endidx, flag_dict, default_completer
193
193
return []
194
194
195
195
completions = []
196
- flag_processed = False
196
+ flag_present = False
197
197
198
198
# Must have at least the command and one argument for a flag to be present
199
199
if len (tokens ) > 1 :
@@ -204,9 +204,10 @@ def flag_based_complete(text, line, begidx, endidx, flag_dict, default_completer
204
204
# Check if the flag is in the dictionary
205
205
if flag in flag_dict :
206
206
207
+ flag_present = True
208
+
207
209
# Check if this flag does completions using an Iterable
208
210
if isinstance (flag_dict [flag ], collections .Iterable ):
209
- flag_processed = True
210
211
strs_to_match = flag_dict [flag ]
211
212
completions = [cur_str for cur_str in strs_to_match if cur_str .startswith (text )]
212
213
@@ -216,12 +217,11 @@ def flag_based_complete(text, line, begidx, endidx, flag_dict, default_completer
216
217
217
218
# Otherwise check if this flag does completions with a function
218
219
elif callable (flag_dict [flag ]):
219
- flag_processed = True
220
220
completer_func = flag_dict [flag ]
221
221
completions = completer_func (text , line , begidx , endidx )
222
222
223
223
# Check if we need to run the default completer
224
- if default_completer is not None and not flag_processed :
224
+ if default_completer is not None and not flag_present :
225
225
completions = default_completer (text , line , begidx , endidx )
226
226
227
227
completions .sort ()
@@ -254,34 +254,34 @@ def index_based_complete(text, line, begidx, endidx, index_dict, default_complet
254
254
# Invalid syntax for shlex (Probably due to missing closing quote)
255
255
return []
256
256
257
- completions = []
257
+ if len (tokens ) == 0 :
258
+ return []
258
259
259
- # Must have at least the command
260
- if len (tokens ) > 0 :
260
+ completions = []
261
261
262
- # Get the index of the token being completed
263
- index = len (tokens )
262
+ # Get the index of the token being completed
263
+ index = len (tokens )
264
264
265
- # Check if the index is in the dictionary
266
- if index in index_dict :
265
+ # Check if the index is in the dictionary
266
+ if index in index_dict :
267
267
268
- # Check if this index does completions using an Iterable
269
- if isinstance (index_dict [index ], collections .Iterable ):
270
- strs_to_match = index_dict [index ]
271
- completions = [cur_str for cur_str in strs_to_match if cur_str .startswith (text )]
268
+ # Check if this index does completions using an Iterable
269
+ if isinstance (index_dict [index ], collections .Iterable ):
270
+ strs_to_match = index_dict [index ]
271
+ completions = [cur_str for cur_str in strs_to_match if cur_str .startswith (text )]
272
272
273
- # If there is only 1 match and it's at the end of the line, then add a space
274
- if len (completions ) == 1 and endidx == len (line ):
275
- completions [0 ] += ' '
273
+ # If there is only 1 match and it's at the end of the line, then add a space
274
+ if len (completions ) == 1 and endidx == len (line ):
275
+ completions [0 ] += ' '
276
276
277
- # Otherwise check if this index does completions with a function
278
- elif callable (index_dict [index ]):
279
- completer_func = index_dict [index ]
280
- completions = completer_func (text , line , begidx , endidx )
277
+ # Otherwise check if this index does completions with a function
278
+ elif callable (index_dict [index ]):
279
+ completer_func = index_dict [index ]
280
+ completions = completer_func (text , line , begidx , endidx )
281
281
282
- # Otherwise check if there is a default completer
283
- elif default_completer is not None :
284
- completions = default_completer (text , line , begidx , endidx )
282
+ # Otherwise check if there is a default completer
283
+ elif default_completer is not None :
284
+ completions = default_completer (text , line , begidx , endidx )
285
285
286
286
completions .sort ()
287
287
return completions
@@ -1350,6 +1350,7 @@ def complete(self, text, state):
1350
1350
# Overwrite line to pass into completers
1351
1351
line = expanded_line
1352
1352
1353
+ got_matches = False
1353
1354
if command == '' :
1354
1355
compfunc = self .completedefault
1355
1356
else :
@@ -1361,16 +1362,22 @@ def complete(self, text, state):
1361
1362
compfunc = self .completedefault
1362
1363
1363
1364
# If there are subcommands, then try completing those if the cursor is in
1364
- # the correct position, otherwise default to using compfunc
1365
+ # index 1 of the command tokens
1365
1366
subcommands = self .get_subcommands (command )
1366
1367
if subcommands is not None :
1367
1368
index_dict = {1 : subcommands }
1368
- compfunc = functools .partial (index_based_complete ,
1369
- index_dict = index_dict ,
1370
- default_completer = compfunc )
1371
-
1372
- # Call the completer function
1373
- self .completion_matches = compfunc (text , line , begidx , endidx )
1369
+ tmp_matches = index_based_complete (text , line , begidx , endidx , index_dict )
1370
+
1371
+ # If we got sumcommand matches, then save them. Otherwise the cursor isn't in index 1
1372
+ # or there is something else there like a flag. The command specific complete function
1373
+ # will handle those cases.
1374
+ if len (tmp_matches ) > 0 :
1375
+ got_matches = True
1376
+ self .completion_matches = tmp_matches
1377
+
1378
+ # Call the command specific completer function
1379
+ if not got_matches :
1380
+ self .completion_matches = compfunc (text , line , begidx , endidx )
1374
1381
1375
1382
else :
1376
1383
# Complete the command against command names and shortcuts. By design, shortcuts that start with
0 commit comments