CLOSED: [2017-06-03 Sat 11:23] SCHEDULED: <2017-06-03 Sat> :PROPERTIES: :CREATED: [2017-06-03 Sat 10:00] :ID: 2017-06-03-emacs-org :END: :LOGBOOK: - State "DONE" from "DONE" [2017-06-06 Tue 10:39] - State "DONE" from "NEXT" [2017-06-03 Sat 11:23] :END: Update 2017-06-06: added example output of Messages Over the last weeks, I invested much effort in documenting and re-organizing [[https://github.com/novoid/dot-emacs][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 [[id:2017-06-03-emacs-history][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 [[https://en.wikipedia.org/wiki/Usenet][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. #+CAPTION: Tweet by pcalcado. #+ATTR_HTML: :alt OH: I now officially work with people younger than my .emacs file #+ATTR_HTML: :align center :width 584 [[tsfile:2017-06-05T21.28 Twitter.com - pcalcado - OH I now officially work with people younger than my .emacs file -- software fun screenshots publicvoit.png][https://twitter.com/pcalcado/status/871810979180556292]] 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_.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_.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 [[http://orgmode.org/manual/Orgstruct-mode.html][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 [[https://github.com/novoid/dot-emacs/blob/9e23e945134c367f23850c32319a59b403a4e4b8/main.el][here]]. *** Publishing My Emacs Configuration With publishing [[https://github.com/novoid/dot-emacs][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 [[http://orgmode.org][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. There are still [[https://valignatev.com/posts/emacs-org-config/#things-i-didn-t-like][valid arguments against it]]. [[https://archive.org/search.php?query=http%3A%2F%2Fwww.holgerschurig.de%2Fen%2Femacs-init-tangle%2F][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 [[https://github.com/novoid/dot-emacs/blob/master/init.el][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 [[https://github.com/novoid/dot-emacs/blob/master/config.org][viewed here]]. This time, I also replaced the host-specific =init.el= files I mentioned above with a [[id:2017-02-11-my-system-is-foobar][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 [[http://orgmode.org/manual/Sparse-trees.html][sparse trees]] and whatnot. I am able to add comments really easy and with a decent [[https://github.com/joaotavora/yasnippet][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 [[https://www.emacswiki.org/emacs/DotEmacsBankruptcy][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.