Created
April 23, 2023 08:04
-
-
Save jared-hughes/4e1a040cf3cc4dc5aa015e7f1b87216a to your computer and use it in GitHub Desktop.
search_windows. Bind to Super+X. Old code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import sys, tty, termios | |
import subprocess | |
from fuzzywuzzy import fuzz | |
import re | |
import curses | |
from curses import wrapper | |
def getch(): | |
fd = sys.stdin.fileno() | |
old_settings = termios.tcgetattr(fd) | |
try: | |
tty.setraw(sys.stdin.fileno()) | |
ch = sys.stdin.read(1) | |
finally: | |
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) | |
return ch | |
def get_windows(): | |
current = subprocess.Popen("xdotool getwindowfocus getwindowname".split(), stdout=subprocess.PIPE) | |
current = current.stdout.readlines()[0].decode("utf-8")[:-1] | |
p = subprocess.Popen("wmctrl -l".split(), stdout=subprocess.PIPE) | |
windows = {} | |
for line in p.stdout.readlines(): | |
line = line.decode("utf-8") | |
match = re.match(r"(\S*)\s*\S*\s*\S*\s*(.*)", line) | |
id, name = match.groups() | |
# exclude Desktop which would just defocus all windows | |
# exclude the currently active window | |
if name not in ["Desktop", current]: | |
windows[name] = id | |
return windows | |
def similarity(name, query): | |
return fuzz.token_set_ratio(name, query) | |
def closest_sorted(names, query): | |
return sorted(names, reverse=True, key=lambda k: similarity(k, query)) | |
def closest_counts(names, query): | |
names = closest_sorted(names, query) | |
return list(map(lambda k: (k, similarity(k, query)), names)) | |
class Window: | |
def __init__(self, window): | |
self.window = window | |
self.line = 2 | |
def add_line(self, str, *args, **kwargs): | |
self.window.addstr(self.line, 0, str, *args, **kwargs) | |
self.line += 1 | |
def clear(self): | |
self.window.clear() | |
self.line = 2 | |
def __getattr__(self, attr): | |
return getattr(self.window, attr) | |
windows_map = get_windows() | |
windows = get_windows().keys() | |
def open_window(name): | |
id = windows_map[name] | |
subprocess.Popen(["wmctrl", "-a", id, "-i"]) | |
# globals, yay | |
shown_entries = [] | |
query = "" | |
selected_entry = None | |
entry_count = 1 | |
def main(stdscr): | |
scr = Window(stdscr) | |
def update_query(_query): | |
global shown_entries, query, selected_entry | |
query = _query | |
shown_entries = closest_sorted(windows, query)[:entry_count] | |
selected_entry = shown_entries[0] | |
def update_entry(delta=0, set=None): | |
global shown_entries, selected_entry | |
for i, entry in enumerate(shown_entries): | |
if entry == selected_entry: | |
pos = i + delta | |
if set is not None: | |
pos = set | |
if pos < 0: | |
pos = 0 | |
if pos >= entry_count: | |
pos = entry_count - 1 | |
selected_entry = shown_entries[pos] | |
break | |
while True: | |
height, width = scr.getmaxyx() | |
entry_count = min(height - 2, len(windows)) | |
update_entry(0) | |
key = scr.getkey() | |
if key == chr(27): | |
break | |
elif key in ["KEY_RIGHT", "KEY_DOWN"]: | |
update_entry(1) | |
elif key in ["KEY_LEFT", "KEY_UP"]: | |
update_entry(-1) | |
elif key in ["KEY_PPAGE", "KEY_HOME"]: | |
update_entry(set=0) | |
elif key in ["KEY_NPAGE", "KEY_END"]: | |
update_entry(set=entry_count-1) | |
elif key in [chr(127), "KEY_BACKSPACE", "KEY_DC"]: | |
update_query(query[:-1]) | |
elif key in ["KEY_RESIZE", "KEY_IC"]: | |
# ignore | |
pass | |
elif key == "\n": | |
open_window(selected_entry) | |
break | |
else: | |
update_query(query + key) | |
scr.clear() | |
for name in shown_entries: | |
try: | |
if name == selected_entry: | |
scr.add_line(name, curses.A_STANDOUT) | |
else: | |
scr.add_line(name) | |
except: | |
pass | |
scr.line = 0 | |
scr.add_line(query, curses.A_BOLD) | |
scr.refresh() | |
scr.refresh() | |
wrapper(main) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment