-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterface.py
94 lines (82 loc) · 3.16 KB
/
interface.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import time, threading, colorama, sys
import msvcrt
COLS = 80
DEFAULT_IN_HANDLE_PERIOD = 1
DEFAULT_GETCH_DELAY = 0.05 #120words/min, 1200 letters per minutes, 20 letters per second: 0.05sec/l
DEFAULT_ENCODING = 'utf8'
class Interface(object):
"Command line interface object that handles threaded input/output display."
def __init__(self, handleIncoming, handleOutgoing, inHandlePeriod = DEFAULT_IN_HANDLE_PERIOD,
encoding = DEFAULT_ENCODING):
"""Create an interface object and takes two methods that will be called to fetch
incoming messages and redirect outgoing messages to."""
self.handleIncoming = handleIncoming
self.handleOutgoing = handleOutgoing
self.inHandlePeriod = inHandlePeriod
self.encoding = encoding
self.running = False
self.buffer = ''
def goToStart(self):
"Erases the input buffer lines."
inputLength = len(self.buffer) + 3
numInputLines = inputLength // COLS
sys.stdout.write('\x1b[2K')
sys.stdout.write('\x1b[1A\x1b[2K' * numInputLines)
sys.stdout.write('\r')
def writeStartSymbol(self):
"Writes the default start symbol at the start of the line, without a linebreak."
sys.stdout.write('>> ')
def displayInputs(self):
"Calls the incomig messages fetcher passed at creation regularly and displays its results."
while self.running:
messages = self.handleIncoming()
if messages:
self.goToStart()
for mess in messages:
print("<< " + mess)
if messages:
self.writeStartSymbol()
sys.stdout.write(self.buffer)
time.sleep(self.inHandlePeriod)
def readInput(self):
"Reads and displays one character from stdin. Returns the input buffer if CR is received."
data = msvcrt.getch()
#Handles backspace
if data == b'\x08':
if len(self.buffer) > 0:
self.buffer = self.buffer[:-1]
self.goToStart()
self.writeStartSymbol()
sys.stdout.write(self.buffer)
return
#Handle Ctrl+C
if data == b'\x03':
raise KeyboardInterrupt
character = data.decode(self.encoding)
#Handle return
if character == '\r':
if self.buffer != '':
message = self.buffer
self.buffer = ''
return message
else:
return
#Add char to buffer
self.buffer += character
sys.stdout.write(character)
def run(self):
"Starts the two display loops to handle input(main thread)/output(remote)."
colorama.init()
self.running = True
threading.Thread(target = self.displayInputs).start()
self.writeStartSymbol()
while 1:
out = self.readInput()
if out:
print('') #Linebreak
self.writeStartSymbol()
self.handleOutgoing(out)
time.sleep(DEFAULT_GETCH_DELAY)
def stop(self):
"Sets flag to stop output thread."
self.running = False