Create: 2022-07-12, Update: 2022-07-12
I ate my words, I cannot publish a blog post per week. I am having multiple interesting long posts in the process, but none of them have reached my standard of publishing.
This is a short post.
I was again messing with my Emacs config. Somehow I have the idea of
getting rid of use-package
, (in my case, leaf
). They did a great
job of abstracting and packing related configs into a single
block. But too much abstractions make me hard to understand what is
going on under the hood.
I live in the HEAD of Emacs. I regularly compile it from source about every two weeks.
I accidentally discovered that, define-key
and global-set-key
are
now legacy functions.
It is shocking that such common functions are now legacy. The
documentation suggests we should instead use keymap-set
.
For define-key
.
This is a legacy function; see keymap-set for the recommended function to use instead.
For global-set-key
.
This is a legacy function; see keymap-global-set for the recommended function to use instead.
The new functions add a checking to the KEY string parameter.
Originally, if I use global-set-key
, I would use kbd
. I am not a
fan of using backslash.
(global-set-key (kbd "C-c k") #'recompile)
Now we only have to do this. It is a bit easier.
(keymap-global-set "C-c k" #'recompile)
When using the new functions, we have to pay attention to the
key-valid-p
checker. I broke my config with this.
;; Original
(define-key yas-minor-mode-map (kbd "<TAB>") nil)
;; My new attempt, this gives an error.
(keymap-set yas-minor-mode-map "<TAB>" nil)
;; Correct approach.
(keymap-set yas-minor-mode-map "TAB" nil)
(keymap-set yas-minor-mode-map "<tab>" nil)
The new functions have a stricter requirement for the key string.
Here's some example key sequences. "f" (the key f) "S o m" (a three key sequence of the keys S, o and m) "C-c o" (a two key sequence of the keys c with the control modifier and then the key o) "H-<left>" (the key named "left" with the hyper modifier) "M-RET" (the "return" key with a meta modifier) "C-M-<space>" (the "space" key with both the control and meta modifiers) These are the characters that have shorthand syntax: NUL, RET, TAB, LFD, ESC, SPC, DEL. Modifiers have to be specified in this order: A-C-H-M-S-s which is Alt-Control-Hyper-Meta-Shift-super
For Emacs users with a single machine, you can update all your config into using the newer functions.
But if you are like me, running Emacs on multiple machines with different versions. You should beware of the compatibility issues, at least be compatible with the lastest stable.
My solution is to write a simple wrapper.
(defconst *is-older-emacs* (version< emacs-version "29.0.50"))
(if *is-older-emacs*
(progn
(defun drsl/keymap-set (keymap key definition)
"Workaround of keymap-set in older Emacs.
This does not check the validity of key string."
(define-key keymap (kbd key) definition))
(defun drsl/keymap-unset (keymap key &optional remove)
"Workaround of keymap-unset in older Emacs.
This does not check the validity of key string."
;; Older `define-key' only accept 3 arguments.
(define-key keymap (kbd key) nil))
(defun drsl/keymap-global-set (key command)
"Workaround of keymap-global-set in older Emacs.
This does not check the validity of key string."
(drsl/keymap-set (current-global-map) key command))
(defun drsl/keymap-global-unset (key &optional remove)
"Workaround of keymap-global-unset in older Emacs.
This does not check the validity of key string."
(drsl/keymap-unset (current-global-map) key remove))
(defalias 'keymap-set #'drsl/keymap-set)
(defalias 'keymap-unset #'drsl/keymap-unset)
(defalias 'keymap-global-set #'drsl/keymap-global-set)
(defalias 'keymap-global-unset #'drsl/keymap-global-unset))
)
The keymap-set
and keymap-global-set
are only available in the
last HEAD. Emacs 28.1 currently do not have these functions. Be
careful if you want to try.
There are some keymap related update in the latest Emacs, like the
replacement of local-set-key
. I am not going into the details of
them. If you are interested in the function documentations or
definitions, use C-h f to find the function inside Emacs.