26

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?

Drew
  • 75,699
  • 9
  • 109
  • 225
Connor
  • 1,591
  • 1
  • 19
  • 26

3 Answers3

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))
glucas
  • 20,175
  • 1
  • 51
  • 83
15

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)

Resigned June 2023
  • 1,502
  • 15
  • 20
  • 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? – user2237076 Jan 02 '17 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`. – Resigned June 2023 Jan 02 '17 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. – user2237076 Jan 02 '17 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`). – Resigned June 2023 Jan 02 '17 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)
   )
  )
jpmag
  • 1
  • 2
  • 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…). – Resigned June 2023 Aug 02 '17 at 03:42