projectile はプロジェクト内のファイルを検索したりするのに便利なパッケージ
いつも通り el-get からインストールする
(el-get-bundle projectile)
このあたりで有効化しておいている。この順序に意味があったかは忘れた……。
(projectile-mode)
普段 Rails ばっかりやってるのでそれ関係のものを無視リストに入れている。けどあんまりメンテしてない。
(add-to-list 'projectile-globally-ignored-directories "tmp")
(add-to-list 'projectile-globally-ignored-directories ".tmp")
(add-to-list 'projectile-globally-ignored-directories "vendor")
(add-to-list 'projectile-globally-ignored-directories ".sass-cache")
(add-to-list 'projectile-globally-ignored-directories "coverage")
(add-to-list 'projectile-globally-ignored-directories "cache")
(add-to-list 'projectile-globally-ignored-directories "log")
node_modules もここに突っ込んでも良いかもしれない。
(add-to-list 'projectile-globally-ignored-files "gems.tags")
(add-to-list 'projectile-globally-ignored-files "project.tags")
(add-to-list 'projectile-globally-ignored-files "manifest.json")
tags ファイルは昔は使っていたけど、最近は dumb-jump が優秀なのと、面倒で使ってないのでそろそろ gems.tags と project.tags は不要かもしれない。
上の方で helm との連携処理を入れていたが今は大体 ivy に乗り換えているので ivy 連携もしている。
(setq projectile-completion-system 'ivy)
(el-get-bundle counsel-projectile)
counsel-projectile はいくつかの絞り込み処理を提供してくれて便利。それでも足りなかったら自前で何か作ることになるのかなと思っている。
デフォルトでいくつかのキーバインドが用意されてるようだけどそんなものさっぱり覚えられないのでとりあえずいくつかを Hydra で叩けるようにしている
(with-eval-after-load 'pretty-hydra
(pretty-hydra-define
projectile-hydra (:separator "-" :title (concat (nerd-icons-mdicon "nf-md-rocket_launch") " Projectile") :foreign-key warn :quit-key "q" :exit t)
("Find"
(("f" counsel-projectile-find-file "Find File")
("d" counsel-projectile-find-dir "Find Dir")
("r" projectile-recentf "Recentf"))
"Edit"
(("R" projectile-replace "Replace"))
"Jump"
(("l" projectile-edit-dir-locals "dir-locals")
("d" my/projectile-goto-docker-file "Dockerfile")
("c" my/projectile-goto-circleci-config "CircleCI Config")
("r" my/projectile-goto-rubocop-config ".rubocop.yml"))
"Search"
(("g" counsel-projectile-rg "RipGrep(Counsel)")
("G" projectile-ripgrep "RipGrep"))
"Other"
(("p" (counsel-projectile-switch-project 'counsel-projectile-switch-project-action-vc) "Switch Project")
("c" counsel-projectile-org-capture "Capture")
("SPC" my/project-hydra "Hydra")))))
Key | 効果 |
---|---|
f | プロジェクト内のファイルを検索 |
d | プロジェクト内のフォルダを検索 |
r | プロジェクト内で最近触ったファイルのリスト表示 |
R | 一括置換する |
l | .dir-locals.el を開く |
d | Dockerfile を開く |
c | .circieci/config.yml を開く |
r | .rubocop.yml を開く |
d | Dockerfile を開く |
g | RipGrep で検索し counsel で結果を表示 |
G | RipGrep で検索し rg.el のバッファで結果を表示 |
p | 別のプロジェクトに切り替え |
c | プロジェクト用に org-capture でメモを取る |
SPC | プロジェクト固有の Hydra を起動する |
projectile-find-implementation-or-test
projectile-replace-regexp
あたりも使えるようにするともしかしたら便利かもしれない。
プロジェクト固有の Hydra を {project-dir-name}-hydra
のように定義しておけばプロジェクトのディレクトリ名を用いてそれ用の Hydra を呼び出す関数。
プロジェクト固有の Hydra は .dir-locals で定義することを念頭に置いているが、 Emacs の設定ファイルに直接埋め込んでいても特に問題はないはず。
(defun my/project-hydra ()
"Call the project specific hydra."
(interactive)
(let* ((project-path (directory-file-name (projectile-acquire-root)))
(project-dir-name (file-name-base project-path))
(hydra-body (intern (concat project-dir-name "-hydra/body"))))
(cond
((fboundp hydra-body)
(funcall hydra-body))
(t
(user-error "project hydra is not defined on %s." project-dir-name)))))
プロジェクト内に1つしかないようなファイルは completing-read で絞り込む必要がないのでぱぱっと開けるようにするためのコマンドを用意した。
(defun my/projectile-goto-file (file-path)
"Go to the file path"
(let ((path (concat (projectile-acquire-root) file-path)))
(cond
((file-exists-p path)
(find-file path))
(t
(user-error "%s is not found." file-path)))))
実装ファイルなどは特定のフォルダ以下に複数存在するのが一般形なので指定したフォルダ以下のファイルを completing-read で絞り込めるようにしている。
(defun my/projectile-find-file-in-dir (dir-path)
"Find the file path"
(interactive)
(let ((path (concat (projectile-acquire-root) dir-path)))
(cond
((and (file-exists-p path) (file-directory-p path))
(projectile-find-file-in-directory path))
(t
(user-error "%s is not directory." dir-path)))))
今時は Docker がよく使われているので Dockerfile を開くコマンドを用意した。
(defun my/projectile-goto-dockerfile ()
"Find the Dockerfile"
(interactive)
(my/projectile-goto-file "Dockerfile"))
.circleci/config.yml
も時々開くよねってことで追加した
(defun my/projectile-goto-circleci-config ()
"Find the CircleCI config.yml"
(interactive)
(my/projectile-goto-file ".circleci/config.yml"))
Ruby 書いているとお馴染の Gemfile もぱぱっと開きたいので追加
(defun my/projectile-goto-gemfile ()
"Find the Gemfile"
(interactive)
(my/projectile-goto-file "Gemfile"))
Ruby 書いていたら大体 rubocop も使うので追加
(defun my/projectile-goto-rubocop-config ()
"Find the .rubocop.yml"
(interactive)
(my/projectile-goto-file ".rubocop.yml"))
デフォルト設定は妙なインデントが入って来るのでそれを取り除いているだけ
(setopt counsel-projectile-org-capture-templates
'(("t" "[${name}] Task" entry (file+headline "${root}/notes.org" "Tasks") "* TODO %?\n%u\n%a")))