Maintaining emacs configuration by org-babel
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. :-)