Useful Emacs commands for reading

The earliest, yet perhaps most useful functions I've written

📅 4 Oct 2024 | ~3 min read
Tags: #emacs

Since I started using Emacs, I’ve written hundreds of functions that I only used once and then were left to rot in the depths of my init.el.

Today I would like to share some simple commands that I wrote when I was just starting off with Emacs that I had forgotten that I had written and assumed that this was the default behaviour as it now seems to natural to me. A very small amount of the code here will be specific to evil-mode, but it shouldn’t be too difficult to adapt it to work without.

Removing visual fluff

I like to have a clean, distraction free reading experiences in major-modes such as elfeed, eww, and nov.

I achieve this by:

  1. Centring the text in a column and increasing padding.
  2. Hiding the mode-line
  3. Hiding the cursor

Centring text

I use olivetti for centring text and have no complaints. It works seamlessly for my needs. In fact, I also enable this in Org-Mode and Markdown-Mode.

(defun my/centre-visual-fill-on ()
  ;; Centre the text in one column
  (visual-line-mode 1)
  (setq olivetti-body-width 100)
  (olivetti-mode 1))

(defun my/centre-visual-fill-off ()
  (visual-line-mode 0)
  (kill-local-variable 'olivetti-body-width)
  (olivetti-mode 0))

Hiding mode-line

I’ve seen lots of people do this one and it is useful when wanting to focus. Unlike the previous commands, this is something that I sometimes toggle so I made an interactive function too.

(defun my/kill-modeline ()
  (setq-local mode-line-format nil))

(defun my/restore-modeline ()
    (kill-local-variable 'mode-line-format))

(defun my/toggle-modeline ()
  (interactive)
  (if (null mode-line-format)
      (my/restore-modeline)
    (my/kill-modeline)))

Hiding the cursor

This is one that I don’t remember seeing anybody else do, but it’s a game changer. When I’m reading, I’m following with my eyes and I don’t care where the cursor is unless I decide that I want to highlight some text. Again, I want to be able to toggle this quickly so I wrote an interactive function too.

(defun my/hide-cursor-evil ()
  (setq-local evil-default-cursor '(ignore))
  (setq-local cursor-type nil))

(defun my/show-cursor-evil ()
  (kill-local-variable 'evil-default-cursor)
  (kill-local-variable 'cursor-type))

(defun my/toggle-cursor ()
  (interactive)
  (if (null cursor-type)
      (my/show-cursor-evil)
    (my/hide-cursor-evil)))

I combine these three ideas into a simple hook that gets ran whenever I open a new buffer in one of my reading modes.

(defun my/reading-mode-hook ()
  (my/centre-visual-fill-on)
  (my/hide-cursor-evil)
  (my/kill-modeline))
Figure 1: Screenshot showing Org Mode on the left and eww with cursor hidden on the right

Figure 1: Screenshot showing Org Mode on the left and eww with cursor hidden on the right

I’ve seen takes on the previous ideas many times while reading other Emacs users' blogs, but I haven’t seen many users describe how they move around buffers that are primarily meant to be read.

Initially I tried using a form of paging, but I found it tedious to have to scan for where I left off before I scrolled down.

Ultimately, I settled on the following logic, which was very simple to implement:

(defun my-view-down ()
  (interactive)
  (if (null cursor-type)
      (scroll-up-line)
    (next-line)))

(defun my-view-up ()
  (interactive)
  (if (null cursor-type)
      (scroll-down-line)
    (previous-line)))

Tying it all together

I could have come up with a minor mode for enabling this in each major mode, but I like how this reminds me of a time when I didn’t spend so long dicking about with functions that I only use once.

Here is a simple example configuration of how I have elfeed set up.

(use-package elfeed
  :hook
  (elfeed-show-mode . my/reading-mode-hook))

(evil-define-key 'normal elfeed-show-mode-map (kbd "j") 'my-view-down)
(evil-define-key 'normal elfeed-show-mode-map (kbd "k") 'my-view-up)

✉️ Respond by Email.