Added tmux layout maintenance sections

* Support both threading and signal based calls
  * Should provide a smoother UIX under Linux & macOS
This commit is contained in:
2Shirt 2019-11-10 19:10:35 -07:00
parent 0cbc858cf4
commit 196e2adc82
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
3 changed files with 98 additions and 3 deletions

View file

@ -4,6 +4,8 @@
import re
from collections import OrderedDict
# STATIC VARIABLES
ATTRIBUTE_COLORS = (
@ -53,6 +55,17 @@ REGEX_POWER_ON_TIME = re.compile(
r'^(\d+)([Hh].*|\s+\(\d+\s+\d+\s+\d+\).*)'
)
TMUX_SIDE_WIDTH = 20
TMUX_LAYOUT = OrderedDict({
'Top': {'height': 2, 'Check': True},
'Started': {'width': TMUX_SIDE_WIDTH, 'Check': True},
'Progress': {'width': TMUX_SIDE_WIDTH, 'Check': True},
# Testing panes
'Prime95': {'height': 11, 'Check': False},
'Temps': {'height': 1000, 'Check': False},
'SMART': {'height': 3, 'Check': True},
'badblocks': {'height': 5, 'Check': True},
'I/O Benchmark': {'height': 1000, 'Check': False},
})
if __name__ == '__main__':

View file

@ -6,13 +6,14 @@ import logging
import os
import pathlib
import platform
import signal
import time
from collections import OrderedDict
from docopt import docopt
from wk import exe, net, std, tmux
from wk.cfg.hw import TMUX_SIDE_WIDTH
from wk.cfg.hw import TMUX_LAYOUT, TMUX_SIDE_WIDTH
from wk.cfg.main import KIT_NAME_FULL
@ -100,7 +101,36 @@ class State():
},
})
self.top_text = std.color_string('Hardware Diagnostics', 'GREEN')
# Init tmux and start a background process to maintain layout
self.init_tmux()
if hasattr(signal, 'SIGWINCH'):
# Use signal handling
signal.signal(signal.SIGWINCH, self.fix_tmux_layout)
else:
exe.start_thread(self.fix_tmux_layout_loop)
def fix_tmux_layout(self, forced=True, signum=None, frame=None):
# pylint: disable=unused-argument
"""Fix tmux layout based on TMUX_LAYOUT.
NOTE: To support being called by both a signal and a thread
signum and frame must be valid aguments.
"""
try:
tmux.fix_layout(self.panes, TMUX_LAYOUT, forced=forced)
except RuntimeError:
# Assuming self.panes changed while running
pass
def fix_tmux_layout_loop(self):
"""Fix tmux layout on a loop.
NOTE: This should be called as a thread.
"""
while True:
self.fix_tmux_layout(forced=False)
std.sleep(1)
def init_tmux(self):
"""Initialize tmux layout."""

View file

@ -24,6 +24,27 @@ def capture_pane(pane_id=None):
return proc.stdout.strip()
def fix_layout(panes, layout, forced=False):
"""Fix pane sizes based on layout."""
if not (forced or layout_needs_fixed(panes, layout)):
# Layout should be fine
return
# Update panes
for name, data in layout.items():
# Skip missing panes
if name not in panes:
continue
# Resize pane
pane_id = panes[name]
try:
resize_pane(pane_id, **data)
except RuntimeError:
# Assuming pane was closed just before resizing
pass
def get_pane_size(pane_id=None):
"""Get current or target pane size, returns tuple."""
cmd = ['tmux', 'display', '-p']
@ -60,6 +81,32 @@ def kill_pane(*pane_ids):
run_program(cmd+[pane_id], check=False)
def layout_needs_fixed(panes, layout):
"""Check if layout needs fixed, returns bool."""
needs_fixed = False
# Check panes
for name, data in layout.items():
# Skip unpredictably sized panes
if not data.get('Check', False):
continue
# Skip missing panes
if name not in panes:
continue
# Check pane size
pane_id = panes[name]
width, height = get_pane_size(pane_id)
if data.get('width', False) and data['width'] != width:
needs_fixed = True
if data.get('height', False) and data['height'] != height:
needs_fixed = True
# Done
return needs_fixed
def poll_pane(pane_id):
"""Check if pane exists, returns bool."""
cmd = ['tmux', 'list-panes', '-F', '#D']
@ -133,8 +180,13 @@ def prep_file(path):
pass
def resize_pane(pane_id=None, width=None, height=None):
"""Resize current or target pane."""
def resize_pane(pane_id=None, width=None, height=None, **kwargs):
# pylint: disable=unused-argument
"""Resize current or target pane.
NOTE: kwargs is only here to make calling this function easier
by dropping any extra kwargs passed.
"""
cmd = ['tmux', 'resize-pane']
# Safety checks