Getting Emac's Projectile to work with monorepos
I've been trying to use Emacs more lately and completely wean myself off VSCode. Projectile is a built-in "project management" (a project in this sense being a codebase) tool which, especially if paired with a language server, enables a lot of really nice functionality like being able to auto-detect your Python venv and navigate the codebase much easier. I had some problems using it for work though. We use a monorepo - which I've come to like after being hesitent about it at first - which has microservices and discreet libraries as subdirectories. Each microservice/library is, for the purposes of Projectile, its own project. The problem was that Projectile was detecting the entire monorepo as a project root, which was less than helpful.
Projectile works by detecting "sentinel files" along the path when you first open a file or directory that is not in an already detected project. Like most Emacs packages, it's written in a literate style that makes it super easy to read through the source. It looks for the sentinel files following a few different routes, all helpfully explained here. My problem was that Projectile was skipping the files that I wanted it to use to mark the project root and instead hitting the marker at the top of the monorepo. The package provides a few ways to fix this and generally customize how projects are detected: use a .dir-locals.el
which defines the project root in each directory of the projects that I want to define, put a .projectile
file at the project roots, or reorder the relative priority of files and how they're used to delineate projects. I opted for the third since it's the easiest by far (since I wanted the changes to apply across lots of different directories). Inserting the snippet below in my init.el fixed all my Projectile problems (I generally work on Python and Elixir stuff, I'll probably need to add a Cargo.toml
in there for Rust in the future):
(custom-set-variables '(projectile-project-root-files-bottom-up '(
"mix.exs" ; Elixir mix file
"pyproject.toml" ; Pyproject file
".git" ; Git VCS root dir
)))
Shoot me an email if you think there's a better way to do this!