25

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 3

15

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))
1
13

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)

4
  • 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 send C-RET (mine can't). Try C-h k C-RET and see if Emacs actually gets the signal C-RET instead of just RET. 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 and M-n, or Isearch them with C-s, or directly select a candidate with M-1 through M-0 (numbers are shown if you set company-show-numbers). Jan 2, 2017 at 23:30
-1

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)
   )
  )
1
  • 1
    You 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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