Revert "improve code"

This reverts commit 8ea6e37537.
This commit is contained in:
Chrys 2019-08-13 09:44:00 +02:00
parent 8ea6e37537
commit 9e48fb1cf6

View File

@ -1,215 +1,216 @@
#!/bin/python #!/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributers.
import os, struct, sys, pty, tty, termios, shlex, signal, select, pyte, time, fcntl ,getpass import os, struct, sys, pty, tty, termios, shlex, signal, select, pyte, time, fcntl ,getpass
from fenrirscreenreader.core import debug from fenrirscreenreader.core import debug
from fenrirscreenreader.core.eventData import fenrirEventType from fenrirscreenreader.core.eventData import fenrirEventType
from fenrirscreenreader.core.screenDriver import screenDriver from fenrirscreenreader.core.screenDriver import screenDriver
from fenrirscreenreader.utils import screen_utils from fenrirscreenreader.utils import screen_utils
class fenrirScreen(pyte.HistoryScreen): class fenrirScreen(pyte.HistoryScreen):
def set_margins(self, *args, **kwargs): def set_margins(self, *args, **kwargs):
kwargs.pop("private", None) kwargs.pop("private", None)
return super(fenrirScreen, self).set_margins(*args, **kwargs) return super(fenrirScreen, self).set_margins(*args, **kwargs)
class Terminal: class Terminal:
def __init__(self, columns, lines, p_in): def __init__(self, columns, lines, p_in):
self.text = '' self.text = ''
self.attributes = None self.attributes = None
self.screen = fenrirScreen(columns, lines) self.screen = fenrirScreen(columns, lines)
self.screen.set_mode(pyte.modes.LNM) self.screen.set_mode(pyte.modes.LNM)
self.screen.write_process_input = \ self.screen.write_process_input = \
lambda data: p_in.write(data.encode()) lambda data: p_in.write(data.encode())
self.stream = pyte.ByteStream() self.stream = pyte.ByteStream()
self.stream.attach(self.screen) self.stream.attach(self.screen)
def feed(self, data): def feed(self, data):
self.stream.feed(data) self.stream.feed(data)
def updateAttributes(self, initialize = False): def updateAttributes(self, initialize = False):
buffer = self.screen.buffer buffer = self.screen.buffer
lines = None lines = None
if not initialize: if not initialize:
lines = self.screen.dirty lines = self.screen.dirty
else: else:
lines = range(self.screen.lines) lines = range(self.screen.lines)
self.attributes = [[list(attribute[1:]) + [False, 'default', 'default'] for attribute in line.values()] for line in buffer.values()] self.attributes = [[list(attribute[1:]) + [False, 'default', 'default'] for attribute in line.values()] for line in buffer.values()]
for y in lines: for y in lines:
try: try:
t = self.attributes[y] t = self.attributes[y]
except: except:
self.attributes.append([]) self.attributes.append([])
self.attributes[y] = [list(attribute[1:]) + [False, 'default', 'default'] for attribute in (buffer[y].values())] self.attributes[y] = [list(attribute[1:]) + [False, 'default', 'default'] for attribute in (buffer[y].values())]
if len(self.attributes[y]) < self.screen.columns: if len(self.attributes[y]) < self.screen.columns:
diff = self.screen.columns - len(self.attributes[y]) diff = self.screen.columns - len(self.attributes[y])
self.attributes[y] += [['default', 'default', False, False, False, False, False, False, 'default', 'default']] * diff self.attributes[y] += [['default', 'default', False, False, False, False, False, False, 'default', 'default']] * diff
def resize(self, lines, columns): def resize(self, lines, columns):
self.screen.resize(lines, columns) self.screen.resize(lines, columns)
self.setCursor() self.setCursor()
self.updateAttributes(True) self.updateAttributes(True)
def setCursor(self, x = -1, y = -1): def setCursor(self, x = -1, y = -1):
xPos = x xPos = x
yPos = y yPos = y
if xPos == -1: if xPos == -1:
xPos = self.screen.cursor.x xPos = self.screen.cursor.x
if yPos == -1: if yPos == -1:
yPos = self.screen.cursor.y yPos = self.screen.cursor.y
self.screen.cursor.x = min(self.screen.cursor.x, self.screen.columns - 1) self.screen.cursor.x = min(self.screen.cursor.x, self.screen.columns - 1)
self.screen.cursor.y = min(self.screen.cursor.y, self.screen.lines - 1) self.screen.cursor.y = min(self.screen.cursor.y, self.screen.lines - 1)
def GetScreenContent(self): def GetScreenContent(self):
cursor = self.screen.cursor cursor = self.screen.cursor
self.text = '\n'.join(self.screen.display) self.text = '\n'.join(self.screen.display)
self.updateAttributes(self.attributes == None) self.updateAttributes(self.attributes == None)
self.screen.dirty.clear() self.screen.dirty.clear()
return {"cursor": (cursor.x, cursor.y), return {"cursor": (cursor.x, cursor.y),
'lines': self.screen.lines, 'lines': self.screen.lines,
'columns': self.screen.columns, 'columns': self.screen.columns,
"text": self.text, "text": self.text,
'attributes': self.attributes.copy(), 'attributes': self.attributes.copy(),
'screen': 'pty', 'screen': 'pty',
'screenUpdateTime': time.time(), 'screenUpdateTime': time.time(),
}.copy() }.copy()
class driver(screenDriver): class driver(screenDriver):
def __init__(self): def __init__(self):
screenDriver.__init__(self) screenDriver.__init__(self)
self.signalPipe = os.pipe() self.signalPipe = os.pipe()
self.p_out = None self.p_out = None
signal.signal(signal.SIGWINCH, self.handleSigwinch) signal.signal(signal.SIGWINCH, self.handleSigwinch)
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
self.command = self.env['runtime']['settingsManager'].getSetting('general','shell') self.command = self.env['runtime']['settingsManager'].getSetting('general','shell')
self.shortcutType = self.env['runtime']['inputManager'].getShortcutType() self.shortcutType = self.env['runtime']['inputManager'].getShortcutType()
self.env['runtime']['processManager'].addCustomEventThread(self.terminalEmulation) self.env['runtime']['processManager'].addCustomEventThread(self.terminalEmulation)
def getCurrScreen(self): def getCurrScreen(self):
self.env['screen']['oldTTY'] = 'pty' self.env['screen']['oldTTY'] = 'pty'
self.env['screen']['newTTY'] = 'pty' self.env['screen']['newTTY'] = 'pty'
def injectTextToScreen(self, msgBytes, screen = None): def injectTextToScreen(self, msgBytes, screen = None):
if not screen: if not screen:
screen = self.p_out.fileno() screen = self.p_out.fileno()
if isinstance(msgBytes, str): if isinstance(msgBytes, str):
msgBytes = bytes(msgBytes, 'UTF-8') msgBytes = bytes(msgBytes, 'UTF-8')
os.write(screen, msgBytes) os.write(screen, msgBytes)
def getSessionInformation(self): def getSessionInformation(self):
self.env['screen']['autoIgnoreScreens'] = [] self.env['screen']['autoIgnoreScreens'] = []
self.env['general']['prevUser'] = getpass.getuser() self.env['general']['prevUser'] = getpass.getuser()
self.env['general']['currUser'] = getpass.getuser() self.env['general']['currUser'] = getpass.getuser()
def readAll(self, fd, timeout = 9999999, interruptFd = None, len = 2048): def readAll(self, fd, timeout = 9999999, interruptFd = None, len = 2048):
bytes = b'' bytes = b''
fdList = [] fdList = []
fdList += [fd] fdList += [fd]
if interruptFd: if interruptFd:
fdList += [interruptFd] fdList += [interruptFd]
starttime = time.time() starttime = time.time()
while True: while True:
# respect timeout but wait a little bit of time to see if something more is here # respect timeout but wait a little bit of time to see if something more is here
if (time.time() - starttime) >= timeout: if (time.time() - starttime) >= timeout:
break break
r = screen_utils.hasMoreWhat(fdList,0) r = screen_utils.hasMoreWhat(fdList,0)
hasmore = fd in r hasmore = fd in r
if not hasmore: if not hasmore:
break break
# exit on interrupt available # exit on interrupt available
if interruptFd in r: if interruptFd in r:
break break
data = os.read(fd, len) data = os.read(fd, len)
if data == b'': if data == b'':
raise EOFError raise EOFError
bytes += data bytes += data
return bytes return bytes
def openTerminal(self, columns, lines, command): def openTerminal(self, columns, lines, command):
p_pid, master_fd = pty.fork() p_pid, master_fd = pty.fork()
if p_pid == 0: # Child. if p_pid == 0: # Child.
argv = shlex.split(command) argv = shlex.split(command)
env = os.environ.copy() env = os.environ.copy()
#values are VT100,xterm-256color,linux #values are VT100,xterm-256color,linux
try: try:
if env["TERM"] == '': eterm = env["TERM"]
env["TERM"] = 'linux' if eterm == '':
except: env["TERM"] = 'linux'
env["TERM"] = 'linux' except:
os.execvpe(argv[0], argv, env) env["TERM"] = 'linux'
# File-like object for I/O with the child process aka command. os.execvpe(argv[0], argv, env)
p_out = os.fdopen(master_fd, "w+b", 0) # File-like object for I/O with the child process aka command.
return Terminal(columns, lines, p_out), p_pid, p_out p_out = os.fdopen(master_fd, "w+b", 0)
def resizeTerminal(self,fd): return Terminal(columns, lines, p_out), p_pid, p_out
s = struct.pack('HHHH', 0, 0, 0, 0) def resizeTerminal(self,fd):
s = fcntl.ioctl(0, termios.TIOCGWINSZ, s) s = struct.pack('HHHH', 0, 0, 0, 0)
fcntl.ioctl(fd, termios.TIOCSWINSZ, s) s = fcntl.ioctl(0, termios.TIOCGWINSZ, s)
lines, columns, _, _ = struct.unpack('hhhh', s) fcntl.ioctl(fd, termios.TIOCSWINSZ, s)
return lines, columns lines, columns, _, _ = struct.unpack('hhhh', s)
def getTerminalSize(self, fd): return lines, columns
s = struct.pack('HHHH', 0, 0, 0, 0) def getTerminalSize(self, fd):
lines, columns, _, _ = struct.unpack('HHHH', fcntl.ioctl(fd, termios.TIOCGWINSZ, s)) s = struct.pack('HHHH', 0, 0, 0, 0)
return lines, columns lines, columns, _, _ = struct.unpack('HHHH', fcntl.ioctl(fd, termios.TIOCGWINSZ, s))
def handleSigwinch(self, *args): return lines, columns
os.write(self.signalPipe[1], b'w') def handleSigwinch(self, *args):
def terminalEmulation(self,active , eventQueue): os.write(self.signalPipe[1], b'w')
try: def terminalEmulation(self,active , eventQueue):
old_attr = termios.tcgetattr(sys.stdin) try:
tty.setraw(0) old_attr = termios.tcgetattr(sys.stdin)
lines, columns = self.getTerminalSize(0) tty.setraw(0)
if self.command == '': lines, columns = self.getTerminalSize(0)
self.command = screen_utils.getShell() if self.command == '':
terminal, p_pid, self.p_out = self.openTerminal(columns, lines, self.command) self.command = screen_utils.getShell()
lines, columns = self.resizeTerminal(self.p_out) terminal, p_pid, self.p_out = self.openTerminal(columns, lines, self.command)
terminal.resize(lines, columns) lines, columns = self.resizeTerminal(self.p_out)
fdList = [sys.stdin, self.p_out, self.signalPipe[0]] terminal.resize(lines, columns)
while active.value: fdList = [sys.stdin, self.p_out, self.signalPipe[0]]
r, _, _ = select.select(fdList, [], [], 1) while active.value:
# none r, _, _ = select.select(fdList, [], [], 1)
if r == []: # none
continue if r == []:
# signals continue
if self.signalPipe[0] in r: # signals
os.read(self.signalPipe[0], 1) if self.signalPipe[0] in r:
lines, columns = self.resizeTerminal(self.p_out) os.read(self.signalPipe[0], 1)
terminal.resize(lines, columns) lines, columns = self.resizeTerminal(self.p_out)
# input terminal.resize(lines, columns)
if sys.stdin in r: # input
try: if sys.stdin in r:
msgBytes = self.readAll(sys.stdin.fileno()) try:
except (EOFError, OSError): msgBytes = self.readAll(sys.stdin.fileno())
active.value = False except (EOFError, OSError):
break active.value = False
if self.shortcutType == 'KEY': break
try: if self.shortcutType == 'KEY':
self.injectTextToScreen(msgBytes) try:
except: self.injectTextToScreen(msgBytes)
active.value = False except:
break active.value = False
else: break
eventQueue.put({"Type":fenrirEventType.ByteInput, else:
"Data":msgBytes }) eventQueue.put({"Type":fenrirEventType.ByteInput,
# output "Data":msgBytes })
if self.p_out in r: # output
try: if self.p_out in r:
msgBytes = self.readAll(self.p_out.fileno(), timeout=0.001, interruptFd=sys.stdin) try:
except (EOFError, OSError): msgBytes = self.readAll(self.p_out.fileno(), timeout=0.001, interruptFd=sys.stdin)
active.value = False except (EOFError, OSError):
break active.value = False
terminal.feed(msgBytes) break
os.write(sys.stdout.fileno(), msgBytes) terminal.feed(msgBytes)
eventQueue.put({"Type":fenrirEventType.ScreenUpdate, os.write(sys.stdout.fileno(), msgBytes)
"Data":screen_utils.createScreenEventData(terminal.GetScreenContent()) eventQueue.put({"Type":fenrirEventType.ScreenUpdate,
}) "Data":screen_utils.createScreenEventData(terminal.GetScreenContent())
except Exception as e: # Process died? })
print(e) except Exception as e: # Process died?
active.value = False print(e)
finally: active.value = False
os.kill(p_pid, signal.SIGTERM) finally:
self.p_out.close() os.kill(p_pid, signal.SIGTERM)
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attr) self.p_out.close()
eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None}) termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attr)
sys.exit(0) eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None})
sys.exit(0)
def getCurrApplication(self):
pass def getCurrApplication(self):
pass