id:yaottiさんが作っているanything-git-project.el(プロジェクト内のファイルを絞り込んで操作するanything-git-project.el - yaotti's diary)ですが、gitでproject管理している人にとってはすごく便利です。
ただ、一つだけ不満がありました。
そこでちょっとだけ手直ししてみました。
chomp
elisp触ってるとchompが欲しいけど無い、みたいな状況に出会います。そこで以下の関数をユーティリティとして定義しておくと良いと思います。今回の手直しではこれを使ってるので、適当にどこかで定義しておいてください。
(defun chomp (str) (replace-regexp-in-string "[\n\r]+$" "" str))
変更したもの
(defun anything-git-project-project-dir () (chomp (shell-command-to-string "git rev-parse --show-toplevel"))) (defun anything-c-sources-git-project-for () (loop for elt in '(("Modified files (%s)" . "--modified") ("Untracked files (%s)" . "--others --exclude-standard") ("All controlled files in this project (%s)" . "")) collect `((name . ,(format (car elt) (anything-git-project-project-dir))) (init . (lambda () (unless (and ,(string= (cdr elt) "") ;update candidate buffer every time except for that of all project files (anything-candidate-buffer)) (with-current-buffer (anything-candidate-buffer 'global) (insert (shell-command-to-string ,(format "git ls-files --full-name $(git rev-parse --show-cdup) %s" (cdr elt)))))))) (candidates-in-buffer) (display-to-real . (lambda (name) (format "%s/%s" (anything-git-project-project-dir) name))) (type . file)))) (defun anything-git-project () (interactive) (let* ((sources (anything-c-sources-git-project-for))) (anything-other-buffer sources (format "*Anything git project in %s*" (anything-git-project-project-dir)))))
これを使えば以下のように../とかの相対パスではなく、project rootからの相対パスで表示され、移動することができます。以下のような感じ
いくつかの技術的tips
gitで管理されているファイルをrootからの相対パスで取得する
これも簡単で
git ls-files --fullname
としてやれば取得できます。
更に今回はどのディレクトリにいても全ファイル必要なので
git ls-files --full-name $(git rev-parse --show-cdup)
としてあげます。
anything上で見えているものと実行するものを変える
今回現在のディレクトリからの相対パスではなく、project rootからの相対パスを表示するようにしたため、anythingのtype fileでそのまま実行しようとすると違うファイルが選択されてしまいます。そこでanythingのdisplay-to-realを利用して、絶対パスへの書き換えを行なってあげます。
以下の部分が該当しているところ。anything-git-project-project-dirが現在のproject root dirを返してくれるので、それにrootからの相対パスを足してあげて返します。これでちゃんとしたファイルが選択できるようになりました。
(display-to-real . (lambda (name) (format "%s/%s" (anything-git-project-project-dir) name)))
最後に
今回の変更をするにあたり、anything周りのことはEmacsテクニックバイブルが参考になりました。
elisp周りまだぜんぜんわかってないので、Emacs Lispテクニックバイブルも買いたいなー。