0ptr/nullptr/command_line.py
Richard 74ce884b05 major command staff restructure
Heads had to roll
2024-02-09 15:52:30 +01:00

101 lines
2.4 KiB
Python

import shlex
import inspect
import sys
import importlib
import logging
from nullptr.util import AppError
def func_supports_argcount(f, cnt):
argspec = inspect.getargspec(f)
posargs = 0 if argspec.args is None else len(argspec.args)
if argspec.args[0] == 'self':
posargs = posargs - 1
defargs = 0 if argspec.defaults is None else len(argspec.defaults)
varargs = 0 if argspec.varargs is None else len(argspec.varargs)
minargs = posargs - defargs
maxargs = posargs
if cnt < minargs:
return False
if cnt > maxargs:
return varargs > 0
return True
class CommandLine:
def __init__(self):
self.reloading = False
self.stopping = False
def ask_multichoice(self, choices, prompt):
choice = None
while choice not in choices:
choice = input(prompt).lower()
return choice
def stop(self):
self.stopping = True
def prompt(self):
return '> '
def handle_not_found(self, c, args):
print(f'command not found; {c}')
def handle_error(self, cmd, args, e):
logging.error(e, exc_info=not issubclass(type(e), AppError))
def handle_empty(self):
pass
def after_cmd(self):
pass
def handle_eof(self):
print('EOF')
def do_quit(self):
print('byebye!')
self.stopping = True
def do_reload(self):
self.reloading = True
def handle_cmd(self, c):
if c == '':
return self.handle_empty()
args = shlex.split(c)
cmd = args.pop(0)
str_handler = f'do_{cmd}'
if not hasattr(self, str_handler):
try:
self.handle_not_found(cmd, args)
return
except Exception as e:
self.handle_error(cmd, args, e)
handler = getattr(self, str_handler)
if not func_supports_argcount(handler, len(args)):
expect_args = ', '.join(inspect.getargspec(handler).args[1:])
print('expected args: ' + expect_args)
return
try:
handler(*args)
except Exception as e:
self.handle_error(cmd, args, e)
self.after_cmd()
def run(self):
while not self.stopping and not self.reloading:
p = self.prompt()
try:
c = input(p)
except (EOFError, KeyboardInterrupt):
self.handle_eof()
break
try:
self.handle_cmd(c)
except KeyboardInterrupt:
print("Interrupted")
except (Exception) as e:
logging.error(e, exc_info=True)