Added wk/tmux.py

This commit is contained in:
2Shirt 2019-11-09 17:29:31 -07:00
parent 177401ecc8
commit 05d6fb762c
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
2 changed files with 203 additions and 0 deletions

View file

@ -13,6 +13,7 @@ from wk import net
from wk import os
from wk import std
from wk import sw
from wk import tmux
# Check env

202
scripts/wk/tmux.py Normal file
View file

@ -0,0 +1,202 @@
"""WizardKit: tmux Functions"""
# vim: sts=2 sw=2 ts=2
import logging
import pathlib
from wk.exe import run_program
# STATIC_VARIABLES
LOG = logging.getLogger(__name__)
# Functions
def capture_pane(pane_id=None):
"""Capture text from current or target pane, returns str."""
cmd = ['tmux', 'capture-pane', '-p']
if pane_id:
cmd.extend(['-t', pane_id])
# Capture and return
proc = run_program(cmd, check=False)
return proc.stdout.strip()
def get_pane_size(pane_id=None):
"""Get current or target pane size, returns tuple."""
cmd = ['tmux', 'display', '-p']
if pane_id:
cmd.extend(['-t', pane_id])
cmd.append('#{pane_width} #{pane_height}')
# Get resolution
proc = run_program(cmd, check=False)
width, height = proc.stdout.strip().split()
width = int(width)
height = int(height)
# Done
return (width, height)
def kill_all_panes(pane_id=None):
"""Kill all panes except for the current or target pane."""
cmd = ['tmux', 'kill-pane', '-a']
if pane_id:
cmd.extend(['-t', pane_id])
# Kill
run_program(cmd, check=False)
def kill_pane(*pane_ids):
"""Kill pane(s) by id."""
cmd = ['tmux', 'kill-pane', '-t']
# Iterate over all passed pane IDs
for pane_id in pane_ids:
run_program(cmd+[pane_id], check=False)
def poll_pane(pane_id):
"""Check if pane exists, returns bool."""
cmd = ['tmux', 'list-panes', '-F', '#D']
# Get list of panes
proc = run_program(cmd, check=False)
existant_panes = proc.stdout.splitlines()
# Check if pane exists
return pane_id in existant_panes
def prep_action(
cmd=None, working_dir=None, text=None, watch_file=None, watch_cmd='cat'):
"""Prep action to perform during a tmux call, returns list.
This will prep for running a basic command, displaying text on screen,
or monitoring a file. The last option uses cat by default but can be
overridden by using the watch_cmd.
"""
action_cmd = []
if working_dir:
action_cmd.extend(['-c', working_dir])
if cmd:
# Basic command
action_cmd.append(cmd)
elif text:
# Display text
action_cmd.extend([
'watch',
'--color',
'--exec',
'--no-title',
'--interval', '1',
'echo', '-e', text,
])
elif watch_file:
# Monitor file
prep_file(watch_file)
action_cmd.extend([
'watch',
'--color',
'--no-title',
'--interval', '1',
])
if watch_cmd == 'cat':
action_cmd.append('cat')
elif watch_cmd == 'tail':
action_cmd.extend(['tail', '--follow'])
action_cmd.append(watch_file)
else:
LOG.error('No action specified')
raise RuntimeError('No action specified')
# Done
return action_cmd
def prep_file(path):
"""Check if file exists and create empty file if not."""
path = pathlib.Path(path).resolve()
try:
path.touch(exist_ok=False)
except FileExistsError:
# Leave existing files alone
pass
def resize_pane(pane_id=None, width=None, height=None):
"""Resize current or target pane."""
cmd = ['tmux', 'resize-pane']
# Safety checks
if not poll_pane(pane_id):
LOG.error('tmux pane %s not found', pane_id)
raise RuntimeError(f'tmux pane {pane_id} not found')
if not (width or height):
LOG.error('Neither width nor height specified')
raise RuntimeError('Neither width nor height specified')
# Finish building cmd
if pane_id:
cmd.extend(['-t', pane_id])
if width:
cmd.extend(['-x', str(width)])
if height:
cmd.extend(['-y', str(height)])
# Resize
run_program(cmd, check=False)
def split_window(
lines=None, percent=None,
behind=False, vertical=False,
target_id=None, **action):
"""Split tmux window, run action, and return pane_id as str."""
cmd = ['tmux', 'split-window', '-d', '-PF', '#D']
pane_id = None
# Safety checks
if not (lines or percent):
LOG.error('Neither lines nor percent specified')
raise RuntimeError('Neither lines nor percent specified')
# New pane placement
if behind:
cmd.append('-b')
if vertical:
cmd.append('-v')
else:
cmd.append('-h')
if target_id:
cmd.extend(['-t', target_id])
# New pane size
if lines:
cmd.extend(['-l', str(lines)])
elif percent:
cmd.extend(['-p', str(percent)])
# New pane action
cmd.extend(prep_action(**action))
# Run and return pane_id
proc = run_program(cmd, check=False)
return proc.stdout.strip()
def respawn_pane(pane_id, **action):
"""Respawn pane with action."""
cmd = ['tmux', 'respawn-pane', '-k', '-t', pane_id]
cmd.extend(prep_action(**action))
# Respawn
run_program(cmd, check=False)
if __name__ == '__main__':
print("This file is not meant to be called directly.")