Emacs で Ruby の開発環境をさらにめちゃガチャパワーアップしたまとめ

    161227: 内容が古くなったので、書き直しました。

    [toc]

    はじめに

    Ruby 開発環境を整えようとおもったが, 普段よく使っている Eclipse を出すにはスクリプト言語は大げさだ.

    スクリプト言語はコンソール端末で書くに限る.

    というわけで, Emacs 使いなあたしとしては, Emacs での Ruby 環境を整えようとおもった.

    いろんなサイトを参考にしつつ, 導入したものを列挙していく.

    準備

    elip 取得に必要な package.el や el-get.el, git や wget などのツールはインストール済みのこと.

    環境

    • Emacs 24.3.1
    • Ruby 2.1.0

    優れた IDE の条件

    優れた IDE が備えるべき機能は以下

    • シンタックスハイライト/ インデント

      • ruby-mode
    • 検索・置換 iedit, multiple-cursors, helm-ag, helm-swoop…etc
    • タグジャンプ ctags
    • コード補間

      • auto-complete, yasnippet
    • エラーチェック

      • flycheck
    • リファクタリング emacs-refactor
    • インタープリタ・デバッカ inf-ruby, pry
    • プロジェクト管理 projectile

    シンタックスハイライト/ インデント

    ruby-mode

    まずはともあれ, Emacs の ruby-mode を使う.

    .emacs の設定. 拡張子.rb と接頭語 Capfile,Gemfile を Ruby ファイルと認識させる.

    (autoload 'ruby-mode "ruby-mode"
      "Mode for editing ruby source files" t)
     (add-to-list 'auto-mode-alist '("\\.rb$" . ruby-mode))
     (add-to-list 'auto-mode-alist '("Capfile$" . ruby-mode))
     (add-to-list 'auto-mode-alist '("Gemfile$" . ruby-mode))
     (add-to-list 'auto-mode-alist '("[Rr]akefile$" . ruby-mode))

    enhanced-ruby-mode

    今は, enhanced-ruby-mode というものもあるらしい.

    以下の機能を強化.

    • インデント
    • シンタックスハイライト
    • リアルタイムの文法チェック

    自分はただの ruby-mode でいいかな。一応紹介。

    MELPA に入っているので, package.el や el-get.el でインストールできる.

    github の元のリポジトリは開発が止まっているようで, 自分は fork 版を入れる.

    enh-rubu-mode という名前を探してインストールした.

    あとは, 既存の設定で, ruby-mode-hock/ruby-mode-map となっているところを enh-ruby-mode-hock enh-ruby-mode-map で置換する.

    参考:enhanced-ruby-mode の概説 - Qiita

    ruby-electric

    ruby-electric はかっこや do end などの対応関係を自動で補正してくれる.

    (require 'ruby-electric)
    (add-hook 'ruby-mode-hook '(lambda () (ruby-electric-mode t)))
    (setq ruby-electric-expand-delimiters-list nil)

    ruby-block

    ruby-block を導入すると, end に対応する行をハイライトしてくれる.

    ;; ruby-block.el --- highlight matching block
    (require 'ruby-block)
    (ruby-block-mode t)
    (setq ruby-block-highlight-toggle t)

    検索・置換

    検索や置換機能が優れているところが Emacs のいいところ。 以下、自分がよく利用するものを列挙。

    • iedit
    • multiple-cursors
    • helm-ag -> 今は ripgrep の方がよい。
    • helm-swoop

    コードリーディング

    rcodetools ( xmpfilter )

    rcodertools とは, Ruby 開発のためのツール群. emacs 界で有名な, rubikichi 氏の作品.

    以下のような機能をゆうしている.

    • xmpfilter: Test::Unit assert* / RSpec should* 自動生成, コード注釈
    • rct-complete: 高精度メソッド名・クラス名・定数名等補完
    • rct-doc: ドキュメント参照・コードナビゲーター
    • rct-meth-args: 高精度メソッド情報リスト, TAGS ファイル作成
    • rct-fork: Rails 等重いライブラリを予めロードし, 補完を高速化する (サーバ)
    • rct-fork-client: rct-fork サーバが保持する状態から Ruby スクリプトを実行する
    • ruby-toggle-file: テストスクリプトと実装スクリプトを切り換える
    • rbtest: 小規模スクリプトのための埋め込み Test::Unit

    まずは, rcodertools をダウンロードする. gem コマンドで入る.

    $ gem install rcodetools

    gem environment コマンドでインストールされた場所を調べて, rcodetools.el を load-path が通った場所にコピーする.

    $ gem environment
    $ cp /usr/lib/ruby/gems/1.9.1/gems/rcodetools-0.8.5.0/rcodetools.el .

    最後に, rcodetools/bin にパスを通す (ここがハマりポイント!) このページに助けられた.

    .zshenv とかに,

    export PATH=$PATH:$HOME/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/rcodetools-0.8.5.0/bin

    .emacs への設定例は以下.

     ;; rcodetools
    (require 'rcodetools)
    (setq rct-find-tag-if-available nil)
    (defun ruby-mode-hook-rcodetools ()
      (define-key ruby-mode-map "\M-\C-i" 'rct-complete-symbol)
       (define-key ruby-mode-map "\C-c\C-t" 'ruby-toggle-buffer)
       (define-key ruby-mode-map "\C-c\C-f" 'rct-ri))
    (add-hook 'ruby-mode-hook 'ruby-mode-hook-rcodetools)

    xmprilter を使うと Ruby コードの行末に「# =>」を入れて xmpfilter を実行するとその行の返り値を見ることができる.

    rct-complete を使うと, コードの自動補完が使える.

    また, ruby-toggle-buffer はテストコードとソースコードを切り替えることができる.

    切り替えたり, メソッドを補完しながら TDD する方法を TDC と名づけている. (Test Driven Completion) README.TDC を読むと面白い.

    たくさん機能があるので, いろいろ調べるとよい. ちょっとまだつかいこなせてない. 詳しくは README を参照.

    helm-rdefs

    rdefs はソースコードの class や module, def といった宣言のラインを引っ張り出してくれるツール.

    gem install rdefs

    helm I/F を経由して, Emacs から利用することができる.

    .emacs の設定は以下.

    (require 'helm)
    (require 'helm-rdefs)
    (add-hook 'ruby-mode-hook
              (lambda ()
                (define-key ruby-mode-map (kbd "C-c @") 'helm-rdefs)))

    これはなかなかよいツールだ.

    auto-highlight-symbol

    シンボルをハイライト表示してくれる.

    (require 'auto-highlight-symbol)
    (global-auto-highlight-symbol-mode t))

    タグジャンプ

    ctags/ripper-tags

    記事を独立させました.

    試してないけれども、GNU GLOBAL でもタグジャンプができるみたい。

    コード補完

    robe

    Ruby 用の補完をする. 補完は auto-complete という有名な elisp がある. もっと賢いのがオムニ補完と呼ばれるもの. これは文法を解析して補完してくれる.

    el-get 経由で robe-mode を入れる.

    また, pry というものも必要みたい. 詳しくは github の README 参照で.

    gem install pry pry-doc method_source

    設定を追記.

     ; robe
    (autoload 'robe-mode "robe" "Code navigation, documentation lookup and completion for Ruby" t nil)
    (autoload 'robe-ac-setup "robe-ac" "robe auto-complete" nil nil)
    (add-hook 'robe-mode-hook 'robe-ac-setup)

    補完以外にも、ドキュメント参照とか、定義ジャンプができるようだ。すごいぞ robe!!

    • Jump to method definition
    • Jump to super or a constructor called at point
    • Jump to a module or class (provided it has at least one method defined)
    • Display method documentation
    • Display information about method called at point using ElDoc
    • Method and constant name completion

    yasnippet-ruby

    Emacs のスニペット挿入機能といえば, yasnippet だが, その Ruby 用テンプレート群をいれる.

    ここからダウンロードして, yasnippet のスニペット一覧に突っ込む!

    いちおう, yasnippets の設定も載せておく. ここでは, ~/.emacs.d/snippets にいれた.

    (require 'yasnippet)
    (yas/load-directory "~/.emacs.d/snippets")
    (yas-global-mode 1)
    
    ;; 既存スニペットを挿入する
    (define-key yas-minor-mode-map (kbd "C-x i i") 'yas-insert-snippet)
    ;; 新規スニペットを作成するバッファを用意する
    (define-key yas-minor-mode-map (kbd "C-x i n") 'yas-new-snippet)
    ;; 既存スニペットを閲覧・編集する
    (define-key yas-minor-mode-map (kbd "C-x i v") 'yas-visit-snippet-file)

    エラーチェック

    flycheck

    エラーチェックといえば flycheck だ。flymake の時代は終わったと思っている。

    (require 'flycheck)
    (setq flycheck-check-syntax-automatically '(mode-enabled save))
    (add-hook 'ruby-mode-hook 'flycheck-mode)

    ついでに, flycheck をカラフルにする flycheck-color-mode-line も入れた.

    flycheck のチェッカーとして ruby-lint と robocop を入れてみる.

    rubocop

    コーディングスタイルをチェックするために, rubocop を入れてみる. 以下を参考にした.

    まずは, gem で robocop をインストール.

    gem install rubocop

    .emacs の設定は以下.

    (require 'rubocop)
    (add-hook 'ruby-mode-hook 'rubocop-mode)

    標準だと, Ruby コーディングスタイルガイドにしたがっているかチェックできる.

    • https://github.com/bbatsov/ruby-style-guide

      カスタマイズは徐々にしていこう.

      さらに, 前述の flycheck の check ツールに rubocop を組み込むことができる.

      flycheck-list-errors で, flycheck が検出したエラーと一緒にチェックできる. I/F の共通化.

    (flycheck-define-checker ruby-rubocop
       "A Ruby syntax and style checker using the RuboCop tool."
       :command ("rubocop" "--format" "emacs" "--silent"
                 (config-file "--config" flycheck-rubocoprc)
                 source)
       :error-patterns
       ((warning line-start
                 (file-name) ":" line ":" column ": " (or "C" "W") ": " (message)
                 line-end)
        (error line-start
               (file-name) ":" line ":" column ": " (or "E" "F") ": " (message)
               line-end))
        :modes (ruby-mode motion-mode))

    ruby-lint

    semantic (文法解析) 的に解析してくれるらしい. rubocop との違いについても, github の readme にかかれている.

    gem でインストール.

    gem install ruby-lint

    これも, flycheck のインタフェースを利用してチェックさせる.

     ;; definition for flycheck
    (flycheck-define-checker ruby-rubylint
       "A Ruby syntax and style checker using the rubylint tool."
       :command ("ruby-lint" source)
       :error-patterns
       ((warning line-start
                 (file-name) ":" line ":" column ": " (or "C" "W") ": " (message)
                 line-end)
        (error line-start
               (file-name) ":" line ":" column ": " (or "E" "F") ": " (message)
               line-end))
       :modes (ruby-mode ruby-mode))

    リファクタリング

    Ruby リファクタリング環境は以外に貧弱だった. なんとかならないものか・・・.

    anzu

    リファクタリングのリネーム機能を探していたら, これが良さそう.

    置換や検索をおしゃれに実行する Elisp. 詳しくは, 以下.

    (require 'anzu)
    (global-anzu-mode +1)
    
    (set-face-attribute 'anzu-mode-line nil
                        :foreground "yellow" :weight 'bold)
    (custom-set-variables
     '(anzu-mode-lighter "")
     '(anzu-deactivate-region t)
     '(anzu-search-threshold 1000)
     '(anzu-use-mimego t)
     '(anzu-replace-to-string-separator " => "))

    ruby-refactor

    ruby-refactor は, Ruby でリファクタリングをするためのツール.

    .emacs にも設定を追加.

     (require 'ruby-refactor)
    (add-hook 'ruby-mode-hook 'ruby-refactor-mode-launch)

    こんなことができる.

    • Extract to Method (C-c C-r e)
    • Extract Local Variable (C-c C-r v)
    • Extract Constant (C-c C-r c)
    • Add Parameter (C-c C-r p)
    • Extract to Let (C-c C-r l)

    個人的には Extract Method と Rename ができればよいが, Rename はできない.

    また, Extract Method は変数を抽出してはくれないのであまり賢くない.

    インタープリタ・デバッカ

    rubydb

    標準ライブラリのデバッカ. ステップ実行できる. elisp は ruby のソースに梱包されている.

    inf-ruby

    Emacs のバッファから irb を起動する.

    (autoload 'inf-ruby "inf-ruby" "Run an inferior Ruby process" t)
    (add-hook 'ruby-mode-hook 'inf-ruby-minor-mode)

    M-x inf-ruby でバッファが起動. これだけ.

    pry

    inf-ruby よりも高機能らしい REPL.

    (require 'pry)
    ;; optional suggestions
    (global-set-key [S-f9] 'pry-intercept)
    (global-set-key [f9] 'pry-intercept-rerun)

    quickrun

    素早く Ruby スクリプト を実行。

    (require 'quickrun)

    RSpec

    記事を独立させました。

    プロジェクト管理

    rake

    Interaction with rake command tool.

    (use-package rake
      :config
      (eval-after-load 'ruby-mode
        '(define-key ruby-mode-map (kbd "C-!") 'rake))
      (setq rake-completion-system 'helm))

    projectile

    プロジェクト管理といえばこれ。

    Project Interaction Library for Emacs.

    自動でプロジェクトのルートディレクトリを探して, それ以下のファイルを見つけたり色々できる.

    .projectile ファイルをマニュアルで作成することで, そのフォルダを Route Folder と認識出来る.(要 Emacs 再起動)

    (require 'projectile)
    (projectile-global-mode)
    ;; 大きいプロジェクトだと劇的に改善するらしい.
    (setq projectile-enable-caching t)

    projectile-rails

    Ruby on rails 用.

    (require 'projectile-rails)
    (add-hook 'projectile-mode-hook 'projectile-rails-on)