import cmd
import readline
-from ..ui import UserInterface
+from ..command import CommandExit, Command, Argument
+from ..ui import UserInterface, CommandMessage
+# Define a few helper classes. The .__call__ methods of these
+# functions will provide the do_*, help_*, and complete_* methods of
+# HookeCmd.
+
+class CommandMethod (object):
+ def __init__(self, cmd, command):
+ self.cmd = cmd
+ self.command = command
+
+ def __call__(self, *args, **kwargs):
+ raise NotImplementedError
+
+class DoCommand (CommandMethod):
+ def __call__(self, args):
+ args = self._parse_args(self.command, args)
+ self.cmd.inqueue.put(CommandMessage(self.command, args))
+ while True:
+ msg = self.cmd.outqueue.get()
+ if isinstance(msg, CommandExit):
+ break
+ self.cmd.stdout.write(str(msg))
+
+ def _parse_args(self, command, args):
+ print 'ARGS:', args, type(args)
+ return {}
+
+class HelpCommand (CommandMethod):
+ def __call__(self):
+ blocks = [self.command.help(),
+ '------',
+ 'Usage: ' + self._usage_string(),
+ '']
+ self.cmd.stdout.write('\n'.join(blocks))
+
+ def _message(self):
+ return self.command.help()
+
+ def _usage_string(self):
+ return ' '.join([self.command.name, '[args]'])
+
+class CompleteCommand (CommandMethod):
+ def __call__(self, text, line, begidx, endidx):
+ pass
+
+
+# Now onto the main attraction.
class HookeCmd (cmd.Cmd):
- def __init__(self, hooke):
+ def __init__(self, hooke, inqueue, outqueue):
cmd.Cmd.__init__(self)
self.hooke = hooke
self.prompt = 'hooke> '
- self._add_do_methods()
+ self._add_command_methods()
+ self.inqueue = inqueue
+ self.outqueue = outqueue
def _safe_name(self, name):
return name.lower().replace(' ', '_')
- def _add_do_methods(self):
+ def _add_command_methods(self):
for command in self.hooke.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)
- def do_fn(self, args):
- pass
- setattr(self.__class__, 'do_%s' % name, do_fn)
- def help_fn(self):
- pass
- setattr(self.__class__, 'help_%s' % name, help_fn)
- def complete_fn(self, text, line, begidx, endidx):
- pass
- setattr(self.__class__, 'complete_%s' % name, complete_fn)
-
- def _help(self, name, aliases, message, usage_args=None):
- if len(aliases) == 0:
- alias_string = ''
- else:
- alias_string = ' (%s)' % ', '.join(aliases)
- if usage_args == None:
- usage_string = name
- else:
- usage_string = '%s %s' % (name, usage_args)
- self.stdout.write(("""
-%s%s
-
-%s
-------
-Usage: %s
-""" % (name, alias_string, message.strip(), usage_string)).lstrip())
-
- def help_help(self):
- return self._help('help', [], """
+ setattr(self.__class__, 'do_%s' % name,
+ DoCommand(self, command))
+ setattr(self.__class__, 'help_%s' % name,
+ HelpCommand(self, command))
+ setattr(self.__class__, 'complete_%s' % name,
+ CompleteCommand(self, command))
+
+ exit_command = Command(
+ name='exit', aliases=['quit', 'EOF'],
+ help='Exit Hooke cleanly.')
+ exit_command.arguments = [] # remove help argument
+ for name in [exit_command.name] + exit_command.aliases:
+ setattr(self.__class__, 'do_%s' % name,
+ lambda self, args : True)
+ # the True return stops .cmdloop execution
+ setattr(self.__class__, 'help_%s' % name,
+ HelpCommand(self, exit_command))
+
+ help_command = Command(
+ name='help',
+ help="""
Called with an argument, prints that command's documentation.
With no argument, lists all available help topics as well as any
undocumented commands.
-""",
- '[command]')
-
- def do_exit(self, args):
- return True # the True return stops .cmdloop execution
-
- def help_exit(self):
- return self._help('exit', ['quit', 'EOF'], "Exit Hooke cleanly.")
-
- def do_quit(self, args):
- return self.do_exit(args)
-
- def help_quit(self):
- return self.help_exit()
-
- def do_EOF(self, args):
- return self.do_exit(args)
+""".strip())
+ help_command.arguments = [ # overwrite help argument
+ Argument(name='command', type='string', optional=True,
+ help='The name of the command you want help with.')
+ ]
+ setattr(self.__class__, 'help_help',
+ HelpCommand(self, help_command))
- def help_EOF(self):
- return self.help_exit()
class CommandLine (UserInterface):
"""Command line interface. Simple and powerful.
super(CommandLine, self).__init__(name='command line')
def run(self, hooke, ui_to_command_queue, command_to_ui_queue):
- cmd = HookeCmd(hooke)
+ cmd = HookeCmd(hooke,
+ inqueue=ui_to_command_queue,
+ outqueue=command_to_ui_queue)
cmd.cmdloop(self._splash_text())