I'm writing a function to enable binding a "double tap" on a key (or one key then another key in rapid succession) to a function.
It almost works, but not quite. Here is the code I have in my lisp evaluation test chamber:
(setq doubletap-secondtap nil)
(defun doubletap (doubletap-key1 doubletap-key2 doubletap-wait doubletap-function)
(let* ((doubletap-secondtap 't)
(doubletap-event (read-event nil nil doubletap-wait)))
(if doubletap-event
(if (equal doubletap-event doubletap-key2)
(funcall doubletap-function)
(setq unread-command-events
(append (list doubletap-key1 doubletap-event) unread-command-events)) )
(setq unread-command-events
(append (list doubletap-key1) unread-command-events)) )))
(defun doubletap-j-j-godmodeall () (interactive)
(if doubletap-secondtap
(funcall 'self-insert-command 1)
(doubletap 106 106 0.3 'god-mode-all)))
(funcall 'doubletap-j-j-godmodeall)
(global-set-key (kbd "j") 'doubletap-j-j-godmodeall)
(global-set-key (kbd "j") 'self-insert-command)
The first function is intended to do the following:
wait doubletap-wait seconds for input
then
- if input is not given, simulate a keypress of doubletap-key1
- if input is given and it is not doubletap-key2, simulate two keypresses, first doubletap-key1 then doubletap-key2
- if input is given and it is doubletap-key2, call doubletap-function
Because we use plan to bind doubletap-key1 to call the interactive function doubletap-j-j-godmodeall
, we make a flag doubletap-secondtap
to tell doubletap-j-j-godmodeall
whether we are already inside the first function. If the flag is nil, it will call doubletap
, but if it has a value, it will perform the default action self-insert-command.
doubletap-j-j-godmodeall
works perfectly when it isn't bound to anything, as can be seen by evaluating the first three expressions and then evaluating the fourth expression, which is designed to activate god-mode for all buffers when two "j"s are pressed within 0.3 seconds, but otherwise behave like a normal function.
(this will only work if you have god-mode installed; if you don't, try a different function)
Unfortunately, when we evaluate the fifth expression, we find that its behavior becomes bizarre and unexpected. It hangs indefinitely until you either cancel it with "C-g" or press "j". If you press "j," it will toggle god-mode (even if you do it well after 0.3 seconds have passed).
Evaluate the last expression to restore normal behavior.
Can anyone explain this behavior, and more importantly, does anyone know how to make the function work correctly?
key-chord-mode
? It supports double-tapped keys.j
back onto the unread events list before you exit, so you just keep looping through the handler for that.