2026-09-21 forward-paragraph in Magit

As I’ve mentioned many times, I am a heavy Magit user. Pretty often I do code reviews from within Magit. There was one thing that has bothered me for a long time.

While I know that Emacs has good support for moving by code units (like forward-sexp and backward-sexp), I am a lazy person and I often use just C-<down> and C-<up> (forward-paragraph and backward-paragraph). Functions I write (or read) are always separated by at least one empty line (and I consider it a bug when they aren’t), and long functions have parts separated by empty lines, too, so this is surprisingly useful. However, it doesn’t work in Magit when I look at diffs, for an obvious reason: most lines in the diff begin with a + or - and so they are considered one giant paragraph.

At first I thought that I could define my own versions of forward-paragraph and backward-paragraph, just for the Magit buffers which can show diffs. But then it occurred to me that I don’t have to – the only thing I have to do is to set the variables paragraph-start and paragraph-separate to suitable values. It’s still not that simple, though. For starters, the default value of paragraph-separate is huge and complicated regex I’d prefer not to analyze. That is easy, though – I can just say

(setq-local paragraph-separate (format "[+-]?\\(?:%s\\)" paragraph-separate))
(setq-local paragraph-start (format "[+-]?\\(?:%s\\)" paragraph-start))

The second problem I had to solve is that I need to so that only in the Magit buffers which can show a diff. Since I use use-package, this is easy:

(defun mbork-set-up-diff-aware-paragraphs ()
  "Make paragraph-moving commands work in a diff."
  (setq-local paragraph-separate (format "[+-]?\\(?:%s\\)" paragraph-separate))
  (setq-local paragraph-start (format "[+-]?\\(?:%s\\)" paragraph-start)))

(use-package magit
  ;; ...
  :hook (magit-mode . mbork-set-up-diff-aware-paragraphs))

And that’s pretty much it! It’s still not ideal – for example, it jumps over @@ lines which start hunks – but things like that are either easy to solve or not worth solving. And from now on, Magit is even more useful to me!

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryGit