Compare commits

...
6 Commits
Author SHA1 Message Date
Legrems 36bd56bcc4 Update tmux-pane-selection scripts to be more clear 2024-09-02 19:45:42 +02:00
Legrems 78ce7dac48 Update 15.08.2024 2024-08-15 16:10:44 +02:00
Legrems 6b1d53f65d Update tmux pane selection 2024-06-13 22:31:42 +02:00
Legrems c2b6eaa87a Add tmux pane selection 2024-06-10 16:46:58 +02:00
Legrems 953b9a791c Add tmux session select, update other scripts 2024-06-09 03:14:24 +02:00
Legrems d6e0fd4025 Update tmux-ssh-groups 2024-05-29 15:27:19 +02:00
5 changed files with 231 additions and 55 deletions
+15 -2
View File
@@ -2,17 +2,29 @@ import configparser
import sys import sys
import time import time
import libtmux import libtmux
import argparse
from pathlib import Path from pathlib import Path
from pyfzf.pyfzf import FzfPrompt from pyfzf.pyfzf import FzfPrompt
parser = argparse.ArgumentParser()
parser.add_argument("--servers-file", "-f", help="Servers file to connect to")
parser_args = parser.parse_args()
if parser_args.servers_file:
with open(parser_args.servers_file, "r") as file:
data = file.read()
servers = []
for line in data.strip().split("\n"):
servers.append(line.strip())
config = configparser.ConfigParser() config = configparser.ConfigParser()
config_path = Path("~/.ssh-tmux-multi.ini").expanduser() config_path = Path("~/.ssh-tmux-multi.ini").expanduser()
config.read(config_path) config.read(config_path)
fav_key = "Favourite servers" fav_key = "Favourite servers"
fzf = FzfPrompt() fzf = FzfPrompt()
@@ -73,7 +85,8 @@ def write_choosen_servers(servers):
with open(config_path, "w") as file: with open(config_path, "w") as file:
config.write(file) config.write(file)
servers = fzf.prompt(get_favourite_servers_first(), "--cycle --multi --print-query") if not parser_args.servers_file:
servers = fzf.prompt(["Select server to connect to"] + get_favourite_servers_first(), "--cycle --multi --print-query --header-lines 1")
# Strip from query if found else, use the query # Strip from query if found else, use the query
if len(servers) > 1: if len(servers) > 1:
+91
View File
@@ -0,0 +1,91 @@
import libtmux
import sys
import sh
import argparse
from pprint import pprint
from collections import defaultdict
from pyfzf.pyfzf import FzfPrompt
parser = argparse.ArgumentParser()
parser.add_argument("--no-open", action="store_true", help="Do not open tmux window. Mostly for debugging")
parser_args = parser.parse_args()
# Get active tmux sessions
srv = libtmux.Server()
fzf = FzfPrompt()
commands = defaultdict(list)
all_tty = [p.pane_tty for p in srv.panes]
cmd = f"-t {' -t '.join(all_tty)} -o pid:10 -o tty:10 -o command -ww" # -f
sh_commands = sh.ps(cmd.split(' ')).stdout.decode().strip().split("\n")
# Ignore first lines (i.e: table headers)
for cmd in sh_commands[1:]:
pid = cmd[:10].strip()
tty = cmd[10:20].strip()
command = cmd[20:].strip()
tty_number = int(tty.replace("pts/", ""))
if command in ["-zsh", "/bin/zsh"]:
continue
commands[tty_number].append(
{
"pid": int(pid),
"command": command,
}
)
def format_pane(pane):
global commands
tty_number = int(pane.pane_tty.replace("/dev/pts/", ""))
running_commands = sorted(commands[tty_number], key=lambda c: c["pid"])
if len(running_commands) >= 1:
cmd = running_commands[0]
else:
cmd = {"pid": "-", "command": "*command not found*"}
path = pane.pane_current_path.replace("/home/legrems/Documents/Arcanite", "~/D/A")
path = path.replace("/home/legrems/Documents", "~/D")
path = path.replace("/home/legrems", "~")
return [f"{pane.pane_tty}: [{pane.session_name}: {pane.window_name}, {path}]: {cmd['command']}"]
panes = []
for pane in srv.panes:
panes.extend(format_pane(pane))
selections = fzf.prompt(["Select one pane you want to switch to"] + panes, "--cycle --header-lines 1")
if not selections:
sys.exit(0)
pane_name = selections[0]
tty = pane_name.split(":")[0]
selected_pane = srv.panes.get(pane_tty=tty)
if parser_args.no_open:
print(selected_pane)
print(tty)
tty_number = int(tty.replace("/dev/pts/", ""))
pprint(commands[tty_number])
else:
# Go to this session
selected_pane.session.switch_client()
# Select the correct window
selected_pane.window.select()
# And switch to this pane
selected_pane.window.select_pane(selected_pane.pane_id)
+20
View File
@@ -0,0 +1,20 @@
import libtmux
import sys
from pyfzf.pyfzf import FzfPrompt
# Get active tmux sessions
srv = libtmux.Server()
fzf = FzfPrompt()
selections = fzf.prompt(["Select one session you want to switch to"] + [s.name for s in srv.sessions], "--cycle --header-lines 1")
if not selections:
sys.exit(0)
session_name = selections[0]
session = srv.sessions.filter(name=session_name)[0]
session.switch_client()
session.active_window.active_pane.display_message(f"Switched to session: {session_name}")
+2 -1
View File
@@ -12,10 +12,11 @@ folders = [
"~/Documents/PolyLAN/", "~/Documents/PolyLAN/",
"~/Documents/Python/", "~/Documents/Python/",
"~/Documents/", "~/Documents/",
"~/Documents/Games/Minecraft/modded/",
] ]
available_folders = sh.find(*[Path(f).expanduser() for f in folders] + "-mindepth 1 -maxdepth 1 -type d".split(" ")).strip().split("\n") available_folders = sh.find(*[Path(f).expanduser() for f in folders] + "-mindepth 1 -maxdepth 1 -type d".split(" ")).strip().split("\n")
selected = fzf.prompt(available_folders, "--cycle") selected = fzf.prompt(["Select a folder to create or switch session to"] + available_folders, "--cycle --header-lines 1")
if not selected: if not selected:
sys.exit(1) sys.exit(1)
+103 -52
View File
@@ -1,5 +1,6 @@
import libtmux import libtmux
import configparser import configparser
import argparse
import time import time
import sys import sys
import os import os
@@ -9,6 +10,16 @@ from pathlib import Path
from pyfzf.pyfzf import FzfPrompt from pyfzf.pyfzf import FzfPrompt
parser = argparse.ArgumentParser()
parser.add_argument("--no-open", action="store_true", help="Do not open tmux window. Mostly for debugging")
parser.add_argument("--separate-sessions", "-s", action="store_true", help="Use a separate sessions for all of the groups")
parser_args = parser.parse_args()
def get_window_name(session_name):
name = session_name.replace("-", "").replace(" ", " ").replace(" ", "_")
return f"{'' if parser_args.separate_sessions else 'ssh-multig '}{name}"
BASE_PATH = Path("~/.ssh-tmux/").expanduser() BASE_PATH = Path("~/.ssh-tmux/").expanduser()
configs = {} configs = {}
@@ -16,76 +27,116 @@ sections = {}
for subconffile in os.listdir(BASE_PATH): for subconffile in os.listdir(BASE_PATH):
if not subconffile.endswith(".ini"): if not subconffile.endswith(".ini"):
continue continue
prefix = subconffile.replace(".ini", "").capitalize()
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read(BASE_PATH / subconffile) config.read(BASE_PATH / subconffile)
configs[subconffile] = config configs[subconffile] = config
for section in config.sections(): for section in config.sections():
sections[section] = subconffile section_name = f"[{prefix}] {section}"
sections[section_name] = {
"section": section,
"config": subconffile,
}
fzf = FzfPrompt() fzf = FzfPrompt()
selections = fzf.prompt(sections.keys(), "--cycle") selections = fzf.prompt(["Select one or more servers group to open"] + list(sections.keys()), "--cycle --multi --header-lines 1")
if not selections: if not selections:
sys.exit(0) sys.exit(0)
selected_group = selections[0] # Get active tmux sessions
config = configs[sections[selected_group]]
servers = config[selected_group]["servers"].split("\n")
extra_commands = []
if "commands" in config[selected_group].keys():
extra_commands = config[selected_group]["commands"].split("\n")
if not servers:
sys.exit(1)
srv = libtmux.Server() srv = libtmux.Server()
active_sessions = srv.sessions.filter(session_attached='1') active_sessions = srv.attached_sessions
if active_sessions: if parser_args.separate_sessions:
active_session = active_sessions[0] sessions = srv.sessions.filter(name="SSH-MultiG")
else: if sessions:
raw_try = srv.cmd("display", "-p", "#{session_name}").stdout active_session = sessions[0]
if raw_try:
active_session = srv.sessions.filter(name=raw_try[0])[0]
else: else:
active_session = srv.sessions[0] active_session = srv.new_session(session_name="SSH-MultiG")
window_name = f"ssh-multig {selected_group.replace(' ', '_')}" else:
if windows := active_session.windows.filter(name=window_name): if len(active_sessions) > 1:
windows[0].select() session_choice = fzf.prompt(["You have multiple active tmux sessions open. Choose one to create the window on"] + [sess.name for sess in active_sessions], "--cycle --header-lines 1")
sys.exit(0)
window = active_session.new_window(window_name, window_shell=f"ssh {servers[0]}") if not session_choice:
sys.exit(0)
for server in servers[1:]: active_session = srv.sessions.filter(name=session_choice[0])[0]
pane = window.split(shell=f"ssh {server}")
# Select tiled layout each time, to ensure enough space elif len(active_sessions) == 1:
active_session = active_sessions[0]
else:
raw_try = srv.cmd("display", "-p", "#{session_name}").stdout
if raw_try:
active_session = srv.sessions.filter(name=raw_try[0])[0]
else:
active_session = srv.sessions[0]
for selected_group in selections:
info = sections[selected_group]
config = configs[info["config"]]
servers = config[info["section"]]["servers"].split("\n")
extra_commands = []
if "commands" in config[info["section"]].keys():
extra_commands = config[info["section"]]["commands"].split("\n")
if parser_args.no_open:
print(selected_group)
print(f" - Servers ({len(servers)}):")
for server in servers:
print(f" * {server}")
if extra_commands:
print(f" - Extra commands ({len(extra_commands)}):")
for command in extra_commands:
print(f" * {command}")
continue
if not servers:
continue
window_name = get_window_name(selected_group)
if windows := active_session.windows.filter(name=window_name):
windows[0].select()
continue
window = active_session.new_window(window_name, window_shell=f"ssh {servers[0]}")
for server in servers[1:]:
pane = window.split(shell=f"ssh {server}")
# Select tiled layout each time, to ensure enough space
window.select_layout("tiled")
# Wait until tmux finished working
time.sleep(0.05)
# Confirm connection on asking panes
confirmation_needed_text = "Are you sure you want to continue connecting (yes/no/[fingerprint])?"
for pane in window.panes:
pane_content = pane.capture_pane()
if pane_content and confirmation_needed_text == pane_content[-1]:
pane.send_keys("yes")
window.set_window_option("synchronize-panes", "on")
pane = window.panes[0]
pane.send_keys("sudo su -")
for command in extra_commands:
pane.send_keys(command)
window.set_window_option("synchronize-panes", "off")
window.select()
window.select_layout("tiled") window.select_layout("tiled")
# Wait until tmux finished working active_session.switch_client()
time.sleep(0.1)
# Confirm connection on asking panes
confirmation_needed_text = "Are you sure you want to continue connecting (yes/no/[fingerprint])?"
for pane in window.panes:
pane_content = pane.capture_pane()
if pane_content and confirmation_needed_text == pane_content[-1]:
pane.send_keys("yes")
window.set_window_option("synchronize-panes", "on")
pane = window.panes[0]
pane.send_keys("sudo su -")
for command in extra_commands:
pane.send_keys(command)
window.set_window_option("synchronize-panes", "off")
window.select()
window.select_layout("tiled")