2016-06-13 Displaying pdfs on the right

Some time ago I decided that I’ll give PDF tools a shot.

Wow. Just wow. Never going back to Evince. (Well, almost never – Evince does have one or two options not present in PDF Tools, but I hardly ever use them). If you are an Emacs user on GNU+Linux, I strongly advice you to try PDF Tools out. Especially if you do a lot of LaTeX work in AUCTeX (like I do) and/or if you need to read or create PDF annotations (highlighting and/or notes) – it’s really great. (I did once experience some problems with said annotations, though.) I was a bit afraid about the efficiency – but man, it’s really fast! A great piece of work indeed.

I have a few problems with it, though. The biggest one is that C-M-v (scroll-other-window) won’t switch to next page of the pdf. (Emacs’ doc-view has the same problem, and it seems that it’s not trivial to change, at least not without advice). Another one is that sometimes, when I zoom in a bit and do something, my carefully found place in the pdf is gone, and some other place is shown. But none of these is a deal-breaker.

One thing I found really annoying (though it’s not related to PDF Tools – again, doc-view has the same problem): when I pressed C-c C-v (TeX-view), the pdf was shown in a window below the current one. Since most of my documents are in “portrait” mode, this doesn’t make sense at all – I’d very much prefer if the window with the pdf was shown to the right of the current one.

OTOH, I would not want everything to pop up to the right. I use a laptop with a 14” screen, which is just a tad too small for that to be comfortable. (And I’m totally not accustomed to such a behavior.)

Of course, the solution is known already: display-buffer-alist. However, while we’re at it, there is one more thing to take care of: I don’t want the window containing the pdf to be half the screen wide. It doesn’t really make sense, either. The aspect ratio of my screen is 16:9, which means that a horizontal split divides the main window into two almost square halves. OTOH, I use almost exclusively the A4 paper size, whose aspect ratio is √2:1. (Those strange Americans who use those strange paper sizes might want to adjust for that, although even they are not strange enough to use square paper for most of their documents.) This means that by dividing the window in the middle, I waste a lot of screen real estate.

It turns out that making Emacs split windows in the desired proportion is not a trivial task (see here and here for some pointers). In this case, however, it’s not a big problem: I can find out the correct value of the argument for split-window-right by trial and error, and this is exactly what I did.

All in all, let the code speak for itself. It is not very elegant in that I just copy-pasted the split-window-sensibly function and made the changes I needed, but I don’t see how I could achieve my goal in a more elegant way with, say, advice, so who cares. If you want different settings, just play around with the two variables introduced below.

Finally, notice that my previous version of the regex for buffers displayed on the right, which was just "\\.pdf$", does not work if there are two pdfs with the same name, but different directories displayed at the same time, since by default Emacs appends a string of the form <directory> to the end of the buffer name then. Pretty rare, I’d argue, but it actually happened to me, and it was not obvious at first what was going on!

(defvar pdf-minimal-width 72
  "Minimal width of a window displaying a pdf.
If an integer, number of columns.  If a float, fraction of the
original window.")

(defvar pdf-split-width-threshold 120
  "Minimum width a window should have to split it horizontally
for displaying a pdf in the right.")

(defun pdf-split-window-sensibly (&optional window)
  "A version of `split-window-sensibly' for pdfs.
It prefers splitting horizontally, and takes `pdf-minimal-width'
into account."
  (let ((window (or window (selected-window)))
	(width (- (if (integerp pdf-minimal-width)
		      pdf-minimal-width
		    (round (* pdf-minimal-width (window-width window)))))))
    (or (and (window-splittable-p window t)
	     ;; Split window horizontally.
	     (with-selected-window window
	       (split-window-right width)))
	(and (window-splittable-p window)
	     ;; Split window vertically.
	     (with-selected-window window
	       (split-window-below)))
	(and (eq window (frame-root-window (window-frame window)))
	     (not (window-minibuffer-p window))
	     ;; If WINDOW is the only window on its frame and is not the
	     ;; minibuffer window, try to split it vertically disregarding
	     ;; the value of `split-height-threshold'.
	     (let ((split-height-threshold 0))
	       (when (window-splittable-p window)
		 (with-selected-window window
		   (split-window-below))))))))

(defun display-buffer-pop-up-window-pdf-split-horizontally (buffer alist)
  "Call `display-buffer-pop-up-window', using `pdf-split-window-sensibly'
when needed."
  (let ((split-height-threshold nil)
	(split-width-threshold pdf-split-width-threshold)
	(split-window-preferred-function #'pdf-split-window-sensibly))
    (display-buffer-pop-up-window buffer alist)))

(add-to-list 'display-buffer-alist '("\\.pdf\\(<[^>]+>\\)?$" . (display-buffer-pop-up-window-pdf-split-horizontally)))

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryTeX