locate-executable

標準添付の executable-find が全く同じ機能でした。 *1

d:id:elim:20080126:1201802151 のコードは e21 と e22 の時で結果が変わってしまう可能性がありました。

以下のような状況を想定します。

  1. exec-path が ("~/bin" "/bin")
  2. ~/bin/foo.bat と /usr/bin/foo.exe がある

e21 の場合、(concat name exec-suffixes) ではじめに見付かったものになるので /usr/bin/foo.exe が返ってきます。
e22 の場合、exec-path の中ではじめに見付かったものになるので ~/bin/foo.bat が返ります。

結果を同じにするべく、以下のように書き換えてみました。

(defun locate-executable (name)
  (if (and (boundp 'exec-suffixes) (fboundp 'locate-file)) ;; emacs22 feature
      (locate-file name exec-path exec-suffixes 'file-executable-p)
    (let
	((exec-suffixes (list nil ".exe" ".com" ".cmd" ".bat")))
	(caar
	 (remove nil
		 (mapcar #'(lambda (path)
			     (remove nil
				     (mapcar #'(lambda (suffix)
						 (locate-library
						  (concat name suffix) nil (list path)))
					     exec-suffixes)))
			 exec-path))))))
  1. exec-path を順に取り出す
  2. 取り出した exec-path の各要素に対して
    1. exec-suffixes を順に取り出し、 name と結合させファイル名を作る
    2. 作り出したファイル名が存在するか確認させる
  3. caar で一番若い要素を抜く

これで e21 の場合も e22 の場合も同じ値が求まります。


あ、e21 の時は file-executable-p を通していない……。
また今度。

*1:Emacs 22 では実装も同じでした……。