2

I want Emacs to work like this:

  • Let auto-complete auto-popup menu:

    (setq ac-auto-show-menu 0.8)
    (setq ac-delay 0.1)
    
  • Use C-n/p / M-n/p to select auto-complete popup menu candidates:

    (define-key ac-menu-map (kbd "M-n") 'ac-next)
    (define-key ac-menu-map (kbd "M-p") 'ac-previous)
    
  • When selecting a candiate

    • disable TAB / S-TAB in popup menu selection:

      (define-key ac-menu-map (kbd "<tab>") nil)
      (define-key ac-menu-map (kbd "<S-tab>") nil)
      
    • press Enter to select the candiate, without inserting newline:

      ;; ???
      
    • if the candidate is an abbrev, Enter should only select the candiate:

      ;; ???
      

      ... and pressing Space should cause Emacs to auto-expand the abbrev.

    • if the candidate is a dabbrev, pressing M-\ on candidate should trigger dabbrev-expand.

    • pressing TAB / C-i to expand the candidate for yasnippet:

      (setq yas-trigger-key "TAB")
      

      I set this, but the trigger does not expand when I press TAB.

    • pressing TAB to expand a snippet trigger while in a field:

      (setq yas-triggers-in-field t)
      
    • pressing C-j to jump to next field:

      (setq yas-next-field-key '("<tab>")) ;; or "C-j"
      
    • How can I expand a snippet within a snippet using yasnippet?


Some explanations

There are two TABs in Emacs:

  • (kbd "TAB") / (\t, [9])
  • (kbd "<tab>") / ([tab])

If modes like yasnippet and auto-complete want to bind to TAB, their trigger key must be the same as the original tab command. Since Emacs binds indent-for-tab-command to (kbd "TAB"), it's better to use that as the trigger key. yasnippet binds to it by default, and it is easy to set up auto-complete to trigger using TAB as well:

;; trigger using TAB and disable auto-start
(custom-set-variables
 '(ac-trigger-key "TAB")
 '(ac-auto-start nil)
 '(ac-use-menu-map t))

But in some modes (ruby-mode, markdown-mode, org-mode, etc.), the command is bound to (kbd "<tab>"). When the real tab key is typed, the function bound to (kbd "<tab>) has higher priority, so yasnippet and auto-complete are not invoked. This is easy to fix by moving the key binding:

(defun iy-tab-noconflict ()
  (let ((command (key-binding [tab])))                 ; remember command
    (local-unset-key [tab]) ; unset from (kbd "<tab>")
    (local-set-key (kbd "TAB") command)))              ; re-bind to (kbd "TAB")
(add-hook 'ruby-mode-hook 'iy-ac-tab-noconflict)
(add-hook 'markdown-mode-hook 'iy-ac-tab-noconflict)
(add-hook 'org-mode-hook 'iy-ac-tab-noconflict)

My setup

I downloaded yasnippet, auto-complete via the el-get packager manager. I'm using Ubuntu 12.04 and Emacs 24.3.50.1.

Wrapping up

I know this problem is a little long, but it really makes it difficult for me to use auto-complete and yasnippet. If the basic key binding doesn't work smoothly, this slows down my workflow quite a bit. I think many people have similar problems because I found some similar questions on the internet (though none of them are exactly like mine).

As you can see above, some of the relevant settings I already know. (But if you think I made a mistake somewhere, please tell me.) There are also some things I still don't know how to set up (???). Maybe there isn't a way to make all of these settings work together? Let me know if that is the case, and otherwise please make sure none of these setting interfere with each other.

After I get the answer to this question, I hope to write an Emacs extension to initialize all of these settings automatically.

Thanks for your help!

Community
  • 1
  • 1
stardiviner
  • 1,090
  • 1
  • 22
  • 33

2 Answers2

2

I faced the problem you're describing a long time ago and resolved it like this: bind auto-complete to TAB (also C-i which is the same) and yasnippet to C-o. Abbrevs are on C-o as well, but I don't use them a lot.

The advantages are:

  1. No stateful behavior results in a much more relaxed and productive editing.
  2. You no longer think "what will TAB do in this context?" before pressing, you just press it.
  3. You no longer check if you got the expected outcome, because there's only one.
  4. You can use auto-complete while in the process of expanding yasnippet.
  5. C-i and C-o are neighbors and very easy to press.
  6. Yasnippets now expand reliably in any mode since no mode overrides C-o.

This may be not what you want right now but consider trying it: you might like it after a while.

abo-abo
  • 20,038
  • 3
  • 50
  • 71
  • Good Idea, I tried this before, but still try to find a solution for this, because I think TAB is for this action. This seems rediculous. But it did. I found C-o is fine. I will like it. But I still have the problem, about use [Enter] to select the candidate in auto-complete popup menu. And seems yasnippet can not work for me (this is another problem I know). I tried to use [M-x yas-expand] to expand the trigger, but it does not work too. What do you think about this problem ? – stardiviner Nov 11 '13 at 09:08
  • For `auto-complete` I expand always with `tab` or `C-i` never ever with `RET`. For `yasnippet`, you can get `auto-yasnippet` from MELPA and `(global-set-key "\C-o" 'aya-open-line)`. – abo-abo Nov 11 '13 at 09:13
  • No, I do not want to complete with `RET`, I select condicate with `RET`. I let auto-complete auto raise popup menu. I give the `TAB` to snippet engine -> YASnippet. – stardiviner Nov 11 '13 at 09:15
  • As you prefer, I select candidate with `C-i`. – abo-abo Nov 11 '13 at 09:19
  • Sorry, maybe you misunderstand my mean, I mean I use `C-n/p` or `M-n/p` to navigate in auto-complete popup menu. I want to use `RET` to *select* candidate in menu. I think you use `C-i` to enable auto-complete to raise popup menu if I have not misunderstand your words. If I want to use `C-i` to select candidate, I at least need a function to bind, what's the function to select candidate ? – stardiviner Nov 11 '13 at 09:23
  • I almost never navigate. I just type enough so that the candidate that I want is the first one. Then I select it with `C-i`. It's quite productive: over time I get an intuition of how many letters I have to type to get the candidate I want to be first. – abo-abo Nov 11 '13 at 09:27
  • I found the reason, I found `ac-expand` in variable `ac-menu-map`. This is what I want `RET` to map. And `tab` is bind to `ac-expand` by default, that's why I can't understand why you can select with `C-i`. – stardiviner Nov 11 '13 at 09:38
0

Bind RET or <return> to function ac-expand. This is for select candidate.

stardiviner
  • 1,090
  • 1
  • 22
  • 33