Added wk/tmux.py
This commit is contained in:
parent
177401ecc8
commit
05d6fb762c
2 changed files with 203 additions and 0 deletions
|
|
@ -13,6 +13,7 @@ from wk import net
|
||||||
from wk import os
|
from wk import os
|
||||||
from wk import std
|
from wk import std
|
||||||
from wk import sw
|
from wk import sw
|
||||||
|
from wk import tmux
|
||||||
|
|
||||||
|
|
||||||
# Check env
|
# Check env
|
||||||
|
|
|
||||||
202
scripts/wk/tmux.py
Normal file
202
scripts/wk/tmux.py
Normal 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.")
|
||||||
Loading…
Reference in a new issue