現在のバッファで使われている関数の所在を調べる
clパッケージの関数を使っていることを示すのにファイルの冒頭に"require 'cl"が合った方がわかりやすいと思った。
clパッケージに限らずrequireが必要なファイルをすべてファイルの冒頭に書いて置けば、あとで使いやすいかもしれないと思った。
いちいち中身を見るのは面倒なので、emacsに訊けないか調べてみた。
調べた方法(手順)
C-h f で関数のリファレンスを見ている時に、
"describe-function is an interactive compiled Lisp function in`help-fns.el'.
こんな感じの表示があるから、多分内部でどうにかして調べているはず。
なので
- C-h fで調べたい関数名を入力するとhelpが表示される
- describe-function-1を読む
- (symbol-file function 'defun)という部分を発見
symbol-fileを使えば、関数がどこで定義されているか分かりそう。あと、そのままだと表示が長いのでdescribe-simplify-lib-file-nameで縮めてたみたい。
つくれそうだ
以下の手順を踏めば作れそう
- buffer内に含まれる単語を取得(カッコとか外す感じで)
- 関数として認識されているかでフィルタリング
- ファイル名と対応をつける(たぶん、そんなに多くないからhash-tableとかいらない)
実際のコード
(require 'cl) (defun current-buffer-words () (save-excursion (goto-char (point-min)) (let (re) (while (re-search-forward "[^)( \n\t\'\"\;]+" nil t 1) (let ((s (substring-no-properties (match-string 0)))) (push (intern s) re))) (remove-duplicates re)))) (defun word->alist (words) (let (re) (dolist (w words) (when (fboundp w) ;(or (fboundp w) (boundp w)) ;;symbol-fileに'defvarもつければ変数も取得可 (let* ((file (describe-simplify-lib-file-name (symbol-file w 'defun))) (seq (assoc file re))) (if seq (setcdr seq (cons w (cdr seq))) (push (list file w) re)) ))) re)) (defun display-used-functions () (interactive) (let ((l (word->alist (current-buffer-words)))) (with-output-to-temp-buffer "*Used Functions" (dolist (fns l) (unless (eq (car fns) 'nil) (princ (format "====%s=====\n" (car fns))) (princ (cdr fns)) (princ "\n"))) ))) ;;(display-used-functions)
実行結果(例)
====cl.el===== (push) ====cl-seq.el===== (remove-duplicates) ====cl-macs.el===== (dolist) ====help-fns.el===== (describe-simplify-lib-file-name) ====subr.el===== (match-string when symbol-file unless)