Go開発環境をEmacsで整える

#IntelliJのgolang pluginについて
個人的に困っていた問題が解決しているのでIntelliJをメインに利用してます。サーバサイドでの作業時にEmacsを活用してます。

* [go-lang-plugin-org](https://github.com/go-lang-plugin-org/go-lang-idea-plugin)

EmacsはterminalやIntelliJの操作と親和性があるので、継続的に利用しようかと考えてます。

# はじめに
当初IntelliJで開発を進めていて、いつも使ってるIntelliJでとりあえずプラグインを入れて初期設定を済ませると、すぐに入力補完も有効に機能していたおかげでコードを書くことに集中できてとても良かった。
しかし、使っているうちにimportしたpathが解決されなかったりするなど、問題がしばしば起きたりして、まだ安定して利用できる状態ではないなと感じたので、別の開発環境も整えることにした。

特にこだわりもないので、使えそうな環境を色々調べた結果、

* ATOM Editor
* Emacs
* vim
* Sublime Text

あたりがよく使われてそうだったので、有料のSublime Textとサーバにログインした時に余りカスタマイズしてない状態で利用するvimを除く、EmacsとATOM Editorをそれぞれ検討することにした。
このエントリはEmacsに関しての環境構築をめっちゃ久しぶりにやってみたので自分が忘れないようにメモ書きです・・・

# 環境
* Mac OS X Yosemite
* Homebrew
* Go 1.4
* Emacs 24.4
* zsh (/bin/zsh)

## Go
* GOPATH ~/go
* GOROOT /usr/local/opt/go/libexec

### Go Install
`brew install go`

.zshrcとかにGOPATHとかを設定しとく

# Emacs Install
参考: [Macで本家EmacsとHomebrew IMEパッチ版とEmacs Mac PortとAquamacsを比べてみる。](http://www.sevencredit.com/2014/07/02/580/ "Macで本家EmacsとHomebrew IMEパッチ版とEmacs Mac PortとAquamacsを比べてみる。")
```brew install --japanese --cocoa --with-gnutls -v emacs```
Emacs久しぶりで兎に角敷居を下げたかったのもあってGUIも入れた。

Homebrewでインストールすると、`brew linkapps`を実行するように教えてくれるのだけど、これはsymblic linkを`/Applications/`に作成するためSpotlightに登録されなくて起動がとてもめんどくさい。[いい解決策はなさそう](https://github.com/Homebrew/homebrew/issues/4635 "Emacs formula: Emacs.app can't be found via Spotlight")なので、以下を実行してお茶を濁す。
Emacsのバージョンが変わったら毎回実行しないとダメだけど、その時のためにコレを書いてる。
```cp -R /usr/local/Cellar/emacs/24.4/Emacs.app /Applications/```
EmacsをSpotlightで起動できたら成功してます。

# 設定
Emacsの各種設定と併せて調べたメモです。

## Emacsのpackage管理について
Emacsはいろいろpackageが提供されてるのでそれらを利用するが、package周りがややこしい

まずPackage管理するもの？

* package.el(標準でついてくる)
* Cask(今回利用した)
* Pallet
* quelpa


がある。quelpaが一番最近出てきたっぽいけど、情報が適当に見た感じ多そうなCaskを使うことにした。

packageは幾つかの場所に登録されていて、それらから個別にインストールする方法もあるらしいが、都度インストールするのは面倒なのでCaskなどを利用するのが最近の流行りみたい。

* melpha
* marmalade

### Caskのインストール
```brew install cask```
便利だ。
インストールしたら`~/.emacs.d/`に移動して以下を実行
```cask init```
`~/.emacs.d/Cask`が追加される。このCaskファイルに利用したいpackageを記述することでインストール出来る。

### 設定ファイルの配置
`.emacs`このファイルには余り設定は記述しないらしく`.emacs.d/init.el`を読み込ませるだけが最近のやり方らしい。

```
.
├── .emacs
└── .emacs.d
    ├── Cask
    └── init.el
```

## Emacsの設定
Emacsで自分が設定している内容に関して記載してます。
設定の全容については[gistにて公開](https://gist.github.com/shiwork/34058a3666356dd20c21)してます。
### init.el
`init.el`の記述内容は以下のとおり

```el:init.el
;; Emacs package manager
(require 'cask)
(cask-initialize)

;; homebrew
(add-to-list 'exec-path (expand-file-name "/usr/local/bin"))

;; autocomplete
(require 'auto-complete)
(require 'auto-complete-config)
(global-auto-complete-mode t)

;; golang
(add-to-list 'exec-path (expand-file-name "/usr/local/opt/go/libexec/bin"))
(add-to-list 'exec-path (expand-file-name "~/go/bin"))
(add-hook 'go-mode-hook
          (lambda ()
            ;; GOROOT, GOPATH環境変数の読み込み
            (let ((envs '("GOROOT" "GOPATH")))
              (exec-path-from-shell-copy-envs envs))
            (setq-default)
            ;; indentの設定
            (setq tab-width 2)
            (setq standard-indent 2)
            (setq indent-tabs-mode nil)
            ;; godef keybind
            (local-set-key (kbd "M-.") 'godef-jump)
            (local-set-key (kbd "M-,") 'pop-tag-mark)
            ))
(eval-after-load "go-mode"
 '(progn
     (require 'go-autocomplete)
     (add-hook 'go-mode-hook 'go-eldoc-setup)))
```
.emacsの内容

```el:.emacs
(load (expand-file-name (concat (getenv "HOME") "/.emacs.d/init")))
```

### Shellの環境変数を読み込む
godocなんかを`M-x godoc`で実行しようとすると`/bin/bash`にcommand not foundと言われて上手くいかないケースが有る。コレは、bashの環境変数を読み込んでいることが原因。

環境変数の読み込みは`exec-path-from-shell`が行っていて、Caskでインストールしているとcaskのinitializeで実行される。
今回のケースだと、zshの環境変数を読み込んで欲しいので、`echo $SHELL`がzshになっていない場合、必要に応じて`chsh -s /bin/zsh`を実行してzshに変更する

zshは各自の環境に合わせて設定すればよいが、何らかの理由で設定したPathにzshがない場合terminalが起動しなくなるおそれがあるので、homebrewのpathなど初期から入ってないものを設定するのはやめておいたほうが良いと思う。

### 参考資料
* [Emacsのバックアップファイルの保存先変更] (http://tokikane-tec.blogspot.jp/2012/11/emacs_11.html)
* [Emacs golang-mode indent setting] (https://groups.google.com/forum/#!topic/golang-nuts/c176nKcyoDQ)
* [Mac(homebrew)でGoのインストールと、Emacsの環境構築](http://d.hatena.ne.jp/hiro_nemu/20140113/1389620004)

### Emacsに使いやすいように手を入れる
`.emacs`か`init.el`に記述する。この項目は個人の趣味で
#### Option+ArrowsでWindowを移動できるようにする
```el
; Alt+ArrowsでWindowを切り替える
(when (fboundp 'windmove-default-keybindings)
 (windmove-default-keybindings))
(windmove-default-keybindings 'meta)
```

#### Command+right or leftでBufferを切り替える
```el
; Command + right or leftでbufferを切り替える
(global-set-key (kbd "s-<right>") 'next-buffer)
(global-set-key (kbd "s-<left>") 'previous-buffer)
```

#### 補完入力時の大文字小文字を無視
```el
; 補完入力時大文字小文字無視
(setq read-file-name-completion-ignore-case t)
```

#### 対応括弧をハイライト
```el
; 対応する括弧をハイライト
(show-paren-mode 1)
```

#### 編集行をハイライト
```el
; 編集行をハイライト
(global-hl-line-mode)
```

#### emacsが生成する一時ファイルなどの保存場所を変更する
emacsが.#***とか#**#とかあれやこれやをいろんなディレクトリに生成するのを一箇所にまとめたい

```el
;; Backup file directory
(setq backup-directory-alist
      (cons (cons ".*" (expand-file-name "~/.emacs.d/backup"))
            backup-directory-alist))

;; auto-save
(setq auto-save-list-file-prefix "~/.emacs.d/auto-save")
(setq auto-save-file-name-transforms
       `((".*" ,(expand-file-name "~/.emacs.d/auto-save") t)))
(setq tramp-auto-save-directory "~/.emacs.d/auto-save")
```

[ここ](http://stackoverflow.com/questions/5738170/why-does-emacs-create-temporary-symbolic-links-for-modified-files)に記載されているように、emacsはファイルを開くとlock fileとしてシンボリックリンクを作成する。
こいつが結構厄介で、特定のディレクトリ配下にまとめたいがそういったオプション設定が見つからなかったので、無効にして対応した。

```el
;; lock file (.#*)が作成されるのを止める
(setq create-lockfiles nil)
```

## Caskの使い方
[cask.github.io](http://cask.github.io/index.html) こちらの情報を一部抜粋すると
`~/.emacs.d/Cask`に利用したいpackageなどを記述した上で

packageのインストール
`cask install`

利用してるpackage一覧
`cask list`

packageの更新
`cask update`

caskのversion確認
`cask version`

cask自体の更新
`cask upgrade-cask`

## Caskの書き方
[DSL](http://cask.github.io/dsl.html) から一部抜粋
### source
sourceに利用したいpackageリポジトリを記述する
Caskがデフォルトで対応してるリポジトリがあり、それらはURLを登録せずにAliasが有効になってて便利

* gnu (http://elpa.gnu.org/packages/)
* melpa (http://melpa.milkbox.net/packages/)
* marmalade (http://marmalade-repo.org/packages/)
* SC (http://joseito.republika.pl/sunrise-commander/)
* org (http://orgmode.org/elpa/)

```el
(source gnu)
(source melpa)
```
### depends-on
使いたいpackageを書いていくと良さそうだけど、何が必要なのかがわからないので、適当にググって出てきたpackageを登録していく

```el

(depends-on "bind-key")
(depends-on "cask")
(depends-on "dash")
(depends-on "drag-stuff")
(depends-on "exec-path-from-shell")
(depends-on "expand-region")
(depends-on "f")
(depends-on "flycheck")
(depends-on "flycheck-cask")
(depends-on "htmlize")
(depends-on "idle-highlight-mode")
(depends-on "magit")
(depends-on "multiple-cursors")
(depends-on "nyan-mode")
(depends-on "pallet")
(depends-on "popwin")
(depends-on "prodigy")
(depends-on "projectile")
(depends-on "s")
(depends-on "smartparens")
(depends-on "smex")
(depends-on "use-package")
(depends-on "web-mode")
(depends-on "yasnippet")

;; auto-complete
(depends-on "auto-complete")

;; golang
(depends-on "go-mode")
(depends-on "go-autocomplete")
(depends-on "go-eldoc")
(depends-on "go-direx")
```

## packageインストール
`~/.emacs.d/`で実行

`cask install`

# 起動
terminalかApplicationsからEmacsを起動してinstallしたpackageが読み込まれてたら成功

# 使い方
## go-mode
インデントやコードの色分けをしてくれる
### godoc
`M-x godoc`でドキュメントを参照できる
`anything-read-string-mode`がとても良さそうなので後で入れてみる。
### gofmt
`M-x gofmt` コードを整形する
## godef
定義ジャンプを行うためgodefを導入する
godefのinstall
`go get code.google.com/p/rog-go/exp/cmd/godef`

参照したい関数等にカーソルを載せた状態で`C-c C-j`もしくは`M-x godef-jump`を実行すると、定義ファイルに移動することが出来る。
移動元に戻りたい場合は`M-*`で戻れる。

デフォルトのキーバインドだと、非常に入力しづらいので、移動は`M-,`、戻るは`M-.`に割り当てる
elispについては、init.elを参照のこと
## autocomplete
`gocode`と`auto-complete.el`、`go-autocomplete.el`を組み合わせて補完をEmacsで実現する

gocodeのインストール
`go get github.com/nsf/gocode`

autocompleteをinit.elでrequireする(init.elを参照)
documentに含まれるcodeの補完は有効になったが、手元で記述したコードについては現状補完が効かない(調査中)
godefの定義ジャンプで利用してる内容をautocompleteで利用できると良さそうだけどどうすれば良いのだろう。

## Window操作
windowを分割し作業をする際にwindowの移動を十字キーで実現したい
以下の内容をinit.elに追記

```el:init.el
(when (fboundp 'windmove-default-keybindings)
 (windmove-default-keybindings))
(windmove-default-keybindings 'meta)
```

## 参考
### 外部参考リンク
* [EmacsでのGo言語編集環境] (http://unknownplace.org/archives/golang-editing-with-emacs.html)
* [Emacs で Go を書く](http://qiita.com/senda-akiha/items/8bbdd3e59c51d5619ea7)
* [WindMove](http://www.emacswiki.org/emacs/WindMove)
* [.emacs.dを散らかさない保存ファイルの場所を変更する設定まとめ](http://qiita.com/ShingoFukuyama/items/19b02cd1679a6ea0bfdb)
* [Why does emacs create temporary symbolic links for modified files?](http://stackoverflow.com/questions/5738170/why-does-emacs-create-temporary-symbolic-links-for-modified-files)

### 公開資料
* [Emacsの設定内容(gist)](https://gist.github.com/shiwork/34058a3666356dd20c21)

# コメント
Emacs久しぶりにセットアップしたけどいろいろ変わりすぎててめっちゃ調べたのでまとめてます。
とりあえずインストールしただけでGoの環境としてどうかとか徐々に追記していきます(そもそもEmacs力が低すぎてとても苦労していて辛い)