In a terminal window, I'm finding that company-mode completion doesn't work, whereas it does work in a graphical window. For example a down arrow inserts the text OB and M-n simply inserts n.

As a workaround, I've followed this answer to use C-n and C-p like so

(with-eval-after-load 'company
  (define-key company-active-map (kbd "C-n") #'company-select-next)
  (define-key company-active-map (kbd "C-p") #'company-select-previous))

but I'd prefer to use the same keys whether I'm running graphically or via ssh.

This used to work, and I've upgraded my configuration files and installed a lot more packages recently, but even reducing my initialization file down to just the company mode code didn't fix the problem.

Edit: I've isolated the problem down to this line of code that I copied from the graphene package that redefines ESC to abort the completion.

 (define-key company-active-map (kbd "ESC") 'company-abort)

I can see how this might stop M-n and M-p working because ESC has got something to do with the Alt key in emacs. I can workaround the problem in a terminal using

(if (display-graphic-p)
    (with-eval-after-load 'company
      (define-key company-active-map (kbd "ESC") 'company-abort)))

which means that single ESC aborts completion in a graphical frame, and triple ESC aborts in a terminal.

However is it still be possible for the arrow keys to work with single ESC? My preference is to use arrow keys and single escape if possible.

  • The problem here is that ESC sends C-[, M-f sends C-[ f and the down arrow sends C-[ [1;3B. As you can see, ESC is a prefix of the codes sent by both all Meta keys and the arrow keys, so you can't do it; not without hacks like using timers at any rate. Why not get used to C-g for quitting? It's the Emacs standard, and it's arguably easier to type.
    – PythonNut
    Feb 9, 2015 at 17:59

1 Answer 1


You have fallen victim to the limitations of terminal control sequences.

  • <escape> actually sends C-[
  • M-f actually sends C-[ f
  • <up> actually sends C-[ [ A

Becuase <escape> is a prefix of M-f, you can't really bind it. This is not entirely true. You can still bind it using timers that determine whether <escape> is a command or a prefix, but I don't recommend using it.

Long term, C-g is the better solution. It's standardized and should work everywhere in Emacs.

  • Is there a way of adding a small delay to see if the control sequence is longer than C-[ ?
    – Jonathan.
    May 6, 2016 at 10:09

Your Answer

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

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