Ver código fonte

Fix completion for argument of an unknown action

Mike Naberezny 11 anos atrás
pai
commit
7f5948ba70
2 arquivos alterados com 56 adições e 34 exclusões
  1. 39 33
      supervisor/supervisorctl.py
  2. 17 1
      supervisor/tests/test_supervisorctl.py

+ 39 - 33
supervisor/supervisorctl.py

@@ -223,7 +223,45 @@ class Controller(cmd.Cmd):
             raise
         return True
 
-    def completionmatches(self, text, onlygroups=False):
+    def complete(self, text, state, line=None):
+        """Completer function that Cmd will register with readline using
+        readline.set_completer().  This function will be called by readline
+        as complete(text, state) where text is a fragment to complete and
+        state is an integer (0..n).  Each call returns a string with a new
+        completion.  When no more are available, None is returned."""
+        if line is None: # line is only set in tests
+            import readline
+            line = readline.get_line_buffer()
+
+        results = []
+        # blank line completes to action list
+        if not line.strip():
+            results = self._complete_actions(text)
+        else:
+            words = line.split()
+            action = words[0]
+            # incomplete action completes to action list
+            if len(words) == 1 and not line.endswith(' '):
+                results = self._complete_actions(text)
+            # actions that accept an action name
+            elif action in ('help'):
+                results = self._complete_actions(text)
+            # actions that accept a process name
+            elif action in ('clear', 'fg', 'pid', 'restart', 'start',
+                            'stop', 'status', 'tail'):
+                results = self._complete_names(text)
+            # actions that accept a group name
+            elif action in ('add', 'remove', 'update'):
+                results = self._complete_names(text, onlygroups=True)
+        if len(results) > state:
+            return results[state]
+
+    def _complete_actions(self, text):
+        """Helper method used by complete() to generate completion
+        lists of action names"""
+        return [v+' ' for v in self.vocab if v.startswith(text)]
+
+    def _complete_names(self, text, onlygroups=False):
         """Helper method used by complete() to generate completion
         lists for group and process names."""
         groups=[]
@@ -257,38 +295,6 @@ class Controller(cmd.Cmd):
                 results = [i for i in total if i.startswith(text)]
         return results
 
-    def complete(self, text, state, line=None):
-        """Completer function that Cmd will register with readline using
-        readline.set_completer().  This function will be called by readline
-        as complete(text, state) where text is a fragment to complete and
-        state is an integer (0..n).  Each call returns a string with a new
-        completion.  When no more are available, None is returned."""
-        if line is None: # line is only set in tests
-            import readline
-            line = readline.get_line_buffer()
-
-        results = []
-        # blank line completes to command list
-        if not line.strip():
-            results = [v+' ' for v in self.vocab if v.startswith(text)]
-        # whole command without trailing space completes the space
-        elif line.lstrip() in self.vocab:
-            results = [text+' ']
-        else:
-            cmd = line.split()[0]
-            # "help" or incomplete command completes command list
-            if cmd == 'help' or cmd not in self.vocab:
-                results = [v+' ' for v in self.vocab if v.startswith(text)]
-            # commands that accept a process name
-            elif cmd in ('clear', 'fg', 'pid', 'restart', 'start', 'stop',
-                         'status', 'tail'):
-                results = self.completionmatches(text)
-            # commands that accept a group name
-            elif cmd in ('add', 'remove', 'update'):
-                results = self.completionmatches(text, onlygroups=True)
-        if len(results) > state:
-            return results[state]
-
     def do_help(self, arg):
         if arg.strip() == 'help':
             self.help_help()

+ 17 - 1
supervisor/tests/test_supervisorctl.py

@@ -136,13 +136,21 @@ class ControllerTests(unittest.TestCase):
         result = controller.complete('help', 0, line='help')
         self.assertEqual(result, 'help ')
 
-    def test_complete_action_uncompletable(self):
+    def test_complete_unknown_action_uncompletable(self):
         options = DummyClientOptions()
         controller = self._makeOne(options)
         controller.stdout=StringIO()
         result = controller.complete('bad', 0, line='bad')
         self.assertTrue(result is None)
 
+    def test_complete_unknown_action_arg_uncompletable(self):
+        options = DummyClientOptions()
+        controller = self._makeOne(options)
+        controller.stdout=StringIO()
+        controller.vocab = ['help', 'add']
+        result = controller.complete('', 1, line='bad ')
+        self.assertTrue(result is None)
+
     def test_complete_help_empty(self):
         options = DummyClientOptions()
         controller = self._makeOne(options)
@@ -239,6 +247,14 @@ class ControllerTests(unittest.TestCase):
         result = controller.complete('f', 1, line='add f')
         self.assertTrue(result is None)
 
+    def test_complete_reload_arg_uncompletable(self):
+        options = DummyClientOptions()
+        controller = self._makeOne(options)
+        controller.stdout=StringIO()
+        controller.vocab = ['help', 'reload']
+        result = controller.complete('', 1, line='reload ')
+        self.assertTrue(result is None)
+
     def test_nohelp(self):
         options = DummyClientOptions()
         controller = self._makeOne(options)