Walls of Text
2025-04-13
1. Introduction
For a brief spell at work I had one of my monitors turned in portrait orientation, since it was reputed to make reading long web pages, documents, etc. much nicer. After all, a longer column of text would mean less scrolling, quicker scanning, and so on, right? Well, that was all very true, but I didn't really care for it. For one, there are plenty of other things that occupy my displays, and most of those work better in the normal landscape orientation. For another, our eyes are much happier darting from side to side than up and down.
Eons ago, I established a Friday morning ritual of getting breakfast on the way to work. For a number of years, the places I would stop had newspaper machines out front, and some number of quarters would get me the morning news in a form that could soak up spills as easily as it could ink my fingertips. If you ever look at a broadsheet paper, especially inside, you'll notice that no space is wasted: Text is small-ish, margins are tight, and everything is laid out in columns. That last bit is important, as it allows more information to be packed onto a page without compromising readability, making the paper more useful to its readers and less expensive to produce. What if that space efficiency could be brought to the glowing screen?
2. Examples
As a concrete example, consider the following screenshot of RFC 732 shown in Emacs as one usually would:
See how much space is wasted? Now take a look at the same file in a columnar display:
With just one weird trick, I can pack three times as much of this file onto the
screen without sacrificing legibility, making for a vastly more efficient
experience whether I'm reading intently or scanning for a few items of
interest. Here's a more extreme example, the Wikipedia article for newsprint,
shown in a single column in eww
:
Now here in eight columns is the article's entire body:
3. Implementation
The basic idea is that, once we partition an Emacs frame into an appropriate
number of windows, each representing one column, and show the same buffer in
all of them, we can use follow-mode
to do the work of maintaining the effect
of a unified columnar display. The basic mechanism is
(defvar *wall-num-columns* 3) (make-variable-buffer-local '*wall-num-columns*) (defun wall (buffer &optional num-columns) (interactive "bbuffer:") (delete-other-windows) (follow-mode 0) (setf *wall-num-columns* (or num-columns *wall-num-columns*)) (dotimes (i (1- *wall-num-columns*)) (split-window-right) (balance-windows) (other-window 1) (switch-to-buffer buffer)) (other-window 1) (balance-windows) (wall-minor-mode))
After working with this for a bit, I realized that Emacs's default settings for paging were not to my liking; with the following in effect, each Page-Up or Page-Down results a more predictable movement of one full column:
(setf scroll-preserve-screen-position t) (setf next-screen-context-lines 0)
Sometimes it's handy to move by entire screens-worth of text:
(defun wall-next-screen () (interactive) (dotimes (i (length (follow-all-followers))) (scroll-up-command))) (defun wall-prev-screen () (interactive) (dotimes (i (length (follow-all-followers))) (scroll-down-command)))
And sometimes, it's worth changing the number of columns. The use of
follow-all-followers
accounts for those times when not every window in the
frame is part of the text wall.
(defun wall-add-column () (interactive) (wall (current-buffer) (1+ (length (follow-all-followers))))) (defun wall-remove-column () (interactive) (wall (current-buffer) (max 1 (1- (length (follow-all-followers)))))) (defun wall-reset () (interactive) (wall (current-buffer) 3))
Now, to tie everything together as a minor mode. I have found that the volume wheel on my keyboard makes a nice control for whenever I want to increase or decrease other things in an ad hoc way.
(define-minor-mode wall-minor-mode "Turn any buffer into a wall of text." :lighter "wall" :keymap (list (cons (kbd "M-<XF86AudioLowerVolume>") 'wall-remove-column) (cons (kbd "M-<XF86AudioRaiseVolume>") 'wall-add-column) (cons (kbd "C-<next>") 'wall-next-screen) (cons (kbd "C-<prior>") 'wall-prev-screen)) (follow-mode 'toggle)) ;; This lets me wallify any buffer at a moment's notice. (global-set-key (kbd "<M-XF86AudioMute>") 'wall-reset)
4. Wrapping Up
This is hardly the UI tweak to end them all, but it's worked well for me over
the past couple years. I've found it particularly effective combined with
eww
, Emacs's built-in browser, for the bulk of websites that I happen to
frequent.