Uses curses to have a proper terminal UI
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
This commit is contained in:
parent
a28975c895
commit
c609ca998a
|
@ -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,28 +46,48 @@ 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
|
||||
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
|
||||
|
||||
Worm(squirrel).start()
|
||||
squirrel.history = []
|
||||
|
||||
while True:
|
||||
msg = f"<{squirrel.nickname}> {input(f'<{squirrel.nickname}> ')}"
|
||||
for hazelnut in list(squirrel.hazelnuts.values()):
|
||||
pkt = Packet()
|
||||
pkt.magic = 95
|
||||
pkt.version = 0
|
||||
tlv = DataTLV()
|
||||
tlv.data = msg.encode("UTF-8")
|
||||
tlv.sender_id = 42
|
||||
tlv.nonce = 18
|
||||
tlv.length = len(msg) + 1 + 1 + 8 + 4
|
||||
pkt.body = [tlv]
|
||||
pkt.body_length = tlv.length + 2
|
||||
squirrel.send_packet(hazelnut, pkt)
|
||||
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:
|
||||
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
|
||||
pkt.version = 0
|
||||
tlv = DataTLV()
|
||||
tlv.data = msg.encode("UTF-8")
|
||||
tlv.sender_id = 42
|
||||
tlv.nonce = 18
|
||||
tlv.length = len(tlv.data) + 1 + 1 + 8 + 4
|
||||
pkt.body = [tlv]
|
||||
pkt.body_length = tlv.length + 2
|
||||
squirrel.send_packet(hazelnut, pkt)
|
||||
|
||||
|
||||
class TLV:
|
||||
|
@ -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()
|
||||
|
|
|
@ -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()
|
Loading…
Reference in New Issue