Seven Story Rabbit Hole

Sometimes awesome things happen in deep rabbit holes. Or not.

   images

Configure Emacs as a Go Editor From Scratch

This explains the steps to get a productive Emacs environment for Go programming on OSX, starting from scratch.

Install Emacs

I recommend using the emacs from emacsformacosx.com.

It has a GUI installer so I won’t say much more about it.

Install lastest version of Go

See Installing Go

After installing, you’ll want to define the following environment variables in your ~/.bash_profile.

1
2
3
4
export GOROOT=/usr/local/go            
export GOPATH=~/Development/gocode
export PATH=$PATH:$GOROOT/bin
export PATH=$PATH:$GOPATH/bin

These might be different on your system.

Install additional go tools (godoc, etc)

To get the godoc tool as well as others, run:

1
go get golang.org/x/tools/cmd/...

I ended up getting an error:

1
2
3
$ go get golang.org/x/tools/cmd/...
# golang.org/x/tools/go/ssa/interp
Development/gocode/src/golang.org/x/tools/go/ssa/interp/external.go:244: undefined: syscall.Pipe2

which is documented in issue 13831

To get around this, you can install the tools you need directly via:

1
2
3
4
5
6
go get golang.org/x/tools/cmd/godoc
go get golang.org/x/tools/cmd/cover
go get golang.org/x/tools/cmd/gorename
go get golang.org/x/tools/cmd/goimports
go get golang.org/x/tools/cmd/oracle
go get golang.org/x/tools/cmd/vet

Install Melpa

Melpa is a package manager for Emacs, and is required for go-mode

To configure emacs for melpa:

  • Create a new file ~/.emacs.d/init.el
  • Add the following contents:
