Better terminal refresh

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
This commit is contained in:
Yohann D'ANELLO 2020-12-21 16:04:01 +01:00
parent c609ca998a
commit 04f31a1159
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
2 changed files with 32 additions and 26 deletions

View File

@ -50,29 +50,21 @@ class Squinnondation:
screen = term_manager.screen screen = term_manager.screen
screen.addstr(0, 0, "Enter your nickname: ") screen.addstr(0, 0, "Enter your nickname: ")
nickname = screen.getstr().decode("UTF-8") nickname = screen.getstr().decode("UTF-8")
squirrel = Squirrel(nickname, instance.bind_address, instance.bind_port) squirrel = Squirrel(nickname, instance.bind_address, instance.bind_port)
squirrel.refresh_history()
squirrel.refresh_input()
if not instance.args.bind_only: if not instance.args.bind_only:
hazelnut = Hazelnut(address=instance.client_address, port=instance.client_port) hazelnut = Hazelnut(address=instance.client_address, port=instance.client_port)
squirrel.hazelnuts[(instance.client_address, instance.client_port)] = hazelnut squirrel.hazelnuts[(instance.client_address, instance.client_port)] = hazelnut
squirrel.history = []
def refresh() -> None:
screen.clear()
screen.refresh()
for i, msg in enumerate(squirrel.history[max(0, len(squirrel.history) - curses.LINES + 2):]):
screen.addstr(i, 0, msg)
screen.addstr(curses.LINES - 1, 0, f"<{squirrel.nickname}> ")
screen.refresh()
squirrel.refresh = refresh
Worm(squirrel).start() Worm(squirrel).start()
while True: while True:
refresh() squirrel.refresh_history()
msg = screen.getstr().decode("UTF-8") squirrel.refresh_input()
msg = screen.getstr(curses.LINES - 1, 3 + len(squirrel.nickname)).decode("UTF-8")
msg = f"<{squirrel.nickname}> {msg}" msg = f"<{squirrel.nickname}> {msg}"
squirrel.history.append(msg) squirrel.history.append(msg)
@ -387,8 +379,12 @@ class Squirrel(Hazelnut):
# Bind the socket # Bind the socket
self.socket.bind((str(self.address), self.port)) self.socket.bind((str(self.address), self.port))
self.history = []
self.history_pad = curses.newpad(curses.LINES - 2, curses.COLS)
self.input_pad = curses.newpad(1, curses.COLS)
self.hazelnuts = dict() self.hazelnuts = dict()
print(f"Listening on {self.address}:{self.port}") self.history.append(f"<system> Listening on {self.address}:{self.port}")
def find_hazelnut(self, address: str, port: int) -> Hazelnut: def find_hazelnut(self, address: str, port: int) -> Hazelnut:
""" """
@ -426,6 +422,23 @@ class Squirrel(Hazelnut):
""" """
return self.socket.recvfrom(1024) return self.socket.recvfrom(1024)
def refresh_history(self) -> None:
"""
Rewrite the history of the messages.
"""
self.history_pad.erase()
for i, msg in enumerate(self.history[max(0, len(self.history) - curses.LINES + 2):]):
self.history_pad.addstr(i, 0, msg)
self.history_pad.refresh(0, 0, 0, 0, curses.LINES - 2, curses.COLS)
def refresh_input(self) -> None:
"""
Redraw input line. Must not be called while the message is not sent.
"""
self.input_pad.erase()
self.input_pad.addstr(0, 0, f"<{self.nickname}> ")
self.input_pad.refresh(0, 0, curses.LINES - 1, 0, curses.LINES - 1, curses.COLS - 1)
class Worm(Thread): class Worm(Thread):
""" """
@ -438,12 +451,11 @@ class Worm(Thread):
self.squirrel = squirrel self.squirrel = squirrel
def run(self) -> None: def run(self) -> None:
self.squirrel.history = []
while True: while True:
try: try:
pkt, hazelnut = self.squirrel.receive_packet() pkt, hazelnut = self.squirrel.receive_packet()
except ValueError as error: except ValueError as error:
print("An error occured while receiving a packet: ", error) self.squirrel.history.append("<system> An error occured while receiving a packet: {}".format(error))
else: else:
self.squirrel.history.append(pkt.body[0].data.decode('UTF-8')) self.squirrel.history.append(pkt.body[0].data.decode('UTF-8'))
self.squirrel.refresh() self.squirrel.refresh_history()

View File

@ -14,12 +14,8 @@ class TermManager: # pragma: no cover
self.screen = curses.initscr() self.screen = curses.initscr()
# convert escapes sequences to curses abstraction # convert escapes sequences to curses abstraction
self.screen.keypad(True) self.screen.keypad(True)
# stop printing typed keys to the terminal
# curses.noecho()
# send keys through without having to press <enter>
# curses.cbreak()
# make cursor invisible # make cursor invisible
# curses.curs_set(False) curses.curs_set(False)
# Catch mouse events # Catch mouse events
curses.mousemask(True) curses.mousemask(True)
# Enable colors # Enable colors
@ -32,7 +28,5 @@ class TermManager: # pragma: no cover
exc_traceback: TracebackType) -> None: exc_traceback: TracebackType) -> None:
# restore the terminal to its original state # restore the terminal to its original state
self.screen.keypad(False) self.screen.keypad(False)
# curses.echo() curses.curs_set(True)
# curses.nocbreak()
# curses.curs_set(True)
curses.endwin() curses.endwin()