1 """Defines :class:`CommandLine` for driving Hooke from the command
7 import readline # including readline makes cmd.Cmd.cmdloop() smarter
9 from ..command import CommandExit, Command, Argument
10 from ..ui import UserInterface, CommandMessage
13 # Define a few helper classes. The .__call__ methods of these
14 # functions will provide the do_*, help_*, and complete_* methods of
17 class CommandMethod (object):
18 def __init__(self, cmd, command):
20 self.command = command
22 def __call__(self, *args, **kwargs):
23 raise NotImplementedError
25 def command_parser(command):
26 p = optparse.OptionParser()
28 for a in command.arguments:
30 continue # 'help' is a default OptionParser option
31 if a.optional == True:
33 '--%s' % a.name.replace('_', '-'),
34 dest=a.name, default=a.default)
36 args.append((a.name.replace('_', '-'), a))
39 class DoCommand (CommandMethod):
40 def __init__(self, *args, **kwargs):
41 super(DoCommand, self).__init__(*args, **kwargs)
42 self.parser,self.args = command_parser(self.command)
44 def __call__(self, args):
45 args = self._parse_args(self.command, args)
46 self.cmd.inqueue.put(CommandMessage(self.command, args))
48 msg = self.cmd.outqueue.get()
49 if isinstance(msg, CommandExit):
51 self.cmd.stdout.write(str(msg))
53 def _parse_args(self, command, args):
54 print 'ARGS:', args, type(args)
57 class HelpCommand (CommandMethod):
58 def __init__(self, *args, **kwargs):
59 super(HelpCommand, self).__init__(*args, **kwargs)
60 self.parser,self.args = command_parser(self.command)
63 blocks = [self.command.help(),
65 'Usage: ' + self._usage_string(),
67 self.cmd.stdout.write('\n'.join(blocks))
70 return self.command.help()
72 def _usage_string(self):
73 if len(self.args) == len(self.command.arguments):
76 options_string = '[options]'
77 arg_string = ' '.join([name for name,arg in self.args])
78 return ' '.join([x for x in [self.command.name,
83 class CompleteCommand (CommandMethod):
84 def __call__(self, text, line, begidx, endidx):
88 # Now onto the main attraction.
90 class HookeCmd (cmd.Cmd):
91 def __init__(self, hooke, inqueue, outqueue):
92 cmd.Cmd.__init__(self)
94 self.prompt = 'hooke> '
95 self._add_command_methods()
96 self.inqueue = inqueue
97 self.outqueue = outqueue
99 def _safe_name(self, name):
100 return name.lower().replace(' ', '_')
102 def _add_command_methods(self):
103 for command in self.hooke.commands:
104 command.name = self._safe_name(command.name)
105 command.aliases = [self._safe_name(n) for n in command.aliases]
106 for name in [command.name] + command.aliases:
107 name = self._safe_name(name)
108 setattr(self.__class__, 'do_%s' % name,
109 DoCommand(self, command))
110 setattr(self.__class__, 'help_%s' % name,
111 HelpCommand(self, command))
112 setattr(self.__class__, 'complete_%s' % name,
113 CompleteCommand(self, command))
115 exit_command = Command(
116 name='exit', aliases=['quit', 'EOF'],
117 help='Exit Hooke cleanly.')
118 exit_command.arguments = [] # remove help argument
119 for name in [exit_command.name] + exit_command.aliases:
120 setattr(self.__class__, 'do_%s' % name,
121 lambda self, args : True)
122 # the True return stops .cmdloop execution
123 setattr(self.__class__, 'help_%s' % name,
124 HelpCommand(self, exit_command))
126 help_command = Command(
129 Called with an argument, prints that command's documentation.
131 With no argument, lists all available help topics as well as any
132 undocumented commands.
134 help_command.arguments = [ # overwrite help argument
135 Argument(name='command', type='string', optional=True,
136 help='The name of the command you want help with.')
138 setattr(self.__class__, 'help_help',
139 HelpCommand(self, help_command))
142 class CommandLine (UserInterface):
143 """Command line interface. Simple and powerful.
146 super(CommandLine, self).__init__(name='command line')
148 def run(self, hooke, ui_to_command_queue, command_to_ui_queue):
149 cmd = HookeCmd(hooke,
150 inqueue=ui_to_command_queue,
151 outqueue=command_to_ui_queue)
152 cmd.cmdloop(self._splash_text())