Skip to content

Instantly share code, notes, and snippets.

Created September 5, 2016 08:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/56473f34704f3e9725076fd2215cdf94 to your computer and use it in GitHub Desktop.
Save anonymous/56473f34704f3e9725076fd2215cdf94 to your computer and use it in GitHub Desktop.
import pynput.keyboard # from pynput.keyboard import Key, Listener, Controller
import operator
import functools
from pynput._util.xorg_keysyms import KEYSYMS
import traceback
reset_queue_key = pynput.keyboard.Key.pause
log_function_calls = False
def log_calls(f):
if not log_function_calls:
return f
def f_with_call_logging(*args):
print("[begin] " + f.__name__)
f(*args)
print("[ended] " + f.__name__)
return f_with_call_logging
@log_calls
def ends_with_sublist(sub, lst):
n = len(sub)
if n > len(lst) or len(sub) == 0 or len(lst) == 0:
return False
matched = 0
ret = False
for i in range(len(sub), 0, -1):
if sub[:i] == lst[-i:]:
matched = i
break
print("matched : ", matched, "/", n)
return matched == n
class HotKeyMan(object):
def __init__(self):
self._pressing = list()
#self._press_history = list()
self._comb_history = list()
self._is_comb = False
self._registered_hotkeys = dict()
self._registered_sequences = dict()
self._log_calls = False
# def register_hotkey(self, hotkeys_list, call):
# if not self._validate_hotkeys(hotkeys_list):
# print("invalid hotkeys")
# return
# self._registered_hotkeys[frozenset(hotkeys_list)] = call
# print("[hotkey registered] " + str(frozenset(hotkeys_list)))
def register_comb_sequence(self, sequence_list, call):
if not self._validate_sequence(sequence_list):
print("invalid sequence")
return
comb_seq = list()
for key_combination in sequence_list:
if isinstance(key_combination, str):
comb_seq.append(frozenset([key_combination,]))
elif isinstance(key_combination, list) or isinstance(key_combination, tuple):
comb_seq.append(frozenset(key_combination))
else:
print("invalid sequence")
return
self._registered_sequences[tuple(comb_seq)] = call
print("[sequence registered] " + str(tuple(comb_seq)))
@staticmethod
def _validate_hotkeys(hotkeys_list):
#TODO
pass
return True
@staticmethod
def _validate_sequence(sequence_list):
#TODO
pass
return True
@log_calls
def _on_press(self, key):
if hasattr(key, "name"):
self._pressing.insert(0, key.name)
elif hasattr(key, "char"):
self._pressing.insert(0, key.char)
self._pressing = self._pressing[:10] # limit length
self._handle_key_sequences()
return True
# def _handle_pressing_keys(self):
# combinations = set()
# for i in range(1, len(self._pressing) + 1):
# combinations_by_i = (frozenset(c) for c in itertools.combinations(self._pressing, i))
# combinations = combinations.union(combinations_by_i)
# #print("combinations: ")
# for c in combinations:
# #print(" " + str(c))
# if c in self._registered_hotkeys:
# print("[TRIGGERED] " + str(c))
# self._registered_hotkeys[c]()
# #print("/combinations")
@log_calls
def _handle_key_sequences(self):
#self._press_history.append(frozenset(self._pressing))
#self._press_history = self._press_history[-10:]
if len(self._pressing) > 1 and not self._is_comb:
self._comb_history.pop()
self._comb_history.append(frozenset(self._pressing))
self._comb_history = self._comb_history[-10:]
for key_seq, func in self._registered_sequences.items():
# print(" key_seq : ", str(key_seq), "\n", "comb_history : ", self._comb_history)
if ends_with_sublist(key_seq, tuple(self._comb_history)):
print("[TRIGGERED] " + str(key_seq))
self._registered_sequences[key_seq]()
@log_calls
def _on_release(self, key):
try:
if hasattr(key, "name"):
self._pressing.remove(key.name)
elif hasattr(key, "char"):
self._pressing.remove(key.char)
else:
# TODO
#print("============= WHAT HAPPENED? ===============")
pass
#print("released {}".format(key))
except:
print(dir(key))
traceback.print_stack()
self._pressing.clear()
if self._pressing:
self._is_comb = True
else:
self._is_comb = False
if key == reset_queue_key:
self._pressing.clear()
#return False # Stop listener
def listen(self):
# Collect events until released
with pynput.keyboard.Listener(on_press=self._on_press,
on_release=self._on_release) as listener:
listener.join()
print("stopped")
#hkm = HotKeyMan()
#hkm.register_comb_sequence([('alt', 'r'), 'h', 'a', 'l', 'l', 'o'], lambda:print('wtb: true programmer'))
#hkm.register_comb_sequence([("alt", "r")], lambda:print("foo"))
#hkm.register_comb_sequence([("alt", "r"), ("alt", "y")], lambda:print("bar"))
#def fdo():
# print("t e s t")
#hkm.register_comb_sequence(list("test"), fdo)
#hkm.listen()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment