Contents

Maintaining emacs configuration by org-babel

Contents

My .emacs file has more than 2500 lines, making it increasingly difficult to maintain. At the same time, I frequently update my .emacs for two main reasons:

  • There are new modes that I really want to use (Emacs enthusiasts will know what I mean)
  • I need to modify my .emacs configuration to fix bugs caused by the latest Emacs update.

Finally, I have decided to find a smarter way to maintain my .emacs file. My solution is to use org mode with org-babel.

Babel is an org mode extension that allows org to execute source code within an Org document. It is a powerful and helpful tool for writing articles with source code snippets. Org-babel also provides a “tangle” function which links source code blocks in the Org document to external files. This linkage is bi-directional, meaning that updating the source code in a block in the Org document can easily tangle to the external source code files, and updates made to the source code file can also be easily reflected back in the source code block in the Org document it is linked to. Using the tangle function of babel, I can maintain the contents of my .emacs file in Org format and use org-tangle to automatically generate the .emacs file.

For exampale, let's say I have an Org file as given below:

* Load Paths
#+begin_src emacs-lisp :tangle dot_emacs.el :comments link
  ;; Latest Org mode source code
  (add-to-list 'load-path "~/.emacs.d/org-mode/lisp")
  ;; mpvi
  (add-to-list 'load-path "~/.emacs.d/mpvi/")
#+end_src
* General Settings
#+begin_src emacs-lisp :tangle dot_emacs.el :comments link

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; General Settings
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  (setq warning-minimum-level :emergency)

  (set-default-coding-systems 'utf-8)

  ;; preferred apprarence settings
  (size-indication-mode 1)
  (scroll-bar-mode 0)
  (menu-bar-mode 0)
  (display-battery-mode 1)
  (display-time-mode t)
  (display-line-numbers-mode 1)
#+end_src
* Make Emacs beautiful and east to use
** Lin mode
#+begin_src emacs-lisp :tangle dot_emacs.el :comments link

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; lin setting
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  (require 'lin)
  (setq lin-face 'lin-blue) ; check doc string for alternative styles
  ;; You can use this to live update the face:
  ;; (customize-set-variable 'lin-face 'lin-green)
  (setq lin-mode-hooks
        '(bongo-mode-hook
          dired-mode-hook
          elfeed-search-mode-hook
          git-rebase-mode-hook
          ibuffer-mode-hook
          ilist-mode-hook
          ledger-report-mode-hook
          log-view-mode-hook
          magit-log-mode-hook
          mu4e-headers-mode
          notmuch-search-mode-hook
          notmuch-tree-mode-hook
          occur-mode-hook
          org-agenda-mode-hook
          tabulated-list-mode-hook))
  (global-display-line-numbers-mode)
#+end_src
** Pulsar mode
Pulsar mode is .........
#+begin_src emacs-lisp :tangle dot_emacs.el :comments link

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; pulsar: hightlight current line
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  (require 'pulsar)

  (setq pulsar-pulse-functions
        '(recenter-top-bottom
          move-to-window-line-top-bottom
          reposition-window
          forward-page
          backward-page
          scroll-up-command
          scroll-down-command
          org-next-visible-heading
          org-previous-visible-heading
          org-forward-heading-same-level
          org-backward-heading-same-level
          outline-backward-same-level
          outline-forward-same-level
          outline-next-visible-heading
          outline-previous-visible-heading
          outline-up-heading))

  (setq pulsar-pulse-on-window-change t)
  (setq pulsar-pulse t)
  (setq pulsar-delay 0.1)
  (setq pulsar-iterations 10)
  (setq pulsar-face 'pulsar-red)
  (setq pulsar-highlight-face 'pulsar-yellow)

  (pulsar-global-mode 1)

  ;; OR use the local mode for select mode hooks

  (dolist (hook '(org-mode-hook emacs-lisp-mode-hook))
    (add-hook hook #'pulsar-mode))
#+end_src

This Org file has three headings: “Load Paths”, “General Settings”, and “Make Emacs Beautiful and Easy to Use”. I placed all of the load-paths under the “Load Paths” heading, and some general settings under the “General Settings” heading. For modes that modify Emacs’ default interfaces or make Emacs more convenient to use, I placed their configurations under the “Make Emacs Beautiful and Easy to Use” heading. You can certainly add any heading you like, such as a “Coding” heading for modes related to programming. The contents you want to include in .emacs can be well organized using Org.

In the above sample Org file, there is a property in every source code block.

:tangle dot_emacs.el :comments link

This directs org-babel to extract the current source code block and save it to an external file named dot_emacs.el. Since all the source code blocks in the previous Org file are being saved to the same dot_emacs.el file, when Org executes the tangle command, all these source code blocks will be automatically included in the dot_emacs.el file. To tangle the source code, simply

M-x org-babel-tangle

Then, there should be a dot_emacs.el file in the same folder as the Org file. It is something like

;; [[file:test.org::*Load Paths][Load Paths:1]]
;; Latest Org mode source code
(add-to-list 'load-path "~/.emacs.d/org-mode/lisp")
;; mpvi
(add-to-list 'load-path "~/.emacs.d/mpvi/")
;; Load Paths:1 ends here

;; [[file:test.org::*General Settings][General Settings:1]]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; General Settings
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(setq warning-minimum-level :emergency)

(set-default-coding-systems 'utf-8)

;; preferred apprarence settings
(size-indication-mode 1)
(scroll-bar-mode 0)
(menu-bar-mode 0)
(display-battery-mode 1)
(display-time-mode t)
(display-line-numbers-mode 1)
;; General Settings:1 ends here

;; [[file:test.org::*Lin mode][Lin mode:1]]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; lin setting
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'lin)
(setq lin-face 'lin-blue) ; check doc string for alternative styles
;; You can use this to live update the face:
;; (customize-set-variable 'lin-face 'lin-green)
(setq lin-mode-hooks
      '(bongo-mode-hook
        dired-mode-hook
        elfeed-search-mode-hook
        git-rebase-mode-hook
        ibuffer-mode-hook
        ilist-mode-hook
        ledger-report-mode-hook
        log-view-mode-hook
        magit-log-mode-hook
        mu4e-headers-mode
        notmuch-search-mode-hook
        notmuch-tree-mode-hook
        occur-mode-hook
        org-agenda-mode-hook
        tabulated-list-mode-hook))
(global-display-line-numbers-mode)
;; Lin mode:1 ends here

;; [[file:test.org::*Pulsar mode][Pulsar mode:1]]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; pulsar: hightlight current line
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'pulsar)

(setq pulsar-pulse-functions
      '(recenter-top-bottom
        move-to-window-line-top-bottom
        reposition-window
        forward-page
        backward-page
        scroll-up-command
        scroll-down-command
        org-next-visible-heading
        org-previous-visible-heading
        org-forward-heading-same-level
        org-backward-heading-same-level
        outline-backward-same-level
        outline-forward-same-level
        outline-next-visible-heading
        outline-previous-visible-heading
        outline-up-heading))

(setq pulsar-pulse-on-window-change t)
(setq pulsar-pulse t)
(setq pulsar-delay 0.1)
(setq pulsar-iterations 10)
(setq pulsar-face 'pulsar-red)
(setq pulsar-highlight-face 'pulsar-yellow)

(pulsar-global-mode 1)

;; OR use the local mode for select mode hooks

(dolist (hook '(org-mode-hook emacs-lisp-mode-hook))
  (add-hook hook #'pulsar-mode))
;; Pulsar mode:1 ends here

By doing this, maintaining my .emacs becomes really easy. :-)