Skip to content

Commit 1e3facc

Browse files
committed
Sorting all completion results. Added unit tests for help command.
1 parent fed2325 commit 1e3facc

2 files changed

Lines changed: 51 additions & 15 deletions

File tree

cmd2.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,15 @@ def flag_based_complete(text, line, begidx, endidx, flag_dict, default_completer
182182
being completed
183183
:return: List[str] - a list of possible tab completions
184184
"""
185-
completions = []
186185

187186
# Get all tokens prior to text being completed
188187
try:
189188
tokens = shlex.split(line[:begidx], posix=POSIX_SHLEX)
190189
except ValueError:
191190
# Invalid syntax for shlex (Probably due to missing closing quote)
192-
return completions
191+
return []
192+
193+
completions = []
193194

194195
# Must have at least the command and one argument
195196
if len(tokens) > 1:
@@ -218,6 +219,7 @@ def flag_based_complete(text, line, begidx, endidx, flag_dict, default_completer
218219
elif default_completer is not None:
219220
completions = default_completer(text, line, begidx, endidx)
220221

222+
completions.sort()
221223
return completions
222224

223225

@@ -238,14 +240,15 @@ def index_based_complete(text, line, begidx, endidx, index_dict, default_complet
238240
any index in index_dict
239241
:return: List[str] - a list of possible tab completions
240242
"""
241-
completions = []
242243

243244
# Get all tokens prior to text being completed
244245
try:
245246
tokens = shlex.split(line[:begidx], posix=POSIX_SHLEX)
246247
except ValueError:
247248
# Invalid syntax for shlex (Probably due to missing closing quote)
248-
return completions
249+
return []
250+
251+
completions = []
249252

250253
# Must have at least the command
251254
if len(tokens) > 0:
@@ -274,6 +277,7 @@ def index_based_complete(text, line, begidx, endidx, index_dict, default_complet
274277
elif default_completer is not None:
275278
completions = default_completer(text, line, begidx, endidx)
276279

280+
completions.sort()
277281
return completions
278282

279283

@@ -350,8 +354,8 @@ def path_complete(text, line, begidx, endidx, dir_exe_only=False, dir_only=False
350354
elif os.path.isdir(path_completions[0]) and add_sep_after_tilde:
351355
completions[0] = os.path.sep + completions[0]
352356

353-
# If there are multiple completions, then sort them alphabetically
354-
return sorted(completions)
357+
completions.sort()
358+
return completions
355359

356360

357361
class OptionParser(optparse.OptionParser):
@@ -1336,14 +1340,15 @@ def complete_help(self, text, line, begidx, endidx):
13361340
"""
13371341
Override of parent class method to handle tab completing subcommands
13381342
"""
1339-
completions = []
13401343

13411344
# Get all tokens prior to text being completed
13421345
try:
13431346
tokens = shlex.split(line[:begidx], posix=POSIX_SHLEX)
13441347
except ValueError:
13451348
# Invalid syntax for shlex (Probably due to missing closing quote)
1346-
return completions
1349+
return []
1350+
1351+
completions = []
13471352

13481353
# If we have "help" and a completed command token, then attempt to match subcommands
13491354
if len(tokens) == 2:
@@ -1362,6 +1367,7 @@ def complete_help(self, text, line, begidx, endidx):
13621367
if len(completions) == 1 and endidx == len(line) and self.get_subcommands(completions[0]) is not None:
13631368
completions[0] += ' '
13641369

1370+
completions.sort()
13651371
return completions
13661372

13671373
def precmd(self, statement):
@@ -2067,8 +2073,8 @@ def _shell_command_complete(text, line, begidx, endidx):
20672073
if len(exes) == 1 and endidx == len(line):
20682074
exes[0] += ' '
20692075

2070-
# If there are multiple completions, then sort them alphabetically
2071-
return sorted(exes)
2076+
exes.sort()
2077+
return exes
20722078

20732079
def complete_shell(self, text, line, begidx, endidx):
20742080
"""Handles tab completion of executable commands and local file system paths.

tests/test_completion.py

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,28 +181,28 @@ def test_cmd2_help_completion_single_end(cmd2_app):
181181
endidx = len(line)
182182
begidx = endidx - len(text)
183183
# Even though it is at end of line, no extra space is present when tab completing a command name to get help on
184-
assert cmd2_app.completenames(text, line, begidx, endidx) == ['help']
184+
assert cmd2_app.complete_help(text, line, begidx, endidx) == ['help']
185185

186186
def test_cmd2_help_completion_single_mid(cmd2_app):
187187
text = 'he'
188188
line = 'help he'
189189
begidx = 5
190190
endidx = 6
191-
assert cmd2_app.completenames(text, line, begidx, endidx) == ['help']
191+
assert cmd2_app.complete_help(text, line, begidx, endidx) == ['help']
192192

193193
def test_cmd2_help_completion_multiple(cmd2_app):
194194
text = 'h'
195195
line = 'help h'
196196
endidx = len(line)
197197
begidx = endidx - len(text)
198-
assert cmd2_app.completenames(text, line, begidx, endidx) == ['help', 'history']
198+
assert cmd2_app.complete_help(text, line, begidx, endidx) == ['help', 'history']
199199

200200
def test_cmd2_help_completion_nomatch(cmd2_app):
201201
text = 'z'
202202
line = 'help z'
203203
endidx = len(line)
204204
begidx = endidx - len(text)
205-
assert cmd2_app.completenames(text, line, begidx, endidx) == []
205+
assert cmd2_app.complete_help(text, line, begidx, endidx) == []
206206

207207
def test_shell_command_completion(cmd2_app):
208208
if sys.platform == "win32":
@@ -539,7 +539,7 @@ def get_endidx():
539539
# Run the readline tab-completion function with readline mocks in place
540540
first_match = sc_app.complete(text, state)
541541

542-
assert first_match is not None and sc_app.completion_matches == ['foo', 'bar']
542+
assert first_match is not None and sc_app.completion_matches == ['bar', 'foo']
543543

544544
def test_cmd2_subcommand_completion_nomatch(sc_app):
545545
text = 'z'
@@ -612,3 +612,33 @@ def get_endidx():
612612
first_match = sc_app.complete(text, state)
613613

614614
assert first_match is not None and sc_app.completion_matches == ['foo ']
615+
616+
def test_cmd2_help_subcommand_completion_single_end(sc_app):
617+
text = 'base'
618+
line = 'help base'
619+
endidx = len(line)
620+
begidx = endidx - len(text)
621+
622+
# Commands with subcommands have a space at the end when the cursor is at the end of the line
623+
assert sc_app.complete_help(text, line, begidx, endidx) == ['base ']
624+
625+
def test_cmd2_help_subcommand_completion_single_mid(sc_app):
626+
text = 'ba'
627+
line = 'help base'
628+
begidx = 5
629+
endidx = 6
630+
assert sc_app.complete_help(text, line, begidx, endidx) == ['base']
631+
632+
def test_cmd2_help_subcommand_completion_multiple(sc_app):
633+
text = ''
634+
line = 'help base'
635+
endidx = len(line)
636+
begidx = endidx - len(text)
637+
assert sc_app.complete_help(text, line, begidx, endidx) == ['bar', 'foo']
638+
639+
def test_cmd2_help_subcommand_completion_nomatch(sc_app):
640+
text = 'z'
641+
line = 'help base z'
642+
endidx = len(line)
643+
begidx = endidx - len(text)
644+
assert sc_app.complete_help(text, line, begidx, endidx) == []

0 commit comments

Comments
 (0)