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
|
# Copyright (C) 2020 by eichhornchen, ÿnérant
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
import curses
|
||||||
import socket
|
import socket
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
@ -8,6 +9,8 @@ from ipaddress import IPv6Address
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import Any, List, Optional, Tuple
|
from typing import Any, List, Optional, Tuple
|
||||||
|
|
||||||
|
from squinnondation.term_manager import TermManager
|
||||||
|
|
||||||
|
|
||||||
class Squinnondation:
|
class Squinnondation:
|
||||||
args: Any
|
args: Any
|
||||||
|
@ -43,16 +46,36 @@ class Squinnondation:
|
||||||
instance = Squinnondation()
|
instance = Squinnondation()
|
||||||
instance.parse_arguments()
|
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:
|
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:
|
||||||
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()):
|
for hazelnut in list(squirrel.hazelnuts.values()):
|
||||||
pkt = Packet()
|
pkt = Packet()
|
||||||
pkt.magic = 95
|
pkt.magic = 95
|
||||||
|
@ -61,7 +84,7 @@ class Squinnondation:
|
||||||
tlv.data = msg.encode("UTF-8")
|
tlv.data = msg.encode("UTF-8")
|
||||||
tlv.sender_id = 42
|
tlv.sender_id = 42
|
||||||
tlv.nonce = 18
|
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 = [tlv]
|
||||||
pkt.body_length = tlv.length + 2
|
pkt.body_length = tlv.length + 2
|
||||||
squirrel.send_packet(hazelnut, pkt)
|
squirrel.send_packet(hazelnut, pkt)
|
||||||
|
@ -415,10 +438,12 @@ 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)
|
print("An error occured while receiving a packet: ", error)
|
||||||
else:
|
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