What I want to accomplish is to add a keybinding C-<backspace> to the eshell-mod-map that calls func. That can be done like this,

(use-package eshell
  (defun add-func-keybinding ()
      (kbd "C-<backspace>")
      (lambda ()
        (func "arg"))))
  (eshell-mode . add-func-keybinding))

Now C-<backspace> only calls func when inside an eshell buffer. I thought this should be equivalent to,

(use-package eshell
  :after esh-mode
  (:map eshell-mode-map
     ("C-<backspace>" . (lambda () (interactive) (func "arg")))))

However, this binds C-<backspace> to func everywhere, e. g., if I press C-<backspace> in the *scratch* buffer, that also calls func. This does not happen when the configuration is done as in the former use-package declaration, there the keybinding is kept only inside the eshell buffer.

However, I fail to see the difference between the two declarations. I would like to fix the latter so it has the same effect as the former, since the latter is a bit clearer and nicer. How can I do this?


I would write it that way.

(use-package esh-mode
  :bind (:map eshell-mode-map
              ("C-<backspace>" . my-eshell-mode-func))
  :config (defun my-eshell-mode-func ()
            (func "arg")))

For two reasons:

To answer your "why":
Because your first use-package form binds a define-key form to the hook eshell-mode-hook, which is sort of unrelated to feature eshell (because it belongs to feature esh-mode). But this hook triggers everytime, the feature esh-mode goes into action.
In your second use-package form this connection to feature esh-mode is missing (:after esh-mode results in something different).

Edit: Here is some fun: in old versions of file esh-mode.el eshell-mode-map gets fille as local variable, right in that moment, when eshell-mode was enabled by the user. With killing of the buffer eshell-mode-map went nil again. There is even a comment in source code:

;; FIXME: What the hell!?

That is probably the reason why your first use-package form uses a hook.
This setup of eshell-mode-map as a buffer local variable is still present in version 26.3 of Emacs. So binding your define-key to hook eshell-mode-hook is a valid option until you upgrade.
In more recent versions this has been fixed and my above solution should work.

Be aware, I cannot test this solution, because my emacs is way to old and does not has the line (provide 'esh-mode) in file esh-mode.el. And my OS does not map a backspace key to my physical keyboard.

  • Tested what you have with func replaced with message. Unfortunately, the keybinding was available in *scratch* mode. – scribe Nov 23 '20 at 20:56
  • This sounds like some sort of bug. Anyway, which emacs version are you using? There have been changes in file esh-mode.el. Read my answer again and check for the comment in your esh-mode.el. – jue Nov 23 '20 at 21:00
  • I am using 26.3, could you tell me where to find the esh-mode.el? – scribe Nov 23 '20 at 21:06
  • github.com/emacs-mirror/emacs/tags you can extract this source code to your harddisk and make it known to emacs with variable source-directory you can then easily look up source code of functions and features. – jue Nov 23 '20 at 21:10
  • this weird local variable of eshell-mode-map is still present in 26.3. so you need a hook to set up your key until you upgrade to a more recent version. – jue Nov 23 '20 at 21:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.