Keystroke tracking
Update: 2025-May-09
Demi-fix: Now only tracks command and meta keys
(defun tw/keylog-toggle ()
"Toggle key logging with timestamps. Only logs keys starting with C- or M-, ignoring mouse events."
(interactive)
(let* ((hook-symbol 'tw/keylog--log-command-hook))
(unless (fboundp hook-symbol)
(fset hook-symbol
(lambda ()
(let* ((buffer-name "*Key Log*")
(keys (key-description (this-command-keys-vector))))
(unless (or (string-match-p "<mouse-" keys)
(string-match-p "<wheel-" keys)
(string-match-p "<double-" keys)
(string-match-p "<triple-" keys)
(string-match-p "<down-mouse-" keys)
(string-match-p "<drag-mouse-" keys))
(when (or (string-prefix-p "C-" keys)
(string-prefix-p "M-" keys))
(let ((timestamp (format-time-string "%Y-%m-%d %H:%M:%S")))
(with-current-buffer (get-buffer-create buffer-name)
(goto-char (point-max))
(unless (bolp)
(insert "\n"))
(insert (format "[%s] %s" timestamp keys))
(dolist (win (get-buffer-window-list (current-buffer) nil t))
(with-selected-window win
(goto-char (point-max)))))))))))
(if (member hook-symbol post-command-hook)
(progn
(remove-hook 'post-command-hook hook-symbol)
(message "Key logging stopped."))
(add-hook 'post-command-hook hook-symbol)
(message "Key logging started. See buffer *Key Log*"))))
Update: 2025-May-09
It’s quickly became apparent that this approach is far from ideal. FIXME: Only capture command key strokes (C- and M-) and arguments; which, the more I think about it, the less trivial it becomes.
I wanted a way to see my Emacs key strokes in real time, so I wrote a small function to display them in a buffer. I’m sure there are better, existing solutions but this one works for me. It’s a bit rough at the moment, as I need to find a way of going from this:
[2025-05-08 13:41:20] C-x b
[2025-05-08 13:41:22]
[2025-05-08 13:41:23] k
[2025-05-08 13:41:23] e
[2025-05-08 13:41:23] y
[2025-05-08 13:41:23] SPC
[2025-05-08 13:41:24] l
[2025-05-08 13:41:24] o
[2025-05-08 13:41:24] g
To something like this:
[2025-05-08 13:41:20] C-x b key SPC log
https://github.com/Cthimothy/key-logger
(Defun tw/keylog-toggle ()
"Toggle key logging with timestamps. Ignoring mouse events."
(interactive)
(let* ((buffer-name "*Key Log*")
(hook-symbol 'tw/keylog--log-command-hook))
(unless (fboundp hook-symbol)
(fset hook-symbol
(lambda ()
(let ((keys (key-description (this-command-keys-vector))))
(unless (or (string-match-p "<mouse-" keys)
(string-match-p "<wheel-" keys)
(string-match-p "<double-" keys)
(string-match-p "<triple-" keys)
(string-match-p "<down-mouse-" keys)
(string-match-p "<drag-mouse-" keys))
(let ((timestamp (format-time-string "%Y-%m-%d %H:%M:%S")))
(with-current-buffer (get-buffer-create buffer-name)
(goto-char (point-max))
(unless (bolp)
(insert "\n"))
(insert (format "[%s] %s" timestamp keys))
(dolist (win (get-buffer-window-list (current-buffer) nil t))
(with-selected-window win
(goto-char (point-max))))))))))
(if (member hook-symbol post-command-hook)
(progn
(remove-hook 'post-command-hook hook-symbol)
(message "Key logging stopped."))
(add-hook 'post-command-hook hook-symbol)
(message "Key logging started. See buffer %s" buffer-name))))