As has been discussed before, you cannot bind commands to key-up events. One alternative that comes to mind to achieve similar workflow is to use a transient map like this:
(defvar my-cycling-var 0 "Some variable that I am interested in modifying")
(defvar my-transient-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "<tab>") 'my-forward-command)
(define-key map (kbd "<C-tab>") 'my-forward-command)
(define-key map (kbd "<S-tab>") 'my-backward-command)
(define-key map (kbd "<C-S-tab>") 'my-backward-command)
map)
"A key map used for a demonstration of transient maps")
(defun my-cycling-command ()
"Starts the cycling command and sets the transient key map"
(interactive)
(my-forward-command)
(set-transient-map my-transient-map 'my-keep-keymap))
(defun my-keep-keymap ()
"This function is called each time a key is pressed while the
transient map is active. If this function returns non-nil, the
keymap will stay active."
(let* ((key (this-command-keys))
(binding (lookup-key my-transient-map key)))
(unless binding
(my-end-repeatable-command))
binding))
(defun my-forward-command ()
"Increment my-cycling-var by one"
(interactive)
(setq my-cycling-var (+ 1 my-cycling-var))
(message "my-cycling-var is %d" my-cycling-var))
(defun my-backward-command ()
"Decrement my-cycling-var by one"
(interactive)
(setq my-cycling-var (+ -1 my-cycling-var))
(message "my-cycling-var is %d" my-cycling-var))
(defun my-end-repeatable-command ()
"Take any necessary action after cycling"
(message "my-cycling-var was set to %d" my-cycling-var))
;; Bind my-repeatable-command to Ctrl+TAB
(global-set-key (kbd "<C-tab>") 'my-cycling-command)
This binds my-cycling-command
to C-TAB
. Subsequent presses of TAB
and S-TAB
or C-TAB
and C-S-TAB
will have a cycling effect. As soon as you press any key that is not TAB
, S-TAB
, or RET
, the overlay map disappears and you resume normal editing.
Important Note: Prior to Emacs 24.4, set-transient-map
was named set-temporary-overlay-map
. To be compatible with earlier versions, you will have to use that function name instead.