Emacs: toggle narrowing

Published 2025-05-07

tag(s): #programming #emacs

If you are a relatively new Emacs user, you might have heard of narrowing and think is a niche feature, and I am here to tell you: it is awesome, and you have to try it.[1]
For the non-converts: it is a feature that allows you to see and operate on only a portion of a file at a time. And, fair warning: the rest of this post will use Emacs lingo willy-nilly.

Some commands will act on the active region. If you want to replace text in a function, you would select it with C-M-h mark-defun and invoke M-% query-replace.
But if a command you want to use always acts in the entire buffer, then narrowing is the mechanism to limit its effects. No need to write a new variation, narrow and use it as-is.

Outside of commands, it is a great way to...well, narrow...your focus. You are editing a 8403982498 lines Python module, and working in a particular function. Activate the region in that portion, C-x n n, and scrolling up and down will not take you further than your are of interest. Seems like a minor thing, but it helps a lot.[2]

Enough intro! What about the "toggle" thing?

OK OK!
But first, context! =P

I am working on a 8403982498 lines Python module, my focus is on a particular class, and creating a new variant of it. So I have one (indirect) buffer narrowed to my new code, and another buffer narrowed to the original class.
The catch is that the original class references code outside the class itself. And I searched (and maybe after I share this, someone will point me to it) a built-in way to undoing and re-doing the narrowing quickly, and didn't find it. Usually I would just re-mark the region and C-x n n, but this class is (not) formatted in a way that marking the region is easy - indentation is off, and the code itself is large-ish.
So I wrote this command:


  (defvar-local hoagie-narrow-toggle-markers nil
  "A cons cell (beginning . end) that is updated when using `hoagie-narrow-toggle'.")

  (defun hoagie-narrow-toggle ()
    "Toggle widening/narrowing of the current buffer.
If the buffer is narrowed, store the boundaries in
`hoagie-narrow-toggle-markers' and widen.
If the buffer is widened, then narrow to region if
`hoagie-narrow-toggle-markers' is non nil (and then discard those
markers, resetting the state)."
    (interactive)
    (if (buffer-narrowed-p)
        (progn
          (setf hoagie-narrow-toggle-markers (cons (point-min)
                                                   (point-max)))
          (widen))
      ;; check for toggle markers
      (if (not hoagie-narrow-toggle-markers)
          (message "No narrow toggle markers.")
        ;; do the thing
        (narrow-to-region (car hoagie-narrow-toggle-markers)
                          (cdr hoagie-narrow-toggle-markers))
        (setf hoagie-narrow-toggle-markers nil))))
    

Since I assume people who made it this far in the post are Emacsers, I won't break down the code in detail, it is pretty self-explanatory.
I've been using this for the last couple days, example: I am reading the original code, when I need to jump to a definition somewhere else in the file. I use C-x n t, jump to definition, take notes, etc. Then press C-x n t again and I am back to focus only on the relevant class.

Footnotes
  1. More info here in the manual. Or from Emacs, C-h r, then m, and type "narrowing".
  2. For something slightly more advanced, this article offers a command narrow-to-region-indirect, and you can find here my own variation of it.

Share your thoughts (via email)

Back to top

Back to homepage