Commit 534e503ecb
Unsigned
Layout: unified 路 split
content/blog/2024-03-13-doom-emacs.md added +334
| @@ -0,0 +1,334 @@ | ||
| 1 | +++ | |
| 2 | date = 2024-03-14T16:19:23+00:00 | |
| 3 | title = "Doom Emacs & Org-Mode" | |
| 4 | description = "A quick look at my setup with Doom Emacs and the Org-Mode syntax." | |
| 5 | +++ | |
| 6 | ||
| 7 | ## Screenshots | |
| 8 | ||
| 9 | These screenshots are showing a project opened with projectile, a treemacs side | |
| 10 | pane open with the project contents, multiple buffers tiled next to each other, | |
| 11 | and the help pane open at the bottomm. | |
| 12 | ||
| 13 | The themes are `doom-homage-white` and `doom-dracula`. | |
| 14 | ||
| 15 |  | |
| 17 | ||
| 18 |  | |
| 20 | ||
| 21 | ## Getting Started | |
| 22 | ||
| 23 | I have been switching back and forth between | |
| 24 | [markdown](https://en.wikipedia.org/wiki/Markdown) and | |
| 25 | [org-mode](https://en.wikipedia.org/wiki/Org-mode) recently for my personal note | |
| 26 | taking, wiki, and even this blog. As a result, I have been stumbling further | |
| 27 | into the world of Emacs and found myself at a point where I now prefer to do | |
| 28 | most of my basic editing within Emacs. | |
| 29 | ||
| 30 | I'll leave the markdown vs. org-mode debate for another post, but I love | |
| 31 | org-mode's extensibility and interactive nature within Emacs, but it becomes | |
| 32 | very unwieldy in any other client implementation of org-mode - especially on | |
| 33 | iOS. On the flip side, markdown is limited in functionality and fractured into | |
| 34 | different standards, but it's simple and popular enough that there are a | |
| 35 | plethora of great clients to choose from that will get the job done. | |
| 36 | ||
| 37 | For now, I want to focus on how I have been using Emacs and some of the things | |
| 38 | that would have helped me learn it faster had I known where to start. | |
| 39 | ||
| 40 | ### Installation | |
| 41 | ||
| 42 | This post focuses on [Doom Emacs](https://github.com/doomemacs/doomemacs), which | |
| 43 | is an Emacs framework that provides an alternative experience to the vanilla | |
| 44 | [GNU Emacs](https://www.gnu.org/software/emacs/). | |
| 45 | ||
| 46 | The [Getting Start | |
| 47 | Guide](https://github.com/doomemacs/doomemacs/blob/master/docs/getting_started.org) | |
| 48 | has an extremely detailed walkthrough of installation for all systems, so please | |
| 49 | refer to that guide for up-to-date instructions. | |
| 50 | ||
| 51 | I chose to install on macOS, using the Homebrew option with the | |
| 52 | `railwaycat/emacsmacport` version of Emacs. | |
| 53 | ||
| 54 | Once the program is installed, you can run the program by typing `emacs` in a | |
| 55 | terminal. If you installed a version of Emacs that supports both a GUI and TUI, | |
| 56 | you will have to run `emacs -nw` to get the TUI instead of the default GUI. | |
| 57 | ||
| 58 | ### Configuration | |
| 59 | ||
| 60 | Once installed, you can configure Doom by editing the files within the | |
| 61 | `~/.doom.d/` directory. This directory holds four files: | |
| 62 | ||
| 63 | 1. `config.el` - Personal configuration file | |
| 64 | 2. `custom.el` - Custom set variables | |
| 65 | 3. `init.el` - Doom modules and load order, must run `doom sync` after modifying | |
| 66 | 4. `packages.el` - Declare packages to install in this file, then run `doom | |
| 67 | sync` to install | |
| 68 | ||
| 69 | I only needed a few customizations for my configuration, so I'll list them | |
| 70 | below. | |
| 71 | ||
| 72 | ```lisp | |
| 73 | ;; ~/.doom.d/config.el | |
| 74 | (setq doom-theme 'doom-homage-black) | |
| 75 | (setq display-line-numbers-type t) | |
| 76 | (setq org-directory "~/Documents/Notes/") | |
| 77 | ||
| 78 | ;; lengthy org-publish directives at the bottom of the file | |
| 79 | ``` | |
| 80 | ||
| 81 | ```lisp | |
| 82 | ;; ~/.doom.d/init.el | |
| 83 | (doom! :input | |
| 84 | :completion | |
| 85 | company ; the ultimate code completion backend | |
| 86 | vertico ; the search engine of the future | |
| 87 | ||
| 88 | :ui | |
| 89 | doom ; what makes DOOM look the way it does | |
| 90 | doom-dashboard ; a nifty splash screen for Emacs | |
| 91 | (emoji +unicode) ; 馃檪 | |
| 92 | hl-todo ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW | |
| 93 | minimap ; show a map of the code on the side | |
| 94 | modeline ; snazzy, Atom-inspired modeline, plus API | |
| 95 | ophints ; highlight the region an operation acts on | |
| 96 | (popup +defaults) ; tame sudden yet inevitable temporary windows | |
| 97 | tabs ; a tab bar for Emacs | |
| 98 | treemacs ; a project drawer, like neotree but cooler | |
| 99 | (vc-gutter +pretty) ; vcs diff in the fringe | |
| 100 | vi-tilde-fringe ; fringe tildes to mark beyond EOB | |
| 101 | workspaces ; tab emulation, persistence & separate workspaces | |
| 102 | ||
| 103 | :editor | |
| 104 | (evil +everywhere); come to the dark side, we have cookies | |
| 105 | file-templates ; auto-snippets for empty files | |
| 106 | fold ; (nigh) universal code folding | |
| 107 | snippets ; my elves. They type so I don't have to | |
| 108 | ||
| 109 | :emacs | |
| 110 | dired ; making dired pretty [functional] | |
| 111 | electric ; smarter, keyword-based electric-indent | |
| 112 | undo ; persistent, smarter undo for your inevitable mistakes | |
| 113 | vc ; version-control and Emacs, sitting in a tree | |
| 114 | ||
| 115 | :term | |
| 116 | term ; basic terminal emulator for Emacs | |
| 117 | ||
| 118 | :checkers | |
| 119 | syntax ; tasing you for every semicolon you forget | |
| 120 | ||
| 121 | :tools | |
| 122 | (eval +overlay) ; run code, run (also, repls) | |
| 123 | lookup ; navigate your code and its documentation | |
| 124 | magit ; a git porcelain for Emacs | |
| 125 | ||
| 126 | :os | |
| 127 | (:if (featurep :system 'macos) macos) ; improve compatibility with macOS | |
| 128 | ||
| 129 | :lang | |
| 130 | common-lisp ; if you've seen one lisp, you've seen them all | |
| 131 | emacs-lisp ; drown in parentheses | |
| 132 | markdown ; writing docs for people to ignore | |
| 133 | org ; organize your plain life in plain text | |
| 134 | python ; beautiful is better than ugly | |
| 135 | sh ; she sells {ba,z,fi}sh shells on the C xor | |
| 136 | ||
| 137 | :app | |
| 138 | irc ; how neckbeards socialize | |
| 139 | (rss +org) ; emacs as an RSS reader | |
| 140 | ||
| 141 | (default +bindings +smartparens)) | |
| 142 | ``` | |
| 143 | ||
| 144 | If you're editing these files within Doom directly, remember to run `SPC h r r` | |
| 145 | to reload the configuration. Also remember to run `doom sync` for any changes to | |
| 146 | the `init.el` or `packages.el` files. | |
| 147 | ||
| 148 | ## Basic Functionality | |
| 149 | ||
| 150 | I kept a cheat sheet note open at first with all of the basic functions typed | |
| 151 | out, copied as I went through the tutorial. After a little while, I no longer | |
| 152 | needed it. I highly recommend writing down the most applicable shortcuts for | |
| 153 | your preferred functionality and refer back to it until you've memorized it. | |
| 154 | ||
| 155 | Memorizing the shortcuts will differ based on the type of Emacs framework being | |
| 156 | used. Personally, migrating from vanilla Emacs to Doom Emacs simplified | |
| 157 | everything by a large factor and instantly enabled me to start working on my | |
| 158 | projects, eliminating most of the hurdles I was running into. The vanilla emacs | |
| 159 | hotkeys became obnoxious and I actually stopped using Emacs entirely for about a | |
| 160 | month before trying Doom. | |
| 161 | ||
| 162 | For me, the first logical step is to interact with the local filesystem. To do | |
| 163 | this, I needed to know how to open directories, open files, save files, discard | |
| 164 | changes, close files, and switch between open files. Here are some example | |
| 165 | shortcuts I've written down in order to accomplish file-based actions. | |
| 166 | ||
| 167 | | Doom Hotkey | Emacs Hotkey | Description | | |
| 168 | |-----------------|--------------|----------------------------------------| | |
| 169 | | `SPC :` | `C-x` | Run functions | | |
| 170 | | `SPC f f` | `C-x f` | Open file in buffer | | |
| 171 | | `SPC f d` | `C-x d` | Open directory with `dired` | | |
| 172 | | `i` | `C-x C-q` | Edit current buffer (insert mode) | | |
| 173 | | `q` | `C-x C-q` | Quit out of insert mode | | |
| 174 | | `SPC f s` | `C-x s` | Save current buffer | | |
| 175 | | `SPC b k` | `C-x k` | Kill current buffer | | |
| 176 | | `SPC w h/j/k/l` | `C-x o`[^1] | Move left/down/up/right to next buffer | | |
| 177 | ||
| 178 | [^1] Doom's evil-window functionality is a bit different from GNU Emacs, but you | |
| 179 | can always switch to the "other" buffer with `C-x o` or `C-x b` to get a list of | |
| 180 | buffers to select. | |
| 181 | ||
| 182 | In general, when in Doom, you can press `SPC` and wait a second for the help | |
| 183 | pane to appear with all available hotkey options. For example, you can press | |
| 184 | `SPC`, wait for the help pane, and then select a key such as `g` to enter the | |
| 185 | git help pane and explore further command options. | |
| 186 | ||
| 187 | ## Editing | |
| 188 | ||
| 189 | Next in my process is to dive into editing for any languages I'm currently | |
| 190 | using. In this post, I will just cover Markdown and Org-Mode but I have also | |
| 191 | been slowly adoping some Python and general web dev tools as well. | |
| 192 | ||
| 193 | ### Markdown | |
| 194 | ||
| 195 | Markdown is fairly simple as the syntax is limited, so just make sure the | |
| 196 | `~/.doom.d/init.el` includes the `markdown` declaration in the `:lang` section. | |
| 197 | ||
| 198 | This package includes the following hotkey menus. The insert and toggle menu | |
| 199 | expands further, allowing you to insert various markdown elements and toggle | |
| 200 | things like link hiding. | |
| 201 | ||
| 202 | | Doom Hotkey | Function | | |
| 203 | |------------------------------|--------------------------| | |
| 204 | | `SPC m '` | markdown-edit-code-block | | |
| 205 | | `SPC m e` | markdown-export | | |
| 206 | | `SPC m i` | +insert | | |
| 207 | | `SPC m o` | markdown-open | | |
| 208 | | `SPC m p` | markdown-preview | | |
| 209 | | `SPC m t` | +toggle | | |
| 210 | | `SPC : markdown-table-align` | markdown-table-align | | |
| 211 | ||
| 212 | ### Org-Mode | |
| 213 | ||
| 214 | Similar to the markdown section above, ensure that the `~/.doom.d/init.el` | |
| 215 | includes the `org` declaration in the `:lang` section. | |
| 216 | ||
| 217 | There are a few hot keys, but a quick search with `SPC : org` shows that there | |
| 218 | are 865 possible org-related functions you can run. I won't possibly be able to | |
| 219 | list them all, so I will simply cover a few of the basic commands I use myself. | |
| 220 | ||
| 221 | | Doom Hotkey | Function | | |
| 222 | |----------------|---------------------------------------| | |
| 223 | | `SPC m t` | org-todo | | |
| 224 | | `SPC n t` | org-todo-list | | |
| 225 | | `SPC o A` | org-agenda | | |
| 226 | | `SPC X` | org-capture | | |
| 227 | | `SPC m p p` | org-priority | | |
| 228 | | `SPC m d s` | org-schedule | | |
| 229 | | `TAB` | org-cycle | | |
| 230 | | `SHIFT TAB` | Collapse/open all headings in buffer | | |
| 231 | | `M-q` | Format/wrap current section | | |
| 232 | | `M-Left/Right` | Demote/promote current heading | | |
| 233 | | `M-Down/Up` | Shift current heading section down/up | | |
| 234 | ||
| 235 | #### Org-Publish | |
| 236 | ||
| 237 | Org includes a [publishing management | |
| 238 | system](https://orgmode.org/manual/Publishing.html) by default that allows you | |
| 239 | to export org files to Org, iCalendar, HTML, LaTex, Markdown, ODT, and Plain | |
| 240 | Text. Most of these can be exported into another buffer and opened, or simply to | |
| 241 | an external file. | |
| 242 | ||
| 243 | While inside an org file, simply run `SPC m e` or `M-x org-export-dispatch` to | |
| 244 | open the export menu. This menu will show all options and ask you to select an | |
| 245 | option. If you want to export to HTML, simply press `h` and then `H` (As HTML | |
| 246 | buffer), `h` (As HTML file), or `o` (As HTML file and open). | |
| 247 | ||
| 248 | #### Projects | |
| 249 | ||
| 250 | Some publishing options are easier with a defined project in Emacs. To create a | |
| 251 | project within Emacs, I use two methods: | |
| 252 | ||
| 253 | 1. Add the project via the projectile command `SPC p a`. Does not always work | |
| 254 | for me. | |
| 255 | 2. Add an empty `.projectile` file in the project root. | |
| 256 | ||
| 257 | Once a project has been created, you can create custom publishing actions within | |
| 258 | your `~/.doom.d/config.el` file. For example, here's a test project I created to | |
| 259 | try and convert this blog to org-mode recently. | |
| 260 | ||
| 261 | ```lisp ;; org-publish (require 'ox-publish) | |
| 262 | ||
| 263 | (defun my/org-sitemap-date-entry-format (entry style project) "Format ENTRY in | |
| 264 | org-publish PROJECT Sitemap format ENTRY ENTRY STYLE format that includes | |
| 265 | date." (let ((filename (org-publish-find-title entry project))) (if (= (length | |
| 266 | filename) 0) (format "*%s*" entry) (format "{{{timestamp(%s)}}} | |
| 267 | [[file:%s][%s]]" (format-time-string "%Y-%m-%d" (org-publish-find-date entry | |
| 268 | project)) entry filename)))) | |
| 269 | ||
| 270 | (setq org-export-global-macros '(("timestamp" . "@@html:<time datetime='[$1]' | |
| 271 | class='timestamp'>[$1]</time>@@"))) | |
| 272 | ||
| 273 | (setq org-publish-project-alist | |
| 274 | `(("blog" | |
| 275 | :base-directory "~/Source/cleberg.net/" | |
| 276 | :base-extension "org" | |
| 277 | :recursive t | |
| 278 | :publishing-directory "~/Source/cleberg.net/public/" | |
| 279 | :publishing-function org-html-publish-to-html | |
| 280 | ;; HTML5 | |
| 281 | :html-doctype "html5" | |
| 282 | :html-html5-fancy t | |
| 283 | ;; Disable some Org's HTML defaults | |
| 284 | :html-head-include-scripts nil | |
| 285 | :html-head-include-default-style nil | |
| 286 | :section-numbers nil | |
| 287 | :with-title nil | |
| 288 | ;; Sitemap | |
| 289 | :auto-sitemap t | |
| 290 | :sitemap-title: "Sitemap" | |
| 291 | :sitemap-sort-files anti-chronologically | |
| 292 | ; :sitemap-function my/org-sitemap-date-entry-format | |
| 293 | ;; Customize HTML output | |
| 294 | :html-divs ((preamble "header" "preamble") | |
| 295 | (content "main" "content") | |
| 296 | (postamble "footer" "postamble")) | |
| 297 | :html-head "<meta name='theme-color' content='#111' media='(prefers-color-scheme: dark)'> | |
| 298 | <meta name='theme-color' content='#fff' media='(prefers-color-scheme: light)'> | |
| 299 | <link rel='stylesheet' href='/syntax-theme-dark.css' media='(prefers-color-scheme: dark)'> | |
| 300 | <link rel='stylesheet' href='/syntax-theme-light.css' media='(prefers-color-scheme: light)'> | |
| 301 | <link rel='stylesheet' href='/styles.css' type='text/css'>" | |
| 302 | :html-preamble "<nav class='site-nav' aria-label='site-nav' role='navigation'> | |
| 303 | <ul> | |
| 304 | <li><a href='/'>Home</a></li> | |
| 305 | <li><a href='/blog/'>Blog</a></li> | |
| 306 | <li><a href='/services/'>Services</a></li> | |
| 307 | <li><a href='/wiki/'>Wiki</a></li> | |
| 308 | </ul></nav> | |
| 309 | <h1>%t</h1> | |
| 310 | <time datetime='%d'>%d</time>" | |
| 311 | :html-postamble " | |
| 312 | <p>Last build: %T</p> | |
| 313 | <p>Created with %c</p>" | |
| 314 | ) | |
| 315 | ||
| 316 | ("static" | |
| 317 | :base-directory "~/Source/cleberg.net/static/" | |
| 318 | :base-extension "css\\|txt\\|jpg\\|gif\\|png" | |
| 319 | :recursive t | |
| 320 | :publishing-directory "~/Source/cleberg.net/public/" | |
| 321 | :publishing-function org-publish-attachment) | |
| 322 | ||
| 323 | ("cleberg.net" :components ("blog" "static")))) | |
| 324 | ``` | |
| 325 | ||
| 326 | ## General Thoughts | |
| 327 | ||
| 328 | I have enjoyed Doom Emacs (far more than GNU Emacs) and will likely continue to | |
| 329 | use it as my main editor for the time being. Org-Mode is certainly the largest | |
| 330 | factor here, as I far prefer it over Markdown due to its inherent features and | |
| 331 | detailed markup options. However, working with org-mode on iOS has been a pain | |
| 332 | and I will have to see if there's an easier way to resolve those issues or if | |
| 333 | going back to separate Markdown, Reminders, and Calendar apps is easier to work | |
| 334 | with than an all-in-one org solution. | |