ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

Emacsでmrubyをそこそこ快適に書く

こんにちは、これはEmacs記事です。みなさんはEmacs記事...ではないですよね...。

Haconiwaのおかげですっかりmruby人間になって久しい id:udzura です。

で、宣伝はこんなくらいにしておきまして、なんとなく流れでセットアップしたEmacsによるmruby環境をこの辺で整理しとこうと思ったので、書きます。というか、ほとんどC言語を書くための環境...。平成が終わるとか終わらないとか言っている2016年にEmacsC言語を書く環境の記事を書きます。

なお僕は C言語をまともに書いて2ヶ月ぐらいだったり、あと普通にカーソルキー使う人間だったりするので、その辺りは優しく突っ込んでいただければと...思います...。

何はともあれggtags、その他インストール

GNU Global をおもむろにインストール。

brew install global

GNC Globalを使う際には、言語によっては(というかほとんどの言語では)Pygmentsなどとの連携が必要でやや面倒であるが、C言語なら組み込みで対応しているので便利。

GNU Globalはプロジェクトごとに GTAGS/GRTAGS/GPATH というファイルを生成してインデックスをする。これは、グローバルにgitignoreしておくこと。

cat <<EOC >> ~/.gitignore_global
GPATH
GRTAGS
GTAGS
EOC

で、このGNU Globalを使って

  • 定義ジャンプ
  • 補完
  • eldocの表示

を行ってくれる ggtags を入れておく(今後、入れておくというのはEmacsの標準パッケージマネージャーなどで適宜やっていくという意味)。設定は こちらのサイト を見た。

あと僕は一部の操作(定義ジャンプ)だけ、操作感がいいのでhelm-gtagsを使っている。 M-. で定義ジャンプ。

補完に便利なリポジトリのチェックアウト

基本 ghq をつかって、あらかじめローカルにチェックアウトしておく。

僕は以下のリポジトリghqで直接引っ張っている。mrubyのほか、glibc、libcgroup、libcapをよく使いそうなので落としてある。

ghq get https://github.com/mruby/mruby.git
ghq get git://sourceware.org/git/glibc.git
ghq get git://git.kernel.org/pub/scm/linux/kernel/git/morgan/libcap.git
ghq get git://git.code.sf.net/p/libcg/libcg

そしてカーネル、巨大極まりないリポジトリであるが、これのチェックアウトはこんな感じで...

mkdir -p /Users/udzura/.ghq/git.kernel.org/pub/scm/linux/kernel/git/stable
cd /Users/udzura/.ghq/git.kernel.org/pub/scm/linux/kernel/git/stable
git clone --depth=50 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
# (時間のあるときに git fetch origin --tags )

最後に、それぞれのリポジトリのルートでこれ

gtags

を実行し、 GTAGS ファイルなどを生成しておくのを忘れないようにする。

なお、本記事においては今後も、ghqのルートは「/Users/udzura/.ghq」を前提にしているので、適宜読み替えてほしい。

基本的な設定

ggtags(global)で、これらのGTAGSインデックスを利用できるようにする。環境変数 GTAGSLIBPATH をセットすればOK。init.elの冒頭らへんでやる。

(setenv "GTAGSLIBPATH" (concat
      "/Users/udzura/.ghq/github.com/mruby/mruby"
      ":" "/Users/udzura/.ghq/git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable"
      ":" "/Users/udzura/.ghq/sourceware.org/git/glibc"
      ":" "/Users/udzura/.ghq/git.code.sf.net/p/libcg/libcg"
      ":" "/Users/udzura/.ghq/git.kernel.org/pub/scm/linux/kernel/git/morgan/libcap"))

何かが変だったら、ちゃんとそれぞれのルートにGTAGSなどのファイルができていることを再確認する。

その他の設定でやっていってる箇所はこの辺。

