Emacsと過ごした2017年

昨年(2017年)、エディターをAtomからEmacsに乗り換えました。

特別理由があったわけではないですが、会社のPCがWindowsからMacになったので、
良い機会だと思ってEmacsにしました。

Windows時代にも何度か試そうとはしたけど、ｳﾏｸｲｶﾅｶｯﾀｷｵｸｶﾞ...

徐々に設定ファイルを書きつつ、実際に１年間使い続けてみて、
今となっては非常に快適に使うことができています。

ということで、１年間お世話になった(今もお世話になっている)パッケージ達を紹介していこうと思います。

# サマリ

全30パッケージ。
パッケージ管理には[el-get](https://github.com/dimitri/el-get)を使ってます。
※ [参考情報](#参考情報)に実際の設定ファイルへのリンクを貼ってます。

|カテゴリ|パッケージ名|オススメ度|
|:-----------|:------------|:------------|
|helm系|[helm](#helm)|★★★★★|
|helm系|[helm-ls-git](#helm-ls-git)|★★★★☆|
|helm系|[helm-ghq](#helm-ghq)|★★★★☆|
|helm系|[helm-git-grep](#helm-git-grep)|★★★★☆|
|history系|[undohist](#undohist)|★★☆☆☆|
|history系|[undo-tree](#undo-tree)|★★★☆☆|
|検索・置換系|[ace-isearch](#ace-isearch)|★★★★★|
|検索・置換系|[anzu](#anzu)|★★★★☆|
|検索・置換系|[color-moccur](#color-moccur)|★★☆☆☆|
|検索・置換系|[moccur-edit](#moccur-edit)|★★☆☆☆|
|検索・置換系|[migemo](#migemo)|★★☆☆☆|
|便利系|[multiple-cursors](#multiple-cursors)|★★★★★|
|便利系|[open-junk-file](#open-junk-file)|★★★★★|
|便利系|[minimap](#minimap)|★☆☆☆☆|
|便利系|[exec-path-from-shell](#exec-path-from-shell)|★★★☆☆|
|便利系|[init-loader](#init-loader)|★★★☆☆|
|git系|[magit](#magit)|★☆☆☆☆|
|git系|[git-gutter+](#git-gutter+)|★★☆☆☆|
|コーディング全般|[flycheck](#flycheck)|★★★★☆|
|コーディング全般|[company-mode](#company-mode)|★★★★★|
|JavaScript|[js2-mode](#js2-mode)|★★★★★|
|JavaScript|[company-tern](#company-tern)|★★★★★|
|JavaScript|[coffee-mode](#coffee-mode)|★★★☆☆|
|JavaScript|[web-mode](#web-mode)|★★★★☆|
|Go|[go-mode](#go-mode)|★★★★☆|
|Go|[go-autocomplete](#go-autocomplete)|★★★☆☆|
|Go|[go-eldoc](#go-eldoc)|★★☆☆☆|
|その他メジャーモード|[yaml-mode](#yaml-mode)|★★★☆☆|
|その他メジャーモード|[json-mode](#json-mode)|★★★☆☆|
|その他メジャーモード|[markdown-mode](#markdown-mode)|★★★★★|

※ オススメ度はあくまでも所感です

# helm系

## helm
オススメ度: ★★★★★
概要: インクリメンタルに補完や検索をするためのフレームワーク
一言: とにかくオススメ

```common-lisp
;; helm-find-files
(define-key global-map (kbd "C-x C-f") 'helm-find-files)

;; tab 補完
(define-key helm-find-files-map (kbd "<tab>") 'helm-execute-persistent-action)

;; C-h バックスペース
(define-key helm-find-files-map (kbd "C-h") 'delete-backward-char)

(global-set-key (kbd "M-x") 'helm-M-x)

(global-set-key (kbd "C-x C-r") 'helm-imenu)
```

## helm-ls-git
オススメ度: ★★★★☆
概要: gitで管理されているファイルを[helm](#helm)で絞り込み検索できる
一言: ```helm-mini-default-sources```で色々組み合わせることで、非常に便利に。

```common-lisp
(when (require 'helm-ls-git)
  (when (require 'helm-ghq)
    (custom-set-variables
     '(helm-truncate-lines t)
     '(helm-delete-minibuffer-contents-from-point t)
     '(helm-mini-default-sources '(helm-source-buffers-list
                                   helm-source-ls-git-status
                                   helm-source-files-in-current-dir
                                   helm-source-ls-git
                                   helm-source-recentf
                                   helm-source-ghq)))
    (global-set-key (kbd "C-x C-i") 'helm-mini)))
```

## helm-ghq
オススメ度: ★★★★☆
概要: [ghq](https://github.com/motemen/ghq)を[helm](#helm)インターフェースで使用できる
一言: CLIでも[ghq](https://github.com/motemen/ghq)を重宝しているので、Emacsでも使えるのはありがたい
※ 設定ファイルは[helm-ls-git](#helm-ls-git)参照

## helm-git-grep
オススメ度: ★★★★☆
概要: [git grep](https://git-scm.com/docs/git-grep)を[helm](#helm)インターフェースで使用できる
一言: 大変お世話になっています。

```common-lisp
(when (require 'helm-git-grep)
  (global-set-key (kbd "C-x C-a") 'helm-git-grep)
  ;; Invoke 'helm-git-grep' from isearch.
  (define-key isearch-mode-map (kbd "C-x C-a") 'helm-git-grep-from-isearch)
  ;; Invoke 'helm-git-grep' from other helm.
  (eval-after-load 'helm
    '(define-key helm-map (kbd "C-x C-a") 'helm-git-grep-from-helm)))
```

# history系

## undohist
オススメ度: ★★☆☆☆
概要: Emacsのundoを永続化する
一言: 不意にEmacsを終了してしまった時などに助けられる

```common-lisp
(when (require 'undohist nil t)
  (undohist-initialize))
```

## undo-tree
オススメ度: ★★★☆☆
概要: undo, redoの履歴を可視化してくれる。テンポラリなバージョン管理みたいなイメージ
一言: undo後に何か入力してしまって、redoできなくなった...なんて時に使う

```common-lisp
(when (require 'undo-tree nil t)
  (global-undo-tree-mode))
```

# 検索・置換系

## ace-isearch
オススメ度: ★★★★★
概要: isearchの文字入力に合わせて自動でace-jumpやhelm-swoopを起動してくれる
一言: isearchベースで検索ができるので非常に使い勝手が良い。バッファ内の検索はこれだけで事足りる。

```common-lisp
(when (require 'ace-isearch)
  (global-ace-isearch-mode +1)
  (define-key isearch-mode-map (kbd "M-o") 'helm-multi-swoop-all-from-isearch))
```

## anzu
オススメ度: ★★★★☆
概要: 検索コマンド実行中に, モードラインにマッチするバッファ内の語数と現在のマッチ位置を表示する
一言: とりあえず必須。

```common-lisp
(when (require 'anzu)
  (global-anzu-mode +1))
```

## color-moccur
オススメ度: ★★☆☆☆
概要: 高機能な検索を行える
一言: 検索は[ace-isearch](#ace-isearch)を使うことがほとんどなので、あまり出番なし。

```common-lisp
(when (require 'color-moccur nil t)
  (require 'moccur-edit nil t)
  ;; M-oにoccur-by-moccurを割り当て
  (define-key global-map (kbd "M-o") 'occur-by-moccur)
  ;; スペース区切りでAND検索
  (setq moccur-split-word t)
  ;; ディレクトリ検索のとき除外するファイル
  (add-to-list 'dmoccur-exclusion-mask "\\.DS_Store")
  (add-to-list 'dmoccur-exclusion-mask "^#.+#$")
  ;; Migemoを利用できる環境であればMigemoを使う
  (when (and (executable-find "cmigemo")
             (require 'migemo nil t))
    (setq moccur-use-migemo t)))
```

## moccur-edit
オススメ度: ★★☆☆☆
概要: [color-moccur](#color-moccur)と組み合わせて一括置換を行える
一言: [multiple-cursors](#multiple-cursors)で置換をすることがほとんどなので、あまり出番なし。
※ 設定ファイルは[color-moccur](#color-moccur)参照

## migemo
オススメ度: ★★☆☆☆
概要: ローマ字で日本語の検索が可能になる
一言: [color-moccur](#color-moccur)と組み合わせているが、[color-moccur](#color-moccur)自体をあまり使っていないので出番なし。
※ 設定ファイルは[color-moccur](#color-moccur)参照

# 便利系

## multiple-cursors
オススメ度: ★★★★★
概要: 一度に複数カーソルを操作することができる
一言: 非常に重宝している。複数箇所の編集や置換などのスピードが格段にアップする。

```common-lisp
(when (require 'multiple-cursors)
  (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
  (global-set-key (kbd "C-.") 'mc/mark-next-like-this)
  (global-set-key (kbd "C-,") 'mc/mark-previous-like-this)
  (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this))
```

## exec-path-from-shell
オススメ度: ★★★★★
概要: シェルに設定される環境変数を、Emacsでも参照できるようになる
一言: Emacs外のツール([ghq](https://github.com/motemen/ghq)など)を使うので、PATHを読み込んでいる

```common-lisp
(when (require 'exec-path-from-shell)
  (let ((envs '("PATH")))
    (exec-path-from-shell-copy-envs envs)))
```

## init-loader
オススメ度: ★★★★★
概要: init.elから分割した設定ファイルを読み込むことができる
一言: これを使って、パッケージ毎に設定ファイルを分けている。

```common-lisp
(when (require 'init-loader nil t)
  (init-loader-load "~/.emacs.d/inits"))
```

## open-junk-file
オススメ度: ★★★★★
概要: 使い捨てファイルを簡単に生成できる
一言: ちょっとしたコードやメモを書く時などに使う。

```common-lisp
(when (require 'open-junk-file)
  (setq open-junk-file-format "~/Documents/junk/%Y-%m-%d-%H%M%S.")
  (global-set-key (kbd "C-x j") 'open-junk-file))
```

## minimap
オススメ度: ★☆☆☆☆
概要: Emacsでminimapを使うことができる
一言: あまり出番なし。

# git系

## magit
オススメ度: ★☆☆☆☆
概要: Emacsからgitリポジトリの操作ができる
一言: gitの操作はターミナルで行うことが多いので、あまり出番なし。

## git-gutter+
オススメ度: ★☆☆☆☆
概要: gitのdiffを可視化することができる
一言: あまり出番なし。

```common-lisp
(when (require 'git-gutter+ nil t)
  (global-git-gutter+-mode nil)
)
```

# コーディング全般

## flycheck
オススメ度: ★★★★☆
概要: シンタックスチェックを行うことができる
一言: 非常に重宝している。[js2-mode](#js2-mode), [web-mode](#web-mode), [go-mode](#go-mode)で使用。
※ 設定ファイルは各mode参照。


## company-mode
オススメ度: ★★★★★
概要: 入力補完用のパッケージ
一言: [auto-complete](https://github.com/auto-complete/auto-complete)ではなくこっちを使用。非常に快適。

```common-lisp
(when (require 'company nil t)
  (global-company-mode +1)

  ;; 自動補完を offにしたい場合は, company-idle-delayを nilに設定する
  ;; auto-completeでいうところの ac-auto-start にあたる.
  ;; (custom-set-variables
  ;;  '(company-idle-delay nil))

  (global-set-key (kbd "C-M-i") 'company-complete)

  ;; C-n, C-pで補完候補を次/前の候補を選択
  (define-key company-active-map (kbd "C-n") 'company-select-next)
  (define-key company-active-map (kbd "C-p") 'company-select-previous)
  (define-key company-search-map (kbd "C-n") 'company-select-next)
  (define-key company-search-map (kbd "C-p") 'company-select-previous)

  ;; C-sで絞り込む
  (define-key company-active-map (kbd "C-s") 'company-filter-candidates)

  ;; TABで候補を設定
  (define-key company-active-map (kbd "C-i") 'company-complete-selection)

  ;; 各種メジャーモードでも C-M-iで company-modeの補完を使う
  (define-key emacs-lisp-mode-map (kbd "C-M-i") 'company-complete))
```
# JavaScript

## js2-mode
オススメ度: ★★★★★
概要: JavaScript用モード
一言: 普段JavaScriptを書くことが多いので、非常に重宝している
　　　グローバル変数がハイライトされるのが地味に嬉しい

```common-lisp
(when (require 'js2-mode)
  (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))
  (add-to-list 'auto-mode-alist '("\\.es$" . js2-mode))
  (add-to-list 'auto-mode-alist '("\\.es6$" . js2-mode))
  (add-to-list 'auto-mode-alist '("\\.jsx$" . js2-mode))

  ;; js2-modeのインデントの不具合を解決
  (add-hook 'js2-mode-hook 'js-indent-hook)

  (setq company-tern-property-marker "")
  (defun company-tern-depth (candidate)
    "Return depth attribute for CANDIDATE. 'nil' entries are treated as 0."
    (let ((depth (get-text-property 0 'depth candidate)))
      (if (eq depth nil) 0 depth)))

  (add-hook 'js2-mode-hook
            '(lambda ()
               (setq tern-command '("tern" "--no-port-file"))
               (tern-mode t)))

  (add-to-list 'company-backends 'company-tern)


  (when (require 'flycheck)
     (flycheck-add-mode 'javascript-eslint 'js2-mode))
)
```

## company-tern
オススメ度: ★★★★★
概要: [company-mode](#company-mode)で[tern](https://www.npmjs.com/package/tern)(JavaScriptの静的解析エンジン)を使った補完を行うことができる
一言: JavaScriptを書くなら、これは必須
※ 設定ファイルは[js2-mode](#js2-mode)参照

## coffee-mode
オススメ度: ★★★☆☆
概要: CoffeeScript用モード

```common-lisp
(when (require 'coffee-mode)
  (add-to-list 'auto-mode-alist '("\\.coffee$" . coffee-mode))

  (defun coffee-custom ()
    "coffee-mode-hook"
    (and (set (make-local-variable 'tab-width) 2)
         (set (make-local-variable 'coffee-tab-width) 2))
    )

  (add-hook 'coffee-mode-hook
            '(lambda() (coffee-custom))))
```

## web-mode
オススメ度: ★★★★☆
概要: HTMLテンプレート用モード
一言: 普段は[React](https://reactjs.org/)を使っているのでJSXファイルの編集に利用している

```common-lisp
(when (require 'web-mode)
  (add-to-list 'auto-mode-alist '("\\.jsx$" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.tpl$" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.html$" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.html.erb$" . web-mode))

  (defun web-mode-hook()
    (setq web-mode-markup-indent-offset 4)
    (setq web-mode-css-indent-offset 4)
    (setq web-mode-code-indent-offset 4)
    (lambda ()
      (flycheck-add-mode 'javascript-eslint 'web-mode)
      (flycheck-mode))
  (add-hook 'web-mode-hook 'web-mode-hook)))
```

# Go

## go-mode
オススメ度: ★★★★☆
概要: Go用モード
一言: Goを書くならとりあえず必要

```common-lisp
(require 'go-mode nil t)
(require 'go-autocomplete nil t)
(require 'go-eldoc nil t)
(add-hook 'go-mode-hook 'flycheck-mode)
(add-hook 'go-mode-hook
          (lambda ()
            (setq gofmt-command "goimports")
            (setq tab-width 2)
            (go-eldoc-setup)
            (add-hook 'before-save-hook 'gofmt-before-save)
            (local-set-key (kbd "M-.") 'godef-jump)
            ))
```

## go-autocomplete
オススメ度: ★★★☆☆
概要: [auto-complete](https://github.com/auto-complete/auto-complete)のGo拡張で、いい感じに補完をしてくれる
一言: こちらもGoを書くならとりあえず必要
※ 設定ファイルは[go-mode](#go-mode)参照

## go-eldoc
オススメ度: ★★☆☆☆
概要: カーソル位置のメソッドのドキュメントをmini bufferに表示する
一言: 普段使わないようなメソッドを使う時に便利
※ 設定ファイルは[go-mode](#go-mode)参照

# その他メジャーモード

## json-mode
オススメ度: ★★★☆☆
概要: JSON用モード

```common-lisp
(when (require 'json-mode)
  (add-to-list 'auto-mode-alist '("\\.json$" . json-mode)))
```

## yaml-mode
オススメ度: ★★★☆☆
概要: YAML用モード

```common-lisp
(when (require 'yaml-mode)
  (add-to-list 'auto-mode-alist '("\\.yml$" . yaml-mode)))
```

## markdown-mode
オススメ度: ★★★★★
概要: Markdown用モード
一言: 普段Markdownでメモをとることが多いので、非常に重宝している

```common-lisp
(when (require 'markdown-mode nil t))
```

# おわりに

今後も良さ気なパッケージがあれば、定期的に追記していこうと思います。
２０１８年も変わらず、Emacsにお世話になる予定です。

# 参考情報

実際のinit.elは[こちら](https://github.com/mochi8k/dotfiles/blob/master/emacs/init.el)
各種設定ファイルは[こちら](https://github.com/mochi8k/dotfiles/tree/master/emacs/inits)