I often want to go to a newline while the company mode suggestion is showing. How can I set up company mode so only the tab key triggers a completion?
3 Answers
This is defined in company-active-map
. You can unbind the return key in that map:
(define-key company-active-map (kbd "<return>") nil)
Note however that return and tab do different things when there are multiple candidates. Tab is bound to company-complete-common
, while return is bound to company-complete-selection
. If you unbind the return key then you won't be able to use M-n
and M-p
to pick a completion from the list.
You may want to pick some other key to use for company-complete-selection
, for example:
(with-eval-after-load 'company
(define-key company-active-map (kbd "<return>") nil)
(define-key company-active-map (kbd "RET") nil)
(define-key company-active-map (kbd "C-SPC") #'company-complete-selection))
My complete setup for fixing this annoying default behavior is:
;;; Prevent suggestions from being triggered automatically. In particular,
;;; this makes it so that:
;;; - TAB will always complete the current selection.
;;; - RET will only complete the current selection if the user has explicitly
;;; interacted with Company.
;;; - SPC will never complete the current selection.
;;;
;;; Based on:
;;; - https://github.com/company-mode/company-mode/issues/530#issuecomment-226566961
;;; - https://emacs.stackexchange.com/a/13290/12534
;;; - http://stackoverflow.com/a/22863701/3538165
;;;
;;; See also:
;;; - https://emacs.stackexchange.com/a/24800/12534
;;; - https://emacs.stackexchange.com/q/27459/12534
;; <return> is for windowed Emacs; RET is for terminal Emacs
(dolist (key '("<return>" "RET"))
;; Here we are using an advanced feature of define-key that lets
;; us pass an "extended menu item" instead of an interactive
;; function. Doing this allows RET to regain its usual
;; functionality when the user has not explicitly interacted with
;; Company.
(define-key company-active-map (kbd key)
`(menu-item nil company-complete
:filter ,(lambda (cmd)
(when (company-explicit-action-p)
cmd)))))
(define-key company-active-map (kbd "TAB") #'company-complete-selection)
(define-key company-active-map (kbd "SPC") nil)
;; Company appears to override the above keymap based on company-auto-complete-chars.
;; Turning it off ensures we have full control.
(setq company-auto-complete-chars nil)
(link to current configuration, which has been further improved but is quite complicated by this point)
(updated as per this question)
-
To save the annoyance of keying down and back up to select the first item in the list (as return is inactive until you 'interact') I wanted to add C-RET as binding to complete selection so I could use this on the first item. I tried to include:
(define-key company-active-map (kbd "C-RET") #'company-complete-selection)
but it didn't work. Do you know if this would be possible and how to achieve? Jan 2, 2017 at 15:07 -
@user2237076 You can use
TAB
to select the first item in the list without needing to 'interact'. But to answer your question, I bet your terminal can't sendC-RET
(mine can't). TryC-h k C-RET
and see if Emacs actually gets the signalC-RET
instead of justRET
. Jan 2, 2017 at 16:49 -
I've got tab bound to cycling through the options:
(define-key company-active-map (kbd "TAB") #'company-complete-common-or-cycle)
but it looks like your right, when I changed to something other than C-RET I got the desired behaviour. Thanks. Jan 2, 2017 at 18:32 -
@user2237076 Just some additional info—by default, you can also cycle through the options with
M-p
andM-n
, or Isearch them withC-s
, or directly select a candidate withM-1
throughM-0
(numbers are shown if you setcompany-show-numbers
). Jan 2, 2017 at 23:30
Just saw this while looking for a solution for the same problem (although the annoying keys for me were SPC
and .
).
I find that binding the offending keys to nil
as proposed by @glucas and @Radon Rosborough is a not a nice UX as then you need to manually abort the company dropdown which is disruptive for speed typing.
That is, if company becomes active and you type a key bound to nil
nothing will happen. That's not what you would expect when you type a character. You would expect the character to be inserted.
Rather, it is much more convenient to have emacs automatically call company-abort
and then insert the typed character for you. Here's my solution:
(defun company--my-insert-spc() (interactive) (company-abort)(insert-char #10r32))
(defun company--my-insert-dot() (interactive) (company-abort)(insert-char #10r46))
(define-key company-active-map (kbd "SPC") 'company--my-insert-spc)
(define-key company-active-map (kbd ".") 'company--my-insert-dot)
I think you can easily extend this to RET
by calling (newline)
instead of (insert-char)
, (though I haven't tried that because I do use RET
to select).
Actually I am using use-package
so this is what I have in my init:
(use-package company
:config
(global-company-mode)
(setq company-minimum-prefix-length 3)
(setq company-auto-complete t)
(setq company-show-numbers t)
:bind
(("C-<tab>" . company-complete)
:map company-active-map
("ESC" . company-abort)
;; prevent company from completing on its own when we type regular characters
("SPC" . company--my-insert-spc)
("." . company--my-insert-dot)
)
)
-
1You shouldn't have to manually abort the company dropdown with the code I provided. Typing is completely uninterrupted unless you explicitly interact with the dropdown via M-TAB, C-v, M-v, C-s, etc. Something is wrong with your configuration (which is not surprising since there are like 10 variables you have to set correctly in order to get company to act in a reasonable way…). Aug 2, 2017 at 3:42