From: W. Trevor King Date: Mon, 10 May 2010 19:47:08 +0000 (-0400) Subject: Better solution to internal/external names via `name_fn`. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=b9108c2602cbc3229d651e44886cce3e86bebd19;p=hooke.git Better solution to internal/external names via `name_fn`. --- diff --git a/hooke/command.py b/hooke/command.py index bc18ffd..b6d6b35 100644 --- a/hooke/command.py +++ b/hooke/command.py @@ -113,16 +113,23 @@ class Command (object): argument.validate(value) return params - def help(self, *args): - name_part = 'Command: %s' % self.name + def help(self, name_fn=lambda name:name): + """Return a help message describing the `Command`. + + `name_fn(internal_name) -> external_name` gives calling + :class:`hooke.ui.UserInterface`\s a means of changing the + display names if it wants (e.g. to remove spaces from command + line tokens). + """ + name_part = 'Command: %s' % name_fn(self.name) if len(self.aliases) > 0: - name_part += ' (%s)' % ', '.join(self.aliases) + name_part += ' (%s)' % ', '.join([name_fn(n) for n in aliases]) parts = [name_part] if len(self.arguments) > 0: argument_part = ['Arguments:', ''] for a in self.arguments: argument_part.append(textwrap.fill( - a.help(), + a.help(name_fn), initial_indent="", subsequent_indent=" ")) argument_part = '\n'.join(argument_part) @@ -159,8 +166,15 @@ class Argument (object): def __repr__(self): return self.__str__() - def help(self): - parts = ['%s ' % self.name] + def help(self, name_fn=lambda name:name): + """Return a help message describing the `Argument`. + + `name_fn(internal_name) -> external_name` gives calling + :class:`hooke.ui.UserInterface`\s a means of changing the + display names if it wants (e.g. to remove spaces from command + line tokens). + """ + parts = ['%s ' % name_fn(self.name)] if self.metavar != None: parts.append('%s ' % self.metavar) parts.extend(['(%s) ' % self.type, self._help]) diff --git a/hooke/ui/commandline.py b/hooke/ui/commandline.py index ddf48c9..027a787 100644 --- a/hooke/ui/commandline.py +++ b/hooke/ui/commandline.py @@ -17,8 +17,8 @@ class CommandLineParser (optparse.OptionParser): """Implement a command line syntax for a :class:`hooke.command.Command`. """ - def __init__(self, command): - optparse.OptionParser.__init__(self, prog=command._cl_name) + def __init__(self, command, name_fn): + optparse.OptionParser.__init__(self, prog=name_fn(command.name)) self.command = command self.command_opts = [] self.command_args = [] @@ -26,8 +26,9 @@ class CommandLineParser (optparse.OptionParser): if a.name == 'help': continue # 'help' is a default OptionParser option if a.optional == True: + name = name_fn(a.name) self.add_option( - '--%s' % a._cl_name, dest=a._cl_name, default=a.default) + '--%s' % name, dest=name, default=a.default) self.command_opts.append(a) else: self.command_args.append(a) @@ -47,9 +48,10 @@ class CommandMethod (object): provide the `do_*`, `help_*`, and `complete_*` methods of :class:`HookeCmd`. """ - def __init__(self, cmd, command): + def __init__(self, cmd, command, name_fn): self.cmd = cmd self.command = command + self.name_fn = name_fn def __call__(self, *args, **kwargs): raise NotImplementedError @@ -57,11 +59,11 @@ class CommandMethod (object): class DoCommand (CommandMethod): def __init__(self, *args, **kwargs): super(DoCommand, self).__init__(*args, **kwargs) - self.parser = CommandLineParser(self.command) + self.parser = CommandLineParser(self.command, self.name_fn) def __call__(self, args): try: - args = self._parse_args(self.command, args) + args = self._parse_args(args) except optparse.OptParseError, e: self.cmd.stdout.write(str(e).lstrip()+'\n') self.cmd.stdout.write('Failure\n') @@ -75,16 +77,18 @@ class DoCommand (CommandMethod): break self.cmd.stdout.write(str(msg).rstrip()+'\n') - def _parse_args(self, command, args): + def _parse_args(self, 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(args), + self.name_fn(self.command.name), len(self.parser.command_args))) params = {} for argument in self.parser.command_opts: - params[argument.name] = getattr(options, argument._cl_name) + params[argument.name] = getattr(options, + self.name_fn(argument.name)) for i,argument in enumerate(self.parser.command_args): params[argument.name] = args[i] return params @@ -92,17 +96,17 @@ class DoCommand (CommandMethod): class HelpCommand (CommandMethod): def __init__(self, *args, **kwargs): super(HelpCommand, self).__init__(*args, **kwargs) - self.parser = CommandLineParser(self.command) + self.parser = CommandLineParser(self.command, self.name_fn) def __call__(self): - blocks = [self.command.help(), + blocks = [self.command.help(name_fn=self.name_fn), '------', 'Usage: ' + self._usage_string(), ''] self.cmd.stdout.write('\n'.join(blocks)) def _message(self): - return self.command.help() + return self.command.help(name_fn=self.name_fn) def _usage_string(self): if len(self.parser.command_opts) == 0: @@ -110,8 +114,8 @@ class HelpCommand (CommandMethod): else: options_string = '[options]' arg_string = ' '.join( - [arg._cl_name for arg in self.parser.command_args]) - return ' '.join([x for x in [self.command.name, + [self.name_fn(arg.name) for arg in self.parser.command_args]) + return ' '.join([x for x in [self.parser.prog, options_string, arg_string] if x != '']) @@ -132,31 +136,30 @@ class HookeCmd (cmd.Cmd): self.inqueue = inqueue self.outqueue = outqueue - def _safe_name(self, name): + def _name_fn(self, name): return name.lower().replace(' ', '_') def _add_command_methods(self): for command in self.commands: - self._setup_command(command) - for name in [command._cl_name] + command._cl_aliases: + for name in [command.name] + command.aliases: + name = self._name_fn(name) setattr(self.__class__, 'do_%s' % name, - DoCommand(self, command)) + DoCommand(self, command, self._name_fn)) setattr(self.__class__, 'help_%s' % name, - HelpCommand(self, command)) + HelpCommand(self, command, self._name_fn)) setattr(self.__class__, 'complete_%s' % name, - CompleteCommand(self, command)) + CompleteCommand(self, command, self._name_fn)) 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, lambda self, args : True) # the True return stops .cmdloop execution setattr(self.__class__, 'help_%s' % name, - HelpCommand(self, exit_command)) + HelpCommand(self, exit_command, self._name_fn)) help_command = Command( name='help', @@ -170,20 +173,8 @@ 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] + HelpCommand(self, help_command, self._name_fn)) class CommandLine (UserInterface):