Tuning Emacs to Write Prose in Org and Markdown
14 Aug 2023 Charles Choi
While default (aka vanilla or un-configured) Emacs is serviceable in editing Org and Markdown files, its out-of-the-box experience feels more like I’m programming said files rather than writing them. Thankfully, Emacs has excellent features (both built-in and external packages) to help you focus on writing prose. In this post I'll go over such features. As always, these recommendations are subjective, but I don’t think they fall too far from conventional thinking on the matter.
As to the features that I think help write prose:
- The use of proportional typefaces
- Hiding markup
- Automatic spell checking
- Dictionary lookup of a selected word
- Styling of selected text
- Toggling of hidden markup
- Dynamic completion of a previously written word
- Turn-on word-wrapping
- Navigation and moving of text
- Deleting whitespace
- Word count
Of course all of the above can be keyboard-driven (this is Emacs) but I like the affordance that menus can provide for text operations, particularly for selected text. Nothing wrong with having both.
Before moving forward, I’d also clarify that I’m not defining an explicit Emacs mode for distraction-free interactions as there are other modes which offer this. This post is really about configuration. That all said, let’s configure Emacs!
This post presumes you understand enough of the following:
- How Emacs is initialized
- How to use the menu-driven Customize Emacs feature
- How to install packages
- How to customize an Emacs face
- How Emacs modes and mode hooks work
- Enough Elisp to be dangerous (or at least just copy and paste)
All the configurations in this post have been tested with Emacs 28.2.
Use Proportional Typefaces
For prose, a well-chosen proportional typeface is vastly more readable than a fixed-width one. You can turn-on rendering a proportional typeface in an Emacs buffer by enabling
variable-pitch-mode, typically by adding it via a mode hook in the init file. An Elisp example that does this for both Org and Markdown modes is shown below:
variable-pitch-mode is turned-on, the typeface used to render overlay-free text in the buffer is defined in the Elisp variable
variable-pitch to taste. A menu-driven workflow for configuring any face is conveniently done via the menu-bar flow Options → Customize Emacs → Specific Face… which will prompt you for the face to customize.
Another setting to improve readability is to increase the line spacing via the Elisp variable
line-spacing. As both the Org and Markdown major modes inherit from the Text major mode, we can add a hook to set
line-spacing for both to
text-mode-hook in the init file.
More granular approaches to adjusting line height can be achieved by configuring the height of a face.
Using a different typeface helps to distinguish headers from body text. For Markdown, that face variable is named
markdown-header-face. For Org, there is a set of faces all corresponding to the header level,
N is a value between 1 and 8 inclusive.
While the reader can always choose their own typefaces, size, and spacing, my personal preference is to use the following settings:
||Optima||1.4||height is a scaling value based of default height|
This link shows my implementation of the above settings using
customize-face. Note that the above typefaces are pre-installed on macOS and may not be available for other platforms.
For reference, much of my guidance on typographic configuration is taken from zzamboni.org | Beautifying Org Mode in Emacs. Highly recommended for readers who want to delve further into this.
Both Org and Markdown modes provide variables which support hiding markup delimiters. This makes for a more distraction-free experience.
For Org mode, setting the variable
t will hide the markup around styled text. I also like setting the variable
t so that headers are not so noisy.
For Markdown mode, invoking the function
markdown-toggle-markup-hiding as part of the initialization Markdown hook will achieve the same.
Don't fret about getting back your hidden text. Later in this post we will show how to easily reveal hidden markup.
While spell checking support has long existed in Emacs, automatically checking text as you type is not turned on by default. Using the flyspell and company modes can remedy this, the first to automatically spell check a buffer and the latter to provide candidate replacements for a misspelled word. Enabling this in the init file via the
text-mode-hook turns this on for both
company mode? There are plenty of other completion packages to choose from.
Dictionary Lookup of a Selected Word
Mickey Peterson has an informative post on using the dictionary lookup feature in Emacs 28. However, since macOS is my daily driver, I actually prefer to use the native macOS dictionary via the osx-dictionary package. Regardless of what package you use, having immediate access to a dictionary while writing is extraordinarily useful. While both the native dictionary lookup and
ox-dictionary are built to support keyboard-driven user interfaces, they can also be mouse-driven as well. Detailed below is how I’ve implemented a common GUI UX workflow where invoking a context-menu on a selected word will offer the option to look up that word’s definition.
First off, turn on
context-menu-mode in your init file. Here I’ve turned it on via the
Next up is defining your custom context menu. I’ve written an earlier post on customizing the context menu which I highly recommend reading if you are new to context menus. Adding a menu item to invoke the function
osx-dictionary-search-word-at-point from the
osx-dictionary package is shown in the code fragment below:
1 2 3 4 5 6
To support context sensitivity, the predicate function
use-region-p is used to determine if text is selected; if not then this menu item is not added to the context menu. Note that another custom function
cc/context-menu-last-word-in-region is used to dynamically populate the menu item label with the last word in the selected region.
1 2 3 4 5 6 7
Menu-Driven Styling of Selected Text
Another common GUI UX workflow is to select text and style it (for example bold, italic, code, underline). To implement this behavior in Emacs, I defined a custom keymap
cc/emphasize-menu whose source is shown below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Note the use of predicates for the
:enable properties to support context-sensitive behavior. In the source code above, the functions that actually style the selected text each do the following: 1) test for the current major mode (in this case either Markdown or Org), and 2) invokes the mode-specific function to style the text. For example, to “bold” a text, the following function
cc/emphasize-bold is called:
1 2 3 4 5 6 7
Definitions for all the style (emphasize) functions are at this link.
Menu-Driven Toggling of Hiding Markup (aka “Reveal Codes”)
For those users familiar with WordPerfect, it had a feature called Reveal Codes which enabled the user to explicitly see the codes used to format a document. This same behavior can be emulated for Org and Markdown buffers, via the
markdown-toggle-markup-hiding functions, respectively.
The following code fragment from
cc/context-menu-addons shows how
visible-mode is invoked for Org mode.
1 2 3 4
The following code fragment from
cc/context-menu-addons shows how
markdown-toggle-markup-hiding is invoked for Markdown mode.
1 2 3 4
Context-sensitivity of how the above menu items are displayed is handled by the control flow of
cc/context-menu-addons, which tests for current major mode.
Dynamic Completion of a Previously Written Word
Ever have to type a word in a document that you were going to use multiple times? The function dabbrev-expand (keyboard shortcut
M-/) is your friend. There’s nothing to turn on, you get this behavior for free. Coupled with
company-mode and you will wonder how you lived without it.
Turn-on Word Wrapping
While this is very much a personal preference, over the years I’ve found that treating a text file newline as a paragraph delimiter to be the least-surprising convention to use. With that, turning-on word-wrapping is done via visual-line-mode. I turn this on for all text mode buffers via the
Source link for the above code in my init file.
Navigation and Moving of Text
Mastering both navigation and moving text in Emacs can go a long way towards helping you write better prose as you can focus more on expressing your thoughts instead of just typing.
If you’re going to spend a considerable time with either Markdown or Org, I strongly recommend that you learn the heading/block navigation commands provided by the Org and Markdown major modes. In addition, if you haven’t tried Avy yet, stop here and go make it a part of your life. Emacs Elements provides a video demo of Avy at work, and Irreal posts here on how they use it.
My previous post Moving Text Elegantly in Emacs described how to move around a text object such as a word, sentence, or balanced expression (sexp) forward or backwards, among other operations involving the transpose family of functions.
A fairly recent post on sorting text in Emacs by Susam Pal shows how you can make short work of sorting lines. Highly recommended.
Also useful when reviewing text is to delete whitespace, either vertically in the form of blank lines or horizontally in the form of multiple spaces. Emacs provides a number of functions to address these concerns. While those functions can always be invoked via keyboard, I find it convenient to be access them via menu as well. Shown below is a custom keymap
cc/delete-space-menu invoking some functions that I find useful in this regard.
1 2 3 4 5 6 7 8 9 10 11 12
A common metric is the count of words in a document. The function
count-words can determine this, which can be called from a context menu with the code fragment below:
1 2 3 4 5 6 7 8 9
This post suggests a number of configurations to tune Emacs for writing prose, with an emphasis on support for menu-driven operations. Hope that you find them useful!
A lot of this post was sourced from other posts over the years. For further reading, I encourage you follow the links below.
- zzamboni.org | Beautifying Org Mode in Emacs
- Overlay Properties (GNU Emacs Lisp Reference Manual)
- Line Height (GNU Emacs Lisp Reference Manual)
- Wordsmithing in Emacs - Mastering Emacs
- Dynamic Abbrevs (GNU Emacs Manual)
- Visual Line Mode (GNU Emacs Manual)
- Sorting in Emacs - Susam Pal