From 757ad925b47d24b1d0714671b8f04147a5748480 Mon Sep 17 00:00:00 2001 From: troido Date: Wed, 18 Apr 2018 23:27:34 +0200 Subject: improved input handling renamed InputHandler to CommandHandler. made InputHandler for input code that used to be in gameclient also started my own getstr() replacement. --- asciifarm/client/commandhandler.py | 84 ++++++++++++++++++++++++ asciifarm/client/gameclient.py | 12 +--- asciifarm/client/inputhandler.py | 129 +++++++++++++++---------------------- 3 files changed, 139 insertions(+), 86 deletions(-) create mode 100644 asciifarm/client/commandhandler.py diff --git a/asciifarm/client/commandhandler.py b/asciifarm/client/commandhandler.py new file mode 100644 index 0000000..7eefe5b --- /dev/null +++ b/asciifarm/client/commandhandler.py @@ -0,0 +1,84 @@ + +import shlex + +class InvalidCommandException(Exception): + pass + + +class CommandHandler: + + def __init__(self, client): + self.client = client + + self.commands = { + "send": self.send, + "input": self.input, + "move": self.move, + "say": self.say, + "chat": self.chat, + "log": self.log, + "do": self.do, + "runinput": self.runInput, + "select": self.select, + "inputwithselected": self.actWithSelected, + "eval": self.eval, + "exec": self.exec, + "scrollchat": self.scrollChat + } + + def execute(self, action): + if isinstance(action[0], str): + command = action[0] + if command in self.commands: + self.commands[command](*action[1:]) + else: + raise InvalidCommandException("Invalid command '{}'".format(command)) + else: + raise Exception("Command should be a string") + + + # Commands + + def send(self, data): + self.client.send(data) + + def input(self, action): + self.send(["input", action]) + + def move(self, direction): + self.input(["move", direction]) + + def say(self, text): + self.input(["say", text]) + + def chat(self, text): + self.send(["chat", text]) + + def log(self, text): + self.client.log(text) + + def do(self, actions): + for action in actions: + self.execute(action) + + def runInput(self): + self.client.inputHandler.typing = True + + def select(self, widget, value, relative=False, modular=False): + self.client.display.getWidget(widget).select(value, relative, modular) + + def actWithSelected(self, action, widget): + self.input([action, self.client.display.getWidget(widget).getSelected()]) + + def eval(self, *texts): + text = " ".join(texts) + self.log(eval(text, {"self": self, "client": self.client, "connection": self.client.connection, "display": self.client.display})) + + def exec(self, *texts): + text = " ".join(texts) + exec(text, {"self": self, "client": self.client, "connection": self.client.connection, "display": self.client.display}) + + def scrollChat(self, lines): + self.client.display.scrollBack(lines) + + diff --git a/asciifarm/client/gameclient.py b/asciifarm/client/gameclient.py index ec90cc6..0a9b243 100644 --- a/asciifarm/client/gameclient.py +++ b/asciifarm/client/gameclient.py @@ -15,7 +15,6 @@ from .display.screen import Screen from .display.display import Display from .inputhandler import InputHandler -from .keynames import nameFromKey class Client: @@ -28,8 +27,7 @@ class Client: self.logFile = logFile self.closeMessage = None - self.inputHandler = InputHandler(self, self.display, self.connection) - self.keybindings = keybindings["actions"] + self.inputHandler = InputHandler(self, keybindings["actions"]) self.controlsString = keybindings.get("help", "") @@ -128,12 +126,6 @@ class Client: with(open(self.logFile, 'a')) as f: f.write(text+'\n') - def onInput(self, key): - keyName = nameFromKey(key) - if keyName in self.keybindings: - self.inputHandler.execute(self.keybindings[keyName]) - - def command_loop(self): while self.keepalive: @@ -141,7 +133,7 @@ class Client: if action[0] == "message": self.update(action[1]) elif action[0] == "input": - self.onInput(action[1]) + self.inputHandler.onInput(action[1]) elif action[0] == "error": raise action[1] else: diff --git a/asciifarm/client/inputhandler.py b/asciifarm/client/inputhandler.py index 7fb18ad..1d907e9 100644 --- a/asciifarm/client/inputhandler.py +++ b/asciifarm/client/inputhandler.py @@ -1,96 +1,73 @@ -import shlex - -class InvalidCommandException(Exception): - pass - +from commandhandler import CommandHandler +from .keynames import nameFromKey +import curses +import curses.ascii class InputHandler: - def __init__(self, client, display, connection): + def __init__(self, client, keybindings): self.client = client - self.display = display - self.connection = connection + self.keybindings = keybindings + self.commandHandler = CommandHandler(self.client) - self.commands = { - "send": self.send, - "input": self.input, - "move": self.move, - "say": self.say, - "chat": self.chat, - "log": self.log, - "do": self.do, - "runinput": self.runInput, - "select": self.select, - "inputwithselected": self.actWithSelected, - "eval": self.eval, - "exec": self.exec, - "scrollchat": self.scrollChat - } - - def execute(self, action): - if isinstance(action[0], str): - command = action[0] - if command in self.commands: - self.commands[command](*action[1:]) - else: - raise InvalidCommandException("Invalid command '{}'".format(command)) - else: - raise Exception("Command should be a string") - - - - def send(self, data): - self.client.send(data) - - def input(self, action): - self.send(["input", action]) - - def move(self, direction): - self.input(["move", direction]) + self.typing = False + self.string = "" + self.cursor = 0 - def say(self, text): - self.input(["say", text]) - def chat(self, text): - self.send(["chat", text]) - - def log(self, text): - self.client.log(text) + def onInput(self, key): + if not self.typing: + keyName = nameFromKey(key) + if keyName in self.keybindings: + self.commandHandler.execute(self.keybindings[keyName]) + else: + self.addKey(key) - def do(self, actions): - for action in actions: - self.execute(action) - def runInput(self): - message = self.display.getString() + def processString(self, message): if message: if message[0] == '/': if message[1] == '/': - self.chat(message[1:]) + self.commandHandler.chat(message[1:]) else: try: - self.execute(shlex.split(message[1:])) + self.commandHandler.execute(shlex.split(message[1:])) except InvalidCommandException as e: - self.log(", ".join(e.args)) + self.client.log(", ".join(e.args)) else: - self.chat(message) - - def select(self, widget, value, relative=False, modular=False): - self.display.getWidget(widget).select(value, relative, modular) - - def actWithSelected(self, action, widget): - self.input([action, self.display.getWidget(widget).getSelected()]) - - def eval(self, *texts): - text = " ".join(texts) - self.log(eval(text, {"self": self, "client": self.client, "connection": self.connection, "display": self.display})) - - def exec(self, *texts): - text = " ".join(texts) - exec(text, {"self": self, "client": self.client, "connection": self.connection, "display": self.display}) + self.commandHandler.chat(message) + + + def addKey(self, key): + if curses.ascii.isprint(key): + self.string = self.string[:self.cursor] + chr(key) + self.string[self.cursor:] + self.cursor += 1 + elif key == curses.KEY_BACKSPACE or key == curses.ascii.BS or key == curses.ascii.DEL: + self.string = self.string[:self.cursor-1] + self.string[self.cursor:] + self.cursor = max(self.cursor - 1, 0) + elif key == curses.KEY_RIGHT: + self.cursor = max(self.cursor + 1, len(self.string)) + elif key == curses.KEY_LEFT: + self.cursor = max(self.cursor - 1, 0) + elif key == curses.KEY_DC: + self.string = self.string[:self.cursor] + self.string[self.cursor+1:] + elif key == curses.KEY_HOME: + self.cursor = 0 + elif key == curses.KEY_END: + self.cursor = len(self.string) + + elif key == curses.ascii.ESC or key == curses.KEY_DL: + self.typing = False + self.string = "" + self.cursor = 0 + elif key == curses.ascii.LF or key == curses.ascii.CR: + message = self.string + self.string = "" + self.cursor = 0 + self.typing = False + self.processString(message) + - def scrollChat(self, lines): - self.display.scrollBack(lines) -- cgit