Created
February 11, 2025 15:16
-
-
Save r0x0d/086da4a5c3ffde402a1ad765c606a096 to your computer and use it in GitHub Desktop.
terminal reader with pty spawn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Correct and working version | |
import argparse | |
import json | |
import os | |
import pty | |
import sys | |
class ScriptRecorder: | |
def __init__(self, script_file): | |
self.script = script_file | |
self.in_command = True | |
self.buffer = b'' | |
self.PROMPT_MARKER = b'%c' | |
self.current_command = b'' | |
self.current_output = b'' | |
def write_json_block(self): | |
if self.current_command: | |
block = { | |
"command": self.current_command.decode().strip(), | |
"output": self.current_output.decode().strip() | |
} | |
self.script.write(json.dumps(block, indent=2).encode() + b'\n') | |
self.script.flush() | |
self.current_command = b'' | |
self.current_output = b'' | |
def read(self, fd): | |
data = os.read(fd, 512) | |
if self.PROMPT_MARKER in data: | |
if not self.in_command: | |
self.write_json_block() | |
self.in_command = True | |
elif self.in_command and (b'\r\n' in data or b'\n' in data): | |
self.in_command = False | |
# Remove our marker from the output | |
data = data.replace(self.PROMPT_MARKER, b'') | |
# Store command or output | |
if self.in_command: | |
self.current_command += data | |
else: | |
self.current_output += data | |
return data | |
def main(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument('-a', dest='append', action='store_true') | |
parser.add_argument('-p', dest='use_python', action='store_true') | |
parser.add_argument("-i", dest="print", action="store_true") | |
parser.add_argument('filename', nargs='?', default='typescript') | |
options = parser.parse_args() | |
shell = sys.executable if options.use_python else os.environ.get('SHELL', 'sh') | |
filename = options.filename | |
mode = 'ab' if options.append else 'wb' | |
# Modify PS1 to include our marker | |
user_prompt_command = os.environ.get('CLA_USER_SHELL_PROMPT_COMMAND', r'[\u@\h \W]\$ ') | |
os.environ['PROMPT_COMMAND'] = f'{user_prompt_command}%c' | |
with open(filename, mode) as script: | |
recorder = ScriptRecorder(script) | |
pty.spawn(shell, recorder.read) | |
# Write final block if exists | |
recorder.write_json_block() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment