Skip to content

Instantly share code, notes, and snippets.

@jared-hughes
Created April 23, 2023 08:04
Show Gist options
  • Save jared-hughes/4e1a040cf3cc4dc5aa015e7f1b87216a to your computer and use it in GitHub Desktop.
Save jared-hughes/4e1a040cf3cc4dc5aa015e7f1b87216a to your computer and use it in GitHub Desktop.
search_windows. Bind to Super+X. Old code
#!/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