diff --git a/cliff/commandmanager.py b/cliff/commandmanager.py index ec6918a..ff213e5 100644 --- a/cliff/commandmanager.py +++ b/cliff/commandmanager.py @@ -61,14 +61,10 @@ class CommandManager(object): """Given an argument list, find a command and return the processor and any remaining arguments. """ - search_args = argv[:] - name = '' - while search_args: - if search_args[0].startswith('-'): - name = '%s %s' % (name, search_args[0]) - raise ValueError('Invalid command %r' % name) - next_val = search_args.pop(0) - name = '%s %s' % (name, next_val) if name else next_val + start = self._get_last_possible_command_index(argv) + for i in range(start, 0, -1): + name = ' '.join(argv[:i]) + search_args = argv[i:] if name in self.commands: cmd_ep = self.commands[name] if hasattr(cmd_ep, 'resolve'): @@ -85,3 +81,12 @@ class CommandManager(object): else: raise ValueError('Unknown command %r' % (argv,)) + + def _get_last_possible_command_index(self, argv): + """Returns the index after the last argument + in argv that can be a command word + """ + for i, arg in enumerate(argv): + if arg.startswith('-'): + return i + return len(argv) diff --git a/cliff/tests/test_commandmanager.py b/cliff/tests/test_commandmanager.py index f131712..ffa7d62 100644 --- a/cliff/tests/test_commandmanager.py +++ b/cliff/tests/test_commandmanager.py @@ -70,6 +70,21 @@ def test_add_command(): assert found_cmd is mock_cmd +def test_intersected_commands(): + def foo(arg): + pass + + def foo_bar(): + pass + + mgr = utils.TestCommandManager(utils.TEST_NAMESPACE) + mgr.add_command('foo', foo) + mgr.add_command('foo bar', foo_bar) + + assert mgr.find_command(['foo', 'bar'])[0] is foo_bar + assert mgr.find_command(['foo', 'arg0'])[0] is foo + + def test_load_commands(): testcmd = mock.Mock(name='testcmd') testcmd.name.replace.return_value = 'test'