$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

direx.elでgitプロジェクトのディレクトリツリーを表示する、またはdirex-project.elの紹介

 emacsにはdirex.elという非常に便利なdirectory explorerがあります。これによって、ディレクトリのツリー構造が表示され、diredよりも便利にdirectoryを辿ることが出来るようになりました。

 しかし、デフォルトでは自分にとってはいろいろと不便なときもありました。

  • ~/myprojects/Sample-Project/script/app.psgiを触ってる時に、direxを起動すると、~/myprojects/Sample-Project/scriptのディレクトリからのツリー構造が表示される。実際は~/myprojects/Sample-Projectからのツリー構造が表示されてほしい
  • ~/のツリー構造が開かれている状態で、~/myprojects/Sample-Project/script/app.psgiからdirexを起動すると、~/のツリー構造の中に開かれてしまう。上の構造のものが開かれていたらそれに追従して欲しいけれど、プロジェクトより上に行ってほしくはない。

 そこでとりあえずgitのproject rootからのツリー構造を表示してみようと思い立ちました。

direx:jump-to-git-project-directory

 それで作ったのが、direx:jump-to-git-project-directory。これは現在のprojectがgitのディレクトリであれば、gitのrootからのツリー構造を表示し、そうでなければ普通にdirexを呼び出すというものです。

 下のような感じ。

(defun chomp (str)
  (replace-regexp-in-string "[\n\r]+$" "" str))

(defun git-project-p ()
  (string=
   (chomp
    (shell-command-to-string "git rev-parse --is-inside-work-tree"))
   "true"))

(defun git-root-directory ()
  (cond ((git-project-p)
         (chomp
          (shell-command-to-string "git rev-parse --show-toplevel")))
        (t
         "")))

(defun direx:jump-to-git-project-directory ()
  (interactive)
  (let* ((git-root-dir))
    (setq git-root-dir (git-root-directory))
    (unless (string= git-root-dir "")
      (direx:find-directory-noselect git-root-dir))
    (direx:jump-to-directory-other-window)))

 これらをemacsの設定に追記した上で、direx:jump-to-git-project-directoryを呼ぶと、gitのprojectを考慮してdirexを開いてくれます。なお、gitのprojectであるかどうかを判定するgit-project-pや、gitのroot directoryを返すgit-root-directoryは、汎用的につかえるので別に分けました。

 例えば僕のemacsの設定はemacsというディレクトリの中でgitで管理しているので、以下のように表示されます。gitで管理してる中にいればいつでもこういうふうな表示になってくれます。
f:id:shiba_yu36:20130122111638p:plain

direx-project.el

 それでここまで作ってみて、これってgitに限る話じゃなくてprojectだったらなんでもそうだよなーと思い、いろいろ調べてみたら、direx-project.elというのがありました。
https://github.com/m2ym/direx-el/blob/master/direx-project.el

 この中のdirex-project:jump-to-project-root-other-windowは、そのまま上に書いたような思考を実装したような形だったので、普通にこちらを使えば良いと思いました。

 ただ一点だけ困るのは、projectの中にいないときに(error "Project root not found") が呼ばれて、何も起こらないことです。perlだったらevalでくくって条件分けするのですが、emacsのエラーハンドリングのやり方がよく分からなくて、projectの中にいないときに普通にdirex呼び出すということができないみたいになってしまっています。

まとめ

 今回はdirexでプロジェクトのディレクトリツリーを表示するのと、それに伴ってdirex-project.elを発見した話について書きました。通常はdirex-project.elを使っておくと便利につかえると思います。
 あとemacsのエラーハンドリングよく分からなくて、errorをcatchする方法とか無いか知りたいです。@shiba_yu36まで良ければ教えてください。