Emacs初心者だがオススメ設定を晒させてくれ

普段はXcodeとかのIDEをよく使ってるんですが，最近はJSとかClojureとかでちょこちょこEmacs触ってたら改造にハマってきました．
色々やってきたなかで「使えそう」だと感じた設定の一部を`init.el`形式で晒します．
~~だからみんなもオススメ設定を教えてください！！なんでもしますから！！~~

（間違っている点・改善すべき点が多いかと思いますが，そのときはご指摘いただければ幸いです！）

+ [検索性の向上](http://qiita.com/blue0513/items/ff8b5822701aeb2e9aae#%E6%A4%9C%E7%B4%A2%E6%80%A7%E3%81%AE%E5%90%91%E4%B8%8A)にgrep時のwindow設定に関する記述を追加　(2017/04/07)
+ [Git関係](http://qiita.com/blue0513/items/ff8b5822701aeb2e9aae#git%E9%96%A2%E4%BF%82)の項目を追加　(2017/04/07)

# まずやっておく設定

+ 当然Emacsでは`package-list`からモジュールをダウンロードしてくるのでその設定は必須
+ コマンドキーをメタキーにしておくのはもったいない．**super**を割り当てちゃおう
+ 自動補完がなければ昨今のIDEには勝てない


```el
;; package管理
(package-initialize)
(setq package-archives
	  '(("gnu" . "http://elpa.gnu.org/packages/")
		("melpa" . "http://melpa.org/packages/")
		("org" . "http://orgmode.org/elpa/")))
		
;; cmdキーを superとして割り当てる
(setq mac-command-modifier 'super)

;; バックスペースの設定
(global-set-key (kbd "C-h") 'delete-backward-char)

;; auto-complete（自動補完）
(require 'auto-complete-config)
(global-auto-complete-mode 0.5)
```

# 見た目の設定

+ デフォルトの見た目はお世辞にもかっこいいとは言えない．フォントやカラーテーマ，透明度を変えて玄人感を演出（めっちゃ大事）
+ Emacsは基本split viewしまくるから，どれがアクティブかわかるようにしておいたほうが楽
+ コーディングしてるときにLine Numberが一瞬でわからないのはありえない
+ 邪魔なスクロールバーやメニューバーは隠してしまう
+ directory情報などは必要なだけ可視化


```el
;; font
(add-to-list 'default-frame-alist '(font . "ricty-12"))

;; color theme
(load-theme 'monokai t)

;; alpha
(if window-system 
	(progn
	  (set-frame-parameter nil 'alpha 95)))

;; 非アクティブウィンドウの背景色を設定
(require 'hiwin)
(hiwin-activate)
(set-face-background 'hiwin-face "gray30")

;; line numberの表示
(require 'linum)
(global-linum-mode 1)

;; tabサイズ
(setq default-tab-width 4)

;; メニューバーを非表示
(menu-bar-mode 0)

;; ツールバーを非表示
(tool-bar-mode 0)

;; default scroll bar消去
(scroll-bar-mode -1)

;; 現在ポイントがある関数名をモードラインに表示
(which-function-mode 1)

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

;; リージョンのハイライト
(transient-mark-mode 1)

;; タイトルにフルパス表示
(setq frame-title-format "%f")

;;current directory 表示
(let ((ls (member 'mode-line-buffer-identification
				  mode-line-format)))
  (setcdr ls
	(cons '(:eval (concat " ("
			(abbreviate-file-name default-directory)
			")"))
			(cdr ls))))
```

# 起動はクールに
+ 初期のあいつは早々に退場で
+ 玄人感を出していこう


```el
;; スタートアップメッセージを表示させない
(setq inhibit-startup-message 1)

;; ターミナルで起動したときにメニューを表示しない
(if (eq window-system 'x)
	(menu-bar-mode 1) (menu-bar-mode 0))
(menu-bar-mode nil)

;; scratchの初期メッセージ消去
(setq initial-scratch-message "")
```

# TabやSidebarのカスタム

+ 基本的にelscreenとneotreeの設定
+ **elscreen**は，ChromeやFirefoxみたいにEmacsのwindowをタブ化してくれるすごいやつ
+ **neotree**は，XcodeとかAndroid Studioみたいにサイドバーにdirectory構成を表示してくれるすごいやつ
+ [るびきち「新生日刊Emacs」](http://emacs.rubikitch.com/)様の記事が大変参考になりました


```el
;; elscreen（上部タブ）
(require 'elscreen)
(elscreen-start)
(global-set-key (kbd "s-t") 'elscreen-create)
(global-set-key "\C-l" 'elscreen-next)
(global-set-key "\C-r" 'elscreen-previous)
(global-set-key (kbd "s-d") 'elscreen-kill)
(set-face-attribute 'elscreen-tab-background-face nil
                    :background "grey10"
                    :foreground "grey90")
(set-face-attribute 'elscreen-tab-control-face nil
                    :background "grey20"
                    :foreground "grey90")
(set-face-attribute 'elscreen-tab-current-screen-face nil
                    :background "grey20"
                    :foreground "grey90")
(set-face-attribute 'elscreen-tab-other-screen-face nil
                    :background "grey30"
                    :foreground "grey60")
;;; [X]を表示しない
(setq elscreen-tab-display-kill-screen nil)
;;; [<->]を表示しない
(setq elscreen-tab-display-control nil)
;;; タブに表示させる内容を決定
(setq elscreen-buffer-to-nickname-alist
	  '(("^dired-mode$" .
		 (lambda ()
		   (format "Dired(%s)" dired-directory)))
		("^Info-mode$" .
		 (lambda ()
		   (format "Info(%s)" (file-name-nondirectory Info-current-file))))
		("^mew-draft-mode$" .
		 (lambda ()
		   (format "Mew(%s)" (buffer-name (current-buffer)))))
		("^mew-" . "Mew")
		("^irchat-" . "IRChat")
		("^liece-" . "Liece")
		("^lookup-" . "Lookup")))
(setq elscreen-mode-to-nickname-alist
	  '(("[Ss]hell" . "shell")
		("compilation" . "compile")
		("-telnet" . "telnet")
		("dict" . "OnlineDict")
		("*WL:Message*" . "Wanderlust")))

;; neotree（サイドバー）
(require 'neotree)
(global-set-key "\C-o" 'neotree-toggle)
```

# 操作性の向上
+ 正直これだけやっておいても十分「使える」Editorになるはず
+ `mouse-wheel-scroll-amount`は絶対に必要
+ エラー音は本当に気になるから最初に切っておこう


```el

;; スクロールは1行ごとに
(setq mouse-wheel-scroll-amount '(1 ((shift) . 5)))

;; スクロールの加速をやめる
(setq mouse-wheel-progressive-speed nil)

;; bufferの最後でカーソルを動かそうとしても音をならなくする
(defun next-line (arg)
  (interactive "p")
  (condition-case nil
	  (line-move arg)
	(end-of-buffer)))

;; エラー音をならなくする
(setq ring-bell-function 'ignore)
```

# ウィンドウ操作
+ `golden-ratio-mode`はめっちゃ便利．アクティブビューのサイズをいい感じに拡大してくれる（**NeoTree**と干渉するので例外処理を追加）
+ 各ビューの移動は当然コマンドで


```el
;; golden ratio
(golden-ratio-mode 1)
(add-to-list 'golden-ratio-exclude-buffer-names " *NeoTree*")

;; active window move
(global-set-key (kbd "<C-left>")  'windmove-left)
(global-set-key (kbd "<C-down>")  'windmove-down)
(global-set-key (kbd "<C-up>")    'windmove-up)
(global-set-key (kbd "<C-right>") 'windmove-right)
```

# 検索性の向上

+ いちいち`M-x`するのは面倒なのでキー割り当てちゃおう
+ rgrepしたときのいらないメッセージは消去
+ grepしたときに新規フレームが開くのは面倒なので，別ウィンドウとして表示させてしまう
+ window切り替えは[でらうま倶楽部](http://blog.livedoor.jp/tek_nishi/tag/%E3%83%9E%E3%82%AF%E3%83%AD)様を参考にさせていただきました

```el
;; 大文字・小文字を区別しない
(setq case-fold-search t)

;; ファイル名検索
(define-key global-map [(super i)] 'find-name-dired)

;; ファイル内検索（いらないメッセージは消去）
(define-key global-map [(super f)] 'rgrep)
;; rgrepのheader messageを消去
(defun delete-grep-header ()
  (save-excursion
    (with-current-buffer grep-last-buffer
      (goto-line 5)
      (narrow-to-region (point) (point-max)))))
(defadvice grep (after delete-grep-header activate) (delete-grep-header))
(defadvice rgrep (after delete-grep-header activate) (delete-grep-header))

;; rgrep時などに，新規にwindowを立ち上げる
(setq special-display-buffer-names '("*Help*" "*compilation*" "*interpretation*" "*grep*" ))

;; "grepバッファに切り替える"
(defun my-switch-grep-buffer()
  (interactive)
	(if (get-buffer "*grep*")
			(pop-to-buffer "*grep*")
	  (message "No grep buffer")))
(global-set-key (kbd "s-e") 'my-switch-grep-buffer)

```

# オススメショートカットコマンド
+ このあたりのショートカットは作業効率アップのためには絶対に必要
+ お気に入りはIDEっぽくbufferを切り替えられる`switch-to-prev-buffer`と`switch-to-next-buffer`
+ Emacsはデフォルトだと`redo`できないので，**redo+**を入れておきましょう
+ `recentf-ext`は[Qiita: エコーエリアや*Messages*バッファにメッセージを表示させたくない](http://qiita.com/itiut@github/items/d917eafd6ab255629346)を参考にさせて頂きました

```el

;; 履歴参照
(defmacro with-suppressed-message (&rest body)
  "Suppress new messages temporarily in the echo area and the `*Messages*' buffer while BODY is evaluated."
  (declare (indent 0))
  (let ((message-log-max nil))
    `(with-temp-message (or (current-message) "") ,@body)))
(require 'recentf)
(setq recentf-save-file "~/.emacs.d/.recentf")
(setq recentf-max-saved-items 1000)            ;; recentf に保存するファイルの数
(setq recentf-exclude '(".recentf"))           ;; .recentf自体は含まない
(setq recentf-auto-cleanup 'never)             ;; 保存する内容を整理
(run-with-idle-timer 30 t '(lambda ()          ;; 30秒ごとに .recentf を保存
							 (with-suppressed-message (recentf-save-list))))
(require 'recentf-ext)
(define-key global-map [(super r)] 'recentf-open-files)

;; コメントアウト
;; 選択範囲
(global-set-key (kbd "s-;") 'comment-region)

;; コメントアウト
;; 一行
(defun one-line-comment ()
  (interactive)
  (save-excursion
    (beginning-of-line)
    (set-mark (point))
    (end-of-line)
    (comment-or-uncomment-region (region-beginning) (region-end))))
(global-set-key (kbd "s-/") 'one-line-comment)

;; 直前のバッファに戻る
(global-set-key (kbd "s-[") 'switch-to-prev-buffer)

;; 次のバッファに進む
(global-set-key (kbd "s-]") 'switch-to-next-buffer)

;; redo+
(require 'redo+)
(global-set-key (kbd "C-z") 'redo)
(setq undo-no-redo t) ; 過去のundoがredoされないようにする
(setq undo-limit 600000)
(setq undo-strong-limit 900000)
```

# Git関係

+ line number横に最新のcommitとのdiffがアイコンで表示されます
+ ファイル全体のdiffを見たい時は**magit**を使うとかなり便利
+ `global-auto-revert-mode`で，SourceTreeなどの外部ツールでeditしたときも自動で更新させるように

```el
;; git-gutter-fringe
(global-git-gutter-mode 1)

;; magit
(global-set-key (kbd "C-c C-g") 'magit-diff-working-tree)

;; ファイル編集時に，bufferを再読込
(global-auto-revert-mode 1)
```

# その他

+ なんとEmacsがTerminalになります

```el

;; eshell + shell-pop
(setq shell-pop-shell-type '("eshell" "*eshell*" (lambda () (eshell))))
(global-set-key (kbd "C-c o") 'shell-pop)
```

# 参考資料
[Emacsのオススメ基本設定まとめ](http://qiita.com/yn01/items/b8d3dcb5be9078a6e27f)
[るびきち「新生日刊Emacs」](http://emacs.rubikitch.com/)
[Qiita: エコーエリアや*Messages*バッファにメッセージを表示させたくない](http://qiita.com/itiut@github/items/d917eafd6ab255629346)
その他多くのサイト様を参考にさせて頂きました