π

My Emacs Configuration In Org-mode

Show Sidebar

Update 2017-06-06: added example output of Messages

Over the last weeks, I invested much effort in documenting and re-organizing my Emacs configuration files.

This article describes my previous organiziation methods and the current one, based on well described Elisp code within Org-mode. This ensures optimal navigation through my 8250 lines of configuration, good usability for interested peers like you, and provides better maintainability for myself.

If you're not interested in the previous organization methods, skip the next headings and go to «Current Approach: Elisp in Org-mode».

In case you're interested in my personal Emacs history, you might also be interested in reading more about it.

My First Approach: Chaos

When I first started to use Emacs in the nineties, I had no clue about Elisp nor a deeper understanding of Emacs. My configuration file consisted of many copied snippets from the web and mostly from Usenet.

This caused some pain. I could not deal with weird effects because I had no clue when a new snippet would contradict or clash with previous snippets.

This was no satisfying situation. However, somehow it worked for me: composing Usenet postings, emails, writing LaTeX documents.

OH: I now officially work with people younger than my .emacs file

— Phil Calçado (@pcalcado) June 5, 2017

The only «clever» thing I did was to unify my Emacs configurations for the multiple hosts I was using. I did this with minimal init_<hostname>.el files that called the common main.el file that held all of my Elisp configuration. On each host, I created a symbolic link from the corresponding init_<hostname>.el to init.el. This way, I could use host-specific options while maintaining my general configuration within main.el.

Second Approach: Starting to Understand Elisp and OrgStruct Mode

As my main.el grew to be more than just a few dozens or hundred lines of Elisp, I faced some issues finding specific parts of my configuration. A big non-structured linear list of Elisp setq and defun has no good usability especially when you're not that familiar with (or interested in) Elisp coding and its related helper functions for navigation or jumping to definitions and such.

Therefore, I migrated the comments within my Elisp files to orgstruct mode format.

