Skip to content

Commit f53005f

Browse files
authored
Merge pull request #299 from python-cmd2/subcomplete
Tweaked complete function to handle cases where a flag appears before…
2 parents df2e4b7 + cf23503 commit f53005f

File tree

1 file changed

+39
-32
lines changed

1 file changed

+39
-32
lines changed

cmd2.py

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def flag_based_complete(text, line, begidx, endidx, flag_dict, default_completer
193193
return []
194194

195195
completions = []
196-
flag_processed = False
196+
flag_present = False
197197

198198
# Must have at least the command and one argument for a flag to be present
199199
if len(tokens) > 1:
@@ -204,9 +204,10 @@ def flag_based_complete(text, line, begidx, endidx, flag_dict, default_completer
204204
# Check if the flag is in the dictionary
205205
if flag in flag_dict:
206206

207+
flag_present = True
208+
207209
# Check if this flag does completions using an Iterable
208210
if isinstance(flag_dict[flag], collections.Iterable):
209-
flag_processed = True
210211
strs_to_match = flag_dict[flag]
211212
completions = [cur_str for cur_str in strs_to_match if cur_str.startswith(text)]
212213

@@ -216,12 +217,11 @@ def flag_based_complete(text, line, begidx, endidx, flag_dict, default_completer
216217

217218
# Otherwise check if this flag does completions with a function
218219
elif callable(flag_dict[flag]):
219-
flag_processed = True
220220
completer_func = flag_dict[flag]
221221
completions = completer_func(text, line, begidx, endidx)
222222

223223
# 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:
225225
completions = default_completer(text, line, begidx, endidx)
226226

227227
completions.sort()
@@ -254,34 +254,34 @@ def index_based_complete(text, line, begidx, endidx, index_dict, default_complet
254254
# Invalid syntax for shlex (Probably due to missing closing quote)
255255
return []
256256

257-
completions = []
257+
if len(tokens) == 0:
258+
return []
258259

259-
# Must have at least the command
260-
if len(tokens) > 0:
260+
completions = []
261261

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)
264264

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:
267267

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)]
272272

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] += ' '
276276

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)
281281

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)
285285

286286
completions.sort()
287287
return completions
@@ -1350,6 +1350,7 @@ def complete(self, text, state):
13501350
# Overwrite line to pass into completers
13511351
line = expanded_line
13521352

1353+
got_matches = False
13531354
if command == '':
13541355
compfunc = self.completedefault
13551356
else:
@@ -1361,16 +1362,22 @@ def complete(self, text, state):
13611362
compfunc = self.completedefault
13621363

13631364
# 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
13651366
subcommands = self.get_subcommands(command)
13661367
if subcommands is not None:
13671368
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)
13741381

13751382
else:
13761383
# Complete the command against command names and shortcuts. By design, shortcuts that start with

0 commit comments

Comments
 (0)