home *** CD-ROM | disk | FTP | other *** search
Wrap
#! /usr/bin/env python # # byobu-config # Copyright (C) 2008 Canonical Ltd. # # Authors: Nick Barcet <nick.barcet@ubuntu.com> # Dustin Kirkland <kirkland@canonical.com> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # If you change any strings, please generate localization information with: # ./debian/rules get-po import sys, os, os.path, time, string, commands, gettext, glob, snack from ConfigParser import SafeConfigParser from snack import * HOME=os.getenv("HOME") USER=os.getenv("USER") PKG="byobu" SHARE='/usr/share/'+PKG DOC='/usr/share/doc/'+PKG DEF_ESC="A" RELOAD = "If you are using the default set of keybindings, press\n<F5> or <ctrl-a-R> to activate these changes.\n\nOtherwise, exit this screen session and start a new one." RELOAD_FLAG="/var/run/screen/S-"+USER+"/"+PKG+".reload-required" RELOAD_CMD="screen -X at 0 source $HOME/."+PKG+"/profile" ESC = '' snack.hotkeys[ESC] = ord(ESC) snack.hotkeys[ord(ESC)] = ESC gettext.bindtextdomain(PKG, SHARE+'/po') gettext.textdomain(PKG) _ = gettext.gettext # Command presets for windows creation cmd=( ("System activity", "top", "top"), ("System log", "log", "watch -n 10 tail -n 5 /var/log/syslog /var/log/auth.log /var/log/dmesg"), ("Disk and ram usage", "mem", 'watch -n 30 "df -h; echo ""; free -mt"')) def ioctl_GWINSZ(fd): #### TABULATION FUNCTIONS try: ### Discover terminal width import fcntl, termios, struct, os cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) except: return None return cr def reload_required(): f = open(RELOAD_FLAG,'w') f.close() commands.getoutput(RELOAD_CMD) def terminal_size(): ### decide on *some* terminal size cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) # try open fds if not cr: # ...then ctty try: fd = os.open(os.ctermid(), os.O_RDONLY) cr = ioctl_GWINSZ(fd) os.close(fd) except: pass if not cr: # env vars or finally defaults try: cr = (env['LINES'], env['COLUMNS']) except: cr = (25, 80) return int(cr[1]-5), int(cr[0]-5) # reverse rows, cols def menu(screen, size, isInstalled): if isInstalled: installtext=_("Byobu currently launches at login (toggle off)") else: installtext=_("Byobu currently does not launch at login (toggle on)") li = Listbox(height = 8, width = 60, returnExit = 1) li.append(_("Help"), 1) li.append(_("Change Byobu's colors"), 2) li.append(_("Toggle status notifications"), 3) li.append(_("Change keybinding set"), 4) li.append(_("Change escape sequence"), 5) li.append(_("Create new windows"), 6) li.append(_("Manage default windows"), 7) li.append(installtext, 8) bb = ButtonBar(screen, (("Exit", "exit", ESC),), compact=1) g = GridForm(screen, _(" Byobu Configuration Menu"), 1, 2) g.add(li, 0, 0, padding=(4,2,4,2)) g.add(bb, 0, 1, padding=(1,1,0,0)) if bb.buttonPressed(g.runOnce()) == "exit": return 0 else: return li.current() def messagebox(screen, width, height, title, text, \ scroll=0, \ buttons=((_("Okay"), "okay"),(_("Cancel"), "cancel", ESC)) ): t = Textbox(width, height, text, scroll=scroll ) bb = ButtonBar(screen, buttons, compact = 1) g = GridForm(screen, title, 1, 2) g.add(t, 0, 0, padding=(0,0,0,0)) g.add(bb, 0, 1, padding=(1,1,0,0)) return bb.buttonPressed(g.runOnce()) def help(screen, size, config): for fn in glob.glob(DOC+'*/help.txt'): f=file(fn) text=f.read() f.close() text=text.replace("<esckey>", getesckey(), 1) t = Textbox(70, 14, text, scroll=0) bb = ButtonBar(screen, ((_("Menu"), "menu", ESC),), compact = 1) g = GridForm(screen, _("Byobu Help"), 1, 3) g.add(t, 0, 0, padding=(0,0,0,0)) g.add(bb, 0, 2, padding=(1,1,0,0)) button = bb.buttonPressed(g.runOnce()) return 100 def profile(screen, size): li = Listbox(height = 8, width = 60, scroll = 1, returnExit = 1) for choice in commands.getoutput('byobu-select-profile -l').splitlines(): li.append(choice, choice) bb = ButtonBar(screen, ((_("Apply"), "apply"), (_("Cancel"), "cancel", ESC)), compact = 1) g = GridForm(screen, _("Which profile would you like to use?"), 1, 2) g.add(li, 0, 0, padding=(4,2,4,2)) g.add(bb, 0, 1, padding=(1,1,0,0)) if bb.buttonPressed(g.runOnce()) != "cancel": commands.getoutput('byobu-select-profile --set %s' % li.current()) reload_required() return 100 def keybindings(screen, size): li = Listbox(height = 6, width = 60, returnExit = 1) for choice in commands.getoutput('ls '+SHARE+'/keybindings').splitlines(): if choice != "common" and choice != "none": li.append(choice, choice) li.append("none", "none") bb = ButtonBar(screen, ((_("Apply"), "apply"), (_("Cancel"), "cancel", ESC)), compact = 1) g = GridForm(screen, _("Which set of keybindings would you like to use?"), 1, 2) g.add(li, 0, 0, padding=(4,2,4,2)) g.add(bb, 0, 1, padding=(1,1,0,0)) if bb.buttonPressed(g.runOnce()) != "cancel": switch_keybindings(li.current()) reload_required() return 100 def switch_keybindings(set): commands.getoutput("sed -i -e 's:^source .*$:source "+SHARE+"/keybindings/"+set+":' "+HOME+"/."+PKG+"/keybindings") def newwindow(screen, size): title=Entry(8, text="bash", returnExit=1) titlel=Label(_("Title: ")) command=Entry(20, text="/bin/bash", returnExit=1) commandl=Label(_("Command: ")) rl=Label(_("Presets: ")) if len(cmd) > 10: scroll=1 size=10 else: scroll=0 size = len(cmd) r=CheckboxTree(size, scroll=scroll) count=0 for cur in cmd: r.append(cur[0], count) count=count+1 cb=Checkbox(_("Add to default windows")) bb = ButtonBar(screen, ((_("Apply"), "apply"), (_("Cancel"), "cancel", ESC)), compact = 1) g = GridForm(screen, _("Create new window(s):"), 2, 5 ) g.add(titlel, 0, 0, anchorLeft=1,padding=(4,1,0,1)) g.add(title, 1, 0, anchorLeft=1) g.add(commandl, 0, 1, anchorLeft=1, anchorTop=1,padding=(4,0,0,1)) g.add(command, 1, 1, anchorLeft=1) g.add(rl, 0, 2, anchorLeft=1,padding=(4,0,0,1)) g.add(r, 1, 2) g.add(cb, 1, 3, padding=(4,1,0,1)) g.add(bb, 1, 4, padding=(4,1,0,0)) if bb.buttonPressed(g.runOnce()) != "cancel": sel=r.getSelection() if sel: for s in sel: win='screen -t %s %s' % (cmd[s][1], cmd[s][2]) commands.getoutput(win) if cb.value(): appendwindow(win) else: win='screen -t %s %s' % (title.value(), command.value()) commands.getoutput(win) if cb.value(): appendwindow(win) return 100 def appendwindow(win): f=open(HOME+'/.'+PKG+'/windows', 'a') try: f.write(win+"\n") except IOError: return None finally: f.close() def readwindows(): if not os.path.isfile(HOME+'/.'+PKG+'/windows'): windowsfile=SHARE+'/windows/common' elif os.path.getsize(HOME+'/.'+PKG+'/windows') == 0: windowsfile=SHARE+'/windows/common' else: windowsfile=HOME+'/.'+PKG+'/windows' f=open(windowsfile) try: li=[] for line in f.readlines(): if line.startswith("# "): # this is a comment window=[-1, line] elif line.startswith("#"): # this is an inactive window window=[0, line.lstrip("#")] else: window=[1, line] li.append(window) return li except IOError: return None finally: f.close() def readstatus(): status={} status["arch"]=0 status["battery"]=0 status["cpu_count"]=1 status["cpu_freq"]=1 status["date"]=1 status["disk"]=0 status["ec2_cost"]=0 status["fan_speed"]=0 status["hostname"]=0 status["ip_address"]=0 status["load_average"]=1 status["logo"]=1 status["mail"]=0 status["mem_available"]=1 status["mem_used"]=1 status["menu"]=1 status["network"]=0 status["processes"]=0 status["reboot_required"]=1 status["release"]=1 status["temp_c"]=0 status["temp_f"]=0 status["time"]=1 status["users"]=0 status["updates_available"]=1 status["uptime"]=1 status["whoami"]=0 status["wifi_quality"]=0 if os.path.exists(HOME+'/.'+PKG+'/status'): f=open(HOME+'/.'+PKG+'/status', 'r') for line in f.readlines(): try: line = line.rstrip() (key, val) = line.split("=", 2) if status.has_key(key) and (val == "1" or val == "0"): status[key] = val except: continue f.close() li=[] keys = status.keys() keys.sort() for i in keys: window=[int(status[i]), i] li.append(window) return li def writestatus(items): f=open(HOME+'/.'+PKG+'/status', 'w') try: for i in items: if i[0] == 1: f.write(i[1]+"=1\n") elif i[0] == 0: f.write(i[1]+"=0\n") except IOError: return None finally: f.close() def togglestatus(screen, size): itemlist=readstatus() rl=Label("") r=CheckboxTree(12, scroll=1) count=0 for item in itemlist: if item[0] != -1: r.append(item[1],count,selected=item[0]) count=count+1 bb = ButtonBar(screen, ((_("Apply"), "apply"), (_("Cancel"), "cancel", ESC)), compact = 1) g = GridForm(screen, _("Toggle status notifications:"), 2, 4 ) g.add(rl, 0, 0, anchorLeft=1, anchorTop=1, padding=(4,0,0,1)) g.add(r, 1, 0) g.add(bb, 1, 1, padding=(4,1,0,0)) if bb.buttonPressed(g.runOnce()) != "cancel": count=0 for item in itemlist: if item[0] != -1: item[0] = r.getEntryValue(count)[1] count=count+1 writestatus(itemlist) reload_required() return 100 def writewindows(winlist): f=open(HOME+'/.'+PKG+'/windows', 'w') try: for win in winlist: if win[0] == -1: f.write(win[1]) elif win[0] == 0: f.write("#"+win[1]) else: f.write(win[1]) except IOError: return None finally: f.close() def defaultwindows(screen, size): winlist=readwindows() rl=Label(_("Windows:")) r=CheckboxTree(10, scroll=1) count=0 for win in winlist: if win[0] != -1: r.append(win[1],count,selected=win[0]) count=count+1 bb = ButtonBar(screen, ((_("Apply"), "apply"), (_("Cancel"), "cancel", ESC)), compact = 1) g = GridForm(screen, _("Select window(s) to create by default:"), 2, 4 ) g.add(rl, 0, 0, anchorLeft=1, anchorTop=1, padding=(4,0,0,1)) g.add(r, 1, 0) g.add(bb, 1, 1, padding=(4,1,0,0)) if bb.buttonPressed(g.runOnce()) != "cancel": count=0 for win in winlist: if win[0] != -1: win[0] = r.getEntryValue(count)[1] count=count+1 writewindows(winlist) return 100 def install(screen, size, isInstalled): if not isInstalled: out = commands.getoutput("bash /usr/share/"+PKG+"/byobu-launcher-install") if out == "": out = _("Byobu will be launched automatically next time you login.") button = messagebox(screen, 60, 2, "Message", out, \ buttons=((_("Menu"), ))) return 100 else: out = commands.getoutput("bash /usr/share/"+PKG+"/byobu-launcher-uninstall") if out == "": out = _("Byobu will not be used next time you login.") button = messagebox(screen, 60, 2, _("Message"), out, \ buttons=((_("Menu"), ))) return 101 def appendtofile(p, s): f = open(p, 'a') try: f.write(s) except IOError: return finally: f.close() return def getesckey(): path=HOME+'/.'+PKG+'/keybindings' if not os.path.exists(path): return DEF_ESC line = commands.getoutput("grep ^escape "+path) if line == "": return DEF_ESC return line[line.find('^')+1] def setesckey(key): path = HOME+'/.'+PKG+'/keybindings' if key != "": u = key[0].upper() l = key[0].lower() if os.path.exists(path): out = commands.getoutput("sed -i -e 's/^escape.*$//' "+path) appendtofile(path, "escape ^"+u+l+"\n") out = commands.getoutput("sed -i -e 's/^register.*$//' "+path) out = commands.getoutput("grep -h ^register "+SHARE+"/keybindings/*keys") appendtofile(path, out+"\n") out = commands.getoutput("sed -i -e 's/\"\^a/\"\^"+l+"/g' "+path) out = commands.getoutput("sed -i -e '/^$/d' "+path) def chgesc(screen, size): esc=Entry(2, text=getesckey(), returnExit=1) escl=Label(_("Escape key: ctrl-")) bb = ButtonBar(screen, ((_("Apply"), "apply"), (_("Cancel"), "cancel", ESC)), compact = 1) g = GridForm(screen, _("Change escape sequence:"), 2, 4 ) g.add(escl, 0, 0, anchorLeft=1, padding=(1,0,0,1)) g.add(esc, 1, 0, anchorLeft=1) g.add(bb, 1, 1) g.setTimer(100) loop=1 while loop: which=g.run() if which == "TIMER": val=esc.value() if len(val) > 1: esc.set(val[1]) # Ensure that the escape sequence is not set to a number try: dummy = int(esc.value()) esc.set(DEF_ESC) except: # do nothing dummy = "foo" else: loop=0 screen.popWindow() button = bb.buttonPressed(which) if button != "cancel": setesckey(esc.value()) reload_required() if button == "exit": return 0 return 100 def main(): """This is the main loop of our utility """ size = terminal_size() screen = SnackScreen() screen.drawRootText(1,0,_(' Byobu Configuration Menu')) screen.pushHelpLine(_('<Tab>/<Alt-Tab> between elements | <Enter> selects | <Esc> exits')) config = SafeConfigParser() isInstalled = (commands.getoutput('grep byobu-launcher '+(HOME+'/.profile')) != "") tag = 100 while tag > 0 : tag = menu(screen, size, isInstalled) if tag == 1: tag = help(screen, size, config) elif tag == 2: tag = profile(screen, size) elif tag == 3: tag = togglestatus(screen, size) elif tag == 4: tag = keybindings(screen, size) elif tag == 5: tag = chgesc(screen, size) elif tag == 6: tag = newwindow(screen, size) elif tag == 7: tag = defaultwindows(screen, size) elif tag == 8: tag = install(screen, size, isInstalled) isInstalled=(tag == 100) screen.finish() sys.exit(0) if __name__ == "__main__": main()