今開いているバッファに関連するファイルが特定のプロジェクトに
含まれるかなどを調べるとき、ディレクトリを上位方向へ辿り、
特定のファイルが含まれるかを調べるということがあるかと思いますが、
elispでどう書くのがいいのかわからなかったので、標準ライブラリの
コードを調べました。
それについて示します。
file-name-directoryと directory-file-nameを組み合わせる
file-name-directory関数と directory-file-name関数を交互に使って
いけば良いです。directory-file-nameで末尾のスラッシュを取り除き、
file-name-directoryで親ディレクトリを求めています。末尾がスラッシュ
だと file-name-directoryは同じ名前を返すので、それだけ使って
上へ上へと辿ることはできません。
以下にサンプルコードを示します。
(defun test (start) (let ((dir (file-name-as-directory start)) (prev "")) (while (not (string= dir prev)) (message "%s" dir) (setq prev dir dir (file-name-directory (directory-file-name dir)))))) (test "/home/syohei/program/elisp/")
具体例
具体的に書くとしたら以下のような感じでしょうか.
(Windowsだと動くかどうかわかりません)
(defun my/exists-p (dir targets) (let ((default-directory dir)) (loop for target in targets if (file-exists-p target) return target))) (defun my/find-to-root (start targets) (let ((prev "") (dir (file-name-as-directory start))) (while (and (not (string= dir prev)) (not (my/exists-p dir targets))) (setq prev dir dir (file-name-directory (directory-file-name dir)))) (if (string= prev "/") "cucumber" (concat "bundle exec cucumber")))) (my/find-to-root "/home/syohei/tmp/hoge" '("Gemfile" "Rakefile"))