diff --git a/mitmproxy/tools/console/commander/commander.py b/mitmproxy/tools/console/commander/commander.py index 0feae28ea..47cf1962a 100644 --- a/mitmproxy/tools/console/commander/commander.py +++ b/mitmproxy/tools/console/commander/commander.py @@ -28,15 +28,17 @@ class ListCompleter(Completer): if o.startswith(start): self.options.append(o) self.options.sort() - self.offset = 0 + self.pos = -1 def cycle(self, forward: bool = True) -> str: if not self.options: return self.start - ret = self.options[self.offset] - delta = 1 if forward else -1 - self.offset = (self.offset + delta) % len(self.options) - return ret + if self.pos == -1: + self.pos = 0 if forward else len(self.options) - 1 + else: + delta = 1 if forward else -1 + self.pos = (self.pos + delta) % len(self.options) + return self.options[self.pos] class CompletionState(typing.NamedTuple): diff --git a/test/mitmproxy/tools/console/test_commander.py b/test/mitmproxy/tools/console/test_commander.py index d1c214824..a297fcf7a 100644 --- a/test/mitmproxy/tools/console/test_commander.py +++ b/test/mitmproxy/tools/console/test_commander.py @@ -31,23 +31,35 @@ class TestListCompleter: [ "", ["a", "b", "c"], - ["a", "b", "c", "a"] + ["a", "b", "c", "a"], + ["c", "b", "a", "c"], + ["a", "c", "a", "c"] ], [ "xxx", ["a", "b", "c"], + ["xxx", "xxx", "xxx"], + ["xxx", "xxx", "xxx"], ["xxx", "xxx", "xxx"] ], [ "b", ["a", "b", "ba", "bb", "c"], - ["b", "ba", "bb", "b"] + ["b", "ba", "bb", "b"], + ["bb", "ba", "b", "bb"], + ["b", "bb", "b", "bb"] ], ] - for start, opts, cycle in tests: + for start, opts, cycle, cycle_reverse, cycle_mix in tests: c = commander.ListCompleter(start, opts) for expected in cycle: assert c.cycle() == expected + for expected in cycle_reverse: + assert c.cycle(False) == expected + forward = True + for expected in cycle_mix: + assert c.cycle(forward) == expected + forward = not forward class TestCommandEdit: