Endless Parentheses

Concise ramblings on Emacs productivity.

Support on Gratipay
profile for Malabarba on Stack Exchange

Improving Projectile with extra commands

Admittedly, I’m a very late passenger in this boat — only after 4 years of using Emacs did I decide to try a project manager. Nowadays I can’t even remember my daily workflow without Projectile. This package mostly stays out of your way, and provides a series of useful commands for dealing with a project (which are aware of a lot of languages out-of-the-box). As usual, you can find details in the readme, and we’ll jump straight into useful configurations.

(setq projectile-keymap-prefix (kbd "C-x p"))

This places all Projectile keybinds under C-x p and requires no explanation. Mnemonic keymaps are the best. Most used commands are C-x p f to find a file, and C-x p p to switch-project and bring up the commander menu (see below)

(setq projectile-create-missing-test-files t)

C-x p t creates test files for me.

(setq projectile-switch-project-action
#'projectile-commander)

By default, Projectile brings up the file-finder when you switch project with C-x p p. That’s a reasonable default, but I find a lot of times I’m also looking for magit-status or a shell buffer. Using projectile-commander means I have to hit an extra key, but it always gets me where I want.

Furthermore, the menu of alternatives presented by projectile-commander is very customizable, so we can add anything we want in there.

(require 'projectile)
(def-projectile-commander-method ?s
"Open a *shell* buffer for the project."
;; This requires a snapshot version of Projectile.
(projectile-run-shell))

(def-projectile-commander-method ?c
"Run `compile' in the project."
(projectile-compile-project nil))

The first of those brings up a shell buffer in the project root and the second runs M-x compile. Both are super duper convenient for quickly running builds or custom commands, and which one you use is entirely up to situational preference.

(def-projectile-commander-method ?\C-?
"Go back to project selection."
(projectile-switch-project))

The s key would normally be bound to project-switching. Since we’ve changed that above, it’s useful to make Backspace take that role. This makes sense to me. It’s like I’m “backing out” of the commander menu.

(def-projectile-commander-method ?d
"Open project root in dired."
(projectile-dired))

By default d would be bound to projectile-find-dir, but that’s something I never use. projectile-dired takes you to the root directory instead, which I find more useful.

(def-projectile-commander-method ?F
"Git fetch."
(magit-status)
(if (fboundp 'magit-fetch-from-upstream)
(call-interactively #'magit-fetch-from-upstream)
(call-interactively #'magit-fetch-current)))

(def-projectile-commander-method ?j
"Jack-in."
(let* ((opts (projectile-current-project-files))
(file (ido-completing-read
"Find file: "
opts
nil nil nil nil
(car (cl-member-if
(lambda (f)
(string-match "core\\.clj\\'" f))
opts)))))
(find-file (expand-file-name
file (projectile-project-root)))
(run-hooks 'projectile-find-file-hook)
(cider-jack-in)))

These two are more situational, but I’ve found I use them a lot. Whenever I sit down to work, there’s a good chance I’m either going to start a REPL (j) or fetch git remotes (F).

And last but not nearly least.

(projectile-global-mode)

Update 14 Apr 2016

Used Projectile’s built-in shell and compile commands.

Tags: project, init.el, emacs

Support on Gratipay
comments powered by Disqus