]> git.neil.brown.name Git - freerunner.git/commitdiff
Add the 'runit' toy
authorNeil Brown <neilb@suse.de>
Fri, 30 Jan 2009 21:00:12 +0000 (08:00 +1100)
committerNeil Brown <neilb@suse.de>
Fri, 30 Jan 2009 21:00:12 +0000 (08:00 +1100)
This allows arbitrary (pre configured) program to be run, and output
to be displayed.

runit/runit.py [new file with mode: 0644]

diff --git a/runit/runit.py b/runit/runit.py
new file mode 100644 (file)
index 0000000..68f34c1
--- /dev/null
@@ -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)
+
+