X-Git-Url: http://git.tremily.us/?p=hooke.git;a=blobdiff_plain;f=hooke%2Fui%2Fcommandline.py;h=c601ddcc27e9f2bb6568274508503142567bbe7c;hp=9b2effe5695623419621f18a8a0f79e6d517b81c;hb=565f9d7b69d2e4a9ea447d7a50f8f835c3e08642;hpb=aa94795b6f66934ecbb1b0d8c5561f8916dfd1bd diff --git a/hooke/ui/commandline.py b/hooke/ui/commandline.py index 9b2effe..c601ddc 100644 --- a/hooke/ui/commandline.py +++ b/hooke/ui/commandline.py @@ -1,7 +1,26 @@ +# Copyright (C) 2010 W. Trevor King +# +# This file is part of Hooke. +# +# Hooke is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Hooke is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with Hooke. If not, see +# . + """Defines :class:`CommandLine` for driving Hooke from the command line. """ +import codecs import cmd import optparse import readline # including readline makes cmd.Cmd.cmdloop() smarter @@ -10,6 +29,7 @@ import shlex from ..command import CommandExit, Exit, Command, Argument, StoreValue from ..interaction import Request, BooleanRequest, ReloadUserInterfaceConfig from ..ui import UserInterface, CommandMessage +from ..util.encoding import get_input_encoding, get_output_encoding # Define a few helper classes. @@ -100,8 +120,7 @@ class DoCommand (CommandMethod): self.cmd.stdout.write(str(msg).rstrip()+'\n') def _parse_args(self, args): - argv = shlex.split(args, comments=True, posix=True) - options,args = self.parser.parse_args(argv) + options,args = self.parser.parse_args(args) self._check_argument_length_bounds(args) params = {} for argument in self.parser.command_opts: @@ -339,6 +358,42 @@ class HookeCmd (cmd.Cmd): setattr(self.__class__, 'complete_%s' % name, CompleteCommand(self, command, self._name_fn)) + def parseline(self, line): + """Override Cmd.parseline to use shlex.split. + + Notes + ----- + This allows us to handle comments cleanly. With the default + Cmd implementation, a pure comment line will call the .default + error message. + + Since we use shlex to strip comments, we return a list of + split arguments rather than the raw argument string. + """ + line = line.strip() + argv = shlex.split(line, comments=True, posix=True) + if len(argv) == 0: + return None, None, '' # return an empty line + elif argv[0] == '?': + argv[0] = 'help' + elif argv[0] == '!': + argv[0] = 'system' + return argv[0], argv[1:], line + + def do_help(self, arg): + """Wrap Cmd.do_help to handle our .parseline argument list. + """ + if len(arg) == 0: + return cmd.Cmd.do_help(self, '') + return cmd.Cmd.do_help(self, arg[0]) + + def empytline(self): + """Override Cmd.emptyline to not do anything. + + Repeating the last non-empty command seems unwise. Explicit + is better than implicit. + """ + pass class CommandLine (UserInterface): """Command line interface. Simple and powerful. @@ -346,16 +401,22 @@ class CommandLine (UserInterface): def __init__(self): super(CommandLine, self).__init__(name='command line') - def run(self, commands, ui_to_command_queue, command_to_ui_queue): + def _cmd(self, commands, ui_to_command_queue, command_to_ui_queue): cmd = HookeCmd(self, commands, inqueue=ui_to_command_queue, outqueue=command_to_ui_queue) - cmd.cmdloop(self._splash_text()) + #cmd.stdin = codecs.getreader(get_input_encoding())(cmd.stdin) + cmd.stdout = codecs.getwriter(get_output_encoding())(cmd.stdout) + return cmd + + def run(self, commands, ui_to_command_queue, command_to_ui_queue): + cmd = self._cmd(commands, ui_to_command_queue, command_to_ui_queue) + cmd.cmdloop(self._splash_text(extra_info={ + 'get-details':'run `license`', + })) def run_lines(self, commands, ui_to_command_queue, command_to_ui_queue, lines): - cmd = HookeCmd(self, commands, - inqueue=ui_to_command_queue, - outqueue=command_to_ui_queue) + cmd = self._cmd(commands, ui_to_command_queue, command_to_ui_queue) for line in lines: cmd.onecmd(line)