gemini/20190121-emacs-go-mode.gmi

226 lines
6.4 KiB
Plaintext

# Emacs Go Mode
You will notice how much I use "me" and "I" on this post. This because
your emacs configuration is extremely personal. You are creating a
"dream editor", and the options that I pick might not be of your
preference. Feel free to make it your own!
Back on topic. I started writing Go in late 2015. At first, I used
[Sublime Text], which I like a lot, but I was a little jealous of those
using [vim-go] and I figured there would be a way to make myself at home
writing Go in Emacs. This is how the adventure began.
=> https://www.sublimetext.com/ Sublime Text
=> https://github.com/fatih/vim-go vim-go
# Find a Mode!
The first thing I had to do was find a major mode for Go on emacs. It
didn't take me long to find [go-mode]. Installation is not hard, as
it's available as a package in the MELPA repository. A simple `M-x
package-install go-mode' sufficed. Configuring it was a bit harder.
=> https://github.com/dominikh/go-mode.el go-mode
# Configuration
This is my `.emacs' configuration for Go.
```
;;Load Go-specific language syntax
;;For gocode use https://github.com/mdempsky/gocode
(defun go-mode-setup ()
(go-eldoc-setup))
(add-hook 'go-mode-hook 'go-mode-setup)
;;Format before saving
(defun go-mode-setup ()
(go-eldoc-setup)
(add-hook 'before-save-hook 'gofmt-before-save))
(add-hook 'go-mode-hook 'go-mode-setup)
;;Goimports
(defun go-mode-setup ()
(go-eldoc-setup)
(setq gofmt-command "goimports")
(add-hook 'before-save-hook 'gofmt-before-save))
(add-hook 'go-mode-hook 'go-mode-setup)
;;Godef, shows function definition when calling godef-jump
(defun go-mode-setup ()
(go-eldoc-setup)
(local-set-key (kbd "M-.") 'godef-jump))
(add-hook 'go-mode-hook 'go-mode-setup)
;;Custom Compile Command
(defun go-mode-setup ()
;; (setq compile-command "go build -v && go test -v && go vet && golint && errcheck")
(linum-mode 1)
(setq compile-command "echo Building... && go build -v && echo Testing... && go test -v && echo Linter... && golint")
(setq compilation-read-command nil)
;; (define-key (current-local-map) "\C-c\C-c" 'compile)
(local-set-key (kbd "M-,") 'compile)
(add-hook 'go-mode-hook 'go-mode-setup)
;;Load auto-complete
(ac-config-default)
(require 'auto-complete-config)
(require 'go-autocomplete)
;;Go rename
(require 'go-rename)
;;Configure golint
(add-to-list 'load-path (concat (getenv "GOPATH") "/src/github.com/golang/lint/misc/emacs"))
(require 'golint)
;;Smaller compilation buffer
(setq compilation-window-height 14)
(defun my-compilation-hook ()
(when (not (get-buffer-window "*compilation*"))
(save-selected-window
(save-excursion
(let* ((w (split-window-vertically))
(h (window-height w)))
(select-window w)
(switch-to-buffer "*compilation*")
(shrink-window (- h compilation-window-height)))))))
(add-hook 'compilation-mode-hook 'my-compilation-hook)
;;Other Key bindings
(global-set-key (kbd "C-c C-c") 'comment-or-uncomment-region)
;;Compilation autoscroll
(setq compilation-scroll-output t)
```
# The Basics
That's a lot! Yeah, I know, but before you freak out, I'll give you a
run down of what each block is for (although the comments should help
a lot).
```
;;Load Go-specific language syntax
;;For gocode use https://github.com/mdempsky/gocode
(defun go-mode-setup ()
(go-eldoc-setup))
(add-hook 'go-mode-hook 'go-mode-setup)
;;Format before saving
(defun go-mode-setup ()
(go-eldoc-setup)
(add-hook 'before-save-hook 'gofmt-before-save))
(add-hook 'go-mode-hook 'go-mode-setup)
;;Goimports
(defun go-mode-setup ()
(go-eldoc-setup)
(setq gofmt-command "goimports")
(add-hook 'before-save-hook 'gofmt-before-save))
(add-hook 'go-mode-hook 'go-mode-setup)
```
This block enables `go-mode' and makes sure it runs `gofmt' before
saving. `gofmt' allows our code to be nice and tidy and to let
`go-mode' take care of importing the required packages. Nifty, huh?
Makes coding nicer.
# Making life even easier
Some extra elements to make our lives easier. Not necessary, but nice
to have.
```
;;Custom Compile Command
(defun go-mode-setup ()
;; (setq compile-command "go build -v && go test -v && go vet && golint && errcheck")
(linum-mode 1)
(setq compile-command "echo Building... && go build -v && echo Testing... && go test -v && echo Linter... && golint")
(setq compilation-read-command nil)
;; (define-key (current-local-map) "\C-c\C-c" 'compile)
(local-set-key (kbd "M-,") 'compile)
(add-hook 'go-mode-hook 'go-mode-setup)
```
This is a good one. Here I'm configuring `M-,' (Escape key + comma) to
run `go build', `go test', and `golint'. Extremely simple way make
sure our code compiles.
# Autocomplete and Linting
```
;;Load auto-complete
(ac-config-default)
(require 'auto-complete-config)
(require 'go-autocomplete)
;;Go rename
(require 'go-rename)
;;Configure golint
(add-to-list 'load-path (concat (getenv "GOPATH") "/src/github.com/golang/lint/misc/emacs"))
(require 'golint)
```
Sets up `go-autocomplete' and `go-rename'. `go-rename' only is used if
you want to do project-level renames. Just between us, I barely use
it.
The last block configures the path of the linter. Remember, Emacs is
smart, but not /that/ smart.
# Beautify our editor
```
;;Smaller compilation buffer
(setq compilation-window-height 14)
(defun my-compilation-hook ()
(when (not (get-buffer-window "*compilation*"))
(save-selected-window
(save-excursion
(let* ((w (split-window-vertically))
(h (window-height w)))
(select-window w)
(switch-to-buffer "*compilation*")
(shrink-window (- h compilation-window-height)))))))
(add-hook 'compilation-mode-hook 'my-compilation-hook)
```
All of this to make the compilation buffer smaller than a default
buffer.
```
;;Other Key bindings
(global-set-key (kbd "C-c C-c") 'comment-or-uncomment-region)
```
How about a simple command to comment out big blocks of code? `C-c
C-c'. Also, `compilation-scroll-output' simply scrolls the compilation
buffer all the way to the end.
# What's left?
This is my current set up. It works really well for my needs, but it
might not be yours. Something I'll work on is to integrate `delve'
(golang debugger) into the editor, but I suppose I'm quite old school.
I also have [Magit] integrated into my workflow, but that's a topic
for a different episode. To be honest, I don't miss anything from
Sublime (or Atom or MS Code), plus it already makes use of my favorite
editor. A simple `.emacs' file gives me all the customization that I
need and I know I always have MY set up everywhere.
=> https://magit.vc/ Magit