Elisp code to bind a keychord to another keychord

114 views Asked by At

In Emacs, with the idea of binding a keychord to another keychord, why is this elisp code not working?

(global-set-key (kbd "C-f") (kbd "C-s"))

(The idea being, in this example, to get "C-f" to do the same as "C-s".)

2

There are 2 answers

2
schaueho On

According to the documentation, I was expecting the following to be true: What you are attempting doesn't work, because you're binding the result of (kbd "C-s") to a key, which is an internal Emacs key representation and not the function that is (globally) set to the key. However, as xuchunyang pointed out, that's not entirely correct. global-set-key calls define-key internally which has in its documentation the following part:

(define-key KEYMAP KEY DEF)

In KEYMAP, define key sequence KEY as DEF. KEYMAP is a keymap.

KEY is a string or a vector of symbols and characters, representing a sequence of keystrokes and events. [...] DEF is anything that can be a key's definition:
nil (means key is undefined in this keymap),
a command (a Lisp function suitable for interactive calling),
a string (treated as a keyboard macro), [...]

And indeed, xunchunyang's example (global-set-key [?l] (kbd "C-f") works as you expect. (global-set-key [?l] (kbd "C-s") doesn't work, because isearch-forward expects an argument (the search regexp) which interactive will ask for. Only if you provide one, this particular keyboard macro will work, i.e. (global-set-key [?l] (concat (kbd "C-s") "foo")) will bind a search for "foo" to the key "l".

xuchunyang's answer is absolutely right: the best way is to name the function explicitly via (global-set-key (kbd "C-f") #'isearch-forward). You can easily figure out the function that is bound to a key by typing C-h k and then the key which you want to "copy": e.g. C-h k C-s) will show you that C-s is (usually, cf. below) bound to isearch-forward.

The approach using key-binding could, in the general case, lead to strange results: depending on where and how you execute this (i.e. interactively in some buffer or in your .emacs), results may differ, because key-binding honours current keymaps, which might assign different functions to keys.

2
xuchunyang On

I don't know why it not work either, but the usual way to achieve your purpose is just binding a key to a interactive command, instead of a string or keyboard macro, in this case (kbd "C-s"):

(global-set-key (kbd "C-f") #'isearch-forward)

or (the above is better)

(global-set-key (kbd "C-f") (key-binding (kbd "C-s")))