The only thing (besides installing and activating Orgstruct mode itself) was to follow following comment format:

 ;; -*- orgstruct-heading-prefix-regexp: ";;" -*-
 ;;* General settings

 (setq calendar-week-start-day 1)
 (setq backup-inhibited t)
 […]

 ;;* Themes

 (load-theme 'wombat t)
 […]

 ;;* Org-mode
 […]
 ;;** Agenda
 […]
 ;;*** Agenda files
 […]	  

The first line defines the Orgstruct prefix, in my case: ;;. So when the cursor is on a line starting with two semicolons, I could use some Org-mode features such as expand/collapse via TAB or C-u C-u TAB which was basically the only feature I used within Orgstruct.

This helped a lot over many years.

See my last main.el with this format before I switched to the next organization method here.

Publishing My Emacs Configuration

With publishing my Emacs configuration on GitHub, I wanted to give interested peers the ability to get ideas or follow my configuration changes.

Not that my configuration is that popular - quite the contrary. But this was not the point. Maintaining a public, well documented configuration has some benefits for me as well. For example I can easily link to certain settings within mailinglist emails and I get better maintainability for me as well.

Current Approach: Elisp in Org-mode

As my configuration grew to over 8000 lines, I got unsatisfied with the current situation. I wrote more and more comments (for myself) in Elisp comments, making those comments more and more important in contrast to the Elisp code.

Maintaining Elisp comments is no fun for me. When I added some words within a paragraph, I have to re-align the comment lines in an awkward way. There might be some clever Elisp functions to do this in a sane way.

I chose a different approach: managing my Elisp configuration within an Org-mode file.

I read about it many times but I did not see the advantage until maintaining the Elisp comments got more important for me than the Elisp code.

Holger Schurig published a neat way of managing his Emacs configuration. His init.el has some functions that look for a config.org file and an Elisp file named config.el that holds the tangled Elisp blocks of the first one. In case the config.org file is newer than the config.el file, the Elisp blocks of config.org gets tangled to the config.el file which was evaluated afterwards.

Headings can be ignored by this process with the keyword DISABLED and blocks can be ignored with the usual :tangle no parameter.

As you might know me, I always find some things I would have done differently and so I ignored my unwillingness to code Elisp and came up with my own version of my-tangle-config-org() which you can find in my current init.el file: I added some nice display output (one per heading) and a bit of meta-information.

Holger also provided a very nice hook function which exports the Elisp code whenever the Org-mode file is saved.

My current config.org file can be viewed here.

This time, I also replaced the host-specific init.el files I mentioned above with a different method for host-specific settings which simplified my configuration setup a lot.

The basic format of config.org using this method is like this:

 # -*- mode: org; coding: utf-8; -*-
 # Time-stamp: <2017-06-03 09:58:51 vk>
 #+TODO: ACTIVE | DISABLED
 #+STARTUP: indent

 This is the GNU/Emacs config file of Karl Voit.

 In my geographic area, the week does start with Monday (1) and not
 Sunday (0; default):

 #+BEGIN_SRC emacs-lisp
 (setq calendar-week-start-day 1)
 #+END_SRC

 Personally, I don't like the backup files Emacs is creating. This one
 disables them:

 #+BEGIN_SRC emacs-lisp
 (setq backup-inhibited t)
 #+END_SRC

 * General settings

 #+BEGIN_SRC emacs-lisp
 […]
 #+END_SRC

 * Themes

 I do prefer a dark theme. Wombat did turn out pretty well for me:

 #+BEGIN_SRC emacs-lisp
 (load-theme 'wombat t)
 #+END_SRC

 […]

 * Org-mode
 […]
 ** Agenda
 […]
 *** Agenda files
 […]	  

As you can see, navigation is no big deal since I am perfectly well trained with the Org-mode methods of expand/collapse or sparse trees and whatnot.

I am able to add comments really easy and with a decent yasnippet command for Elisp code blocks, I can quickly add Elisp blocks.

Example Output of Messages Buffer

Here is a reduced sample output of my Messages buffer when starting my Emacs on Windows:

 Loading c:/Users/karl.voit/AppData/Roaming/.emacs.d/config.el (source)...
 config • General settings …
 config • Server mode …
 config • Package …
 config • my-load-local-el() …
 config • my-system-is-FOOBAR …
 config • System-specific paths …
 config • my-binary-found(binaryname) …
 config • my-binary-not-found-list and my-eval-if-binary-or-warn() …
 config • System-specific browse-url-browser …
 »»» I could not locate the PATH-binary for: google-chrome
 config • Styling …
 config • LaTeX …
 »»» I could not locate the PATH-binary for: synctex
 config • GnuPlot …
 »»» I could not locate the PATH-binary for: gnuplot
 config • Org-mode …
 ★→ Org-mode
 config • Load Org and misc contrib packages …
 config • Org-mode docu → my-map o …
 config • debug message: config orgmode finished. …
 →★ orgmode finished in 1.58s
 config • MiniMap …
 config • custom variables …
 config • Closing and end for profiling …
 »»» Binaries not found in checks above: (sass gnuplot synctex google-chrome ditaa chrome ipython)
 →★ finished loading config.org in 11.96s
 Loading c:/Users/karl.voit/AppData/Roaming/.emacs.d/config.el (source)...done
 →★ loading init.el in 12.07s	  

As you can see, I get notified on missing tools such as "google-chrome", "synctex" and so forth. At the end, I get a summary on the binaries that were not found and therefore not configured.

Also handy: the measured times for certain parts of my configuration. Note that the twelve seconds include waiting time for some user prompts (Do you really want to eval following buffer variables?) I can not get rid of so far.

Using my Emacs Configuration

In case you want to check out and use my configuration instead of yours: Don't.

Not because I don't like you to have my configuration. It is not easy to accomplish because I left out some parts. Some of my settings are host-specific and/or depend on path variables, Elisp files I did not add to the GitHub repository, or external tools.

You should only adopt Elisp code you need and understand to avoid Emacs Bankruptcy.

Therefore: please feel free to look up certain tricks and functions and add it to your configuration. But don't use my repository as is and expect it to run on your host.

Comment via email or via Disqus comments below: