Endless Parentheses

Ramblings on productivity and technical subjects.

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,

comments powered by Disqus