Rakefileを再帰的に探してrake testするelisp(TB)

http://d.hatena.ne.jp/modka/20090820/1250759260
書いてみました。*1

(require 'cl)

;;
(defvar raketest-old-color (frame-parameter (selected-frame) 'background-color))
(defvar raketest-output-buffer "*rake test output*")
(defvar raketest-success-color "honeydew")
(defvar raketest-fail-color "LavenderBlush")

;;util
(defsubst raketest-parent-dir (path)
  "return parent directory path of argument."
  (substring-no-properties (file-name-directory path) 0 -1))

(defsubst raketest-find-target-file-dir (path target)
  (let* ((src (nreverse (split-string (raketest-parent-dir path) "/")))
	 (paths (maplist #'(lambda (l) (string-join (reverse l) "/")) src)))
    (loop for path in paths
	  if (file-exists-p (concat path "/" target))
	  return path)))

(defun raketest-find-rakefile-dir (path)
  "find Rakefile upward"
  (raketest-find-target-file-dir path "Rakefile"))

(defun raketest-color-alert/hook (color reply &optional hook)
  (set-background-color color)
  (message reply)
  (run-at-time "1 sec" nil
	       '(lambda () (set-background-color raketest-old-color)))
  (when hook (funcall hook)))

(defsubst raketest-clean-up ()
  (when (get-buffer raketest-output-buffer)
    (with-current-buffer raketest-output-buffer
      (erase-buffer))))

;;interactive functioin
(defun raketest-run ()
  "find Rakefile upward and run `rake test`."
  (interactive)
  (raketest-clean-up)
  (let* ((rake-dir (and (buffer-file-name)
			(raketest-find-rakefile-dir (buffer-file-name))))
	 (cmd (format "cd %s && rake test" rake-dir))
	 (status (call-process-shell-command cmd nil raketest-output-buffer)))
    (case status
      ((0) (raketest-color-alert/hook raketest-success-color "test passed"))
      (otherwise 
       (raketest-color-alert/hook raketest-fail-color "test failed"
				  (lambda () (display-buffer raketest-output-buffer)))
       ))))

追記

string-joinは自分が定義した関数でした。

(defun string-join (sequence separator)
(mapconcat #'identity sequence separator))

こちらの環境*2では、call-process-shell-commandは成功時に0,失敗時に1または127を返しています。

*1:成功/失敗で分岐させたいだけなら、shell-commandよりcall-process-shell-commandの方が適していそうです。

*2:Linux trotr-desktop 2.6.28-14-generic #47-Ubuntu SMP Sat Jul 25 00:28:35 UTC 2009 i686 GNU/Linux