I'll fill out the how and why of this all as I figure out what the hell I'm doing. My current Emacs Configuration is a mess of copy and pasted snippet loosely grouped together. There's a fair number of work around, to transient configuration issues that now no longer exist, and more of stuff cribbed off StackOverflow & held together with string & bubble gum. While not yet calling Configuration Bankrupt's, I am going to try to see if I can restructure this technical debt.
This Emacs configuration is written using the [[https://en.wikipedia.org/wiki/Literate_programming][Literate Programming]] (sort of) paradigm (well sort of) proposed by [[https://en.wikipedia.org/wiki/Donald_Knuth][Donald Knuth]] in 1984, and uses Hlissner's awesome [[https://github.com/doomemacs/doomemacs][Doom Emacs]] configuration framework. While I like Literate Programming, literate configuration can be a mixed bag. Literate Programming produces more prose then code. Discoverability & readability can be drowned out under the prose about the current thoughts, pros & cons, backstory, deciding thoughts, & moral pondering. While this verbosity[fn:4] aids documentation and understanding, its often at the cost of readability. As a compromise I'm going to version both to the verbose =config.org= file and all of the produced configuration files; this will allow us to =git blame= both the this file and the generated files.
I'm utilizing Hlissner's [[https://github.com/doomemacs/doomemacs][Doom Emacs]] frameworks. Doom Emac's configuration is divided into 150 modules, & fair number of convenience functions. Rather than detailing stuff about I'll say to go read [[https://github.com/doomemacs/doomemacs/blob/master/docs/faq.org][FAQs]] & [[https://github.com/doomemacs/doomemacs/blob/master/docs/index.org][Index]].
This org-mode document works by using [[https://orgmode.org/manual/Extracting-Source-Code.html][tangles]]. By default Doom's literate config mode adds any ~#+begin_src~ blocks into the =config.el= file[fn:1]. If you want to tangle to a specific file you pass in a file name.
This document uses [[https://orgmode.org/manual/Noweb-Reference-Syntax.html][noweb reference syntax]]. This allows us to extract bits of configuration into named codeblocks, which can be interpolated into another code block's variable. For example:
There's a fair number of files located in ~$DOOMDIR~. Some are configuration, some are additional tooling not use directly by emacs.
#+begin_src bash :tangle no :exports result :results output verbatim
tree $DOOMDIR -L 2
#+end_src
#+RESULTS:
#+begin_example
.
├── +keybinds.el
├── +orgmode.el
├── config.el
├── config.html
├── config.org
├── dist
│ ├── bundle.js
│ ├── code.css
│ ├── custom.css
│ ├── setup.org
│ └── tufte.css
├── init.el
├── makefile
├── packages.el
└── snippets
└── org-mode
4 directories, 13 files
#+end_example
*** Emacs Configuration Files
Doom will automatically load the following files.
+ =init.el= :: Enabled Doom Modules
+ =package.el= :: Packages to fetch from MELPA, Github, etc.
+ =config.el= :: General Emacs configuration
Any additional files should follow the pattern of =+name.el= and should be scoped to that individual purpose.
This should be loaded by the =config.el= file by using the =load!= macro[fn:7] e.g.
#+begin_src emacs-lisp :tangle no
(load! "+name")
#+end_src
Currently this includes
- =+orgmode.el= :: Additional configuration for Orgmode. Considering this is one of the primary modes I use emacs in there's a fair bit of configuration there.
- =+keybinds.el= :: A relatively new and not fully utilized file. The plan is to use this as a centralized location for all custom keybinds.
*** Other files
There are several other files here not directly used by emacs but are related to it.
- =makefile= :: Install script using make[fn:6].
- =dist/*= :: These are files used by the output of [[https://github.com/ox-tufte/ox-tufte][ox-tufte]].[fn:5]
- =config.html= :: This org file exported from [[https://github.com/ox-tufte/ox-tufte][ox-tufte]]. This is not versioned.
- =snippets/[major mode]/*= :: These are [[https://github.com/joaotavora/yasnippet][YASnippets]]. These are manage by this document. See [[*Snippets][Snippets]] for more.
There [[https://nullprogram.com/blog/2016/12/22/][minor but non-zero start time benefits]] for using Lexical Bindings comments. All files created should start with
As mentioned above, we are versioning the generated emacs lisp configuration. We shouldn't modified these files as they'll be clobbed anytime the org-tangle is run. Lets include a warning to this effect.
The configuration is below is pulled from the template =init.example.el= provided by doom. This one is based off commit [[https://github.com/doomemacs/doomemacs/blob/e96624926d724aff98e862221422cd7124a99c19/templates/init.example.el][e966249]].
The code of these can be found in the [[https://github.com/doomemacs/doomemacs/tree/master/modules][modeules directory]], the read me for each module will list any additional configuration options.
Doom uses [[https://github.com/lassik/emacs-format-all-the-code][emacs-format-all-the-code]] for its formatting. It's a great package, but I use different formatters for a couple language. At this time I'm only going to update =sql-mode= to use [[https://github.com/darold/pgFormatter][pgformatter]]. It's supported, but instead used by default.
Vterm is great. It does require some additional configuration to work properly. See [[https://github.com/doomemacs/doomemacs/tree/master/modules/term/vterm][relavant doc]] for more.
NOTE: =:leader r= is currently being used by roam. See [[*Keybinds][Roam Keybinds]]. This conflicts with the =upload= module. If you wish to use this module in the future you will need to updated one of the keybinds to not conflict.
For use with Github this requires the creation of a Github Token (see [[https://github.com/settings/tokens][here]]). This will need to be appended to your =~/.authinfo.gpg= file using the format below[fn:2].
I use the [[https://www.nerdfonts.com/][nerdfont]]'s [[https://github.com/i-tu/Hasklig][Hasklig]] for my monospace font & Huerta Tipografica's [[https://www.huertatipografica.com/en/fonts/alegreya-ht-pro][ Alegreya]] serif font.
Doom comes with some good keybind macros (see [[https://github.com/doomemacs/doomemacs/blob/master/docs/faq.org#bind-my-own-keys-or-change-existing-ones][here]] for why). Documentation for this can be found [[https://github.com/doomemacs/doomemacs/blob/master/docs/faq.org#bind-my-own-keys-or-change-existing-ones][here]], but in broad strokes:
1. Start with a =map!= macro. You can use
2. When possible use =:when= to limit scope.
3. Use =:prefix= and =:prefix-map= where possible.
4. Always use =:desc= to describe what is being done.
Below is a sample snippet from Rameez Khan's [[https://rameezkhan.me/posts/2020/2020-07-03--adding-keybindings-to-doom-emacs/][blog]] (first hit on "doom emacs keybind" using [[https://duckduckgo.com/][DDG]]):
#+begin_src emacs-lisp :tangle no
(map! :leader
(:prefix-map ("a" . "applications")
(:prefix ("j" . "journal")
:desc "New journal entry" "j" #'org-journal-new-entry
Lets set the local leader to =,=. We may want to remap this to =;= later. Both of these seem to have issues with potential key conflicts with evil-snipe. This seems to primarily exists with regards to org-mode. Github issue can be found [[https://github.com/doomemacs/doomemacs/issues/4242][here]].
#+begin_src emacs-lisp :tangle "+keybinds.el" :noweb no-export :comments no
Some files we'll need to set the major-mode for manually. Either based on where the file is located, or its extension. To do this add the value to the =auto-mode-alist= and specify the major mode.
I am currently using Firefox with [[https://github.com/tridactyl/tridactyl][Tridactyl]]. The =editorcmd= creates a temporary file & opens it with the editor of choice. The domain is included in the temporary file name, but its a fair assumption that it will markdown. We can use this to set the syntax of the file in question. This likely just be markdown.
This file will be needed for emacs batch automation, where its not reasonable to start up my entire working env. This file can be located at =$DOOMDIR/+orgmode.el=.
My notes are stored via [[https://nextcloud.com/][NextCloud]] to sync multiple machines. The Nextcloud directory can be located in a couple different location based off the OS that the machine is running, but where the NextCloud general sync directory may vary based on machine but notes should always be stored at =$HOME/org=.
The standard keybind for getting to Roam's daily capture is pretty long. To capture a Log entry I have to type =SPC n r d T l=. I want to capture as many logs and goals as possible, so lets shorten this up some.
#+begin_src emacs-lisp :tangle "+keybinds.el" :noweb no-export :comments no
[[https://mermaid.js.org/][MermaidJS]] is a diagramming and charting tool similar to Dot/Graphviz, but significantly prettier with less boilerplate. We'll likely only ever want to modify it in the context of =org-mode= so we'll want [[https://github.com/arnm/ob-mermaid][ob-mermaid]].
The snippet below is largely pulled from John Kitchin [[https://emacs.stackexchange.com/questions/63517/org-mode-evaluate-diff-code-block/63520#63520][Stackexchange Post]].
#+begin_src emacs-lisp :tangle "+orgmode.el" :noweb no-export :comments no
(defun org-babel-execute:diff (body params)
"Applies diff patches. Use with care.
See https://emacs.stackexchange.com/questions/63517/org-mode-evaluate-diff-code-block"
Rather than using =org-export-dispatch='s html export, we'll want to use [[https://github.com/ox-tufte/ox-tufte][ox-tufte]]. The HTML output is a more reasonable than the HTML format.
#+BEGIN_SRC emacs-lisp :tangle "packages.el"
(package! ox-tufte)
#+END_SRC
Just load the require to setup the dependency.
#+begin_src emacs-lisp :tangle "+orgmode.el" :noweb no-export :comments no
The syntax highlighting for html is done inline in the by default. We don't want to do that; we're using CSS. See the file in [[file:dist/code.css][code.css]] file for more.
#+begin_src emacs-lisp :tangle "+orgmode.el" :noweb no-export :comments no
To use this you will need to include the setup file. This will load the required css & js files. See [[https://orgmode.org/manual/In_002dbuffer-Settings.html][here]] for more.
#+begin_src org :tangle no
#+SETUPFILE: ~/.dotfiles/emacs/dist/setup.org
#+end_src
This will load the CSS and JS files located in the =dotfiles/emacs/dist/= directory.
GPT is more useful than I thought. Its incredibly helpful for writing prose which I can struggle with due to mild dysgraphia. We will be using the [[https://github.com/karthink/gptel][karthink/gptel]] package.
This package supports multiple LLM backends. I'm going to be using the OpenAI ChatGPT backend by default. We'll need to set the API key. There are a couple ways this can be done, but we're going to set this using =~/.authinfo.gpg=. This will need to be decrypted before use, but this is pretty minor.
We've enabled the [[doom-module:editor snippets][snippets module]] [[*Editor][earlier]]. This will give us use of the [[https://github.com/doomemacs/snippets][Doom Snippets package]], but we'll want to add our own as well. Custom snippets are added under =$DOOMDIR/snippets/= directory. Documentation on how to write snippets can be found at [[http://joaotavora.github.io/yasnippet/snippet-development.html][yas-snippet/documentation]] and [[https://github.com/doomemacs/snippets][doom-snippets github page]].
While we'll want to store these snippets in this orgmode document, using the =+snippets/create= & =snippets/edit= may be useful for creating these.
In my work todo and my roam notes I've been using a list elements with nerd-fonts icons under my section header to provide quick links for the context. Below are a few that I've been using.
[fn:2] See [[https://github.com/doomemacs/doomemacs/tree/master/modules/tools/magit#i-recently-updated-and-now-i-get-deferred-error--wrong-type-argument-sequencep-code-reviewauth-token-set-whenever-i-try-to-review][Doom Magit documentation.]]
[fn:1] See [[https://github.com/doomemacs/doomemacs/tree/master/modules/config/literate#change-where-src-blocks-are-tangled-or-prevent-it-entirely][Doom FAQ on this for more.]]