motion-modeについて
RubyMotion用emacsメジャーモードのmotion-mode、3月から地道に機能を実装しましたが、けっこういい感じに機能が揃ってきたのではないかと思いまして。改めて、解説記事書きます。

今回、motion-upgrade-major-mode-if-motion-projectとかいう長ったらしい名前だったhook用関数をmotion-recognize-projectという名前に変更したので、今まで利用していた方は設定の修正をお願いします。
(add-hook 'ruby-mode-hook 'motion-recognize-project)
インストール方法
ついに、package.el経由でインストールできるようになりました。
https://github.com/milkypostman/melpa/pull/758
MELPAのリポジトリにpull reqしてパッケージを追加してもらいました。MELPAを設定に追加して、M-x pakage-list-packageを使うだけで、motion-modeを導入出来ます。
Emacs24なら以下のコードをinit.elとかに書いておきます。Emacs23以下ならpackage.elをググって適当に入れて下さい。
(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-initialize)
そのあと、M-x package-list-packageを起動して、表示されるメニューの中から、motion-modeを探して、iでマークを付けてxでインストールしちゃって下さい。

辞書ファイルの設定方法
motion-modeがインストールされたディレクトリまで移動して、make_dict.rbに対して、iOS SDKのヘッダーファイルがあるディレクトのfind結果を渡してやると、同じディレクトリにmotion-modeという辞書ファイルが作成されるので、auto-complete-modeで指定されている辞書の置き場に、そのファイルを設置してやると、motion-modeでファイルを開いた際に、辞書に含まれる単語を補完できます。
$ cd ~/.emacs.d/elpa/motion-mode/ $ find /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/System/Library/Frameworks -name "*.h" | xargs ruby bin/make_dict.rb $ cp ./motion-mode ~/.emacs.d/ac-dict $ emacs ~/.emacs.d/init.el # add following setting (add-to-list 'load-path "~/.emacs.d/elisp/motion-mode") (require 'motion-mode) ;; following adding of hook is very important. (add-hook 'ruby-mode-hook 'motion-recognize-project) (add-to-list 'ac-modes 'motion-mode) (add-to-list 'ac-sources 'ac-source-dictionary) ;; set keybindings as you like (define-key motion-mode-map (kbd "C-c C-c") 'motion-execute-rake) (define-key motion-mode-map (kbd "C-c C-d") 'motion-dash-at-point)
機能紹介
motion-modeは、基本的にruby-modeの設定を受け継いで作成しているメジャーモードです。なので、SyntaxHighlight等はruby-modeのままです。 その他にもいろいろ機能があります。
1. RubyMotionプロジェクトかどうかを認識する
これがまずいちばん最初に実装した機能で、これによって、*.rbという拡張子のファイルを開いた時にただのRubyだったら、ruby-modeでファイルを開き、RubyMotionのプロジェクト内のファイルだったら、motion-modeでファイルを開くことができます。
Emacsでは、拡張に関する設定はメジャーモード毎に持てるため、motion-modeでファイルを開けるようになると、それに付随する様々な設定がmotion-mode専用に使えるようになります。
たとえば、キーバインドの設定は、motion-mode専用の物を設定したあとに、他のモードでファイルを開いても他のモードで開いたバッファにはキーバインドの設定は影響を及ぼしません。
なので、Emacsで特定の環境専用の拡張を書こうとしたら、どのタイミングで専用のmajor-modeとしてファイルを開くのかが最初のポイントなのかも。
最初、git rev-parseコマンドに依存した実装を使っていたのですが、syohexさんにリファクタした差分をpull requestしてもらい、gitに依存せずに利用することが出来ました。ありがとうございます!!!
2. auto-complete-modeによる辞書補完
これはひとえに、auto-complete-modeすげーっていうことではあるのですが、auto-complete-modeではメジャーモードに応じた辞書ファイルの読み込み+辞書補完が出来るため、github上のyasObjcというスクリプトを流用して、iOS SDKのヘッダーファイルから辞書を作り出す、make_dict.rbというスクリプトを作って対応しました。
ただ、今のところiOS SDKのヘッダーファイルに存在するクラス名、メソッド名だけっぽいので、Objective-Cに標準で存在するクラスなどの単語も辞書化出来るように改良の余地があるかなと思います。
3. rakeタスクの実行サポート
motion-execute-rakeというコマンドを実装しました。これを好きなキーバインドに割り当てると(デフォルトではキーバインドは用意していないので)、Emacs内からrakeタスクが実行できるようになります。C-c C-cがおすすめです。
単に、C-c C-cで実行すると、そのままrakeが実行され、C-uのprefixをつけて実行すると(つまりC-u C-c C-c)、ミニバッファにrakeのサブコマンドの入力を促すプロンプトが現れ、rake specなどが実行できるようになります。
4. Interactive Debuggerの操作 in Emacs
3のrakeタスクでデフォルトで実行される”rake”コマンドで、ビルドされ、その後のInteractive Debugger用のコンソールをEmacs上で操作出来ます。

