Skip to content
Snippets Groups Projects
Commit 6303e22f authored by Seblu's avatar Seblu
Browse files

add history system

parent 40535698
No related branches found
No related tags found
No related merge requests found
......@@ -19,13 +19,15 @@ import getpass
settings = {
"port": "1984",
"timeout": "5"
"timeout": "5",
"hsize": "100"
}
try:
# parse rc file
if "HOME" in os.environ:
settings["alias"] = "%s/.cc-cli.conf"%os.environ["HOME"]
settings["history"] = "%s/.cc-cli.history"%os.environ["HOME"]
if os.access("%s/.cc-cli.conf"%os.environ["HOME"], os.R_OK):
fparser = ConfigParser.SafeConfigParser()
fparser.read("%s/.cc-cli.conf"%os.environ["HOME"])
......@@ -72,13 +74,20 @@ try:
dest="timeout",
default="10",
help="connection timeout")
oparser.add_option("--history-file",
action="store",
dest="history",
default="",
help="History file")
oparser.add_option("--history-size",
action="store",
dest="hsize",
default="",
help="History max entry count")
(options, args) = oparser.parse_args()
# options handling
for i in ("debug", "login", "server", "port", "timeout"):
for i in ("debug", "login", "server", "port", "timeout", "history", "hsize"):
if hasattr(options, i):
o = getattr(options, i)
if o:
......@@ -96,18 +105,12 @@ try:
if "server" not in settings:
raise BadArgument("No server address")
# check port value
try:
settings["port"] = int(settings["port"])
except:
raise BadArgument("Invalid port number")
# check timeout value
try:
settings["timeout"] = int(settings["timeout"])
except:
raise BadArgument("Invalid timeout")
# check int values
for i in "port", "timeout", "hsize":
try:
settings[i] = int(settings[i])
except:
raise BadArgument("Invalid %s number"%i)
# check login
if "login" not in settings:
settings["login"] = raw_input("Login: ")
......@@ -117,8 +120,8 @@ try:
settings["pass"] = getpass.getpass("Password: ")
# start cli
cli = cli.Cli(settings, args)
cli.start()
cli = cli.Cli(settings)
cli.start(" ".join(args))
except BadArgument, e:
printer.error("Bad Argument: %s"%str(e))
oparser.print_help()
......
......@@ -12,67 +12,74 @@ import ssl
import threading
import subprocess
import ConfigParser
import cccli
from cccli import printer, command
from cccli.clierror import *
import re
from cccli import printer, command, version, debug
from cccli.command import Command
from cccli.clierror import *
from sjrpc.core.exceptions import *
from sjrpc.client import SimpleRpcClient
from sjrpc.utils import RpcHandler, ConnectionProxy, pure
import sjrpc.core.exceptions
import re
import readline
class Cli(object):
def __init__(self, settings, args):
self._settings = settings
self.alias = Alias(settings.get("alias", ""))
self.alias.load()
self.interactive = sys.stderr.isatty() and sys.stdin.isatty()
self._prompt = "> "
self._commands = args
def __init__(self, settings):
self.isinteractive = sys.stderr.isatty() and sys.stdin.isatty()
self.settings = settings
self.prompt = "> "
self.rpc = None
self.alias = Alias()
self.history = History()
def start(self):
def start(self, line=""):
'''Start a CLI'''
# not interactive is command line
if line:
self.isinteractive = False
# start readline and load history
if self.isinteractive:
import readline
self.history.readline = readline
self.history.load(self.settings.get("history", ""))
self.history.maxsize(self.settings.get("hsize", None))
# load alias
self.alias.load(self.settings.get("alias", ""))
printer.debug("Alias: %s"%self.alias)
# Connecting
self._connect()
# authentifications
self._auth()
# run parsing args
if len(self._commands) > 0:
self._parse_line(" ".join(self._commands))
elif self.interactive:
self._interactive_parser()
if line:
self._parse_line(line)
else:
self._parser()
self._shell()
self.history.save(self.settings.get("history", ""))
def _connect(self):
printer.debug("Connecting...")
rpcc = SimpleRpcClient.from_addr(self._settings["server"],
self._settings["port"],
rpcc = SimpleRpcClient.from_addr(self.settings["server"],
self.settings["port"],
enable_ssl=True,
default_handler=CliHandler(),
on_disconnect="quit",
timeout=self._settings["timeout"]
timeout=self.settings["timeout"]
)
rpcc.start(daemonize=True)
self.rpc = ConnectionProxy(rpcc)
def _auth(self):
printer.debug("Authenticating...")
if self.rpc.authentify(self._settings["login"], self._settings["pass"]):
if self.rpc.authentify(self.settings["login"], self.settings["pass"]):
printer.debug("Authenticated.")
else:
printer.fatal("Autentification failed!")
def _interactive_parser(self):
'''Interactive shell parser'''
# init readline
def _shell(self):
'''Shell parser'''
while True:
try:
line = raw_input(self._prompt)
line = raw_input(self.prompt)
self._parse_line(line)
except EOFError:
printer.out("")
......@@ -81,19 +88,8 @@ class Cli(object):
break
except KeyboardInterrupt:
printer.out("")
try:
pass
#readline.write_history_file(self._settings["histfile"])
except IOError:
pass
printer.out("Tcho!")
def _parser(self):
'''Non interactive parser'''
while True:
line = raw_input(self._prompt)
self._parse_line(line)
def _parse_line(self, line):
'''Parse a line (more than one command)'''
for cmd in line.split(";"):
......@@ -130,11 +126,11 @@ class Cli(object):
printer.error("command: %s."%str(e))
else:
printer.error("No command: %s."%argv[0])
except sjrpc.core.exceptions.RpcError, e:
if cccli.debug: raise
except RpcError, e:
if debug: raise
printer.error("sjRPC: %s"%str(e))
except Exception, e:
if cccli.debug: raise
if debug: raise
printer.error("%s: %s."%(argv[0], str(e)))
def _lex_argv(self, string):
......@@ -143,28 +139,70 @@ class Cli(object):
class Alias(dict):
''' Alias wrapper'''
def __init__(self, filename):
self._filename = filename
def load(self):
def load(self, filename):
'''load alias from file'''
if os.access(self._filename, os.R_OK):
if os.access(filename, os.R_OK):
fparser = ConfigParser.SafeConfigParser()
fparser.read(self._filename)
fparser.read(filename)
if fparser.has_section("alias"):
self.clear()
self.update(fparser.items("alias"))
def save(self):
def save(self, filename):
'''save alias on file'''
if os.access(self._filename, os.R_OK or os.W_OK):
if os.access(filename, os.R_OK or os.W_OK):
fparser = ConfigParser.SafeConfigParser()
fparser.read(self._filename)
fparser.read(filename)
fparser.remove_section("alias")
fparser.add_section("alias")
for n,v in self.items():
fparser.set("alias", n, v)
fparser.write(open(self._filename, "w"))
fparser.write(open(filename, "w"))
class History(object):
'''History class'''
def __init__(self, readline=None):
self.readline = readline
def __nonzero__(self):
return not self.readline is None
def __getattribute__(self, name):
r = object.__getattribute__(self, "readline")
if name == "readline":
return r
if r is None:
return lambda *a,**k: None
return object.__getattribute__(self, name)
def __iter__(self):
for i in range(1, len(self)):
yield self.readline.get_history_item(i)
def __len__(self):
return self.readline.get_current_history_length()
def load(self, path):
'''Load history from a file'''
try:
self.readline.read_history_file(path)
except IOError:
pass
def save(self, path):
'''Save history into path'''
try:
self.readline.write_history_file(path)
except IOError:
pass
def maxsize(self, size=None):
'''Set or return max history size'''
if size is not None:
self.readline.set_history_length(size)
return self.readline.get_history_length()
class CliHandler(RpcHandler):
'''Handle RPC incoming request'''
......@@ -172,9 +210,8 @@ class CliHandler(RpcHandler):
@pure
def get_tags(self, tags=()):
if "version" in tags:
return { "version": cccli.version }
return { "version": version }
@pure
def quit(self, rpc=None):
printer.fatal("Disconnected from server!")
......@@ -126,7 +126,7 @@ class Command(object):
printer.out("%s=%s"%(argv[1], self.cli.alias[argv[1]]))
elif len(argv) == 3:
self.cli.alias[argv[1]] = argv[2]
self.cli.alias.save()
self.cli.alias.save(self.cli.settings.get("alias", ""))
else:
raise BadArgument()
cmd_alias.usage = "alias [name] [value]"
......@@ -139,7 +139,7 @@ class Command(object):
if argv[1] not in self.cli.alias:
raise BadArgument("%s: No such alias"%argv[1])
del self.cli.alias[argv[1]]
self.cli.alias.save()
self.cli.alias.save(self.cli.settings.get("alias", ""))
cmd_unalias.usage = "unalias [name]"
cmd_unalias.desc = "Remove an aliases"
......@@ -150,6 +150,15 @@ class Command(object):
cmd_rcmd.usage = "rcmd"
cmd_rcmd.desc = "Print remote command list"
def cmd_history(self, argv):
'''Show history of commands'''
if not self.cli.history:
raise Exception("History is disabled")
for l in self.cli.history:
printer.out(l)
cmd_history.usage = "history"
cmd_history.desc = "Show commands history"
def cmd_list(self, argv):
'''List objects'''
if len(argv) == 1:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment