+#!/usr/bin/env python3
+import curses
+import socket
+import queue
+import threading
+from plomrogue.io_tcp import PlomSocket
+
+def recv_loop(plom_socket, q):
+ for msg in plom_socket.recv():
+ q.put(msg)
+
+class TUI:
+
+ def __init__(self, socket, q):
+ self.queue = q
+ self.socket = socket
+ self.log = []
+ self.log_msg("hallo")
+ self.log_msg("welt")
+ self.do_refresh = True
+ curses.wrapper(self.loop)
+
+ def log_msg(self, msg):
+ self.log += [msg]
+ if len(self.log) > 100:
+ self.log = self.log[-100:]
+
+ def loop(self, stdscr):
+
+ def msg_into_lines_of_width(msg, width):
+ chunk = ''
+ lines = []
+ x = 0
+ for i in range(len(msg)):
+ x += 1
+ if x >= width or msg[i] == "\n":
+ lines += [chunk]
+ chunk = ''
+ x = 0
+ if msg[i] != "\n":
+ chunk += msg[i]
+ lines += [chunk]
+ return lines
+
+ def reset_screen_size():
+ self.rows, self.cols = stdscr.getmaxyx()
+ self.cols -= 1 # ugly TODO ncurses bug workaround, FIXME
+ self.window_width = self.cols // 2
+
+ def recalc_input_lines():
+ self.input_lines = msg_into_lines_of_width(input_prompt +input_,
+ self.window_width)
+
+ def draw_history():
+ lines = []
+ for line in self.log:
+ lines += msg_into_lines_of_width(line, self.window_width)
+ lines.reverse()
+ max_y = self.rows - len(self.input_lines)
+ for i in range(len(lines)):
+ if (i >= max_y):
+ break
+ stdscr.addstr(max_y - i - 1, self.window_width, lines[i])
+
+ def draw_input():
+ y = self.rows - len(self.input_lines)
+ for i in range(len(self.input_lines)):
+ stdscr.addstr(y, self.window_width, self.input_lines[i])
+ y += 1
+
+ curses.curs_set(False) # hide cursor
+ stdscr.timeout(10)
+ reset_screen_size()
+ input_ = ''
+ input_prompt = '> '
+ while True:
+
+ if self.do_refresh:
+ self.do_refresh = False
+ stdscr.clear()
+ recalc_input_lines()
+
+ draw_input()
+ draw_history()
+
+ while True:
+ try:
+ msg = self.queue.get(block=False)
+ self.log_msg(msg)
+ self.do_refresh = True
+ except queue.Empty:
+ break
+
+ try:
+ key = stdscr.getkey()
+ except curses.error:
+ continue
+ self.do_refresh = True
+
+ if key == 'KEY_RESIZE':
+ reset_screen_size()
+ elif key == 'KEY_BACKSPACE':
+ input_ = input_[:-1]
+ elif key == '\n': # Return key
+ self.socket.send(input_)
+ input_ = ""
+ else:
+ input_ += key
+ # TODO find out why - 1 is necessary here
+ max_length = self.window_width * self.rows - len(input_prompt) - 1
+ if len(input_) > max_length:
+ input_ = input_[:max_length]
+
+s = socket.create_connection(('127.0.0.1', 5000))
+plom_socket = PlomSocket(s)
+q = queue.Queue()
+t = threading.Thread(target=recv_loop, args=(plom_socket, q))
+t.start()
+TUI(plom_socket, q)