1
2
3
(require 'package)
(add-to-list 'package-archives
  '("melpa" . "http://melpa.milkbox.net/packages/") t)

Restart emacs and run M-x package-list-packages and you should see it contacting http://melpa.milkbox.net and you should also see lot of packages listed as being from the melpa archive.

Install go-mode

Run M-x package-install and when prompted, enter go-mode and hit enter.

I got the following warnings:

1
2
3
4
5
6
7
Compiling file /Users/tleyden/.emacs.d/elpa/go-mode-20160127.4/go-mode.el at Sat Feb  6 17:58:11 2016
Entering directory `/Users/tleyden/.emacs.d/elpa/go-mode-20160127.4/'
go-mode.el:16:1:Warning: cl package required at runtime

In go-mode:
go-mode.el:917:10:Warning: `font-lock-syntactic-keywords' is an obsolete
    variable (as of 24.1); use `syntax-propertize-function' instead.

Restart Emacs and open a .go file, you should see the mode as “Go” rather than “Fundamental”.

For a full description of what go-mode can do for you, see Dominik Honnef’s blog, but one really useful thing to be aware of is that you can quickly import packages via C-c C-a

Update Emacs path to find godoc

Run M-x package-install and enter exec-path-from-shell

I got this warning:

1
2
3
4
5
6
7
8
Compiling file /Users/tleyden/.emacs.d/elpa/exec-path-from-shell-20160112.2246/exec-path-from-shell-pkg.el at Sat Feb  6 18:20:55 2016
Entering directory `/Users/tleyden/.emacs.d/elpa/exec-path-from-shell-20160112.2246/'

Compiling file /Users/tleyden/.emacs.d/elpa/exec-path-from-shell-20160112.2246/exec-path-from-shell.el at Sat Feb  6 18:20:55 2016

In exec-path-from-shell-setenv:
exec-path-from-shell.el:189:11:Warning: assignment to free variable
    `eshell-path-env'

Restart emacs.

Update Emacs config for godoc

It’s really useful to be able to able to pull up 3rd party or standard library docs from within Emacs using the godoc tool.

PATH

Add the following to your ~/.emacs.d/init.el file so that it gets the PATH environment:

1
2
3
4
5
6
7
8
9
10
(defun set-exec-path-from-shell-PATH ()
  (let ((path-from-shell (replace-regexp-in-string
                          "[ \t\n]*$"
                          ""
                          (shell-command-to-string "$SHELL --login -i -c 'echo $PATH'"))))
    (setenv "PATH" path-from-shell)
    (setq eshell-path-env path-from-shell) ; for eshell users
    (setq exec-path (split-string path-from-shell path-separator))))

(when window-system (set-exec-path-from-shell-PATH))

NOTE: according to this StackOverflow post, it’s possible to achieve this via downloading the exec-path-from-shell emacs plugin from Marmelade or Melpa.

GOPATH

1
(setenv "GOPATH" "/Users/tleyden/Development/gocode")

(replace the above path to the absolute path to the directory where you store your Go code)

After doing this step, you should be able to run M-x godoc and it should be able to autocomplete paths of packages. (of course, you may want to go get some packages first if you don’t have any)

Automatically call gofmt on save

gofmt reformats code into the One True Go Style Coding Standard. You’ll want to call it every time you save a file.

Add these to your ~/.emacs.d/init.el:

1
2
3
(setq exec-path (cons "/usr/local/go/bin" exec-path))
(add-to-list 'exec-path "/Users/tleyden/Development/gocode/bin")
(add-hook 'before-save-hook 'gofmt-before-save)

(replace the above path to the absolute path to your $GOPATH/bin directory)

After this step, whenever you save a Go file, it will automatically reformat the file with gofmt.

Godef

Godef is essential: it lets you quickly jump around the code, as you might be used to with a full featured IDE.

From what I can tell, installing go-mode seems to automatically install godef.

To verify that godef is indeed installed:

  • Putting the cursor over a method name
  • Try doing M-x godef-jump to jump into the method, and M-* to go back.

In order to add godef key bindings, add these to your ~/.emacs.d/init.el:

1
2
3
4
5
6
(defun my-go-mode-hook ()
  ; Call Gofmt before saving                                                    
  (add-hook 'before-save-hook 'gofmt-before-save)
  ; Godef jump key binding                                                      
  (local-set-key (kbd "M-.") 'godef-jump))
(add-hook 'go-mode-hook 'my-go-mode-hook)

and remove your previous call to (add-hook 'before-save-hook 'gofmt-before-save) since it’s now redundant

Now you can jump into code with M-. and jump back with M-*

Autocomplete

Install melpa auto-complete via M-x package-install followed by auto-complete

I got these warnings

Add the following to your ~/.emacs.d/init.el file:

1
2
3
(defun auto-complete-for-go ()
  (auto-complete-mode 1))
(add-hook 'go-mode-hook 'auto-complete-for-go)

Restart emacs, and if you open a .go file the mode should be Go AC (AC == AutoComplete)

Before further verifying, we need to install go-autocomplete in the next step.

go-autocomplete

The basic autocomplete installed is not as “go aware” as it should be. The go-autocomplete (aka nsf/gocode) package fixes that.

Install the melpa package via M-x package-install followed by go-autocomplete

Add the following to your ~/.emacs.d/init.el file:

1
2
3
(defun auto-complete-for-go ()
(auto-complete-mode 1))
 (add-hook 'go-mode-hook 'auto-complete-for-go)

Actually I’m not sure if this gets added automatically when installing go-autocomplete. If it’s already in your ~/.emacs.d/init.el file then you can skip that.

You’ll also need the following (as recommended in gocode issue 325):

1
2
(with-eval-after-load 'go-mode
   (require 'go-autocomplete))

Now restart emacs, and when you start typing the name of a field in a struct it will popup something that looks like this:

screenshot

Note that is more “go-aware” than the default auto-complete functionality.

Customize the emacs compile command to run go build

It’s convenient to be able to run M-x compile to compile and test your Go code from within emacs.

To do that, edit your ~/.emacs.d/init.el and replace your go-mode hook with:

1
2
3
4
5
6
7
8
9
10
(defun my-go-mode-hook ()
  ; Call Gofmt before saving
  (add-hook 'before-save-hook 'gofmt-before-save)
  ; Customize compile command to run go build
  (if (not (string-match "go" compile-command))
      (set (make-local-variable 'compile-command)
           "go build -v && go test -v && go vet"))
  ; Godef jump key binding
  (local-set-key (kbd "M-.") 'godef-jump))
(add-hook 'go-mode-hook 'my-go-mode-hook)

After that, restart emacs, and when you type M-x compile, it should try to execute go build -v && go test -v && go vet instead of the default behavior. On some projects, you might also want to run go generate before go build

Power tip: you can jump straight to each compile error by running C-x `. Each time you do it, it will jump to the next error.

Continue to Part 2

go-imports and go-oracle are covered in Part 2

References

Comments