From c0911e484ad7df3e1d3abe5840af81783e2b329b Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 20 Aug 2010 06:43:17 -0400 Subject: [PATCH] Command line UI now handles EOF during request/response interactions. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit For example $ echo | ./bin/hk.py -c 'new_playlist' -c 'glob_curves_to_playlist test/data/*' --persist used to loop forever thinking it was getting invalid responses to Exit? [y/N] Also, change str() to unicode() in DoCommand.__call__ to handle non-ascii messages (e.g. µ (micro) from SI units). --- hooke/interaction.py | 8 ++++++++ hooke/plugin/engine.py | 2 +- hooke/ui/commandline.py | 31 ++++++++++++++++++++++++++----- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/hooke/interaction.py b/hooke/interaction.py index f5c39bf..168c905 100644 --- a/hooke/interaction.py +++ b/hooke/interaction.py @@ -86,6 +86,14 @@ class Response (Interaction): super(Response, self).__init__(type) self.value = value +class EOFResponse (Response): + """End of user input. + + After this point, no more user interaction is possible. + """ + def __init__(self): + super(EOFResponse, self).__init__('EOF', None) + class BooleanRequest (Request): def __init__(self, msg, default=None): super(BooleanRequest, self).__init__( diff --git a/hooke/plugin/engine.py b/hooke/plugin/engine.py index 6564549..e4176d1 100644 --- a/hooke/plugin/engine.py +++ b/hooke/plugin/engine.py @@ -22,7 +22,7 @@ associated :class:`hooke.command.Command`\s for basic interaction. """ -from ..command import CommandExit, Exit, Command, Argument +from ..command import Exit, Command, Argument from ..interaction import BooleanRequest from . import Builtin diff --git a/hooke/ui/commandline.py b/hooke/ui/commandline.py index 01a66f8..efed634 100644 --- a/hooke/ui/commandline.py +++ b/hooke/ui/commandline.py @@ -30,10 +30,11 @@ except ImportError, e: import logging logging.warn('could not import readline, bash-like line editing disabled.') import shlex +import sys from ..command import CommandExit, Exit, Command, Argument, StoreValue -from ..engine import CommandMessage -from ..interaction import Request, ReloadUserInterfaceConfig +from ..engine import CommandMessage, CloseEngine +from ..interaction import EOFResponse, Request, ReloadUserInterfaceConfig from ..ui import UserInterface from ..util.convert import from_string from ..util.encoding import get_input_encoding, get_output_encoding @@ -41,6 +42,13 @@ from ..util.encoding import get_input_encoding, get_output_encoding # Define a few helper classes. +class EOF (EOFError): + """Raise upon reaching the end of the input file. + + After this point, no more user interaction is possible. + """ + pass + class Default (object): """Marker for options not given on the command line. """ @@ -154,9 +162,12 @@ class DoCommand (CommandMethod): self.cmd.ui.reload_config(msg.config) continue elif isinstance(msg, Request): - self._handle_request(msg) + try: + self._handle_request(msg) + except EOF: + return True continue - self.cmd.stdout.write(str(msg).rstrip()+'\n') + self.cmd.stdout.write(unicode(msg).rstrip()+'\n') def _parse_args(self, args): options,args = self.parser.parse_args(args) @@ -226,7 +237,17 @@ class DoCommand (CommandMethod): self.cmd.stdout.write(''.join([ error.__class__.__name__, ': ', str(error), '\n'])) self.cmd.stdout.write(prompt_string) - value = parser(msg, self.cmd.stdin.readline()) + stdin = sys.stdin + try: + sys.stdin = self.cmd.stdin + raw_response = raw_input() + except EOFError, e: + self.cmd.inqueue.put(EOFResponse()) + self.cmd.inqueue.put(CloseEngine()) + raise EOF + finally: + sys.stdin = stdin + value = parser(msg, raw_response) try: response = msg.response(value) break -- 2.26.2