#!/usr/bin/env python import os,sys,imp,pycurses,gtk,time,thread,threading,glib,gobject THREADING=sys.argv.__contains__('-t') or False import pygtk,gtk,gobject,gio,cairo,pango,pangocairo pygtk.require('2.0') namespace = {'__builtins__': __builtins__, '__name__': '__main__', '__doc__': None, 'os':os,'sys':sys,'imp':imp, 'gtk':gtk,'gobject':gobject,'gdk':gtk.gdk, 'gio':gio,'pango':pango,'cairo':cairo, 'pangocairo':pangocairo} class console(): class Console(pycurses.Console): def __init__(self, namespace,banner=None,quit_func=None): self.cons=getattr(self,'cons',[self]);self.priority=0 self.events=getattr(self,'events',[]) if not banner: self.banner = ('shell %s Console\n ' % sys.version) self.namespace=namespace.copy() self.namespace.update({'this':self}) pycurses.Console.__init__(self,self.namespace,banner=self.banner,use_rlcompleter=True,quit_func=quit_func) def _branch(self): self.cons.append( console.Console(self.namespace,quit_func=lambda: self.destroy()) ) self.events.append(self.cons[-1].run) def response(self, dialog, response_id): if response_id == 0: pass elif response_id == 1: self.banner = None self.clear() elif response_id == 2: self.dialog() self.namespace=namespace elif(response_id == -1): self.destroy() self.grab_focus() def browse_response(self, dlg, response_id): if response_id != gtk.RESPONSE_APPLY: #dlg.hide() return proc_name = dlg.get_selected() if not proc_name: return #proc = pdb[proc_name] cmd = '' #if len(proc.return_vals) > 0: # cmd = ', '.join([x[1].replace('-', '_') # for x in return_vals]) + ' = ' # cmd = cmd + '%s' % proc[x].replace('-', '_') # if len(proc.params) > 0 and proc.params[0][1] == 'run-mode': # params = proc.params[1:] # else: # params = proc.params # cmd = cmd + '(%s)' % ', '.join([x[1].replace('-', '_') # for x in params]) buffer = self.buffer lines = buffer.get_line_count() iter = buffer.get_iter_at_line_offset(lines - 1, 4) buffer.delete(iter, buffer.get_end_iter()) buffer.place_cursor(buffer.get_end_iter()) buffer.insert_at_cursor(cmd) def browse(self): if not self.browse_dlg: pass dlg.connect('response', self.browse_response) dlg.connect('row-activated', lambda dlg: dlg.response(gtk.RESPONSE_APPLY)) self.browse_dlg = dlg self.browse_dlg.present() def save_response(self, dlg, response_id): if response_id == gtk.RESPONSE_DELETE_EVENT: self.save_dlg = None return elif response_id == gtk.RESPONSE_OK: filename = dlg.get_filename() try: logfile = open(filename, 'w') except (IOError, e): print("Could not open '%s' for writing: %s" % (filename, e.strerror)) return buffer = self.buffer start = buffer.get_start_iter() end = buffer.get_end_iter() log = buffer.get_text(start, end, False) try: logfile.write(log) logfile.close() except (IOError, e): print("Could not write to '%s': %s" % (filename, e.strerror)) return def save_dialog(self): if not self.save_dlg: dlg = gtk.FileChooserDialog(_("Save Console Output"), parent=self, action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) dlg.set_default_response(gtk.RESPONSE_OK) dlg.set_alternative_button_order((gtk.RESPONSE_OK, gtk.RESPONSE_CANCEL)); dlg.connect('response', self.save_response) self.save_dlg = dlg self.save_dlg.present() def main(self,win=None,doc=None,id=-1): self.hid=True;self.live=True;self.idle=[] if THREADING: gtk.gdk.threads_init() #self.ctx=gobject.MainContext() self.loop=gobject.MainLoop()#self.ctx) self.ctx=self.loop.get_context() if not (win and getattr(self,'win',None)): if not getattr(self.cons[id],'win',None): setattr(self.cons[id],'win',gtk.Window(gtk.WINDOW_TOPLEVEL));self.cons[id].win.body=gtk.VBox(); self.cons[id].win.add(self.cons[id].win.body); win=self.cons[id].win.body; elif (not getattr(self,'win',None)): if isinstance(self.win,gtk.VBox): pass else: self.win.add(doc) if not getattr(win,'box',None): setattr(win,'box',[]) win.box.append(gtk.ScrolledWindow()); win.add(win.box[-1]) win.box[-1].add(self.cons[id]);self.idle.append(self.cons[id].win.show_all); if not THREADING: gobject.idle_add(self.idle.pop(0)) #gtk.gdk.threads_leave(); else: self.events.append(self.loop.run) while(self.live): if len(self.idle)>0: for anev in self.idle: if 'method' in str(type(anev)): self.events.append(anev) self.idle.pop(0) gtk.gdk.threads_enter() self.ctx.iteration(False) gtk.gdk.threads_leave() def run(self): if THREADING: #self.id=thread.start_new_thread(self.main,()); self.thread=threading.Thread(target=self.main);self.thread.start() else: self.main() def __init__(self): self.events=getattr(self,'events',[]) self.idle=getattr(self,'idle',[]) namespace.update({'root':self}) self.this=self.__class__.Console(namespace) #if THREADING: # gtk.gdk.threads_init() self.this.run(); self.counter=0;self.needed=True; while (self.needed): #for anevent in getattr(gtk.gdk.event_peek(),'__iter__',[]): # if len(self.events)>10: # for event in range(10,len(self.events)): # self.events.pop(-1); # self.events.insert(0,anevent); # self.counter+=1; consId=0; for cons in map(lambda x:getattr(x,'events',[]),self.this.cons): for event in cons: if 'method' in str(type(event)): self.idle.append(gobject.idle_add(event));print(event); elif isinstance(event,tuple) or isinstance(event,list): if len(event)>1 and 'method' in str(type(event[0])): self.idle.append(gobject.idle_add(event[0],tuple(event[1:]))); elif len(event): self.idle.append(gobject.idle_add(event[0])) self.this.cons[consId].events.pop(self.this.cons[consId].events.index(event)) cons=[] threadCtx=getattr(getattr(self.this.cons[consId],'ctx',None),'iteration',None) if threadCtx and threadCtx(False): self.this.cons[consId].priority+=1;#this.cons[consId].priority= consId+=1;consId%=len(self.this.cons) gtk.gdk.threads_enter() gtk.main_iteration(False) gtk.gdk.threads_leave() print("exiting."); if __name__=='__main__': head=console.Console(namespace);head.run()