1 """Defines :class:`CommandLine` for driving Hooke from the command
8 from ..command import CommandExit, Command, Argument
9 from ..ui import UserInterface, CommandMessage
11 # Define a few helper classes. The .__call__ methods of these
12 # functions will provide the do_*, help_*, and complete_* methods of
15 class CommandMethod (object):
16 def __init__(self, cmd, command):
18 self.command = command
20 def __call__(self, *args, **kwargs):
21 raise NotImplementedError
23 class DoCommand (CommandMethod):
24 def __call__(self, args):
25 args = self._parse_args(self.command, args)
26 self.cmd.inqueue.put(CommandMessage(self.command, args))
28 msg = self.cmd.outqueue.get()
29 if isinstance(msg, CommandExit):
31 self.cmd.stdout.write(str(msg))
33 def _parse_args(self, command, args):
34 print 'ARGS:', args, type(args)
37 class HelpCommand (CommandMethod):
39 blocks = [self.command.help(),
41 'Usage: ' + self._usage_string(),
43 self.cmd.stdout.write('\n'.join(blocks))
46 return self.command.help()
48 def _usage_string(self):
49 return ' '.join([self.command.name, '[args]'])
51 class CompleteCommand (CommandMethod):
52 def __call__(self, text, line, begidx, endidx):
56 # Now onto the main attraction.
58 class HookeCmd (cmd.Cmd):
59 def __init__(self, hooke, inqueue, outqueue):
60 cmd.Cmd.__init__(self)
62 self.prompt = 'hooke> '
63 self._add_command_methods()
64 self.inqueue = inqueue
65 self.outqueue = outqueue
67 def _safe_name(self, name):
68 return name.lower().replace(' ', '_')
70 def _add_command_methods(self):
71 for command in self.hooke.commands:
72 command.name = self._safe_name(command.name)
73 command.aliases = [self._safe_name(n) for n in command.aliases]
74 for name in [command.name] + command.aliases:
75 name = self._safe_name(name)
76 setattr(self.__class__, 'do_%s' % name,
77 DoCommand(self, command))
78 setattr(self.__class__, 'help_%s' % name,
79 HelpCommand(self, command))
80 setattr(self.__class__, 'complete_%s' % name,
81 CompleteCommand(self, command))
83 exit_command = Command(
84 name='exit', aliases=['quit', 'EOF'],
85 help='Exit Hooke cleanly.')
86 exit_command.arguments = [] # remove help argument
87 for name in [exit_command.name] + exit_command.aliases:
88 setattr(self.__class__, 'do_%s' % name,
89 lambda self, args : True)
90 # the True return stops .cmdloop execution
91 setattr(self.__class__, 'help_%s' % name,
92 HelpCommand(self, exit_command))
94 help_command = Command(
97 Called with an argument, prints that command's documentation.
99 With no argument, lists all available help topics as well as any
100 undocumented commands.
102 help_command.arguments = [ # overwrite help argument
103 Argument(name='command', type='string', optional=True,
104 help='The name of the command you want help with.')
106 setattr(self.__class__, 'help_help',
107 HelpCommand(self, help_command))
110 class CommandLine (UserInterface):
111 """Command line interface. Simple and powerful.
114 super(CommandLine, self).__init__(name='command line')
116 def run(self, hooke, ui_to_command_queue, command_to_ui_queue):
117 cmd = HookeCmd(hooke,
118 inqueue=ui_to_command_queue,
119 outqueue=command_to_ui_queue)
120 cmd.cmdloop(self._splash_text())