Useful Emacs commands for reading
The earliest, yet perhaps most useful functions I've written
📅 4 Oct 2024 | ~3 min readTags: #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:
- Centring the text in a column and increasing padding.
- Hiding the mode-line
- 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))
Navigating
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:
- If the cursor is visible, move the cursor up or down one line
- If the cursor is not visible, scroll the buffer up or down one line
(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.