#!/usr/bin/env python
# vim: fileencoding=utf-8 ft=python et sw=4 ts=4 sts=4 tw=79
from __future__ import (
generators, division, absolute_import, with_statement, print_function
)
import urwid
# from twisted.internet import reactor
from twisted.internet.task import LoopingCall
from twisted.internet.utils import getProcessOutput
pane_format = 'session_name window_index pane_id pane_title'.split()
# TODO: use tmux in command mode:
# tmux -L tst -C a -t 0 \; refresh-client -C 256,128
def exit_program(button):
raise urwid.ExitMainLoop()
class TST(object):
"""
Vertical tree-style-tabs alike for tmux.
"""
def __init__(self, sockname='tst'):
self.sockname = sockname
self._redraw_pending = False
self.head = [urwid.Text('TST'), urwid.Divider()]
self.body = urwid.SimpleFocusListWalker(self.head)
self.main = urwid.Padding(urwid.ListBox(self.body), left=2, right=2)
self.top = urwid.Overlay(
self.main,
urwid.SolidFill(u'\N{MEDIUM SHADE}'),
align='center', width=('relative', 60),
valign='middle', height=('relative', 60),
min_width=20, min_height=9
)
def call_tmux(self, *args):
"""
Run tmux executable with socket option set.
"""
return getProcessOutput('/usr/bin/tmux', ('-L', self.sockname) + args)
def get_panes(self):
"""
Call tmux to get list of panes.
"""
return self.call_tmux(*'list-panes -a -F'.split() + ['|'.join((
'#{%s}' % i for i in pane_format
))]).addCallback(self.got_panes)
def got_panes(self, s):
"""
Process list of panes and update TST accordingly.
"""
buttons = []
for line in s.split('\n'):
if not line:
continue
d = dict(zip(pane_format, line.split('|')))
b = urwid.Button('%(pane_id)s %(pane_title)s' % d,
self.clicked,
d['window_index'])
buttons.append(urwid.AttrMap(b, None, focus_map='reversed'))
self.body[2:] = buttons
# self.mainloop.draw_screen()
self.redraw()
def redraw(self):
"""
Schedule window redraw at closest idle time.
"""
if self._redraw_pending:
return
self._redraw_pending = True
self.reactor.callLater(0, self._do_redraw)
def _do_redraw(self):
self._redraw_pending = False
self.mainloop.draw_screen()
def clicked(self, button, window):
self.call_tmux('select-window', '-t', window)
def run(self, reactor=None):
"""
Run the TST application.
"""
if reactor is None:
from twisted.internet import reactor
self.reactor = reactor
self.get_panes()
self.paneloop = LoopingCall(self.get_panes)
self.paneloop.start(1)
self.mainloop = urwid.MainLoop(
self.main,
palette=[('reversed', 'standout', '')],
event_loop=urwid.TwistedEventLoop(reactor)
)
self.mainloop.run()
if __name__ == '__main__':
TST().run()