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
REThas 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-keysincompany-complete-if-explicit, the returned value is<return>. - The
key-bindingfunction does not appear to do the key translation that usually occurs, so that(key-binding (kbd "RET"))isnewlinebut(key-binding (kbd "<return>"))isnil. - The error is thrown because
nilis 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)?