From: Neil Brown Date: Fri, 30 Jan 2009 21:00:12 +0000 (+1100) Subject: Add the 'runit' toy X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=9ae659890f84c8dea77863e020034c494b790414;p=freerunner.git Add the 'runit' toy This allows arbitrary (pre configured) program to be run, and output to be displayed. --- diff --git a/runit/runit.py b/runit/runit.py new file mode 100644 index 0000000..68f34c1 --- /dev/null +++ b/runit/runit.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +# This software is copyright Neil Brown 2009. +# It is licensed to you under the terms of the +# GNU General Public License version 2. +# +# run a program given on args. +# +# TODO: +# Make it easier to scroll. +# Maybe don't require 'sh -c' for scripts +# Kill off children on exit + +import os,sys,fcntl +import gtk,pango, gobject +from subprocess import Popen, PIPE + +class Runit(gtk.Window): + def __init__(self, args): + gtk.Window.__init__(self) + self.set_default_size(480, 640) + self.create_ui() + self.show() + self.args = args + if args[0] == 'sh' and args[1] == '-c': + self.set_title(args[2]) + else: + self.set_title(args[0]) + self.run() + + + def run(self): + self.pipe = Popen(self.args, + stdout=PIPE, stderr=PIPE, + close_fds = True) + + def set_noblock(f): + flg = fcntl.fcntl(f, fcntl.F_GETFL, 0) + fcntl.fcntl(f, fcntl.F_SETFL, flg | os.O_NONBLOCK) + set_noblock(self.pipe.stdout) + set_noblock(self.pipe.stderr) + self.wc = gobject.child_watch_add(self.pipe.pid, self.done) + self.wout = gobject.io_add_watch(self.pipe.stdout, gobject.IO_IN, self.read) + self.werr = gobject.io_add_watch(self.pipe.stderr, gobject.IO_IN, self.read) + + def create_ui(self): + v = gtk.VBox() + self.add(v) + v.show() + + h = gtk.HBox(); h.show() + v.pack_end(h, expand=False) + + b = gtk.Button('EXIT'); + fd = pango.FontDescription('sans 20') + fd.set_absolute_size(19 * pango.SCALE) + b.child.modify_font(fd) + h.add(b) + b.connect('clicked', self.close) + b.show() + + b = gtk.Button('RERUN'); + b.child.modify_font(fd) + h.add(b) + b.connect('clicked', self.rerun) + + self.rerunb = b + + sw = gtk.ScrolledWindow(); sw.show() + sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + v.add(sw) + + tv = gtk.TextView() + sw.add(tv) + tv.modify_font(fd) + tv.set_wrap_mode(gtk.WRAP_CHAR) + + self.buff = tv.get_buffer() + + tv.show() + + def read(self, f, dir): + l = f.read() + self.buff.insert(self.buff.get_end_iter(), l) + if l == "": + return False + return True + + def done(self, *a): + self.rerunb.show() + def set_block(f): + flg = fcntl.fcntl(f, fcntl.F_GETFL, 0) + fcntl.fcntl(f, fcntl.F_SETFL, flg & ~ os.O_NONBLOCK) + self.read(self.pipe.stdout, None) + self.read(self.pipe.stderr, None) + gobject.source_remove(self.wout) + gobject.source_remove(self.werr) + self.pipe.stdout.close() + self.pipe.stderr.close() + self.pipe = None + + def close(self, *a): + gtk.main_quit() + + def rerun(self, *a): + self.rerunb.hide() + self.buff.insert(self.buff.get_end_iter(), "------------------------------------------------------------------\n") + self.run() + + +def main(args): + Runit(args[1:]) + gtk.main() + +if __name__ == '__main__': + main(sys.argv) + +