2

I want to achieve something like this:

(setq my-global-keybindings
      '(([?\C-x ?\C-d] . dired)
        ([?\C-x ?\C-b] . ibuffer)
        ([?\C-x b] . ivy-switch-buffer)))

(apply #'bind-keys* my-global-keybindings)

But bind-keys* is a macro here.

Drew
  • 29,895
  • 7
  • 74
  • 104
godblessfq
  • 218
  • 1
  • 10
  • You can't. Macros do stuff with code so you cannot apply it and if you pass a variable the macro will only see the variable as code and needs to be able to do its stuff with that without knowing what that will represent later when the program runs. In fact you must assume it should be able to do its work before `my-global-keybindings` exists. Macros are code transformations and has nothing to do with the runtime. – Sylwester Nov 24 '18 at 12:53
  • Does [this SE.emacs post](https://emacs.stackexchange.com/a/28120/105) answer your question? (It uses `bind-keys` and not `bind-keys*`.) – Drew Nov 24 '18 at 17:11

1 Answers1

1

In the specific case of binding keys, I think the better option is to look for a function that replaces that bind-keys* macro (I don't see any justification why it should be a macro rather than a function).

But as for the more general question, here's how I'd do it:

(defmacro my-multi-bind-keys (bindings)
  (macroexp-progn
    (mapcar (lambda (binding)
             `(bind-keys* ,@binding))
            bindings)))
(my-multi-bind-keys (([?\C-x ?\C-d] dired)
                     ([?\C-x ?\C-b] ibuffer)
                     ([?\C-x b] ivy-switch-buffer)))

Note that using a setq like you did is problematic: macros needs to be expanded during compilation but the setq should not be executed by the compiler (it should be compiled by the compiler to be run when the code is later executed) so there's no sound way for the macro to get access to the var's value (at least until time-travel is made to work).

Stefan
  • 27,908
  • 4
  • 53
  • 82