Uses curses to have a proper terminal UI

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 a28975c895
commit c609ca998a
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
2 changed files with 83 additions and 20 deletions

View File

@ -1,6 +1,7 @@
# Copyright (C) 2020 by eichhornchen, ÿnérant
# SPDX-License-Identifier: GPL-3.0-or-later
import curses
import socket
from argparse import ArgumentParser
from enum import Enum
@ -8,6 +9,8 @@ from ipaddress import IPv6Address
from threading import Thread
from typing import Any, List, Optional, Tuple
from squinnondation.term_manager import TermManager
class Squinnondation:
args: Any
@ -43,16 +46,36 @@ class Squinnondation:
instance = Squinnondation()
instance.parse_arguments()
squirrel = Squirrel(input("Enter your nickname: "), instance.bind_address, instance.bind_port)
with TermManager() as term_manager:
screen = term_manager.screen
screen.addstr(0, 0, "Enter your nickname: ")
nickname = screen.getstr().decode("UTF-8")
squirrel = Squirrel(nickname, instance.bind_address, instance.bind_port)
if not instance.args.bind_only:
hazelnut = Hazelnut(address=instance.client_address, port=instance.client_port)
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()
while True:
msg = f"<{squirrel.nickname}> {input(f'<{squirrel.nickname}> ')}"
refresh()
msg = screen.getstr().decode("UTF-8")
msg = f"<{squirrel.nickname}> {msg}"
squirrel.history.append(msg)
for hazelnut in list(squirrel.hazelnuts.values()):
pkt = Packet()
pkt.magic = 95
@ -61,7 +84,7 @@ class Squinnondation:
tlv.data = msg.encode("UTF-8")
tlv.sender_id = 42
tlv.nonce = 18
tlv.length = len(msg) + 1 + 1 + 8 + 4
tlv.length = len(tlv.data) + 1 + 1 + 8 + 4
pkt.body = [tlv]
pkt.body_length = tlv.length + 2
squirrel.send_packet(hazelnut, pkt)
@ -415,10 +438,12 @@ class Worm(Thread):
self.squirrel = squirrel
def run(self) -> None:
self.squirrel.history = []
while True:
try:
pkt, hazelnut = self.squirrel.receive_packet()
except ValueError as error:
print("An error occured while receiving a packet: ", error)
else:
print(pkt.body[0].data.decode('UTF-8'))
self.squirrel.history.append(pkt.body[0].data.decode('UTF-8'))
self.squirrel.refresh()

View File

@ -0,0 +1,38 @@
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
# SPDX-License-Identifier: GPL-3.0-or-later
import curses
from types import TracebackType
class TermManager: # pragma: no cover
"""
The TermManager object initializes the terminal, returns a screen object and
de-initializes the terminal after use
"""
def __init__(self):
self.screen = curses.initscr()
# convert escapes sequences to curses abstraction
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
# curses.curs_set(False)
# Catch mouse events
curses.mousemask(True)
# Enable colors
curses.start_color()
def __enter__(self):
return self
def __exit__(self, exc_type: type, exc_value: Exception,
exc_traceback: TracebackType) -> None:
# restore the terminal to its original state
self.screen.keypad(False)
# curses.echo()
# curses.nocbreak()
# curses.curs_set(True)
curses.endwin()