#!/usr/bin/python3 """Prototype of Meckle: a graphical agent speaking text with a principal. The Meckle agent opens a window to provide a GUI for the principal. The principal sends commands to the agent, and the agent notifies the principal of any relevant events such as button clicks. With the agent meckling on the display on behalf of the principal, the principal can happily run on an Arduino, or be a sed script, or a playback of a previously recorded meckling session. XXX not sure how to get this to actually work with tkinter. w.tk.createfilehandler(infile, tkinter.READABLE, callback) would probably work, at least on Unix, but obviously that isn't what the Python REPL uses. Do I need to run the mainloop in a background thread? Or do the I/O in a background thread? Just calling .update() after every command isn't good enough; it does cause the window to appear at least, but it isn't interactive until after the next command. Meckle is inspired by RIPScrip, NAPLPS, Videotex and similar teletext systems, HTML forms, SGI’s Buttonfly, Tcl/Tk, text terminals, the MGR windowing system Caleb Winston’s STDG, Dave Long’s window manager in awk, and a conversation I had once at a party with someone who I perhaps mistakenly remembered to be Richard Uhtenwoldt. """ from __future__ import print_function import tkinter def run_agent(infile, outfile): w = tkinter.Tk() # Ugh, how do I read input while also displaying the window? XXX while True: line = infile.readline() if not line: break if handle(w, line) == 'exit': break # XXX this doesn't quite work as desired, though it helps a bit... w.update() commands = {} def handle(w, line): words = line.split() if len(words) < 1: return handler = commands.get(words[0]) if handler is None: print("command not understood", words[0]) return return handler(w, words) def command(f): commands[f.__name__] = f return f @command def button(w, words): b = tkinter.Button(w, text=words[1], command=lambda: print("click", words[1])) b.pack() @command def mainloop(w, words): tkinter.mainloop() return 'exit' if __name__ == '__main__': import sys run_agent(sys.stdin, sys.stdout)