From 84647964e4c9b35c8ecd938571ee37cf4b2856c9 Mon Sep 17 00:00:00 2001 From: Seblu Date: Wed, 29 Dec 2010 14:18:57 +0100 Subject: [PATCH] lexer handle quoting read from argline like stdin fix bug on debuging --- bin/cc-cli | 9 +++--- cccli/cli.py | 83 +++++++++++++++++++++++++----------------------- cccli/printer.py | 6 ++-- 3 files changed, 51 insertions(+), 47 deletions(-) diff --git a/bin/cc-cli b/bin/cc-cli index 3fa0116..0482435 100755 --- a/bin/cc-cli +++ b/bin/cc-cli @@ -13,7 +13,7 @@ import pprint import re import warnings -from cccli import version, debug +import cccli from cccli.cli import Cli from cccli.printer import Printer from cccli.exception import * @@ -51,7 +51,7 @@ try: # Parse line argument oparser = optparse.OptionParser(usage="usage: %prog [options] [commands]", - version=version) + version=cccli.version) oparser.add_option("-d", "--debug", action="store_true", dest="debug", @@ -98,7 +98,7 @@ try: # debug stuff if "debug" in settings: - debug = bool(settings["debug"]) + cccli.debug = bool(settings["debug"]) else: warnings.filterwarnings("ignore") printer.debug("Debugging on") @@ -131,9 +131,8 @@ except BadArgument, e: except KeyboardInterrupt: exit(1) except Exception, e: - if debug: + if cccli.debug: printer.fatal(str(e), exitcode=-1) raise printer.warn("This is a not expected error, please report it!") printer.fatal(str(e)) - diff --git a/cccli/cli.py b/cccli/cli.py index aedb884..1384ff6 100644 --- a/cccli/cli.py +++ b/cccli/cli.py @@ -9,6 +9,8 @@ import os, os.path import sys import re import subprocess +import shlex +import StringIO from cccli import version, debug from cccli.command import Command, Alias @@ -21,37 +23,38 @@ from sjrpc.core.exceptions import * class Cli(object): def __init__(self, settings): - self.isinteractive = sys.stderr.isatty() and sys.stdin.isatty() self.settings = settings - self.prompt = "> " + self.prompt = "" self.rpc = None self.printer = None self.alias = Alias() def start(self, line=""): '''Start a CLI''' - # not interactive if command line + # line stuff if line: - self.isinteractive = False + sys.stdin = StringIO.StringIO(line) + # set interactive mode + self.interactive = sys.stderr.isatty() and sys.stdin.isatty() # start printer and load history - self.printer = Printer(self.isinteractive) + self.printer = Printer(self.interactive) self.printer.history.load(self.settings.get("history", "")) self.printer.history.maxsize(self.settings.get("hsize", None)) # load alias self.alias.load(self.settings.get("alias", "")) + # print debug + self.printer.debug("Interactive: %s"%self.interactive) self.printer.debug("Alias: %s"%self.alias) + self.printer.debug("Loaded history: %s"%len(self.printer.history)) # Connecting self._connect() # authentifications self._auth() - # run parsing args - if line: - self._parse_line(line) - else: - self._shell() + # Parsing + self._parse() + # save history self.printer.history.save(self.settings.get("history", "")) - def _connect(self): self.printer.debug("Connecting...") rpcc = SimpleRpcClient.from_addr(self.settings["server"], @@ -65,50 +68,46 @@ class Cli(object): self.rpc = ConnectionProxy(rpcc) def _auth(self): + '''Handle server authentification''' self.printer.debug("Authenticating...") if self.rpc.authentify(self.settings["login"], self.settings["pass"]): self.printer.debug("Authenticated.") else: self.printer.fatal("Autentification failed!") - def _shell(self): - '''Shell parser''' + def _parse(self): + '''Parse a line''' + prompt = "> " if self.interactive else "" while True: try: - line = self.printer.getline(self.prompt) - self._parse_line(line) + argv = shlex.split(self.printer.getline(prompt), comments=True) + # alias subsitution + if argv[0] in self.alias: + argv[0] = self.alias[argv[0]] + except ValueError, e: + self.printer.error("Lexer: %s"%str(e)) + continue except EOFError: - self.printer.out("") break except SystemExit: break except KeyboardInterrupt: self.printer.out("") - self.printer.out("Tcho!") + self._exec_command(argv) + if self.interactive: + self.printer.out("tcho!") - def _parse_line(self, line): - '''Parse a line (more than one command)''' - for cmd in line.split(";"): - if (cmd.strip() == "" or cmd[0] == "#"): - continue - elif (cmd[0] == "!"): - p = subprocess.Popen(cmd[1:], close_fds=True, shell=True) + def _exec_command(self, argv): + '''Execute command''' + try: + if (argv[0] == "!"): + p = subprocess.Popen(argv[1:], close_fds=True, shell=True) p.wait() ret = p.returncode - elif (cmd[0] == "?"): + elif (argv[0] == "?"): Command(["help"], self).call() else: - self._parse_command(cmd) - - def _parse_command(self, cmd): - try: - # lex command - argv = self._lex_argv(cmd) - # alias subs - if argv[0] in self.alias: - argv[0] = self.alias[argv[0]] - # execute command - Command(argv, self).call() + Command(argv, self).call() except BadArgument, e: if str(e): self.printer.error("Bad argument: %s."%str(e)) @@ -129,10 +128,6 @@ class Cli(object): if debug: raise self.printer.error("%s: %s."%(argv[0], str(e))) - def _lex_argv(self, string): - '''Lex command argument''' - return string.split(" ") - class CliHandler(RpcHandler): '''Handle RPC incoming request''' @@ -144,3 +139,11 @@ class CliHandler(RpcHandler): @pure def quit(self, rpc=None): self.printer.fatal("Disconnected from server!") + +class CliLexer(object): + + def __init__(self, fd): + self.fd = fd + + def get_next_token(self): + pass diff --git a/cccli/printer.py b/cccli/printer.py index c25135b..93b95f0 100644 --- a/cccli/printer.py +++ b/cccli/printer.py @@ -9,7 +9,7 @@ import sys import os import getpass -from cccli import debug +import cccli color = { # regular @@ -80,7 +80,7 @@ class Printer(object): nl) def debug(self, message, fd=sys.stderr, nl=os.linesep): - if debug: + if cccli.debug: self.out(message, fd, nl) def getline(self, msg, history=True): @@ -119,6 +119,8 @@ class History(object): yield self.readline.get_history_item(i) def __len__(self): + if self.readline is None: + return 0 return self.readline.get_current_history_length() def load(self, path): -- GitLab