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

Add a completion class to handle completion

parent 905a492c
No related branches found
No related tags found
No related merge requests found
......@@ -31,11 +31,11 @@ settings = {
try:
# Early debug loading
if "CC_DEBUG" in os.environ:
settings["debug"] = "True"
cccli.debug = True
settings["debug"] = "True"
# load a printer
printer = Printer(False)
printer = Printer()
# Parse line argument
oparser = optparse.OptionParser(usage="usage: %prog [options] [commands]",
......@@ -127,12 +127,12 @@ try:
raise BadArgument("Invalid %s number"%i)
# check login
if "login" not in settings:
printer.setinteractive()
printer.set_interactive()
settings["login"] = printer.ask("Login: ")
# check password
if "pass" not in settings:
printer.setinteractive()
printer.set_interactive()
settings["pass"] = printer.getpass("Password: ")
# print settings
......@@ -150,7 +150,8 @@ except cliError as e:
printer.error("cliError: %s"%str(e))
except Exception as e:
if cccli.debug:
printer.fatal("%s: %s"%(type(e), str(e)), quit=False)
if "printer" in locals():
printer.fatal("%s: %s"%(type(e), str(e)), quit=False)
raise
printer.warn("This is a not expected error, please report it!")
printer.fatal(str(e))
......@@ -33,24 +33,11 @@ class Cli(object):
# line stuff
if line:
sys.stdin = StringIO.StringIO(line)
# start printer
self.printer = Printer()
# set interactive mode
self.interactive = sys.stderr.isatty() and sys.stdin.isatty()
# start printer and load history
self.printer = Printer(self.interactive,
historyfile=self.settings.get("history", ""),
historysize=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()
# auth
self._auth()
# set prompt
if self.interactive:
if sys.stderr.isatty() and sys.stdin.isatty():
self.printer.debug("Interactive mode")
self.prompt = "%s%s%s%s>%s%s%s "%(color["["],
color["light"],
color["]"],
......@@ -58,6 +45,21 @@ class Cli(object):
color["["],
color["reset"],
color["]"])
self.printer.set_interactive()
# load history
self.printer.history.load(self.settings.get("history", ""))
self.printer.history.maxsize(self.settings.get("hsize", None))
self.printer.debug("Loaded history: %s"%len(self.printer.history))
# enable completion
self.printer.completion.set_completer(self._completer)
# set prompt
# load alias
self.alias.load(self.settings.get("alias", ""))
self.printer.debug("Alias: %s"%self.alias)
# connecting
self._connect()
# auth
self._auth()
# parsing
self._parse()
# save history
......@@ -114,8 +116,7 @@ class Cli(object):
break
except SystemExit:
break
if self.interactive:
self.printer.out("tcho!")
self.printer.interactive("tcho!")
def _exec_command(self, argv):
'''Execute command'''
......@@ -154,6 +155,18 @@ class Cli(object):
self.printer.error("%s: %s"%(type(e), str(e)))
self.printer.warn("This is a not expected error, please report it!")
def _completer(self, texte, state):
'''Return the list of completion'''
comp = self.printer.completion
stripped = comp.get_buf()[:comp.get_begin() + 1].lstrip()
if state == 0 and texte == "" and stripped != "":
return None
cl = [ c for c in Command.list() if c.startswith(texte) ]
if state < len(cl):
return cl[state]
return None
class CliHandler(RpcHandler):
'''Handle RPC incoming request'''
......
......@@ -48,19 +48,13 @@ color = {
class Printer(object):
'''Print relative class'''
def __init__(self, interactive=False, historyfile=None, historysize=None):
def __init__(self):
self.readline = None
self.history = History()
self.historyfile = historyfile
self.historysize = historysize
if interactive:
self.setinteractive()
def isinteractive(self):
'''Return if printer is in interactive mode'''
return self.readline is not None
self.completion = Completion()
def setinteractive(self):
def set_interactive(self):
'''Set interactive mode'''
if self.readline is not None:
return
try:
......@@ -70,12 +64,8 @@ class Printer(object):
self.readline = readline
# enable history
self.history.readline = readline
# load history
self.history.read(self.historyfile)
self.history.maxsize(self.historysize)
# start prompt completer
self.readline.set_completer(self.completer)
self.readline.parse_and_bind("tab: complete")
# enable completion
self.completion.readline = readline
def out(self, message="", fd=sys.stdout, nl=os.linesep, flush=True):
'''Print a message in fd ended by nl'''
......@@ -107,6 +97,11 @@ class Printer(object):
if cccli.debug:
self.out(message, fd, nl)
def interactive(self, message, fd=sys.stderr, nl=os.linesep):
'''Print only in interactive mode'''
if self.readline is not None:
self.out(message, fd, nl)
def getline(self, prompt, history=True):
'''Read a line from stdin'''
try:
......@@ -157,15 +152,6 @@ class Printer(object):
rows, cols, px_x, px_y = struct.unpack("HHHH", resp)
return rows, cols
def completer(self, texte, state):
r = self.readline
if state == 0 and texte == "" and r.get_line_buffer()[:r.get_begidx() + 1].lstrip() != "":
return None
cl = [ c for c in Command.list() if c.startswith(texte) ]
if state < len(cl):
return cl[state]
return None
class History(object):
'''History class'''
......@@ -176,12 +162,12 @@ class History(object):
return self.readline is not 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)
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):
if self.readline is None:
......@@ -229,6 +215,33 @@ class History(object):
'''Clear history'''
self.readline.clear_history()
# Need to be at end of file to fix cross loading of printer by command and command by printer
# So i maybe should change the design of import
from cccli.command import Command
class Completion(object):
'''Handle completion functions'''
def __init__(self):
self.readline = 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 get_buf(self):
'''Return current readline buffer'''
return self.readline.get_line_buffer()
def get_begin(self):
'''Get the beginning index of the readline tab-completion scope'''
return self.readline.get_begidx()
def get_end(self):
'''Get the ending index of the readline tab-completion scope'''
return self.readline.get_begidx()
def set_completer(self, func):
'''Set completer function'''
self.readline.set_completer(func)
self.readline.parse_and_bind("tab: complete")
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