Rubyのソースコード(C言語)解析支援ツール list-call-seq.rb

RubyソースコードはC言語であってもきちんとRDoc形式のドキュメントが書いている。そこでは、「call-seq:」の後の行に深くインデントを取ってメソッドの使い方が書いてある。つまり、call-seqの後の行を拾っていけば、そのソースコードはどんなメソッドを定義しているかがわかる。たとえば、prec.cに対して実行してみるとこんな感じだ。「-n」、「-H」オプションをつけるとgccの出力のようになる。

$ list-call-seq.rb -nH prec.c
prec.c:22:   num.prec(klass)   => a_klass
prec.c:43:   num.prec_i  =>  Integer
prec.c:60:   num.prec_f  =>  Float
prec.c:77:   Mod.induced_from(number)  =>  a_mod
prec.c:99:   included

以下からもってけ!
http://www.rubyist.net/~rubikitch/archive/list-call-seq.rb

ついでにanything.elの設定も

anything.elと併用すると鬼のように便利なんだがw

;; 俺拡張からの抜き出し
(defvar anything-current-buffer nil)
(defadvice anything (before get-current-buffer activate)
  (setq anything-current-buffer (current-buffer)))
(defvar anything-candidate-cache-by-buffer nil)
(make-variable-buffer-local 'anything-candidate-cache-by-buffer)
(defun anything-get-cached-candidates (source)
  "Return the cached value of candidates for SOURCE.
Cache the candidates if there is not yet a cached value."
  (let* ((name (assoc-default 'name source))
         (candidate-cache (assoc name anything-candidate-cache))
         candidates cached-tick tick)

    (if candidate-cache
        (setq candidates (cdr candidate-cache))
      (unless (with-current-buffer anything-current-buffer
                (and (assoc 'invariant source)
                     (eq (setq tick (buffer-modified-tick))
                         (setq cached-tick (assoc-default 'tick anything-candidate-cache-by-buffer)))
                     (setq candidates (assoc-default name anything-candidate-cache-by-buffer))))
               
        (setq candidates (anything-get-candidates source))

        (if (processp candidates)
            (progn
              (push (cons candidates
                          (append source 
                                  (list (cons 'item-count 0)
                                        (cons 'incomplete-line ""))))
                    anything-async-processes)
              (set-process-filter candidates 'anything-output-filter)
              (setq candidates nil))

          (unless (assoc 'volatile source)
            (setq candidate-cache (cons name candidates))
            (push candidate-cache anything-candidate-cache)
            (with-current-buffer anything-current-buffer
              (unless (eq tick cached-tick)
                (setq anything-candidate-cache-by-buffer
                      `((tick . ,tick))))
              (push candidate-cache anything-candidate-cache-by-buffer)))))
      candidates)))

;; ここが本題
(defvar anything-c-source-list-call-seq
  '((name . "Ruby Source (call-seq)")
    (candidates
     . (lambda ()
         (with-current-buffer anything-current-buffer
           (when (and buffer-file-name (eq major-mode 'c-mode))
             (split-string (shell-command-to-string
                            (format "list-call-seq.rb -n %s"  buffer-file-name))
                           "\n")))))
    (invariant)
    (action
     ("Goto line" .
      (lambda (candidate)
        (and (string-match "^\\([0-9]+\\)" candidate)
             (goto-line (string-to-int (match-string 1 candidate)))))))))