mirror of
https://github.com/dustinkirkland/byobu
synced 2025-08-20 13:33:23 -07:00
* debian/control, debian/rules, README, usr/bin/byobu-config,
usr/bin/byobu-config => usr/lib/byobu/include/config.py, usr/bin/byobu-select-session, usr/bin/byobu-select-session => usr/lib/byobu/include/select-session.py, usr/lib/byobu/include/constants, usr/lib/byobu/include/Makefile.am: - LP: #1253458 - introduce a new BYOBU_PYTHON environment variable, that defines your desired python interpreter - prefer python, then python2, then python3
This commit is contained in:
parent
971f3c1971
commit
c0f4dbc00c
10 changed files with 599 additions and 531 deletions
2
README
2
README
|
@ -18,7 +18,7 @@ install locally, using the following instructions...
|
||||||
cd byobu*
|
cd byobu*
|
||||||
./configure --prefix="$HOME/byobu"
|
./configure --prefix="$HOME/byobu"
|
||||||
4) OPTIONAL: Use python from your environment, rather than from your distro
|
4) OPTIONAL: Use python from your environment, rather than from your distro
|
||||||
sed -i -e "s:/usr/bin/python:/usr/bin/env python" usr/bin/* usr/lib/byobu/include/*
|
echo "export BYOBU_PYTHON='/usr/bin/env python'" >> $HOME/.bashrc
|
||||||
5) Build:
|
5) Build:
|
||||||
make
|
make
|
||||||
6) Install:
|
6) Install:
|
||||||
|
|
9
debian/changelog
vendored
9
debian/changelog
vendored
|
@ -6,6 +6,15 @@ byobu (5.68) unreleased; urgency=low
|
||||||
- add a new status item, to show the session name
|
- add a new status item, to show the session name
|
||||||
* usr/lib/byobu/include/icons, usr/lib/byobu/session:
|
* usr/lib/byobu/include/icons, usr/lib/byobu/session:
|
||||||
- use an icon for the session status item
|
- use an icon for the session status item
|
||||||
|
* debian/control, debian/rules, README, usr/bin/byobu-config,
|
||||||
|
usr/bin/byobu-config => usr/lib/byobu/include/config.py,
|
||||||
|
usr/bin/byobu-select-session, usr/bin/byobu-select-session =>
|
||||||
|
usr/lib/byobu/include/select-session.py,
|
||||||
|
usr/lib/byobu/include/constants, usr/lib/byobu/include/Makefile.am:
|
||||||
|
- LP: #1253458
|
||||||
|
- introduce a new BYOBU_PYTHON environment variable, that defines
|
||||||
|
your desired python interpreter
|
||||||
|
- prefer python, then python2, then python3
|
||||||
|
|
||||||
-- Dustin Kirkland <kirkland@ubuntu.com> Mon, 02 Dec 2013 18:46:28 -0600
|
-- Dustin Kirkland <kirkland@ubuntu.com> Mon, 02 Dec 2013 18:46:28 -0600
|
||||||
|
|
||||||
|
|
4
debian/control
vendored
4
debian/control
vendored
|
@ -14,8 +14,8 @@ Depends:
|
||||||
${misc:Depends}, ${perl:Depends}, ${python:Depends},
|
${misc:Depends}, ${perl:Depends}, ${python:Depends},
|
||||||
debconf (>= 0.5) | debconf-2.0,
|
debconf (>= 0.5) | debconf-2.0,
|
||||||
gettext-base,
|
gettext-base,
|
||||||
python,
|
python3|python,
|
||||||
python-newt (>= 0.52.2-11),
|
python3-newt|python-newt,
|
||||||
tmux (>= 1.5) | screen,
|
tmux (>= 1.5) | screen,
|
||||||
gawk
|
gawk
|
||||||
Recommends:
|
Recommends:
|
||||||
|
|
2
debian/rules
vendored
2
debian/rules
vendored
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
override_dh_auto_build:
|
override_dh_auto_build:
|
||||||
# Check python syntax
|
# Check python syntax
|
||||||
pep8 --verbose --repeat --ignore W191,E501 usr/bin/byobu-config usr/bin/byobu-select-session
|
pep8 --verbose --repeat --ignore W191,E501 usr/lib/byobu/include/config.py usr/lib/byobu/include/select-session.py
|
||||||
# Check shell syntax
|
# Check shell syntax
|
||||||
sh -n `find . -type f -exec grep -l "^\#\!/bin/sh" '{}' \;`
|
sh -n `find . -type f -exec grep -l "^\#\!/bin/sh" '{}' \;`
|
||||||
# Check for bashisms in shell scripts
|
# Check for bashisms in shell scripts
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
#!/usr/bin/python
|
#!/bin/sh -e
|
||||||
#
|
#
|
||||||
# byobu-config
|
# byobu-config - interactive byobu configuration wrapper script
|
||||||
# Copyright (C) 2008 Canonical Ltd.
|
# Copyright (C) 2013 Dustin Kirkland
|
||||||
# Copyright (C) 2008-2013 Dustin Kirkland <kirkland@byobu.co>
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Authors: Nick Barcet <nick.barcet@ubuntu.com>
|
# Authors: Dustin Kirkland <kirkland@byobu.co>
|
||||||
# Dustin Kirkland <kirkland@byobu.co>
|
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,366 +17,8 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# If you change any strings, please generate localization information with:
|
PKG="byobu"
|
||||||
# ./debian/rules get-po
|
[ -z "${BYOBU_PREFIX}" ] && export BYOBU_PREFIX="/usr" || export BYOBU_PREFIX
|
||||||
|
. "${BYOBU_PREFIX}/lib/${PKG}/include/common"
|
||||||
|
|
||||||
import sys
|
${BYOBU_PYTHON} "${BYOBU_PREFIX}/lib/${PKG}/include/config.py"
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import time
|
|
||||||
import string
|
|
||||||
import subprocess
|
|
||||||
import gettext
|
|
||||||
import glob
|
|
||||||
|
|
||||||
|
|
||||||
def error(msg):
|
|
||||||
print("ERROR: %s" % msg)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
import snack
|
|
||||||
from snack import *
|
|
||||||
except:
|
|
||||||
error("Could not import the python snack module")
|
|
||||||
|
|
||||||
|
|
||||||
PKG = "byobu"
|
|
||||||
HOME = os.getenv("HOME")
|
|
||||||
USER = os.getenv("USER")
|
|
||||||
BYOBU_CONFIG_DIR = os.getenv("BYOBU_CONFIG_DIR", HOME + "/.byobu")
|
|
||||||
BYOBU_RUN_DIR = os.getenv("BYOBU_RUN_DIR", HOME + "/.cache/byobu")
|
|
||||||
BYOBU_BACKEND = os.getenv("BYOBU_BACKEND", "tmux")
|
|
||||||
BYOBU_SOCKETDIR = os.getenv("SOCKETDIR", "/var/run/screen")
|
|
||||||
BYOBU_PREFIX = os.getenv("BYOBU_PREFIX", "/usr")
|
|
||||||
SHARE = BYOBU_PREFIX + '/share/' + PKG
|
|
||||||
DOC = BYOBU_PREFIX + '/share/doc/' + PKG
|
|
||||||
if not os.path.exists(SHARE):
|
|
||||||
SHARE = BYOBU_CONFIG_DIR + "/" + SHARE
|
|
||||||
if not os.path.exists(DOC):
|
|
||||||
DOC = BYOBU_CONFIG_DIR + "/" + DOC
|
|
||||||
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 session and start a new one."
|
|
||||||
RELOAD_FLAG = "%s/reload-required" % (BYOBU_RUN_DIR)
|
|
||||||
ESC = ''
|
|
||||||
snack.hotkeys[ESC] = ord(ESC)
|
|
||||||
snack.hotkeys[ord(ESC)] = ESC
|
|
||||||
gettext.bindtextdomain(PKG, SHARE + '/po')
|
|
||||||
gettext.textdomain(PKG)
|
|
||||||
_ = gettext.gettext
|
|
||||||
|
|
||||||
|
|
||||||
def ioctl_GWINSZ(fd):
|
|
||||||
# Discover terminal width
|
|
||||||
try:
|
|
||||||
import fcntl
|
|
||||||
import termios
|
|
||||||
import struct
|
|
||||||
import os
|
|
||||||
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
|
|
||||||
except:
|
|
||||||
return None
|
|
||||||
return cr
|
|
||||||
|
|
||||||
|
|
||||||
def reload_required():
|
|
||||||
try:
|
|
||||||
if not os.path.exists(BYOBU_CONFIG_DIR):
|
|
||||||
# 493 (decimal) is 0755 (octal)
|
|
||||||
# Use decimal for portability across all python versions
|
|
||||||
os.makedirs(BYOBU_CONFIG_DIR, 493)
|
|
||||||
f = open(RELOAD_FLAG, 'w')
|
|
||||||
f.close()
|
|
||||||
if BYOBU_BACKEND == "screen":
|
|
||||||
subprocess.call([BYOBU_BACKEND, "-X", "at", "0", "source", "%s/profile" % BYOBU_CONFIG_DIR])
|
|
||||||
except:
|
|
||||||
True
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
# reverse rows, cols
|
|
||||||
return int(cr[1] - 5), int(cr[0] - 5)
|
|
||||||
|
|
||||||
|
|
||||||
def menu(snackScreen, 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=6, width=60, returnExit=1)
|
|
||||||
li.append(_("Help -- Quick Start Guide"), 1)
|
|
||||||
li.append(_("Toggle status notifications"), 2)
|
|
||||||
li.append(_("Change escape sequence"), 3)
|
|
||||||
li.append(installtext, 4)
|
|
||||||
bb = ButtonBar(snackScreen, (("Exit", "exit", ESC),), compact=1)
|
|
||||||
g = GridForm(snackScreen, _(" 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(snackScreen, width, height, title, text, scroll=0, buttons=((_("Okay"), "okay"), (_("Cancel"), "cancel", ESC))):
|
|
||||||
t = Textbox(width, height, text, scroll=scroll)
|
|
||||||
bb = ButtonBar(snackScreen, buttons, compact=1)
|
|
||||||
g = GridForm(snackScreen, 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(snackScreen, size):
|
|
||||||
f = open(DOC + '/help.' + BYOBU_BACKEND + '.txt')
|
|
||||||
text = f.read()
|
|
||||||
f.close()
|
|
||||||
text = text.replace("<esckey>", getesckey(), 1)
|
|
||||||
t = Textbox(67, 16, text, scroll=1, wrap=1)
|
|
||||||
bb = ButtonBar(snackScreen, ((_("Menu"), "menu", ESC),), compact=1)
|
|
||||||
g = GridForm(snackScreen, _("Byobu Help"), 2, 4)
|
|
||||||
g.add(t, 1, 0)
|
|
||||||
g.add(bb, 1, 1, padding=(1, 1, 0, 0))
|
|
||||||
button = bb.buttonPressed(g.runOnce())
|
|
||||||
return 100
|
|
||||||
|
|
||||||
|
|
||||||
def readstatus():
|
|
||||||
status = {}
|
|
||||||
glo = {}
|
|
||||||
loc = {}
|
|
||||||
for f in [SHARE + '/status/status', BYOBU_CONFIG_DIR + '/status']:
|
|
||||||
if os.path.exists(f):
|
|
||||||
try:
|
|
||||||
exec(open(f).read(), glo, loc)
|
|
||||||
except:
|
|
||||||
error("Invalid configuration [%s]" % f)
|
|
||||||
if BYOBU_BACKEND == "tmux":
|
|
||||||
items = "%s %s" % (loc["tmux_left"], loc["tmux_right"])
|
|
||||||
else:
|
|
||||||
items = "%s %s %s %s" % (loc["screen_upper_left"], loc["screen_upper_right"], loc["screen_lower_left"], loc["screen_lower_right"])
|
|
||||||
for i in items.split():
|
|
||||||
if i.startswith("#"):
|
|
||||||
i = i.replace("#", "")
|
|
||||||
status[i] = "0"
|
|
||||||
else:
|
|
||||||
status[i] = "1"
|
|
||||||
li = []
|
|
||||||
keys = status.keys()
|
|
||||||
for i in sorted(keys):
|
|
||||||
window = [int(status[i]), i]
|
|
||||||
li.append(window)
|
|
||||||
return li
|
|
||||||
|
|
||||||
|
|
||||||
def genstatusstring(s, status):
|
|
||||||
new = ""
|
|
||||||
glo = {}
|
|
||||||
loc = {}
|
|
||||||
exec(open(SHARE + '/status/status').read(), glo, loc)
|
|
||||||
for i in loc[s].split():
|
|
||||||
if i.startswith("#"):
|
|
||||||
i = i.replace("#", "")
|
|
||||||
if status[i] == 1:
|
|
||||||
new += " " + i
|
|
||||||
else:
|
|
||||||
new += " #" + i
|
|
||||||
return new
|
|
||||||
|
|
||||||
|
|
||||||
def writestatus(items):
|
|
||||||
status = {}
|
|
||||||
path = BYOBU_CONFIG_DIR + '/status'
|
|
||||||
for i in items:
|
|
||||||
status[i[1]] = i[0]
|
|
||||||
for key in ["tmux_left", "tmux_right", "screen_upper_left", "screen_upper_right", "screen_lower_left", "screen_lower_right"]:
|
|
||||||
if key.startswith(BYOBU_BACKEND):
|
|
||||||
f = open(path, "r")
|
|
||||||
lines = f.readlines()
|
|
||||||
f.close()
|
|
||||||
f = open(path, "w")
|
|
||||||
for l in lines:
|
|
||||||
if l.startswith("%s=" % key):
|
|
||||||
val = genstatusstring(key, status)
|
|
||||||
f.write("%s=\"%s\"\n" % (key, val))
|
|
||||||
else:
|
|
||||||
f.write(l)
|
|
||||||
f.close
|
|
||||||
|
|
||||||
|
|
||||||
def togglestatus(snackScreen, 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(snackScreen, ((_("Apply"), "apply"), (_("Cancel"), "cancel", ESC)), compact=1)
|
|
||||||
g = GridForm(snackScreen, _("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 install(snackScreen, size, isInstalled):
|
|
||||||
out = ""
|
|
||||||
if isInstalled:
|
|
||||||
if subprocess.call(["byobu-launcher-uninstall"]) == 0:
|
|
||||||
out = _("Byobu will not be launched next time you login.")
|
|
||||||
button = messagebox(snackScreen, 60, 2, _("Message"), out, buttons=((_("Menu"), )))
|
|
||||||
return 101
|
|
||||||
else:
|
|
||||||
if subprocess.call(["byobu-launcher-install"]) == 0:
|
|
||||||
out = _("Byobu will be launched automatically next time you login.")
|
|
||||||
button = messagebox(snackScreen, 60, 2, "Message", out, buttons=((_("Menu"), )))
|
|
||||||
return 100
|
|
||||||
|
|
||||||
|
|
||||||
def appendtofile(p, s):
|
|
||||||
f = open(p, 'a')
|
|
||||||
try:
|
|
||||||
f.write(s)
|
|
||||||
except IOError:
|
|
||||||
f.close()
|
|
||||||
return
|
|
||||||
f.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def getesckey():
|
|
||||||
line = ""
|
|
||||||
if BYOBU_BACKEND == "tmux":
|
|
||||||
path = BYOBU_CONFIG_DIR + '/keybindings.tmux'
|
|
||||||
if os.path.exists(path):
|
|
||||||
for l in open(path):
|
|
||||||
if l.startswith("set -g prefix "):
|
|
||||||
line = l
|
|
||||||
else:
|
|
||||||
return DEF_ESC
|
|
||||||
else:
|
|
||||||
path = BYOBU_CONFIG_DIR + '/keybindings'
|
|
||||||
if os.path.exists(path):
|
|
||||||
for l in open(path):
|
|
||||||
if l.startswith("escape "):
|
|
||||||
line = l
|
|
||||||
else:
|
|
||||||
return DEF_ESC
|
|
||||||
if line == "":
|
|
||||||
return DEF_ESC
|
|
||||||
esc = line[line.find('^') + 1]
|
|
||||||
if esc == "`":
|
|
||||||
esc = " "
|
|
||||||
return esc
|
|
||||||
|
|
||||||
|
|
||||||
def setesckey(key):
|
|
||||||
if key.isalpha():
|
|
||||||
subprocess.call(["byobu-ctrl-a", "screen", key])
|
|
||||||
|
|
||||||
|
|
||||||
def chgesc(snackScreen, size):
|
|
||||||
esc = Entry(2, text=getesckey(), returnExit=1)
|
|
||||||
escl = Label(_("Escape key: ctrl-"))
|
|
||||||
bb = ButtonBar(snackScreen, ((_("Apply"), "apply"), (_("Cancel"), "cancel", ESC)), compact=1)
|
|
||||||
g = GridForm(snackScreen, _("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 escape sequence is not \ or /
|
|
||||||
if val == '/' or val == '\\':
|
|
||||||
esc.set(DEF_ESC)
|
|
||||||
# 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
|
|
||||||
snackScreen.popWindow()
|
|
||||||
button = bb.buttonPressed(which)
|
|
||||||
if button != "cancel":
|
|
||||||
setesckey(esc.value())
|
|
||||||
reload_required()
|
|
||||||
if button == "exit":
|
|
||||||
return 0
|
|
||||||
return 100
|
|
||||||
|
|
||||||
|
|
||||||
def autolaunch():
|
|
||||||
if os.path.exists(BYOBU_CONFIG_DIR + "/disable-autolaunch"):
|
|
||||||
return 0
|
|
||||||
try:
|
|
||||||
for line in open("%s/.profile" % HOME):
|
|
||||||
if "byobu-launch" in line:
|
|
||||||
return 1
|
|
||||||
except:
|
|
||||||
return 0
|
|
||||||
if os.path.exists("/etc/profile.d/Z98-%s.sh" % PKG):
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""This is the main loop of our utility"""
|
|
||||||
size = terminal_size()
|
|
||||||
snackScreen = SnackScreen()
|
|
||||||
snackScreen.drawRootText(1, 0, _('Byobu Configuration Menu'))
|
|
||||||
snackScreen.pushHelpLine(_('<Tab> between elements | <Enter> selects | <Esc> exits'))
|
|
||||||
isInstalled = autolaunch()
|
|
||||||
tag = 100
|
|
||||||
while tag > 0:
|
|
||||||
tag = menu(snackScreen, size, isInstalled)
|
|
||||||
if tag == 1:
|
|
||||||
tag = help(snackScreen, size)
|
|
||||||
elif tag == 2:
|
|
||||||
tag = togglestatus(snackScreen, size)
|
|
||||||
elif tag == 3:
|
|
||||||
tag = chgesc(snackScreen, size)
|
|
||||||
elif tag == 4:
|
|
||||||
tag = install(snackScreen, size, isInstalled)
|
|
||||||
isInstalled = autolaunch()
|
|
||||||
snackScreen.finish()
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
#!/usr/bin/python
|
#!/bin/sh -e
|
||||||
#
|
#
|
||||||
# byobu-select-session
|
# byobu-select-session - interactive session select wrapper script
|
||||||
# Copyright (C) 2010 Canonical Ltd.
|
# Copyright (C) 2013 Dustin Kirkland
|
||||||
# Copyright (C) 2012-2013 Dustin Kirkland <kirkland@byobu.co>
|
|
||||||
#
|
#
|
||||||
# Authors: Dustin Kirkland <kirkland@byobu.co>
|
# Authors: Dustin Kirkland <kirkland@byobu.co>
|
||||||
# Ryan C. Thompson <rct@thompsonclan.org>
|
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,156 +17,8 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
PKG="byobu"
|
||||||
|
[ -z "${BYOBU_PREFIX}" ] && export BYOBU_PREFIX="/usr" || export BYOBU_PREFIX
|
||||||
|
. "${BYOBU_PREFIX}/lib/${PKG}/include/common"
|
||||||
|
|
||||||
import os
|
${BYOBU_PYTHON} "${BYOBU_PREFIX}/lib/${PKG}/include/select-session.py"
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
PKG = "byobu"
|
|
||||||
SHELL = os.getenv("SHELL", "/bin/bash")
|
|
||||||
HOME = os.getenv("HOME")
|
|
||||||
BYOBU_CONFIG_DIR = os.getenv("BYOBU_CONFIG_DIR", HOME + "/.byobu")
|
|
||||||
BYOBU_BACKEND = os.getenv("BYOBU_BACKEND", "tmux")
|
|
||||||
choice = -1
|
|
||||||
sessions = []
|
|
||||||
text = []
|
|
||||||
|
|
||||||
BYOBU_UPDATE_ENVVARS = ["DISPLAY", "DBUS_SESSION_BUS_ADDRESS", "SESSION_MANAGER", "GPG_AGENT_INFO", "XDG_SESSION_COOKIE", "XDG_SESSION_PATH", "GNOME_KEYRING_CONTROL", "GNOME_KEYRING_PID", "GPG_AGENT_INFO", "SSH_ASKPASS", "SSH_AUTH_SOCK", "SSH_AGENT_PID", "WINDOWID", "UPSTART_JOB", "UPSTART_EVENTS", "UPSTART_SESSION", "UPSTART_INSTANCE"]
|
|
||||||
|
|
||||||
|
|
||||||
def get_sessions():
|
|
||||||
sessions = []
|
|
||||||
i = 0
|
|
||||||
output = False
|
|
||||||
if BYOBU_BACKEND == "screen":
|
|
||||||
try:
|
|
||||||
output = subprocess.Popen(["screen", "-ls"], stdout=subprocess.PIPE).communicate()[0]
|
|
||||||
except subprocess.CalledProcessError as cpe:
|
|
||||||
# screen -ls seems to always return 1
|
|
||||||
if cpe.returncode != 1:
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
output = cpe.output
|
|
||||||
if not sys.stdout.encoding is None:
|
|
||||||
output = output.decode(sys.stdout.encoding)
|
|
||||||
if output:
|
|
||||||
for s in output.splitlines():
|
|
||||||
s = re.sub(r'\s+', ' ', s)
|
|
||||||
# Ignore hidden sessions (named sessions that start with a ".")
|
|
||||||
if s and s != " " and (s.find(" ") == 0 and len(s) > 1 and s.count("..") == 0):
|
|
||||||
text.append("screen: %s" % s.strip())
|
|
||||||
items = s.split(" ")
|
|
||||||
sessions.append("screen____%s" % items[1])
|
|
||||||
i += 1
|
|
||||||
if BYOBU_BACKEND == "tmux":
|
|
||||||
output = subprocess.Popen(["tmux", "list-sessions"], stdout=subprocess.PIPE).communicate()[0]
|
|
||||||
output = output.decode(sys.stdout.encoding)
|
|
||||||
if output:
|
|
||||||
for s in output.splitlines():
|
|
||||||
if s:
|
|
||||||
text.append("tmux: %s" % s.strip())
|
|
||||||
sessions.append("tmux____%s" % s.split(":")[0])
|
|
||||||
i += 1
|
|
||||||
return sessions
|
|
||||||
|
|
||||||
|
|
||||||
def update_environment(session):
|
|
||||||
backend, session_name = session.split("____", 2)
|
|
||||||
for var in BYOBU_UPDATE_ENVVARS:
|
|
||||||
value = os.getenv(var)
|
|
||||||
if value:
|
|
||||||
if backend == "tmux":
|
|
||||||
cmd = ["tmux", "setenv", "-t", session_name, var, value]
|
|
||||||
else:
|
|
||||||
cmd = ["screen", "-S", session_name, "-X", "setenv", var, value]
|
|
||||||
print("Sending variable: %s" % (cmd, ))
|
|
||||||
subprocess.call(cmd, stdout=open(os.devnull, "w"))
|
|
||||||
|
|
||||||
|
|
||||||
def attach_session(session):
|
|
||||||
print("Attaching: [%s]\n" % session)
|
|
||||||
update_environment(session)
|
|
||||||
backend, session_name = session.split("____", 2)
|
|
||||||
# must use the binary, not the wrapper!
|
|
||||||
if backend == "tmux":
|
|
||||||
os.execvp("tmux", ["", "-2", "attach", "-t", session_name])
|
|
||||||
else:
|
|
||||||
os.execvp("screen", ["", "-AOxRR", session_name])
|
|
||||||
|
|
||||||
# Confirm nested session, if necessary
|
|
||||||
if os.getenv("BYOBU_NESTING", "0") != "1":
|
|
||||||
if (BYOBU_BACKEND == "tmux" and os.getenv("TMUX")) or (BYOBU_BACKEND == "screen" and "screen" in os.getenv("TERM")):
|
|
||||||
sys.stderr.write("WARNING: Sessions should be nested with care.\n")
|
|
||||||
try:
|
|
||||||
nest = raw_input("Are you sure you want to run Byobu inside another session? [y/N]: ")
|
|
||||||
if nest != "Y" and nest != "y":
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
if os.getenv("TMUX"):
|
|
||||||
os.unsetenv("TMUX")
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
sys.stdout.write("\n")
|
|
||||||
sys.exit(1)
|
|
||||||
except:
|
|
||||||
sys.stdout.write("\n")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
sessions = get_sessions()
|
|
||||||
|
|
||||||
show_shell = os.path.exists("%s/.always-select" % (BYOBU_CONFIG_DIR))
|
|
||||||
if len(sessions) > 1 or show_shell:
|
|
||||||
sessions.append("NEW")
|
|
||||||
text.append("Create a new Byobu session (%s)" % BYOBU_BACKEND)
|
|
||||||
sessions.append("SHELL")
|
|
||||||
text.append("Run a shell without Byobu (%s)" % SHELL)
|
|
||||||
|
|
||||||
if len(sessions) > 1:
|
|
||||||
sys.stdout.write("\nByobu sessions...\n\n")
|
|
||||||
tries = 0
|
|
||||||
while tries < 3:
|
|
||||||
i = 1
|
|
||||||
for s in text:
|
|
||||||
sys.stdout.write(" %d. %s\n" % (i, s))
|
|
||||||
i += 1
|
|
||||||
try:
|
|
||||||
choice = int(input("\nChoose 1-%d [1]: " % (i - 1)))
|
|
||||||
if choice >= 1 and choice < i:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
tries += 1
|
|
||||||
choice = -1
|
|
||||||
sys.stderr.write("\nERROR: Invalid input\n")
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
sys.stdout.write("\n")
|
|
||||||
sys.exit(0)
|
|
||||||
except:
|
|
||||||
if choice == "" or choice == -1:
|
|
||||||
choice = 1
|
|
||||||
break
|
|
||||||
tries += 1
|
|
||||||
choice = -1
|
|
||||||
sys.stderr.write("\nERROR: Invalid input\n")
|
|
||||||
elif len(sessions) == 1:
|
|
||||||
# Auto-select the only session
|
|
||||||
choice = 1
|
|
||||||
|
|
||||||
if choice >= 1:
|
|
||||||
if sessions[choice - 1] == "NEW":
|
|
||||||
# Create a new session
|
|
||||||
if BYOBU_BACKEND == "tmux":
|
|
||||||
os.execvp("byobu", ["", "new-session", SHELL])
|
|
||||||
else:
|
|
||||||
os.execvp("byobu", ["", SHELL])
|
|
||||||
elif sessions[choice - 1] == "SHELL":
|
|
||||||
os.execvp(SHELL, [SHELL])
|
|
||||||
else:
|
|
||||||
# Attach to the chosen session; must use the binary, not the wrapper!
|
|
||||||
attach_session(sessions[choice - 1])
|
|
||||||
|
|
||||||
# No valid selection, default to the youngest session, create if necessary
|
|
||||||
if BYOBU_BACKEND == "tmux":
|
|
||||||
args = ""
|
|
||||||
else:
|
|
||||||
args = "-AOxRR"
|
|
||||||
os.execvp("byobu", ["", args])
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
inclibdirdir = $(prefix)/lib/@PACKAGE@/include
|
inclibdirdir = $(prefix)/lib/@PACKAGE@/include
|
||||||
inclibdir_SCRIPTS = common constants cycle-status dirs icons mondrian notify_osd shutil ec2instancespricing.py tmux-detach-all-but-current-client toggle-utf8
|
inclibdir_SCRIPTS = common config.py constants cycle-status dirs icons mondrian notify_osd shutil ec2instancespricing.py select-session.py tmux-detach-all-but-current-client toggle-utf8
|
||||||
|
|
385
usr/lib/byobu/include/config.py
Executable file
385
usr/lib/byobu/include/config.py
Executable file
|
@ -0,0 +1,385 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# config.py
|
||||||
|
# Copyright (C) 2008 Canonical Ltd.
|
||||||
|
# Copyright (C) 2008-2013 Dustin Kirkland <kirkland@byobu.co>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Authors: Nick Barcet <nick.barcet@ubuntu.com>
|
||||||
|
# Dustin Kirkland <kirkland@byobu.co>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import time
|
||||||
|
import string
|
||||||
|
import subprocess
|
||||||
|
import gettext
|
||||||
|
import glob
|
||||||
|
|
||||||
|
|
||||||
|
def error(msg):
|
||||||
|
print("ERROR: %s" % msg)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
import snack
|
||||||
|
from snack import *
|
||||||
|
except:
|
||||||
|
error("Could not import the python snack module")
|
||||||
|
|
||||||
|
|
||||||
|
PKG = "byobu"
|
||||||
|
HOME = os.getenv("HOME")
|
||||||
|
USER = os.getenv("USER")
|
||||||
|
BYOBU_CONFIG_DIR = os.getenv("BYOBU_CONFIG_DIR", HOME + "/.byobu")
|
||||||
|
BYOBU_RUN_DIR = os.getenv("BYOBU_RUN_DIR", HOME + "/.cache/byobu")
|
||||||
|
BYOBU_BACKEND = os.getenv("BYOBU_BACKEND", "tmux")
|
||||||
|
BYOBU_SOCKETDIR = os.getenv("SOCKETDIR", "/var/run/screen")
|
||||||
|
BYOBU_PREFIX = os.getenv("BYOBU_PREFIX", "/usr")
|
||||||
|
SHARE = BYOBU_PREFIX + '/share/' + PKG
|
||||||
|
DOC = BYOBU_PREFIX + '/share/doc/' + PKG
|
||||||
|
if not os.path.exists(SHARE):
|
||||||
|
SHARE = BYOBU_CONFIG_DIR + "/" + SHARE
|
||||||
|
if not os.path.exists(DOC):
|
||||||
|
DOC = BYOBU_CONFIG_DIR + "/" + DOC
|
||||||
|
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 session and start a new one."
|
||||||
|
RELOAD_FLAG = "%s/reload-required" % (BYOBU_RUN_DIR)
|
||||||
|
ESC = ''
|
||||||
|
snack.hotkeys[ESC] = ord(ESC)
|
||||||
|
snack.hotkeys[ord(ESC)] = ESC
|
||||||
|
gettext.bindtextdomain(PKG, SHARE + '/po')
|
||||||
|
gettext.textdomain(PKG)
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
|
def ioctl_GWINSZ(fd):
|
||||||
|
# Discover terminal width
|
||||||
|
try:
|
||||||
|
import fcntl
|
||||||
|
import termios
|
||||||
|
import struct
|
||||||
|
import os
|
||||||
|
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
return cr
|
||||||
|
|
||||||
|
|
||||||
|
def reload_required():
|
||||||
|
try:
|
||||||
|
if not os.path.exists(BYOBU_CONFIG_DIR):
|
||||||
|
# 493 (decimal) is 0755 (octal)
|
||||||
|
# Use decimal for portability across all python versions
|
||||||
|
os.makedirs(BYOBU_CONFIG_DIR, 493)
|
||||||
|
f = open(RELOAD_FLAG, 'w')
|
||||||
|
f.close()
|
||||||
|
if BYOBU_BACKEND == "screen":
|
||||||
|
subprocess.call([BYOBU_BACKEND, "-X", "at", "0", "source", "%s/profile" % BYOBU_CONFIG_DIR])
|
||||||
|
except:
|
||||||
|
True
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
# reverse rows, cols
|
||||||
|
return int(cr[1] - 5), int(cr[0] - 5)
|
||||||
|
|
||||||
|
|
||||||
|
def menu(snackScreen, 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=6, width=60, returnExit=1)
|
||||||
|
li.append(_("Help -- Quick Start Guide"), 1)
|
||||||
|
li.append(_("Toggle status notifications"), 2)
|
||||||
|
li.append(_("Change escape sequence"), 3)
|
||||||
|
li.append(installtext, 4)
|
||||||
|
bb = ButtonBar(snackScreen, (("Exit", "exit", ESC),), compact=1)
|
||||||
|
g = GridForm(snackScreen, _(" 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(snackScreen, width, height, title, text, scroll=0, buttons=((_("Okay"), "okay"), (_("Cancel"), "cancel", ESC))):
|
||||||
|
t = Textbox(width, height, text, scroll=scroll)
|
||||||
|
bb = ButtonBar(snackScreen, buttons, compact=1)
|
||||||
|
g = GridForm(snackScreen, 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(snackScreen, size):
|
||||||
|
f = open(DOC + '/help.' + BYOBU_BACKEND + '.txt')
|
||||||
|
text = f.read()
|
||||||
|
f.close()
|
||||||
|
text = text.replace("<esckey>", getesckey(), 1)
|
||||||
|
t = Textbox(67, 16, text, scroll=1, wrap=1)
|
||||||
|
bb = ButtonBar(snackScreen, ((_("Menu"), "menu", ESC),), compact=1)
|
||||||
|
g = GridForm(snackScreen, _("Byobu Help"), 2, 4)
|
||||||
|
g.add(t, 1, 0)
|
||||||
|
g.add(bb, 1, 1, padding=(1, 1, 0, 0))
|
||||||
|
button = bb.buttonPressed(g.runOnce())
|
||||||
|
return 100
|
||||||
|
|
||||||
|
|
||||||
|
def readstatus():
|
||||||
|
status = {}
|
||||||
|
glo = {}
|
||||||
|
loc = {}
|
||||||
|
for f in [SHARE + '/status/status', BYOBU_CONFIG_DIR + '/status']:
|
||||||
|
if os.path.exists(f):
|
||||||
|
try:
|
||||||
|
exec(open(f).read(), glo, loc)
|
||||||
|
except:
|
||||||
|
error("Invalid configuration [%s]" % f)
|
||||||
|
if BYOBU_BACKEND == "tmux":
|
||||||
|
items = "%s %s" % (loc["tmux_left"], loc["tmux_right"])
|
||||||
|
else:
|
||||||
|
items = "%s %s %s %s" % (loc["screen_upper_left"], loc["screen_upper_right"], loc["screen_lower_left"], loc["screen_lower_right"])
|
||||||
|
for i in items.split():
|
||||||
|
if i.startswith("#"):
|
||||||
|
i = i.replace("#", "")
|
||||||
|
status[i] = "0"
|
||||||
|
else:
|
||||||
|
status[i] = "1"
|
||||||
|
li = []
|
||||||
|
keys = status.keys()
|
||||||
|
for i in sorted(keys):
|
||||||
|
window = [int(status[i]), i]
|
||||||
|
li.append(window)
|
||||||
|
return li
|
||||||
|
|
||||||
|
|
||||||
|
def genstatusstring(s, status):
|
||||||
|
new = ""
|
||||||
|
glo = {}
|
||||||
|
loc = {}
|
||||||
|
exec(open(SHARE + '/status/status').read(), glo, loc)
|
||||||
|
for i in loc[s].split():
|
||||||
|
if i.startswith("#"):
|
||||||
|
i = i.replace("#", "")
|
||||||
|
if status[i] == 1:
|
||||||
|
new += " " + i
|
||||||
|
else:
|
||||||
|
new += " #" + i
|
||||||
|
return new
|
||||||
|
|
||||||
|
|
||||||
|
def writestatus(items):
|
||||||
|
status = {}
|
||||||
|
path = BYOBU_CONFIG_DIR + '/status'
|
||||||
|
for i in items:
|
||||||
|
status[i[1]] = i[0]
|
||||||
|
for key in ["tmux_left", "tmux_right", "screen_upper_left", "screen_upper_right", "screen_lower_left", "screen_lower_right"]:
|
||||||
|
if key.startswith(BYOBU_BACKEND):
|
||||||
|
f = open(path, "r")
|
||||||
|
lines = f.readlines()
|
||||||
|
f.close()
|
||||||
|
f = open(path, "w")
|
||||||
|
for l in lines:
|
||||||
|
if l.startswith("%s=" % key):
|
||||||
|
val = genstatusstring(key, status)
|
||||||
|
f.write("%s=\"%s\"\n" % (key, val))
|
||||||
|
else:
|
||||||
|
f.write(l)
|
||||||
|
f.close
|
||||||
|
|
||||||
|
|
||||||
|
def togglestatus(snackScreen, 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(snackScreen, ((_("Apply"), "apply"), (_("Cancel"), "cancel", ESC)), compact=1)
|
||||||
|
g = GridForm(snackScreen, _("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 install(snackScreen, size, isInstalled):
|
||||||
|
out = ""
|
||||||
|
if isInstalled:
|
||||||
|
if subprocess.call(["byobu-launcher-uninstall"]) == 0:
|
||||||
|
out = _("Byobu will not be launched next time you login.")
|
||||||
|
button = messagebox(snackScreen, 60, 2, _("Message"), out, buttons=((_("Menu"), )))
|
||||||
|
return 101
|
||||||
|
else:
|
||||||
|
if subprocess.call(["byobu-launcher-install"]) == 0:
|
||||||
|
out = _("Byobu will be launched automatically next time you login.")
|
||||||
|
button = messagebox(snackScreen, 60, 2, "Message", out, buttons=((_("Menu"), )))
|
||||||
|
return 100
|
||||||
|
|
||||||
|
|
||||||
|
def appendtofile(p, s):
|
||||||
|
f = open(p, 'a')
|
||||||
|
try:
|
||||||
|
f.write(s)
|
||||||
|
except IOError:
|
||||||
|
f.close()
|
||||||
|
return
|
||||||
|
f.close()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def getesckey():
|
||||||
|
line = ""
|
||||||
|
if BYOBU_BACKEND == "tmux":
|
||||||
|
path = BYOBU_CONFIG_DIR + '/keybindings.tmux'
|
||||||
|
if os.path.exists(path):
|
||||||
|
for l in open(path):
|
||||||
|
if l.startswith("set -g prefix "):
|
||||||
|
line = l
|
||||||
|
else:
|
||||||
|
return DEF_ESC
|
||||||
|
else:
|
||||||
|
path = BYOBU_CONFIG_DIR + '/keybindings'
|
||||||
|
if os.path.exists(path):
|
||||||
|
for l in open(path):
|
||||||
|
if l.startswith("escape "):
|
||||||
|
line = l
|
||||||
|
else:
|
||||||
|
return DEF_ESC
|
||||||
|
if line == "":
|
||||||
|
return DEF_ESC
|
||||||
|
esc = line[line.find('^') + 1]
|
||||||
|
if esc == "`":
|
||||||
|
esc = " "
|
||||||
|
return esc
|
||||||
|
|
||||||
|
|
||||||
|
def setesckey(key):
|
||||||
|
if key.isalpha():
|
||||||
|
subprocess.call(["byobu-ctrl-a", "screen", key])
|
||||||
|
|
||||||
|
|
||||||
|
def chgesc(snackScreen, size):
|
||||||
|
esc = Entry(2, text=getesckey(), returnExit=1)
|
||||||
|
escl = Label(_("Escape key: ctrl-"))
|
||||||
|
bb = ButtonBar(snackScreen, ((_("Apply"), "apply"), (_("Cancel"), "cancel", ESC)), compact=1)
|
||||||
|
g = GridForm(snackScreen, _("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 escape sequence is not \ or /
|
||||||
|
if val == '/' or val == '\\':
|
||||||
|
esc.set(DEF_ESC)
|
||||||
|
# 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
|
||||||
|
snackScreen.popWindow()
|
||||||
|
button = bb.buttonPressed(which)
|
||||||
|
if button != "cancel":
|
||||||
|
setesckey(esc.value())
|
||||||
|
reload_required()
|
||||||
|
if button == "exit":
|
||||||
|
return 0
|
||||||
|
return 100
|
||||||
|
|
||||||
|
|
||||||
|
def autolaunch():
|
||||||
|
if os.path.exists(BYOBU_CONFIG_DIR + "/disable-autolaunch"):
|
||||||
|
return 0
|
||||||
|
try:
|
||||||
|
for line in open("%s/.profile" % HOME):
|
||||||
|
if "byobu-launch" in line:
|
||||||
|
return 1
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
if os.path.exists("/etc/profile.d/Z98-%s.sh" % PKG):
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""This is the main loop of our utility"""
|
||||||
|
size = terminal_size()
|
||||||
|
snackScreen = SnackScreen()
|
||||||
|
snackScreen.drawRootText(1, 0, _('Byobu Configuration Menu'))
|
||||||
|
snackScreen.pushHelpLine(_('<Tab> between elements | <Enter> selects | <Esc> exits'))
|
||||||
|
isInstalled = autolaunch()
|
||||||
|
tag = 100
|
||||||
|
while tag > 0:
|
||||||
|
tag = menu(snackScreen, size, isInstalled)
|
||||||
|
if tag == 1:
|
||||||
|
tag = help(snackScreen, size)
|
||||||
|
elif tag == 2:
|
||||||
|
tag = togglestatus(snackScreen, size)
|
||||||
|
elif tag == 3:
|
||||||
|
tag = chgesc(snackScreen, size)
|
||||||
|
elif tag == 4:
|
||||||
|
tag = install(snackScreen, size, isInstalled)
|
||||||
|
isInstalled = autolaunch()
|
||||||
|
snackScreen.finish()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -53,6 +53,17 @@ $BYOBU_SED --follow-symlinks "s///" </dev/null 2>/dev/null && BYOBU_SED="$BYOBU_
|
||||||
# Determine if we have ulimit support
|
# Determine if we have ulimit support
|
||||||
$BYOBU_TEST ulimit >/dev/null 2>&1 && export BYOBU_ULIMIT="ulimit" || export BYOBU_ULIMIT="false"
|
$BYOBU_TEST ulimit >/dev/null 2>&1 && export BYOBU_ULIMIT="ulimit" || export BYOBU_ULIMIT="false"
|
||||||
|
|
||||||
|
# Find a suitable python interpreter, if undefined
|
||||||
|
if [ -z "$BYOBU_PYTHON" ]; then
|
||||||
|
if $BYOBU_TEST python >/dev/null 2>&1; then
|
||||||
|
BYOBU_PYTHON="python"
|
||||||
|
elif $BYOBU_TEST python2 >/dev/null 2>&1; then
|
||||||
|
BYOBU_PYTHON="python2"
|
||||||
|
elif $BYOBU_TEST python3 >/dev/null 2>&1; then
|
||||||
|
BYOBU_PYTHON="python3"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Default colors
|
# Default colors
|
||||||
export BYOBU_DARK="black"
|
export BYOBU_DARK="black"
|
||||||
export BYOBU_LIGHT="white"
|
export BYOBU_LIGHT="white"
|
||||||
|
|
174
usr/lib/byobu/include/select-session.py
Executable file
174
usr/lib/byobu/include/select-session.py
Executable file
|
@ -0,0 +1,174 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# select-session.py
|
||||||
|
# Copyright (C) 2010 Canonical Ltd.
|
||||||
|
# Copyright (C) 2012-2013 Dustin Kirkland <kirkland@byobu.co>
|
||||||
|
#
|
||||||
|
# Authors: Dustin Kirkland <kirkland@byobu.co>
|
||||||
|
# Ryan C. Thompson <rct@thompsonclan.org>
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
PKG = "byobu"
|
||||||
|
SHELL = os.getenv("SHELL", "/bin/bash")
|
||||||
|
HOME = os.getenv("HOME")
|
||||||
|
BYOBU_CONFIG_DIR = os.getenv("BYOBU_CONFIG_DIR", HOME + "/.byobu")
|
||||||
|
BYOBU_BACKEND = os.getenv("BYOBU_BACKEND", "tmux")
|
||||||
|
choice = -1
|
||||||
|
sessions = []
|
||||||
|
text = []
|
||||||
|
|
||||||
|
BYOBU_UPDATE_ENVVARS = ["DISPLAY", "DBUS_SESSION_BUS_ADDRESS", "SESSION_MANAGER", "GPG_AGENT_INFO", "XDG_SESSION_COOKIE", "XDG_SESSION_PATH", "GNOME_KEYRING_CONTROL", "GNOME_KEYRING_PID", "GPG_AGENT_INFO", "SSH_ASKPASS", "SSH_AUTH_SOCK", "SSH_AGENT_PID", "WINDOWID", "UPSTART_JOB", "UPSTART_EVENTS", "UPSTART_SESSION", "UPSTART_INSTANCE"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_sessions():
|
||||||
|
sessions = []
|
||||||
|
i = 0
|
||||||
|
output = False
|
||||||
|
if BYOBU_BACKEND == "screen":
|
||||||
|
try:
|
||||||
|
output = subprocess.Popen(["screen", "-ls"], stdout=subprocess.PIPE).communicate()[0]
|
||||||
|
except subprocess.CalledProcessError as cpe:
|
||||||
|
# screen -ls seems to always return 1
|
||||||
|
if cpe.returncode != 1:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
output = cpe.output
|
||||||
|
if not sys.stdout.encoding is None:
|
||||||
|
output = output.decode(sys.stdout.encoding)
|
||||||
|
if output:
|
||||||
|
for s in output.splitlines():
|
||||||
|
s = re.sub(r'\s+', ' ', s)
|
||||||
|
# Ignore hidden sessions (named sessions that start with a ".")
|
||||||
|
if s and s != " " and (s.find(" ") == 0 and len(s) > 1 and s.count("..") == 0):
|
||||||
|
text.append("screen: %s" % s.strip())
|
||||||
|
items = s.split(" ")
|
||||||
|
sessions.append("screen____%s" % items[1])
|
||||||
|
i += 1
|
||||||
|
if BYOBU_BACKEND == "tmux":
|
||||||
|
output = subprocess.Popen(["tmux", "list-sessions"], stdout=subprocess.PIPE).communicate()[0]
|
||||||
|
output = output.decode(sys.stdout.encoding)
|
||||||
|
if output:
|
||||||
|
for s in output.splitlines():
|
||||||
|
if s:
|
||||||
|
text.append("tmux: %s" % s.strip())
|
||||||
|
sessions.append("tmux____%s" % s.split(":")[0])
|
||||||
|
i += 1
|
||||||
|
return sessions
|
||||||
|
|
||||||
|
|
||||||
|
def update_environment(session):
|
||||||
|
backend, session_name = session.split("____", 2)
|
||||||
|
for var in BYOBU_UPDATE_ENVVARS:
|
||||||
|
value = os.getenv(var)
|
||||||
|
if value:
|
||||||
|
if backend == "tmux":
|
||||||
|
cmd = ["tmux", "setenv", "-t", session_name, var, value]
|
||||||
|
else:
|
||||||
|
cmd = ["screen", "-S", session_name, "-X", "setenv", var, value]
|
||||||
|
print("Sending variable: %s" % (cmd, ))
|
||||||
|
subprocess.call(cmd, stdout=open(os.devnull, "w"))
|
||||||
|
|
||||||
|
|
||||||
|
def attach_session(session):
|
||||||
|
print("Attaching: [%s]\n" % session)
|
||||||
|
update_environment(session)
|
||||||
|
backend, session_name = session.split("____", 2)
|
||||||
|
# must use the binary, not the wrapper!
|
||||||
|
if backend == "tmux":
|
||||||
|
os.execvp("tmux", ["", "-2", "attach", "-t", session_name])
|
||||||
|
else:
|
||||||
|
os.execvp("screen", ["", "-AOxRR", session_name])
|
||||||
|
|
||||||
|
# Confirm nested session, if necessary
|
||||||
|
if os.getenv("BYOBU_NESTING", "0") != "1":
|
||||||
|
if (BYOBU_BACKEND == "tmux" and os.getenv("TMUX")) or (BYOBU_BACKEND == "screen" and "screen" in os.getenv("TERM")):
|
||||||
|
sys.stderr.write("WARNING: Sessions should be nested with care.\n")
|
||||||
|
try:
|
||||||
|
nest = raw_input("Are you sure you want to run Byobu inside another session? [y/N]: ")
|
||||||
|
if nest != "Y" and nest != "y":
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
if os.getenv("TMUX"):
|
||||||
|
os.unsetenv("TMUX")
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.stdout.write("\n")
|
||||||
|
sys.exit(1)
|
||||||
|
except:
|
||||||
|
sys.stdout.write("\n")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
sessions = get_sessions()
|
||||||
|
|
||||||
|
show_shell = os.path.exists("%s/.always-select" % (BYOBU_CONFIG_DIR))
|
||||||
|
if len(sessions) > 1 or show_shell:
|
||||||
|
sessions.append("NEW")
|
||||||
|
text.append("Create a new Byobu session (%s)" % BYOBU_BACKEND)
|
||||||
|
sessions.append("SHELL")
|
||||||
|
text.append("Run a shell without Byobu (%s)" % SHELL)
|
||||||
|
|
||||||
|
if len(sessions) > 1:
|
||||||
|
sys.stdout.write("\nByobu sessions...\n\n")
|
||||||
|
tries = 0
|
||||||
|
while tries < 3:
|
||||||
|
i = 1
|
||||||
|
for s in text:
|
||||||
|
sys.stdout.write(" %d. %s\n" % (i, s))
|
||||||
|
i += 1
|
||||||
|
try:
|
||||||
|
choice = int(input("\nChoose 1-%d [1]: " % (i - 1)))
|
||||||
|
if choice >= 1 and choice < i:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
tries += 1
|
||||||
|
choice = -1
|
||||||
|
sys.stderr.write("\nERROR: Invalid input\n")
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.stdout.write("\n")
|
||||||
|
sys.exit(0)
|
||||||
|
except:
|
||||||
|
if choice == "" or choice == -1:
|
||||||
|
choice = 1
|
||||||
|
break
|
||||||
|
tries += 1
|
||||||
|
choice = -1
|
||||||
|
sys.stderr.write("\nERROR: Invalid input\n")
|
||||||
|
elif len(sessions) == 1:
|
||||||
|
# Auto-select the only session
|
||||||
|
choice = 1
|
||||||
|
|
||||||
|
if choice >= 1:
|
||||||
|
if sessions[choice - 1] == "NEW":
|
||||||
|
# Create a new session
|
||||||
|
if BYOBU_BACKEND == "tmux":
|
||||||
|
os.execvp("byobu", ["", "new-session", SHELL])
|
||||||
|
else:
|
||||||
|
os.execvp("byobu", ["", SHELL])
|
||||||
|
elif sessions[choice - 1] == "SHELL":
|
||||||
|
os.execvp(SHELL, [SHELL])
|
||||||
|
else:
|
||||||
|
# Attach to the chosen session; must use the binary, not the wrapper!
|
||||||
|
attach_session(sessions[choice - 1])
|
||||||
|
|
||||||
|
# No valid selection, default to the youngest session, create if necessary
|
||||||
|
if BYOBU_BACKEND == "tmux":
|
||||||
|
args = ""
|
||||||
|
else:
|
||||||
|
args = "-AOxRR"
|
||||||
|
os.execvp("byobu", ["", args])
|
Loading…
Add table
Add a link
Reference in a new issue