3も4も、comint-modeってのを使ってます。
5. flymakeによる構文チェック
flymake自体はEmacs標準の構文チェック用の機能で、motion-mode上でも利用できるように対応しました。macruby -cを利用してエラーをチェックしています。
この対応の実装のためにflymake-easy(簡単にflymake対応するためのライブラリ)とflymake-cursor(エラー箇所にカーソルを合わせるとエラー内容がミニバッファに表示される)という拡張を使っています。
flymakeが嫌いな人はmotion-flymakeという変数にnilを設定すると、flymakeを利用しなくなります。
(setq motion-flymake nil)
6. Dash.appによるドキュメント検索
Dash.appって使ってますか?基本無料(時たま課金を促す表示が出る)で、いろいろな言語とかフレームワークのドキュメントがさくさく(ネットでググるよりレスポンスが良い)調べられてすごく好きです。
このアプリで、RubyMotionのドキュメントも検索出来るのですが、IDEみたいに簡単にドキュメント引けたらいいなと思い、カーソル上の単語にたいして、motion-dash-at-pointを実行するとそのままDash.appで単語の内容を検索できるようにしました。適当にキーバインドを割り当てるとだいぶ良い感じです。
これにはOS Xのopenコマンドを使って以下の様なスキーマで検索してます。
open dash://rubuymotion:hoge_keywords
7. Objective-Cの呼び出し形式からRuby形式にコードを変換
Watsonさんとnaoyaさんに煽られて、kyamaguchi/SublimeObjC2RubyMotionをEmacsに移植した機能になります。
以下の様なObjective-Cのコードを
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.rootViewController = self.myNavController; [self.window makeKeyAndVisible];
以下の様なRuby形式の呼び出しに変換する機能です。
_window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) self.window.rootViewController = self.myNavController self.window.makeKeyAndVisible
元の拡張はSublime Text用だったのでpythonで書かれておりましたが、pythonに依存したくないため、Rubyで書きなおして(RubyならばRubyMotion利用者は利用できる前提)、Emacsから呼び出すようにしました。使用する時は、バッファー内で範囲を選択して、M-x motion-convert-code-regionを 呼び出すと選択部分が変換されます。
shell-command-on-regionという選択範囲を外部コマンドの標準入力に投げて出力をバッファに挿入するコマンドを利用しています。
おわりに
当初、RubyでiOS開発してみたいがためにRubyMotionを購入しました。いざemacsでコード書こうと思ったら、Emacsってそんなに書きやすい環境ではないな、と思ってちょっとした拡張書いてみようと思ったところからmotion-modeの開発が始まりました。
その後naoyaさんとかwatsonさんに煽られ、機能追加したりして、なりゆきで煽られ駆動開発していたら自分自身全然iOSアプリ書けないけど拡張書くみたいな人になっちゃって良くないなぁと思いました。
ということで最近は、まずiOS開発そのものを学ぶため詳解Objetive-CとかUIKit詳解リファレンスを読んだり、 最近ちょっと話題になっているミクシィ社のiOS開発研修資料を元にRubyMotionでコードを書いたりして勉強しております。
あと、github上の英語のREADME.md、TOEIC400点台の英語力で書いたのでおかしい所あれば直していただけるとすごく嬉しいです…


