#!/usr/bin/env python3 import json from select import select from subprocess import check_output, Popen, PIPE import sys def remove_empty_outputs(obj): return [o for o in obj if o['full_text'].strip() != ''] first = True def print_i3stat(j): global first j = remove_empty_outputs(j) sys.stdout.write(('' if first else ',') + json.dumps(j) + '\n') sys.stdout.flush() first = False def parse_i3stat(s): if s[0] == ',': s = s[1:] j = json.loads(s) return j def parse_kbdlayout(s): colors = { 'us(intl)' : '#66ccff', 'ru(phonetic)' : '#ff3300', 'il(biblicalSIL)' : '#c1b876' } flags = { 'us(intl)' : 'πŸ‡ΊπŸ‡Έ', 'ru(phonetic)' : 'πŸ‡·πŸ‡Ί', 'il(biblicalSIL)' : 'πŸ“œ' } try: color = colors[s] flag = flags[s] except: color = '#cccccc' flag = 'πŸ’»' return [{'full_text': flag + ' ' + s, 'color': color}] def merge_status_items(*args): return [item for sublist in args for item in sublist] if __name__ == '__main__': timeout = 0.1 # open subprocesses i3stat = Popen(['i3status'], stdout=PIPE, bufsize=0, close_fds=True) kbdlayout = Popen(['unbuffer', 'kbdlayout'], stdout=PIPE, bufsize=0, close_fds=True) # skip i3status header sys.stdout.write(i3stat.stdout.readline().decode('utf8')) sys.stdout.write(i3stat.stdout.readline().decode('utf8')) stat, kbd = [], [] try: stdouts = [p.stdout for p in [i3stat, kbdlayout]] while True: fs = select(stdouts, [], [])[0] for f in fs: line = f.readline()[:-1].decode('utf8') if f == kbdlayout.stdout: kbd = parse_kbdlayout(line) elif f == i3stat.stdout: stat = parse_i3stat(line) print_i3stat(merge_status_items(kbd, stat)) except Exception as e: print(e) i3stat.kill() kbdlayout.kill()