My current Go autocompletion setup in GNU Emacs

August 19, 2016

A while back I wrote about getting gocode based autocompletion working in GNU Emacs, and then about things about the autocompletion that I was unsatisfied with. After a certain amount of struggling I actually wound up with a Go autocompletion setup that I'm happy with, and I've now realized that I never wrote it up, and there is one change that wound up quite important for me.

GNU Emacs has at least two auto-completion systems, auto-complete and company-mode. In my original approach I followed gocode's recommendation and used auto-complete. I have now switched to company-mode and I like this much better, in large part because I've been able to do much more customization of how it behaves than I managed with auto-complete.

My first set of customizations are more or less gocode's recommended ones. I enable on company-mode only in Go code, and I copied many of the possible improvements it lists:

(setq company-tooltip-limit 15)
(setq company-idle-delay .15)
(setq company-echo-delay 0)
(setq company-begin-commands '(self-insert-command))

This still left my general issues with autocompletion, so I got out a big hammer and started changing company-mode's key bindings so that they didn't steal keys from me in a way that irritated me.

; complete selections with Control-Return, not
; normal Return.
(define-key company-active-map (kbd "RET") nil)
(define-key company-active-map (kbd "<return>") nil)
(define-key company-active-map (kbd "C-<return>") 'company-complete-selection)

; Use C-Up/Down to move through the selection list
(define-key company-active-map (kbd "<down>") nil)
(define-key company-active-map (kbd "<up>") nil)
(define-key company-active-map (kbd "C-<down>") 'company-select-next-or-abort)
(define-key company-active-map (kbd "C-<up>") 'company-select-previous-or-abort)

The result of these bindings is that company-mode is relatively inoffensive. In practice, often it's enough that it tells me what's available and I wind up just typing out the function or variable name myself. But at least some of the time I'll wind up using C-return once I've typed enough to make the name unambiguous. This means that I'm not making much use of its power, but at least it's inoffensive and helpful.

(Actively looking at company-mode in the process of writing this entry has suggested a number of things I should remember about it, like that TAB will complete as much as possible, up to and including everything.)

Overall my experience with company-mode in Go has been pleasant. It doesn't seem to hurt and it's non-distracting enough and potentially helpful enough that I keep it around. It's even reached the point where I'm a bit annoying when it doesn't offer suggestions for various reasons, such as that I haven't yet run goimports to actually add an import for the new package that I'm using and that I want names from.

(This is a kind of chicken and egg situation. I need to write something that uses the package before goimports will auto-add it for me, but I need it added before company-mode will start conveniently completing names so that I can use the package. The real answer turns out to be that I should remember the go-mode C-c C-a binding to add an import by hand.)

One of the things that I have wound up quite liking about company-mode is simply that I can modify it like this. Possibly auto-complete can be modified in this way too, but it was easy enough for me to work out how to do it to company-mode even as a semi-outsider to GNU Emacs mode hacking.

(I have some additional bindings I consider experimental, which I've decided not to mention any specifics about. That it's easy enough to bind things that I do have experimental bindings is nice.)

Written on 19 August 2016.
« Localhost is (sometimes) a network
My pragmatic decision on GNU Emacs versus vim for my programming »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Fri Aug 19 23:25:51 2016
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.