Ruby リファレンスマニュアル(通称るりま)と ReFe2 をインストール・ Emacs で参照する・ anything.el との連携

[update] Ruby リファレンスマニュアルを Emacs で参照・ anything.el との連携(改訂版) - http://rubikitch.com/に移転しました

るりまがリリースされたのでインストールしてみる。かなりの充実ぶりに驚く。
次世代 ReFe は BitClust というツールがベースとなっている。 BitClust はリファレンスマニュアル用ツール群で専用 Web サーバーなどを提供しているみたい。

とりあえず展開して BitClust をインストール。

インストール

url=http://www.ruby-lang.org/ja/man/archive/ruby-refm-1.9.0-dynamic.tar.bz2
cd ~/compile; wget $url
cd `basename $url .tar.bz2`
cd bitclust; sudo ruby setup.rb

ReFe2 を使う

ReFe2 を使うには、データベースを指定しないといけない。いちいち指定するのがめんどいので、さくっとスクリプトを作成。 1.8.6 と 1.9.0 両対応なので、古い方との差分も出すようにしてみた。以下からもってけ!

http://www.rubyist.net/~rubikitch/archive/refe2

#!/bin/sh
cd ~/compile/ruby-refm-1.9.0-dynamic/bitclust/
old=/tmp/refm.old
new=/tmp/refm.new
cat <<XXXX
##################################################
# ruby 1.9.0                                     #
##################################################
XXXX
ruby -Ke -Ilib bin/refe.rb -d ../db-1_9_0 "$@" | tee $new
cat <<XXXX
##################################################
# changes from ruby 1.8.6                        #
##################################################
XXXX
ruby -Ke -Ilib bin/refe.rb -d ../db-1_8_6 "$@" > $old
diff -u $old $new
rm -f $old $new


たとえば「 refe2 Array flatten 」とすると「 Array#flatten 」の説明がでてくる。

##################################################
# ruby 1.9.0                                     #
##################################################
Array#flatten
--- flatten(lv = nil)     -> Array
--- flatten!(lv = nil)    -> self | nil

flatten は自身を再帰的に平滑化した配列を生成して返します。 flatten! は
自身を再帰的かつ破壊的に平滑化し、平滑化が行われた場合は self をそうでない
場合は nil を返します。
lv が指定された場合、 lv の深さまで再帰的に平滑化します。

@param lv 平滑化の再帰の深さを整数で指定します。 nil を指定した場合、再帰の深さの制限無しに平滑化します。

@raise ArgumentError 配列要素が自身を含むような無限にネストした配列に対して flatten を呼んだ場合に発生します。

    # 自身を再帰的に平滑化する例。
    a = [1, [2, 3, [4], 5]]
    p a.flatten                     #=> [1, 2, 3, 4, 5]
    p a                             #=> [1, [2, 3, [4], 5]]

    # 自身を破壊的に平滑化する例。
    a = [[[1, [2, 3]]]]
    p a.flatten!                    #=> [1, 2, 3]
    p a                             #=> [1, 2, 3]

    # 平滑化が行われない場合は nil を返す。
    p [1, 2, 3].flatten!            #=> nil
 
    # 平滑化の再帰の深さを指定する例。
    a = [ 1, 2, [3, [4, 5] ] ]
    a.flatten(1)              #=> [1, 2, 3, [4, 5]]

##################################################
# changes from ruby 1.8.6                        #
##################################################
--- /tmp/refm.old	2007-12-28 04:07:12.735596235 +0900
+++ /tmp/refm.new	2007-12-28 04:07:12.235567620 +0900
@@ -1,11 +1,13 @@
 Array#flatten
---- flatten               -> Array
---- flatten!              -> self | nil
+--- flatten(lv = nil)     -> Array
+--- flatten!(lv = nil)    -> self | nil
 
 flatten は自身を再帰的に平滑化した配列を生成して返します。 flatten! は
 自身を再帰的かつ破壊的に平滑化し、平滑化が行われた場合は self をそうでない
 場合は nil を返します。
+lv が指定された場合、 lv の深さまで再帰的に平滑化します。
 
+@param lv 平滑化の再帰の深さを整数で指定します。 nil を指定した場合、再帰の深さの制限無しに平滑化します。
 
 @raise ArgumentError 配列要素が自身を含むような無限にネストした配列に対して flatten を呼んだ場合に発生します。
 
@@ -21,4 +23,8 @@
 
     # 平滑化が行われない場合は nil を返す。
     p [1, 2, 3].flatten!            #=> nil
+ 
+    # 平滑化の再帰の深さを指定する例。
+    a = [ 1, 2, [3, [4, 5] ] ]
+    a.flatten(1)              #=> [1, 2, 3, [4, 5]]
 

クラス名・メソッド名の目次を作成する。

bitclust コマンドでクラス名やメソッド名をリストすることができる。全リストを保存しておく。

cd ~/compile/ruby-refm-1.9.0-dynamic/bitclust/
(ruby -Ke -Ilib bin/bitclust.rb --database ../db-1_9_0 list --class; ruby -Ke -Ilib bin/bitclust.rb --database ../db-1_9_0 list --method) > refe2.index

そして、 Emacs で使うために S 式にしておく。

ruby -ne 'print "# (refe2 \"",$_.chomp,"\")\n"' refe2.index > refe2.e

いちおう、作成したものを置いておくから作業が面倒な人はもってけ!
http://www.rubyist.net/~rubikitch/archive/refe2.e

Emacs で使う。

Emacs で使うために、さくっと refe2 関数を作成。
refe2.e を開いて、見たいドキュメントの S 式を指定して C-e C-x C-e すれば、ドキュメントがポップアップする。もちろん対話的にも使える。

(defun refe2 (kw)
  (interactive "sReFe2: ")
  (let ((coding-system-for-read 'euc-japan))
    (with-current-buffer (get-buffer-create (concat "*refe2:" kw "*"))
      (when (zerop (buffer-size))
        (call-process "refe2" nil t t kw)
        (diff-mode))
      (setq minibuffer-scroll-window (get-buffer-window (current-buffer) t))
      (goto-char (point-min))
      (display-buffer (current-buffer)))))

anything.el との連携

俺は anything の熱狂的ユーザーなので anything で絞り込み検索できないと気がすまない。以下の設定で使えるようになる。 refe2.e はこのために作ったのだ。

(defun anything-c-source-static-escript (symbol desc filename &rest other-attrib)
  `((name . ,desc)
    (candidates . ,symbol)
    ,@other-attrib
    (init
     . (lambda ()
         (unless (and (boundp ',symbol) ,symbol)
           (with-current-buffer (find-file-noselect ,filename)
             (setq ,symbol (split-string (buffer-string) "\n" t))))))
    (action
     ("Eval it"
      . (lambda (cand)
          (with-temp-buffer
            (insert cand)
            (cd ,(file-name-directory filename))
            (backward-sexp 1)
            (eval (read (current-buffer)))))))))

(setq anything-c-source-refe2
      (anything-c-source-static-escript
       'anything-c-refe2-candidates "ReFe2"
       "~/compile/ruby-refm-1.9.0-dynamic/bitclust/refe2.e"
       '(requires-pattern . 3)))
(setq anything-sources (list anything-c-source-refe2))
--><

もちろん anything-sources は各自好きなように設定してくれ。

これだけたくさんの要素があるのに、動作はかなり速いね。 langhelp の Emacs インターフェース部分を anything で置き換えようかな…。そもそも anything のようなものが欲しくて langhelp を作ったんだから。

追記

refe2 コマンドは、古いバージョンとの diff を取るようにした。それに伴い refe2 バッファは diff-mode に。