This is the second post in my Emacs From Scratch series.
In Part 1, we’ve set up the UI and evil mode. Today we’ll set up a way to manage projects, quickly find files, set up custom keybindings, interact with Git and open a terminal inside Emacs.
Table of Contents
- Project manager
- Custom keybindings
- Fuzzy finding
- Git integration
- Small tweaks
Vim is usually terminal-first; you navigate to a directory and open Vim. Emacs is the other way around; you start Emacs, open a project and maybe a terminal buffer (see Terminal further down).
Let’s set up Projectile to manage our projects and quickly find files.
You can now run
Opt-x on macOS) and type
projectile-add-known-project to add a project as well as
projectile-switch-project to open a project.
This is neither fast, nor discoverable. Let’s set up some custom keybindings.
Before we define our own keybindings, we need to do something to improve discoverability. which-key will show available commands as you start a keybinding sequence:
We’ll use general.el because it makes
it super easy to define keybindings and allows us to define them in a
SPC as our leader key, which allows us to press
SPC and have all our custom keybindings show up.
:which-key to add a description that will show up next to the
To add custom keybindings to Projectile, we need to edit the
definition and move it after the
use-package general function:
Now we can press
SPC and get suggestions that we can navigate along.
SPC SPC lets you open a file in the current project (or a project if none is open),
SPC b opens buffer options,
SPC p project options, etc.
This is what it looks like:
But when you try to find a file, or add a project, you’ll notice that this is clunky as you need to type the exact path for it to work. Let’s fix that.
We’ll be using ivy as our generic completion frontend. This will make choosing files and projects a lot more ergonomic:
Now we get a list of possible entries and live-search.
To manage source control, we’ll use Magit, which is–rightfully–widely considered to be the best Git client ever:
To make Magit work nicely with Evil, let’s add evil-collection:
In addition we need to add this to the
:init block of
use-package evil to
prevent evil and evil-collection interfering:
SPC g g will open up the current Git status.
You can stage single files with
s, all files with
S and commit by pressing
Finally, we want to highlight uncommited changes in the gutter:
Even though we’ll try to make everything work from inside Emacs, sometimes it’s just quicker and easier to have a shell.
We’ll use vterm as a terminal emulator we can use inside emacs.
We’ll also install vterm-toggle, a package that allows us to toggle between the active buffer and a vterm buffer:
SPC ' will open a terminal. Pressing it again will hide it, but keep any processes running.
As every time, we’ll do a few small tweaks:
Ctrl-u work like in Vim
Add the following to the
:init block of
We want similar behaviour to commentary.vim and comment objects in/out with
Optimizing the garbage collector
We’ll use GCMH, “the Garbage Collector Magic Hack”, to minimize GC interference with user activity:
Move this up to be the first package loaded after configuring
use-package, to improve start-up time.
Don’t use ESC as a modifier
If you want to exit a menu,
<escape> is the key of choice, esp. coming from Vim. Let’s match that behaviour:
We now have everything we need to manage projects, navigate to files, run terminal commands and manage Git. Starting with this post, I’m using this very setup to edit this series.
In part 3, we’ll set up Tree-sitter and, if available, LSP for Rust, Go, TypeScript and Markdown.