From 47ba6bced90a7b8fb0de491f20a97a21769eb0e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Sat, 22 Dec 2018 11:31:42 +0100 Subject: [PATCH] eoptasks: add curses/emoji status screen --- eoptasks/eoptasks.py | 104 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 9 deletions(-) diff --git a/eoptasks/eoptasks.py b/eoptasks/eoptasks.py index c1d0860..3f75cdd 100755 --- a/eoptasks/eoptasks.py +++ b/eoptasks/eoptasks.py @@ -16,9 +16,12 @@ import argparse import configparser +import curses +import json import os import random import re +import socket import sys import time @@ -92,12 +95,66 @@ def filter_servers(servers, args): selected_servers = servers return selected_servers +def status_window(session_name): + curses.setupterm() + window = curses.initscr() + window.addstr(0, 0, 'eoptasks', curses.A_STANDOUT) + window.addstr(0, 10, '🙂') + curses.curs_set(0) + window.refresh() + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + server_address = '/tmp/.eoptasks.%s' % session_name + sock.bind(server_address) + sock.listen(1) + e = None + while True: + connection, client_address = sock.accept() + try: + json_msg = b'' + while True: + data = connection.recv(5000) + if not data: + break + json_msg += data + servers_info = json.loads(json_msg.decode('utf-8')) + finally: + connection.close() + + try: + height, width = window.getmaxyx() + max_length = max([len(x) for x in servers_info.keys()]) + 4 + nb_columns = (width-4) // max_length + + for i, server_name in enumerate(servers_info): + y = 2 + (i//nb_columns) + x = 1 + (width//nb_columns) * (i%nb_columns) + window.addstr(y, x+3, server_name) + status_icon = { + 'running': '⏳', + 'done': '🆗', + }.get(servers_info[server_name]['status'], '💤') + window.addstr(y, x, status_icon) + if y > height-4: + break + window.refresh() + total_servers = len(servers_info.keys()) + running_servers = len([x for x in servers_info.values() if x['status'] == 'running']) + done_servers = len([x for x in servers_info.values() if x['status'] == 'done']) + if total_servers == done_servers: + break + except Exception as e: + window.addstr(0, 10, '😡 %r' % e) + window.refresh() + os.unlink(server_address) + window.addstr(0, 10, '😎') + window.refresh() + time.sleep(5) + args = parse_args() if args.session_name: - print('eoptasks, tmux session %s' % args.session_name) - time.sleep(3600) + status_window(args.session_name) sys.exit(0) servers = get_servers() @@ -118,6 +175,11 @@ if not args.cmd: def init_tmux_session(): tmux_session_name = 's%s' % random.randrange(1000) + server_address = '/tmp/.eoptasks.%s' % tmux_session_name + try: + os.unlink(server_address) + except OSError: + pass os.system('tmux new-session -s %s -n 🌑 -d %s --status-window %s' % ( tmux_session_name, sys.argv[0], tmux_session_name)) return tmux_session_name @@ -152,8 +214,32 @@ else: status_window = session.attached_window + all_servers = selected_servers[:] total_number = len(selected_servers) random.shuffle(selected_servers) + + servers_info = {} + for server in selected_servers: + servers_info[server.name] = {'status': ''} + + def send_status(): + current_windows = [x.name for x in session.list_windows()] + for server in all_servers: + server_info = servers_info[server.name] + if server.name in current_windows: + server_info['status'] = 'running' + elif server_info['status'] == 'running': + server_info['status'] = 'done' + + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + server_address = '/tmp/.eoptasks.%s' % tmux_session_name + try: + sock.connect(server_address) + except socket.error: + return + sock.sendall(json.dumps(servers_info).encode('utf-8')) + sock.close() + while selected_servers: current_clusters = [cluster_name(x.name) for x in session.list_windows()] for server in selected_servers[:]: @@ -168,7 +254,10 @@ else: else: time.sleep(0.1) while len(session.list_windows()) > 5: + send_status() time.sleep(0.1) + send_status() + percentage = len(selected_servers) / total_number if percentage == 1: status_window.rename_window('🌕') @@ -178,12 +267,9 @@ else: status_window.rename_window('🌓') elif percentage >= 0.25: status_window.rename_window('🌒') + while len(session.list_windows()) > 1: + send_status() time.sleep(0.1) - try: - status_window.kill_window() - except libtmux.exc.LibTmuxException: - # killing the last window will end the tmux session, and it's not - # handled correctly by kill_window as it ends by updating the list - # of windows (and hitting the dead tmux). - pass + status_window.rename_window('🌕') + send_status()