Use ._cl_name and ._cl_aliases instead of overwriting .name and .aliases.
authorW. Trevor King <wking@drexel.edu>
Mon, 10 May 2010 19:27:12 +0000 (15:27 -0400)
committerW. Trevor King <wking@drexel.edu>
Mon, 10 May 2010 19:27:12 +0000 (15:27 -0400)
We don't change the keys hardcoded into the Command._run methods, so
we need to keep the original names.  Hmm, I'll have to adjust
Command.help and Argument.help to use the external names...

hooke/ui/commandline.py

index 9d1806e3778b939af3e148da0ee4ccbd17088f28..ddf48c9e31a3c47c2bf2ff02a43c6cdd2cfa0fd2 100644 (file)
@@ -8,7 +8,6 @@ import readline # including readline makes cmd.Cmd.cmdloop() smarter
 import shlex
 
 from ..command import CommandExit, Command, Argument
-from ..compat.odict import odict
 from ..ui import UserInterface, CommandMessage
 
 
@@ -19,19 +18,19 @@ class CommandLineParser (optparse.OptionParser):
     :class:`hooke.command.Command`.
     """
     def __init__(self, command):
-        optparse.OptionParser.__init__(self, prog=command.name)
+        optparse.OptionParser.__init__(self, prog=command._cl_name)
         self.command = command
-        self.command_opts = odict()
-        self.command_args = odict()
+        self.command_opts = []
+        self.command_args = []
         for a in command.arguments:
             if a.name == 'help':
                 continue # 'help' is a default OptionParser option
-            name = a.name.replace('_', '-')
             if a.optional == True:
-                self.add_option('--%s' % name, dest=a.name, default=a.default)
-                self.command_opts[name] = a
+                self.add_option(
+                    '--%s' % a._cl_name, dest=a._cl_name, default=a.default)
+                self.command_opts.append(a)
             else:
-                self.command_args[name] = a
+                self.command_args.append(a)
 
     def exit(self, status=0, msg=None):
         """Override :meth:`optparse.OptionParser.exit` which calls
@@ -64,7 +63,7 @@ class DoCommand (CommandMethod):
         try:
             args = self._parse_args(self.command, args)
         except optparse.OptParseError, e:
-            self.cmd.stdout.write(str(e))
+            self.cmd.stdout.write(str(e).lstrip()+'\n')
             self.cmd.stdout.write('Failure\n')
             return
         self.cmd.inqueue.put(CommandMessage(self.command, args))
@@ -79,11 +78,15 @@ class DoCommand (CommandMethod):
     def _parse_args(self, command, args):
         argv = shlex.split(args, comments=True, posix=True)
         options,args = self.parser.parse_args(argv)
+        if len(args) != len(self.parser.command_args):
+            raise optparse.OptParseError('%d arguments given, but %s takes %d'
+                                         % (len(args), command._cl_name,
+                                            len(self.parser.command_args)))
         params = {}
-        for name,argument in self.parser.command_opts.items():
-            params[name] = getattr(options, name)
-        for name,argument in self.parser.command_args.items():
-            params[name] = value
+        for argument in self.parser.command_opts:
+            params[argument.name] = getattr(options, argument._cl_name)
+        for i,argument in enumerate(self.parser.command_args):
+            params[argument.name] = args[i]
         return params
 
 class HelpCommand (CommandMethod):
@@ -106,8 +109,8 @@ class HelpCommand (CommandMethod):
             options_string = ''
         else:
             options_string = '[options]'
-        arg_string = ' '.join([name for name,arg
-                               in self.parser.command_args.items()])
+        arg_string = ' '.join(
+            [arg._cl_name for arg in self.parser.command_args])
         return ' '.join([x for x in [self.command.name,
                                      options_string,
                                      arg_string]
@@ -134,10 +137,8 @@ class HookeCmd (cmd.Cmd):
 
     def _add_command_methods(self):
         for command in self.commands:
-            command.name = self._safe_name(command.name)
-            command.aliases = [self._safe_name(n) for n in command.aliases]
-            for name in [command.name] + command.aliases:
-                name = self._safe_name(name)
+            self._setup_command(command)
+            for name in [command._cl_name] + command._cl_aliases:
                 setattr(self.__class__, 'do_%s' % name,
                         DoCommand(self, command))
                 setattr(self.__class__, 'help_%s' % name,
@@ -148,6 +149,7 @@ class HookeCmd (cmd.Cmd):
         exit_command = Command(
             name='exit', aliases=['quit', 'EOF'],
             help='Exit Hooke cleanly.')
+        self._setup_command(exit_command)
         exit_command.arguments = [] # remove help argument
         for name in [exit_command.name] + exit_command.aliases:
             setattr(self.__class__, 'do_%s' % name,
@@ -168,9 +170,21 @@ undocumented commands.
             Argument(name='command', type='string', optional=True,
                      help='The name of the command you want help with.')
             ]
+        self._setup_command(help_command)
         setattr(self.__class__, 'help_help',
                 HelpCommand(self, help_command))
 
+    def _setup_command(self, command):
+        """Attach some UI specific data to `command`.  After this
+        point, the :attr:`commands` are read only.
+        """
+        command._cl_name = self._safe_name(command.name)
+        command._cl_aliases = [self._safe_name(n) for n in command.aliases]
+        for argument in command.arguments:
+            argument._cl_name = self._safe_name(argument.name)
+            argument._cl_aliases = [self._safe_name(n)
+                                    for n in argument.aliases]
+
 
 class CommandLine (UserInterface):
     """Command line interface.  Simple and powerful.