Cloning, narrowing, and Emacs
I don't write much Elisp anymore — for the most part I have my Emacs doing what I need, and I'd rather use the standard features that I do not have to maintain myself.
But lately I've started using two standard features more than before:
- Narrowing — the ability to display only part of a buffer. The rest of it's all still there in the file; we just temporarily do not see it in the editor window.
- Cloning — have additional buffers visiting the same file. It differs from just having the same buffer in multiple windows because settings like narrowing are specific to the whole buffer.
So I've found myself doing these steps often: first clone the buffer, then narrow the clone. Then usually I'll display both buffers in adjacent windows, moving back-and-forth, but knowing that a stray keystroke will not send one or the other buffer scrolling off to a weird position.
The one irritation is that the built-in clone-indirect-buffer
modifies the setup of buffers and windows in the frame — and I do not
like it when something messes with my mise en place! So here is a
quick interactive Elisp function for cloning the buffer and narrowing
it to the active region.
(defun clone-and-narrow (region-start region-end) "Clone the current buffer, and narrow the clone to the current (live) region" ;; Provide the start and end of the current region as the two ;; arguments (interactive "r") (cond ;; Make sure there is a well-defined and live region specified by ;; the arguments ((and (use-region-p) region-start region-end) ;; Deactivate the mark (deactivate-mark t) (let ((new-buffer)) ;; Return a new buffer viewing the same file as the current ;; buffer, and use that buffer as current for subsequent ;; operations. (setf new-buffer (clone-indirect-buffer nil nil)) (set-buffer new-buffer) ;; Narrow the buffer to the given region. (narrow-to-region region-start region-end) ;; Display the new clone within the current window. (switch-to-buffer new-buffer))) ;; Show a message if there is no live region, but no beepy drama (t (message "Void region"))))