(require 'ggtags)
(add-hook 'c-mode-common-hook
          (lambda ()
            (when (derived-mode-p 'c-mode 'c++-mode 'asm-mode)
              (ggtags-mode 1))))

;; helmをつかってジャンプしたい時は
(setq ggtags-completing-read-function nil)

;; eldoc で定義を表示したい
(setq-local eldoc-documentation-function #'ggtags-eldoc-function)

;; c-mode-hookたち
;; auto-complete.el は入っている前提
(add-hook 'c-mode-common-hook
    (lambda ()
      (setq c-default-style "k&r") ;; カーニハン・リッチースタイル
      (setq indent-tabs-mode nil)  ;; タブは利用しない
      (setq c-basic-offset 2)      ;; indent は 2 スペース
      (eldoc-mode t)               ;; use eldoc
      ;; c-eldoc は凄いが、なんか固まるので使うのをやめた...
      (add-to-list 'ac-sources 'ac-source-gtags) ;; ac-source に追加
      ))

(追記: mruby コアのスタイルはGNUスタイルだそうですが、僕は普段のmgemをK&Rベース+2スペースタブで書いているのでこのようにしています)

ここまででこんな感じになるはず。

eldoc

f:id:udzura:20160721142222p:plain

補完

f:id:udzura:20160721142236p:plain

定義ジャンプ

f:id:udzura:20160721142320g:plain

Cヘッダーの補完

ここまででもかなり捗ると思うが、ヘッダーの補完も入れる。

(require 'auto-complete-c-headers)
(add-hook 'c-mode-hook '(setq ac-sources (append ac-sources '(ac-source-c-headers))))

ヘッダーの検索先としてさっきまでに落としたmrubyやkernelを追加するため、こんな感じでヘッダー検索先関数を定義して使う。

(defun my-get-include-directories ()
  (list "." "/usr/include" "/usr/local/include"
        "/Users/udzura/.ghq/github.com/mruby/mruby/include"
        "/Users/udzura/.ghq/sourceware.org/git/glibc/include"
        "/Users/udzura/.ghq/git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable/include"
        "/Users/udzura/.ghq/git.code.sf.net/p/libcg/libcg/include"
        "/Users/udzura/.ghq/git.kernel.org/pub/scm/linux/kernel/git/morgan/libcap/libcap/include"))

(setq achead:get-include-directories-function 'my-get-include-directories)

このようになっています。

f:id:udzura:20160721142301p:plain

ビルド環境とか

今回は開発するものがするもの(Linux向けのコンテナエンジン・ライブラリ)なので、VagrantCentOS 7 VMを作って、 ghqのルートを共有フォルダにしてCentOS 7でビルドをしている。ポイントとして、補完のためのソース一式はMacに落としているが、ビルド自体は行っていないところ。そういうこともできる。

で、下で紹介する mruby-mrbgem-template を使えばrake一発でmgemを含むmrubyをビルドできる秘伝のRakefileを作ってくれるので、VM上ではひとまず温かみのあるビルドをしている...。

その気になれば Guard とかそういう系のファイル変更監視ツール使えそう、使えばいいんじゃないだろうか。Emacsからビルド等は、やっていない。

その他便利情報

最後に、mrubyのgem(mgem)の雛形を一発で作る便利手順を。

今やっているのは、まずmruby-mrbgem-templateのプロジェクト自体をビルドして、mrubyバイナリを(Macで)作る。

そのmrubyを「mruby-mrbgem-template」という名前にしてパスの通ったところに置く

cp mruby/bin/mruby /usr/local/bin/mruby-mrbgem-template

あとは以下のようなテンプレートを用意し、さっきのコマンドでキックする。

params = {
  :mrbgem_name    => 'mruby-test-mgem',
  :license        => 'MIT',
  :github_user    => 'udzura',
  :mrbgem_prefix  => '.',
  :class_name     => 'Test',
  :author         => 'Uchio Kondo',
  :local_builder  => true,
  :ci             => :matrix,
}

c = MrbgemTemplate.new params

c.create
$ mruby-mrbgem-template template.rb  
Generate all files of mruby-test-mgem
create dir : ./mruby-test-mgem
create dir : ./mruby-test-mgem/src
create file: ./mruby-test-mgem/src/mrb_test.c
create file: ./mruby-test-mgem/src/mrb_test.h
create dir : ./mruby-test-mgem/mrblib
create file: ./mruby-test-mgem/mrblib/mrb_test.rb
create dir : ./mruby-test-mgem/test
create file: ./mruby-test-mgem/test/mrb_test.rb
create file: ./mruby-test-mgem/mrbgem.rake
create file: ./mruby-test-mgem/Rakefile
add gitignore entry: ./mruby-test-mgem/.gitignore
create file: ./mruby-test-mgem/mruby-test-mgem.gem
create file: ./mruby-test-mgem/.travis.yml
create file: ./mruby-test-mgem/.travis_build_config.rb
create file: ./mruby-test-mgem/README.md
create file: ./mruby-test-mgem/LICENSE

  > create udzura/mruby-test-mgem repository on github.
  > turn on Travis CI https://travis-ci.org/profile of udzura/mruby-test-mgem repository.
  > edit your mruby-test-mgem code, then run the following command:

  cd ./mruby-test-mgem
  git init
  git add .
  git commit -m "first commit"
  git remote add origin git@github.com:udzura/mruby-test-mgem.git
  git push -u origin master

  > finally, pull-request mruby-test-mgem.gem to mgem-list https://github.com/bovi/mgem-list

このプロジェクトはいきなりrakeでビルドできるはず。 このPR で秘伝のマトリックスビルド設定なども入れたので便利にお使いください。


ということで、mruby周りの開発の一助になれば幸い。思ったんですけどM○tzご本人がEmacsユーザのはずなのでその設定が知りたい...。

とにかくGNU Globalが便利、ソースコードリーディングにも便利なので、 Vimその他の方も是非設定するといいかと思います。Vimmer皆さん向けの便利記事です。

Enjoy programming!!1