#!/usr/bin/env python2

import os, threading, locale, sys

from gi.repository import GObject, Gtk, Gdk

GObject.threads_init()
Gdk.threads_init()

encoding = locale.getpreferredencoding()
utf8conv = lambda x : unicode(x, encoding).encode('utf8')

class Command(Gtk.ScrolledWindow):
    def __init__(self):
        super(Command, self).__init__()
        self.view = Gtk.TextView()
        self.view.set_editable(False)
        self.view.set_cursor_visible(False)
        self.buffer = self.view.get_buffer()
        self.add(self.view)
        self.listeners = []

    def clear(self):
        self.buffer.set_text('')
        #self.buffer.insert_at_cursor('=======\n')

    def add_listener(self, listener):
        self.listeners.append(listener)

    def run(self, command):
        thread = threading.Thread(target=self._read_command_output, args=(command,))
        thread.start()

    def _read_command_output(self, command):
        stdin, stdouterr = os.popen4(command)
        while 1:
            line = stdouterr.readline()
            if not line:
                break
            Gdk.threads_enter()
            self.add_text(utf8conv(line))
            Gdk.threads_leave()
        for listener in self.listeners:
            listener(command, self.buffer.get_text())

    def add_text(self, line):
        if not line.endswith('\n'):
            line += '\n'
        self.buffer.insert_at_cursor(line)
        adj = self.get_vadjustment()
        adj.set_value(adj.get_upper() - adj.get_page_size())

if __name__ == '__main__':
    import signal
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    command = Command(' '.join(sys.argv[1:]))

    window = Gtk.Window()
    window.add(command)
    window.set_default_size(800, 600)
    window.show_all()
    window.connect("delete-event", Gtk.main_quit)
    Gtk.main()