You can read about my other Emacs configurations .
I recently bought Mastering Emacs (I’ll share my thoughts in a future post) and it is provided in both EPUB and PDF format.
Naturally I wanted to use Emacs to read the book, because:
I didn’t want to open yet-another tool (Calibre I love you, but your ebook reader is sloooow and clunky)
I wanted to be able to try things as I was reading them
…you can safely evaluate elisp from an info buffer; a web browser session; or indeed anywhere else.
I wanted to be able to reference interesting things, bookmark them and add them to my notes or Zettelkasten
There’s a section in Mastering Emacs that mentions how to read EPUBs in Emacs, but here is how I set it up.
It’s in three steps:
- Add ability to have a column of text in the centre of my window - this isn’t something required for reading books, it’s something I’ve wanted for a while.
- Make the centre column width adaptive to my window size
- Configure Emacs to open EPUBs
visual-fill-column
I like the option of distraction free reading and writing. That means sometimes,
I want to have my text centred on my screen, but, also not taking up the full
width (especially on a wide-screen monitor). I guess I could resize my window
(frame
in Emacs parlance), but the computer should do the work for me.
So I use visual-fill-column
:
The primary purpose of visual-fill-column-mode is to wrap text at fill-column in buffers that use visual-line-mode.
Centering the text - Another use case for visual-fill-column is to centre the
text in a window. This effect is achieved by setting the user option
visual-fill-column-center-text
. Note that visual-fill-column-mode is not
dependent on visual-line-mode
, so it can be used to centre text in buffers that
use auto-fill-mode
or in programming modes.
I simply added this to my setup:
(use-package visual-fill-column)
Adaptive centre column width
I didn’t just want to have my centre column being defined by fill-column
(the column beyond which automatic line-wrapping should happen), I wanted it
to be adaptive. I want a comfortable centre column, wider for wide screens, but
not too wide. How’s that for a hand-waving definition?
So I came up with my-centre-width
- it calculates what the fill-column
size
should be for “comfortable” centring.
For small windows (window-width
<= 1.1 * fill-column
) we simply return 90%
of the fill-column
; for larger windows we get the maximum of either half the
current window-width
or the fill-column
. The max is there for something like
fill-column
being 100, and window-width
being 120 - in that case the result
would be 100 (fill-column
), rather than 60
(half window-width
).
(defun my-centre-width ()
"Return a fill column that makes centring pleasant regardless of screen size"
(let ((window-width (window-width)))
(floor (if (<= window-width (* 1.1 fill-column))
(* 0.9 window-width)
(max (/ window-width 2) fill-column)))))
As an aside: Don’t you just love that name spaces
in (Common/Emacs) Lisp allow the function window-width
to co-exist with the
variable window-width
!
nov.el
nov.el provides a major mode for reading EPUB documents.
Following the README I’ve come up with the following variation…
(use-package nov
:init (defun my-nov-font-setup ()
(face-remap-add-relative 'variable-pitch :family "Liberation Serif"
:height 1.3)
(setq fill-column (my-centre-width)
nov-text-width (- fill-column 2)
visual-fill-column-center-text t))
:hook ((nov-mode . my-nov-font-setup)
(nov-mode . visual-line-mode)
(nov-mode . visual-fill-column-mode)))
(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
What I’ve done here is specified that I want the Liberation
font. I’m setting
the fill column to be my “comfortable” width (for visual-fill-column
mode)
and setting nov-text-width
to be slightly smaller so that nov
mode renders
the text correctly in the centre of the screen.
If you don’t have the Liberation
font installed (like I didn’t) and you use
Homebrew as your package manager, it’s as simple as
brew install homebrew/cask-fonts/font-liberation
…and then
Reading EPUBs is as simple as opening the file!