Search code examples
emacskey-bindings

passing function arguments in elisp


I have a function defined in my init.el:

(defun bind-key (keymap)
    (evil-define-key '(normal insert) keymap (kbd "C-=") 'some-function))

(bind-key 'c++-mode-map)

But evil-define-key does not bind the C-= to some-function in keymap.

However, invoke evil-define-key directly is ok:

(evil-define-key '(normal insert) c++-mode-map (kbd "C-=") 'some-function)

I have tried:

(bind-key 'c++-mode-map)
(bind-key c++-mode-map)

Neither works.

I have googled for passing keymaps to a function, but found no solution. Then, I noticed evil-define-key is a macro. But I can not found solutions in this situation.

How can I get bind-key to work? By passing a keymap to it, the function binds C-= to some-function in in the keymap?


Solution

  • As you've noticed, this is trickier than it looks because evil-define-key is a macro (defined here). It takes a symbol that names a keymap variable, and binds the key once that variable has been defined. However, in this case it gets the symbol keymap instead of c++-mode-map, since a macro invocation receives as arguments the literal values in the call.

    You can get around this by changing your own function into a macro. That means that instead of just running some code, it needs to return some code that then gets evaluated. Like this:

    (defmacro bind-key (keymap)
      `(evil-define-key '(normal insert) ,keymap (kbd "C-=") 'some-function))
    

    The backquote introduces a form that gets returned verbatim, except for values inside it preceded by a comma.

    Invoke it with (bind-key c++-mode-map), and it should be equivalent to your explicit call to evil-define-key.