I have put the following code (partially adapted from a company-mode
issue and a Stack Exchange question) in my init.el
in order to adjust the keybindings active in the company-mode
completions menu:
(defun company-complete-if-explicit ()
"Complete the current selection, but only if the user has interacted
explicitly with Company."
(interactive)
(if (company-explicit-action-p)
(company-complete)
(call-interactively
(key-binding (this-command-keys)))))
(define-key company-active-map (kbd "<return>") #'company-complete-if-explicit)
(define-key company-active-map (kbd "RET") #'company-complete-if-explicit)
(define-key company-active-map (kbd "TAB") #'company-complete-selection)
(define-key company-active-map (kbd "SPC") nil)
(setq company-auto-complete-chars nil)
In terminal Emacs, pressing RET
will dismiss the completions menu and insert a newline. However, if I have explicitly interacted with the menu (for instance, using up
and down
), then RET
will instead insert the selected completion.
The problem is that this doesn't work in windowed Emacs: if I press <return>
while the completions menu is showing (but I haven't explicitly interacted with it), then instead of Emacs inserting a newline, I receive the following error:
Debugger entered--Lisp error: (wrong-type-argument commandp nil)
call-interactively(nil)
(if (company-explicit-action-p) (company-complete) (call-interactively (key-binding (this-command-keys))))
company-complete-if-explicit()
call-interactively(company-complete-if-explicit nil nil)
command-execute(company-complete-if-explicit)
I debugged this, and here is what I think is happening:
- In windowed Emacs, the Return key sends
<return>
instead ofRET
. - Only
RET
has a binding (tonewline
), but normally<return>
is translated automatically toRET
, so the Return key still inserts a newline in windowed Emacs. - When I call
this-command-keys
incompany-complete-if-explicit
, the returned value is<return>
. - The
key-binding
function does not appear to do the key translation that usually occurs, so that(key-binding (kbd "RET"))
isnewline
but(key-binding (kbd "<return>"))
isnil
. - The error is thrown because
nil
is then passed tocall-interactively
.
My question is therefore: what is the best way to fix this problem (either by making key-binding
perform automatic translations, or otherwise)?