Skip to content

Commit

Permalink
feat: PTY output parser
Browse files Browse the repository at this point in the history
  • Loading branch information
tomlin7 committed Apr 18, 2024
1 parent 2e89a38 commit e4ce539
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 20 deletions.
46 changes: 38 additions & 8 deletions mono/ansi.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
import re

from __future__ import annotations

SEQ = re.compile(r'\x1b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
NEWLINE = re.compile(r'\x1b\[\d+\;1H')
import re
import typing

def strip_ansi_escape_sequences(string):
return SEQ.sub('', string)
if typing.TYPE_CHECKING:
from .terminal import Terminal

def replace_newline(string):
return NEWLINE.sub('\n', string)
class OutputParser:
def __init__(self, terminal:Terminal):
self.terminal = terminal

def parse(self, buf: str):
display_text = ""
i = 0
while i < len(buf):
match buf[i]:
case '\x07':
# bell
...
case '\x08':
# backspace
...
case '\x09':
# tab
...
case '\x0a':
# newline
# self.terminal._newline()
...
case '\x0d':
# carriage return
...
case '\x1b':
# parse escape sequence
...
case _:
display_text += buf[i]
i += 1

return display_text
22 changes: 10 additions & 12 deletions mono/terminal.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import re
import tkinter as tk
from threading import Thread
from tkinter import ttk
Expand All @@ -8,10 +9,10 @@
else:
from ptyprocess import PtyProcessUnicode as PTY

from mono.ansi import OutputParser
from mono.theme import Theme
from mono.utils import Scrollbar

from .ansi import replace_newline, strip_ansi_escape_sequences
from .text import TerminalText


Expand Down Expand Up @@ -55,6 +56,8 @@ def __init__(self, master, cwd=".", theme: Theme=None, standalone=True, *args, *
self.text.grid(row=0, column=0, sticky=tk.NSEW)
self.text.bind("<Return>", self.enter)

self.parser = OutputParser(self)

self.terminal_scrollbar = Scrollbar(self, style="MonoScrollbar")
self.terminal_scrollbar.grid(row=0, column=1, sticky='NSW')

Expand Down Expand Up @@ -94,6 +97,11 @@ def run_command(self, command: str) -> None:
self.text.insert("end", command, "command")
self.enter()

def clear(self) -> None:
"""Clear the terminal."""

self.text.clear()

def enter(self, *_) -> None:
"""Enter key event handler for running commands."""

Expand All @@ -109,12 +117,7 @@ def enter(self, *_) -> None:
def _write_loop(self) -> None:
while self.alive:
if buf := self.p.read():
p = buf.find('\x1b]0;')

if p != -1:
buf = buf[:p]
buf = [strip_ansi_escape_sequences(i) for i in replace_newline(buf).splitlines()]
self._insert('\n'.join(buf))
self._insert('\n'.join(self.parser.parse(buf)))

def _insert(self, output: str, tag='') -> None:
self.text.insert(tk.END, output, tag)
Expand All @@ -125,11 +128,6 @@ def _insert(self, output: str, tag='') -> None:
def _newline(self):
self._insert('\n')

def clear(self) -> None:
"""Clear the terminal."""

self.text.clear()

# TODO: Implement a better way to handle key events.
def _ctrl_key(self, key: str) -> None:
if key == 'c':
Expand Down

0 comments on commit e4ce539

Please sign in to comment.