Emacs
Go

Go開発環境をEmacsで整える

More than 3 years have passed since last update.

IntelliJのgolang pluginについて

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

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を比べてみる。
brew install --japanese --cocoa --with-gnutls -v emacs
Emacs久しぶりで兎に角敷居を下げたかったのもあってGUIも入れた。

Homebrewでインストールすると、brew linkappsを実行するように教えてくれるのだけど、これはsymblic linkを/Applications/に作成するため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にて公開してます。

init.el

init.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の内容

.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に使いやすいように手を入れる

.emacsinit.elに記述する。この項目は個人の趣味で

Option+ArrowsでWindowを移動できるようにする

; Alt+ArrowsでWindowを切り替える
(when (fboundp 'windmove-default-keybindings)
 (windmove-default-keybindings))
(windmove-default-keybindings 'meta)

Command+right or leftでBufferを切り替える

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

補完入力時の大文字小文字を無視

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

対応括弧をハイライト

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

編集行をハイライト

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

emacsが生成する一時ファイルなどの保存場所を変更する

emacsが.#**とか#*#とかあれやこれやをいろんなディレクトリに生成するのを一箇所にまとめたい

;; 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")

ここに記載されているように、emacsはファイルを開くとlock fileとしてシンボリックリンクを作成する。
こいつが結構厄介で、特定のディレクトリ配下にまとめたいがそういったオプション設定が見つからなかったので、無効にして対応した。

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

Caskの使い方

cask.github.io こちらの情報を一部抜粋すると
~/.emacs.d/Caskに利用したいpackageなどを記述した上で

packageのインストール
cask install

利用してるpackage一覧
cask list

packageの更新
cask update

caskのversion確認
cask version

cask自体の更新
cask upgrade-cask

Caskの書き方

DSL から一部抜粋

source

sourceに利用したいpackageリポジトリを記述する
Caskがデフォルトで対応してるリポジトリがあり、それらはURLを登録せずにAliasが有効になってて便利

(source gnu)
(source melpa)

depends-on

使いたいpackageを書いていくと良さそうだけど、何が必要なのかがわからないので、適当にググって出てきたpackageを登録していく

(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

gocodeauto-complete.elgo-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に追記

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

参考

外部参考リンク

公開資料

コメント

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