<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Emacs on Manuel Herrmann</title>
    <link>https://blog.0x17.de/tags/emacs/</link>
    <description>Recent content in Emacs on Manuel Herrmann</description>
    <image>
      <title>Manuel Herrmann</title>
      <url>https://blog.0x17.de/images/mh.jpg</url>
      <link>https://blog.0x17.de/images/mh.jpg</link>
    </image>
    <generator>Hugo -- 0.159.0</generator>
    <language>en</language>
    <lastBuildDate>Sat, 26 Apr 2025 00:00:00 +0200</lastBuildDate>
    <atom:link href="https://blog.0x17.de/tags/emacs/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Building a Modular Emacs Configuration</title>
      <link>https://blog.0x17.de/post/modular-emacs-config/</link>
      <pubDate>Sat, 26 Apr 2025 00:00:00 +0200</pubDate>
      <guid>https://blog.0x17.de/post/modular-emacs-config/</guid>
      <description>&lt;p&gt;Maintaining a clean, organized Emacs configuration becomes increasingly important as your setup grows. A modular approach separates concerns, simplifies troubleshooting, and makes your configuration more maintainable over time. In this article, I&amp;rsquo;ll share how I structure my Emacs configuration for maximum flexibility and sustainability.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;intro&#34; loading=&#34;lazy&#34; src=&#34;https://blog.0x17.de/post/modular-emacs-config/intro.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-problem-with-monolithic-configurations&#34;&gt;The Problem with Monolithic Configurations&lt;/h2&gt;
&lt;p&gt;Many Emacs users start with a single &lt;code&gt;.emacs&lt;/code&gt; or &lt;code&gt;init.el&lt;/code&gt; file. This works fine at first, but as your configuration grows to accommodate different programming languages, workflows, and packages, a single file becomes unwieldy. Common issues include:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Maintaining a clean, organized Emacs configuration becomes increasingly important as your setup grows. A modular approach separates concerns, simplifies troubleshooting, and makes your configuration more maintainable over time. In this article, I&rsquo;ll share how I structure my Emacs configuration for maximum flexibility and sustainability.</p>
<p><img alt="intro" loading="lazy" src="/post/modular-emacs-config/intro.png"></p>
<h2 id="the-problem-with-monolithic-configurations">The Problem with Monolithic Configurations</h2>
<p>Many Emacs users start with a single <code>.emacs</code> or <code>init.el</code> file. This works fine at first, but as your configuration grows to accommodate different programming languages, workflows, and packages, a single file becomes unwieldy. Common issues include:</p>
<ul>
<li>Hard-to-find settings when you need to make changes</li>
<li>Difficult debugging when something breaks</li>
<li>Challenging to selectively enable/disable features</li>
<li>Poor organization making it hard to understand your own setup</li>
</ul>
<h2 id="a-modular-approach">A Modular Approach</h2>
<p>Let&rsquo;s explore a modular configuration structure based on <a href="https://github.com/0x17de/emacs-config">my personal setup</a> that addresses these issues.</p>
<h3 id="root-configuration-file">Root Configuration File</h3>
<p>The entry point for my configuration is <code>_0x17de-emacs.el</code>, which defines the base setup and loads other modules:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(setq initial-scratch-message <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>      ring-bell-function <span style="color:#a6e22e">#&#39;</span>ignore)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(defvar _0x17de/load-path (<span style="color:#a6e22e">file-name-directory</span> (or load-file-name <span style="color:#a6e22e">buffer-file-name</span>))
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;Path of the _0x17de emacs config&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(defun _0x17de/load (paths)
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;Load files relative to this emacs config.&#34;</span>
</span></span><span style="display:flex;"><span>  (when (not (<span style="color:#a6e22e">listp</span> paths))
</span></span><span style="display:flex;"><span>    (setq paths (<span style="color:#a6e22e">list</span> paths)))
</span></span><span style="display:flex;"><span>  (dolist (path paths)
</span></span><span style="display:flex;"><span>    (condition-case err
</span></span><span style="display:flex;"><span>        (<span style="color:#a6e22e">load</span> (<span style="color:#a6e22e">expand-file-name</span> path _0x17de/load-path))
</span></span><span style="display:flex;"><span>      (<span style="color:#a6e22e">error</span> (<span style="color:#a6e22e">message</span> <span style="color:#e6db74">&#34;Failed to load _0x17de-config sub-library at %S: %S&#34;</span> path err)))))
</span></span></code></pre></div><p>The key here is the <code>_0x17de/load</code> function that loads modules with error handling, preventing a failure in one module from breaking your entire configuration.</p>
<h3 id="directory-structure">Directory Structure</h3>
<p>My configuration is organized into clear directories:</p>
<ul>
<li><code>init/</code> - Core settings (startup, UI, packages)</li>
<li><code>langs/</code> - Language-specific configurations</li>
<li><code>utils/</code> - General utilities and enhancements</li>
<li><code>ext/</code> - External packages not available in package repositories</li>
</ul>
<p>This structure makes it immediately clear where to find specific settings.</p>
<h3 id="core-initialization">Core Initialization</h3>
<p>The initialization sequence loads modules in logical groups:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(_0x17de/load
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;./init/custom.el&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#e6db74">&#34;./init/speedup.el&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#e6db74">&#34;./init/package.el&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#e6db74">&#34;./init/encoding.el&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#e6db74">&#34;./init/gui.el&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#e6db74">&#34;./init/exwm.el&#34;</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(_0x17de/load
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;./utils/exec-path-from-shell&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#e6db74">&#34;./utils/minibuffer&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#e6db74">&#34;./utils/indention&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#75715e">;; ... more utilities ... </span>
</span></span><span style="display:flex;"><span>   ))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(_0x17de/load
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;./langs/common&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#e6db74">&#34;./langs/ansible&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#e6db74">&#34;./langs/plantuml&#34;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#75715e">;; ... more languages ...</span>
</span></span><span style="display:flex;"><span>   ))
</span></span></code></pre></div><p>This approach lets you:</p>
<ol>
<li>Control the order of initialization</li>
<li>Group related components</li>
<li>Easily comment out modules you don&rsquo;t want to load</li>
</ol>
<h3 id="graceful-error-handling">Graceful Error Handling</h3>
<p>A crucial aspect of this setup is the error handling in the <code>_0x17de/load</code> function. If a module fails to load, it displays a message but continues loading other modules:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(condition-case err
</span></span><span style="display:flex;"><span>    (<span style="color:#a6e22e">load</span> (<span style="color:#a6e22e">expand-file-name</span> path _0x17de/load-path))
</span></span><span style="display:flex;"><span>  (<span style="color:#a6e22e">error</span> (<span style="color:#a6e22e">message</span> <span style="color:#e6db74">&#34;Failed to load _0x17de-config sub-library at %S: %S&#34;</span> path err)))
</span></span></code></pre></div><p>This prevents a single module failure from breaking your entire Emacs experience.</p>
<h2 id="specialized-module-examples">Specialized Module Examples</h2>
<p>Let&rsquo;s examine a few module types to see how they encapsulate specific functionality.</p>
<h3 id="language-support">Language Support</h3>
<p>Language-specific modules handle everything needed for a particular language. For example, my Go configuration:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(use-package go-mode
</span></span><span style="display:flex;"><span>  :defer <span style="color:#66d9ef">t</span>
</span></span><span style="display:flex;"><span>  :bind
</span></span><span style="display:flex;"><span>  (:map go-mode-map
</span></span><span style="display:flex;"><span>        ([tab] <span style="color:#f92672">.</span> <span style="color:#e6db74">&#39;company-indent-or-complete-common</span>)
</span></span><span style="display:flex;"><span>        ([f1] <span style="color:#f92672">.</span> lsp-describe-thing-at-point)
</span></span><span style="display:flex;"><span>        ([f12] <span style="color:#f92672">.</span> lsp-find-definition)
</span></span><span style="display:flex;"><span>        (<span style="color:#e6db74">&#34;S-&lt;f12&gt;&#34;</span> <span style="color:#f92672">.</span> lsp-find-references))
</span></span><span style="display:flex;"><span>  :hook
</span></span><span style="display:flex;"><span>  (go-mode <span style="color:#f92672">.</span> (lambda ()
</span></span><span style="display:flex;"><span>               (setq tab-width <span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span>               (setq company-backends <span style="color:#f92672">&#39;</span>(company-capf
</span></span><span style="display:flex;"><span>                                        company-files))
</span></span><span style="display:flex;"><span>               (setq gofmt-command <span style="color:#e6db74">&#34;goimports&#34;</span>)
</span></span><span style="display:flex;"><span>               (add-hook <span style="color:#e6db74">&#39;before-save-hook</span> <span style="color:#e6db74">&#39;gofmt-before-save</span>)
</span></span><span style="display:flex;"><span>               (go-guru-hl-identifier-mode)
</span></span><span style="display:flex;"><span>               (lsp-deferred)
</span></span><span style="display:flex;"><span>               <span style="color:#75715e">;; ... more settings ...</span>
</span></span><span style="display:flex;"><span>               )))
</span></span></code></pre></div><p>This module:</p>
<ul>
<li>Loads only when editing Go files (<code>:defer t</code>)</li>
<li>Sets up keybindings specific to Go files</li>
<li>Configures language-specific tools and formatting</li>
<li>Integrates with <a href="https://en.wikipedia.org/wiki/Language_Server_Protocol">LSP</a> for auto-completions and advanced IDE features</li>
</ul>
<h3 id="utility-modules">Utility Modules</h3>
<p>Utilities enhance the core editing experience regardless of the file type you&rsquo;re editing. For example, my multiple-cursors configuration:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(defun _0x17de/add-multiple-cursors-to-non-empty-lines (start end)
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;Add a cursor in each non-empty line of selection&#34;</span>
</span></span><span style="display:flex;"><span>  (interactive <span style="color:#e6db74">&#34;r&#34;</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">;; ... implementation ...</span>
</span></span><span style="display:flex;"><span>  )
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(use-package multiple-cursors
</span></span><span style="display:flex;"><span>  :init
</span></span><span style="display:flex;"><span>  (global-unset-key (kbd <span style="color:#e6db74">&#34;M-&lt;down-mouse-1&gt;&#34;</span>))
</span></span><span style="display:flex;"><span>  :bind
</span></span><span style="display:flex;"><span>  ((<span style="color:#e6db74">&#34;C-M-z C-c&#34;</span> <span style="color:#f92672">.</span> mc/edit-lines)
</span></span><span style="display:flex;"><span>   (<span style="color:#e6db74">&#34;C-M-z C-M-c&#34;</span> <span style="color:#f92672">.</span> _0x17de/add-multiple-cursors-to-non-empty-lines)
</span></span><span style="display:flex;"><span>   (<span style="color:#e6db74">&#34;C-M-z &gt;&#34;</span> <span style="color:#f92672">.</span> mc/mark-next-like-this)
</span></span><span style="display:flex;"><span>   <span style="color:#75715e">;; ... more bindings ...</span>
</span></span><span style="display:flex;"><span>   ))
</span></span></code></pre></div><p>This module encapsulates a complete feature set with custom functions and keybindings.</p>
<h3 id="feature-flags">Feature Flags</h3>
<p>For optional features, I use custom variables as feature flags:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(defcustom _0x17de/use-exwm <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;Non-nil means EXWM will be enabled.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">When this option is enabled, EXWM will be loaded and configured
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">as the window manager for this session.&#34;</span>
</span></span><span style="display:flex;"><span>  :type <span style="color:#e6db74">&#39;boolean</span>
</span></span><span style="display:flex;"><span>  :group <span style="color:#e6db74">&#39;_0x17de</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(when _0x17de/use-exwm
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">;; ... EXWM configuration ...</span>
</span></span><span style="display:flex;"><span>  )
</span></span></code></pre></div><p>This allows toggling features without commenting out code or editing multiple files.</p>
<h2 id="benefits-of-this-approach">Benefits of This Approach</h2>
<p>This modular approach offers several advantages:</p>
<ol>
<li><strong>Maintainability</strong>: Each module has a single responsibility</li>
<li><strong>Performance</strong>: Lazy loading modules when needed</li>
<li><strong>Portability</strong>: Easy to share modules between configurations</li>
<li><strong>Resilience</strong>: Failures in one module don&rsquo;t break everything</li>
<li><strong>Clarity</strong>: Clear organization makes finding settings easier</li>
<li><strong>Flexibility</strong>: Enable/disable features without editing code</li>
</ol>
<h2 id="leveraging-built-in-emacs-utilities">Leveraging Built-in Emacs Utilities</h2>
<p>Emacs provides several powerful utilities that make modular configurations easier to implement and maintain.</p>
<h3 id="use-package-package-management-made-simple">use-package: Package Management Made Simple</h3>
<p>While not built into Emacs core (but bundled with Emacs 29+), <code>use-package</code> is essential for modular configurations:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(use-package python
</span></span><span style="display:flex;"><span>  :ensure <span style="color:#66d9ef">nil</span>  <span style="color:#75715e">; Don&#39;t try to install built-in packages</span>
</span></span><span style="display:flex;"><span>  :defer <span style="color:#66d9ef">t</span>     <span style="color:#75715e">; Only load when needed</span>
</span></span><span style="display:flex;"><span>  :bind (:map python-mode-map
</span></span><span style="display:flex;"><span>          ([f12] <span style="color:#f92672">.</span> lsp-find-definition)
</span></span><span style="display:flex;"><span>          (<span style="color:#e6db74">&#34;S-&lt;f12&gt;&#34;</span> <span style="color:#f92672">.</span> lsp-find-references))
</span></span><span style="display:flex;"><span>  :hook ((python-mode <span style="color:#f92672">.</span> (lambda ()
</span></span><span style="display:flex;"><span>                          (company-mode <span style="color:#66d9ef">t</span>)
</span></span><span style="display:flex;"><span>                          (flycheck-mode <span style="color:#66d9ef">t</span>)
</span></span><span style="display:flex;"><span>                          (lsp-deferred))))
</span></span><span style="display:flex;"><span>  :config     <span style="color:#75715e">; Executed after the package loads</span>
</span></span><span style="display:flex;"><span>  (setq python-indent-offset <span style="color:#ae81ff">4</span>))
</span></span></code></pre></div><p>Key <code>use-package</code> keywords:</p>
<ul>
<li><code>:ensure</code> - Controls package installation</li>
<li><code>:defer</code> - Enables lazy loading</li>
<li><code>:bind</code> - Sets up keybindings (with automatic lazy loading)</li>
<li><code>:hook</code> - Adds mode hooks (with automatic lazy loading)</li>
<li><code>:init</code> - Code executed before loading</li>
<li><code>:config</code> - Code executed after loading</li>
<li><code>:custom</code> - Sets custom variables</li>
<li><code>:commands</code> - Creates autoloaded commands (callable via M-x or keybindings)</li>
</ul>
<p>This declarative approach keeps package configuration concentrated in one place rather than scattered throughout your init file.</p>
<h3 id="defcustom-user-configurable-variables">defcustom: User-Configurable Variables</h3>
<p><code>defcustom</code> creates proper user options with documentation, custom types, and integration with Emacs&rsquo; customization interface:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(defcustom _0x17de/python-global-virtualenv-dir <span style="color:#e6db74">&#34;~/.venv&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;Default directory for Python virtual environments.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">This is used by pyvenv to locate and activate virtual environments.&#34;</span>
</span></span><span style="display:flex;"><span>  :type <span style="color:#e6db74">&#39;directory</span>
</span></span><span style="display:flex;"><span>  :group <span style="color:#e6db74">&#39;_0x17de</span>
</span></span><span style="display:flex;"><span>  :safe <span style="color:#a6e22e">#&#39;stringp</span>)
</span></span></code></pre></div><p>Benefits of <code>defcustom</code> over regular variables:</p>
<ol>
<li><strong>Type checking</strong> - The <code>:type</code> property validates values</li>
<li><strong>Documentation</strong> - Self-documents the option</li>
<li><strong>UI integration</strong> - Works with <code>customize-*</code> commands</li>
<li><strong>Safety</strong> - The <code>:safe</code> property helps with security</li>
<li><strong>Organization</strong> - Options can be grouped logically</li>
</ol>
<h3 id="define-minor-mode-creating-toggleable-features">define-minor-mode: Creating Toggleable Features</h3>
<p>For modular features that can be enabled/disabled, <code>define-minor-mode</code> is perfect:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(define-minor-mode latex-compile-on-save-mode
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;Refresh the preview on save&#34;</span>
</span></span><span style="display:flex;"><span>  :lighter <span style="color:#e6db74">&#34; LTeXcos&#34;</span>
</span></span><span style="display:flex;"><span>  :group latex-compile-on-save
</span></span><span style="display:flex;"><span>  (if latex-compile-on-save-mode
</span></span><span style="display:flex;"><span>      (add-hook <span style="color:#e6db74">&#39;after-save-hook</span> <span style="color:#e6db74">&#39;latex-compile-on-save--compile</span> <span style="color:#66d9ef">nil</span> <span style="color:#66d9ef">t</span>)
</span></span><span style="display:flex;"><span>    (remove-hook <span style="color:#e6db74">&#39;after-save-hook</span> <span style="color:#e6db74">&#39;latex-compile-on-save--compile</span> <span style="color:#66d9ef">t</span>)))
</span></span></code></pre></div><p>This creates a toggleable mode with:</p>
<ul>
<li>A proper minor mode that can be enabled/disabled with <code>M-x</code></li>
<li>Automatic hook management when enabled/disabled</li>
<li>Integration with the mode line via <code>:lighter</code></li>
</ul>
<h3 id="eval-after-load-targeted-configuration">eval-after-load: Targeted Configuration</h3>
<p>For smaller configurations without <code>use-package</code>, <code>eval-after-load</code> provides similar lazy-loading capabilities:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(eval-after-load <span style="color:#e6db74">&#39;python-mode</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#39;</span>(progn
</span></span><span style="display:flex;"><span>     (<span style="color:#a6e22e">define-key</span> python-mode-map (kbd <span style="color:#e6db74">&#34;C-c C-r&#34;</span>) <span style="color:#e6db74">&#39;python-shell-send-region</span>)
</span></span><span style="display:flex;"><span>     (setq python-indent-offset <span style="color:#ae81ff">4</span>)))
</span></span></code></pre></div><p>This defers execution until the specified feature is loaded, improving startup times.</p>
<h3 id="with-eval-after-load-modern-alternative">with-eval-after-load: Modern Alternative</h3>
<p>A more modern, macro-based version of <code>eval-after-load</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(with-eval-after-load <span style="color:#e6db74">&#39;org</span>
</span></span><span style="display:flex;"><span>  (setq org-hide-emphasis-markers <span style="color:#66d9ef">t</span>)
</span></span><span style="display:flex;"><span>  (add-hook <span style="color:#e6db74">&#39;org-mode-hook</span> <span style="color:#a6e22e">#&#39;</span>visual-line-mode))
</span></span></code></pre></div><p>This is cleaner than <code>eval-after-load</code> because it doesn&rsquo;t require quoting the body.</p>
<h3 id="autoload-manual-lazy-loading">autoload: Manual Lazy Loading</h3>
<p>For maximum control over lazy loading:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span><span style="color:#75715e">;;;###autoload</span>
</span></span><span style="display:flex;"><span>(defun my/open-config-file ()
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#34;Open the main configuration file.&#34;</span>
</span></span><span style="display:flex;"><span>  (interactive)
</span></span><span style="display:flex;"><span>  (find-file (<span style="color:#a6e22e">expand-file-name</span> <span style="color:#e6db74">&#34;_0x17de-emacs.el&#34;</span> _0x17de/load-path)))
</span></span></code></pre></div><p>The <code>;;;###autoload</code> cookie tells Emacs to make the function available without loading the entire file.</p>
<h2 id="implementation-tips">Implementation Tips</h2>
<p>If you want to build a similar configuration:</p>
<ol>
<li><strong>Start small</strong>: Begin with a single file and add more as needed</li>
<li><strong>Use consistent naming</strong>: Establish a convention for module files</li>
<li><strong>Leverage use-package</strong>: For declarative, lazy-loaded package configuration</li>
<li><strong>Add error handling</strong>: Ensure graceful recovery from failures</li>
<li><strong>Document with defcustom</strong>: For user-facing configuration options</li>
<li><strong>Use minor modes</strong>: For toggleable features</li>
<li><strong>Embrace lazy loading</strong>: With autoload, eval-after-load, and with-eval-after-load</li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>A modular Emacs configuration significantly improves maintainability and flexibility. By separating concerns into discrete modules with clear responsibilities, you can build a robust, personalized environment that evolves with your needs while remaining manageable.</p>
<p>This approach has served me well, allowing my configuration to grow from a few basic settings to a comprehensive development environment without becoming unwieldy. The time invested in proper organization pays dividends in the long term through improved stability and ease of modification.</p>
<p>Feel free to adapt this structure to your own needs or explore my complete configuration for more ideas and inspiration.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Getting Started with Emacs Lisp: Core Concepts Explained</title>
      <link>https://blog.0x17.de/post/emacs-list-introduction/</link>
      <pubDate>Sat, 29 Mar 2025 00:00:00 +0100</pubDate>
      <guid>https://blog.0x17.de/post/emacs-list-introduction/</guid>
      <description>&lt;p&gt;Emacs Lisp (often abbreviated as Elisp) is the programming language that powers the extensibility of the Emacs text editor. It&amp;rsquo;s a dialect of Lisp that has been adapted specifically for text editing tasks. While it might look unusual at first glance, understanding a few key concepts opens up a world of possibilities for customizing your Emacs experience.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;elisp&#34; loading=&#34;lazy&#34; src=&#34;https://blog.0x17.de/post/emacs-list-introduction/elisp.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;In this article, we&amp;rsquo;ll explore some of the fundamental concepts in Emacs Lisp that often confuse newcomers.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Emacs Lisp (often abbreviated as Elisp) is the programming language that powers the extensibility of the Emacs text editor. It&rsquo;s a dialect of Lisp that has been adapted specifically for text editing tasks. While it might look unusual at first glance, understanding a few key concepts opens up a world of possibilities for customizing your Emacs experience.</p>
<p><img alt="elisp" loading="lazy" src="/post/emacs-list-introduction/elisp.png"></p>
<p>In this article, we&rsquo;ll explore some of the fundamental concepts in Emacs Lisp that often confuse newcomers.</p>
<h2 id="variables-global-vs-local-scope">Variables: Global vs Local Scope</h2>
<p>Elisp provides several ways to define variables, each with different scoping behaviors.</p>
<h3 id="setq-global-variables"><code>setq</code>: Global Variables</h3>
<p>The <code>setq</code> function is used to define and set global variables:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(setq my-variable <span style="color:#e6db74">&#34;Hello, world!&#34;</span>)
</span></span></code></pre></div><p>These variables are accessible from anywhere in your Emacs session once defined. They&rsquo;re ideal for configuration settings or values that need to persist.</p>
<h3 id="let-and-let-local-variables"><code>let</code> and <code>let*</code>: Local Variables</h3>
<p>For variables with limited scope, Elisp provides <code>let</code> and <code>let*</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span><span style="color:#75715e">;; Using let for local binding</span>
</span></span><span style="display:flex;"><span>(let ((x <span style="color:#ae81ff">5</span>)
</span></span><span style="display:flex;"><span>      (y <span style="color:#ae81ff">10</span>))
</span></span><span style="display:flex;"><span>  (<span style="color:#a6e22e">message</span> <span style="color:#e6db74">&#34;Sum: %d&#34;</span> (<span style="color:#a6e22e">+</span> x y)))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">;; x and y are not accessible here</span>
</span></span></code></pre></div><p>The difference between <code>let</code> and <code>let*</code> is significant:</p>
<ul>
<li><code>let</code> evaluates all variable expressions before binding</li>
<li><code>let*</code> evaluates in sequence, allowing later variables to reference earlier ones</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span><span style="color:#75715e">;; This won&#39;t work with let</span>
</span></span><span style="display:flex;"><span>(let ((x <span style="color:#ae81ff">5</span>)
</span></span><span style="display:flex;"><span>      (y (<span style="color:#a6e22e">+</span> x <span style="color:#ae81ff">2</span>)))  <span style="color:#75715e">; Error: x is not yet bound when this is evaluated</span>
</span></span><span style="display:flex;"><span>  (<span style="color:#a6e22e">message</span> <span style="color:#e6db74">&#34;y: %d&#34;</span> y))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">;; This works with let*</span>
</span></span><span style="display:flex;"><span>(let* ((x <span style="color:#ae81ff">5</span>)
</span></span><span style="display:flex;"><span>       (y (<span style="color:#a6e22e">+</span> x <span style="color:#ae81ff">2</span>)))  <span style="color:#75715e">; Works because x is already bound</span>
</span></span><span style="display:flex;"><span>  (<span style="color:#a6e22e">message</span> <span style="color:#e6db74">&#34;y: %d&#34;</span> y))  <span style="color:#75715e">; Output: &#34;y: 7&#34;</span>
</span></span></code></pre></div><h2 id="understanding-quote-">Understanding Quote (<code>'</code>)</h2>
<p>One of the most distinctive features of Lisp is the quote character (<code>'</code>). It prevents evaluation of an expression, instead treating it as data.</p>
<h3 id="quoting-variables">Quoting Variables</h3>
<p>When you place a quote in front of a symbol:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span><span style="color:#e6db74">&#39;my-symbol</span>
</span></span></code></pre></div><p>You&rsquo;re telling Elisp, &ldquo;Don&rsquo;t evaluate this symbol, just give me the symbol itself.&rdquo; This is similar to references in other programming languages.</p>
<p>Without the quote, Elisp would try to look up the value of the variable <code>my-symbol</code>.</p>
<h3 id="list-syntax--vs-list--and-cons-">List Syntax: <code>'(...)</code> vs <code>(list ...)</code> and <code>(cons ...)</code></h3>
<p>Lists are fundamental data structures in Lisp. There are several ways to create them:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span><span style="color:#75715e">;; These are equivalent:</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#39;</span>(a b c)
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">list</span> <span style="color:#e6db74">&#39;a</span> <span style="color:#e6db74">&#39;b</span> <span style="color:#e6db74">&#39;c</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">;; These are also equivalent:</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#39;</span>(a <span style="color:#f92672">.</span> b)
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">cons</span> <span style="color:#e6db74">&#39;a</span> <span style="color:#e6db74">&#39;b</span>)
</span></span></code></pre></div><p>The quoted form <code>'(...)</code> is concise but has a limitation: everything inside is automatically quoted. This means you can&rsquo;t mix evaluated and non-evaluated expressions.</p>
<p>When to use each:</p>
<ul>
<li>Use <code>'(...)</code> for literal lists that don&rsquo;t need evaluation</li>
<li>Use <code>(list ...)</code> when you need to mix literals and evaluated expressions:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(setq name <span style="color:#e6db74">&#34;John&#34;</span>)
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">list</span> <span style="color:#e6db74">&#39;person</span> name <span style="color:#e6db74">&#39;age</span> <span style="color:#ae81ff">30</span>)  <span style="color:#75715e">; =&gt; (person &#34;John&#34; age 30)</span>
</span></span></code></pre></div><h2 id="understanding-cons-cells-car-and-cdr">Understanding Cons Cells: CAR and CDR</h2>
<p>At the heart of Lisp&rsquo;s data structures is the &ldquo;cons cell&rdquo; - a simple pair of values. Each cons cell has two parts, traditionally accessed with the functions <code>car</code> and <code>cdr</code> (pronounced &ldquo;could-er&rdquo;):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(setq my-pair (<span style="color:#a6e22e">cons</span> <span style="color:#e6db74">&#39;a</span> <span style="color:#e6db74">&#39;b</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">car</span> my-pair)  <span style="color:#75715e">; =&gt; a</span>
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">cdr</span> my-pair)  <span style="color:#75715e">; =&gt; b</span>
</span></span></code></pre></div><p>These peculiarly named functions are historical artifacts from the original Lisp implementation on IBM machines:</p>
<ul>
<li><code>car</code>: Contents of the Address part of Register</li>
<li><code>cdr</code>: Contents of the Decrement part of Register</li>
</ul>
<p>In modern terms, think of them as:</p>
<ul>
<li><code>car</code>: head (first element)</li>
<li><code>cdr</code>: tail (rest of the list)</li>
</ul>
<p>Lists in Lisp are actually chains of cons cells that always terminate with <code>nil</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span><span style="color:#75715e">;; This list:</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#39;</span>(<span style="color:#ae81ff">1</span> <span style="color:#ae81ff">2</span> <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">;; Is actually structured as:</span>
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">cons</span> <span style="color:#ae81ff">1</span> (<span style="color:#a6e22e">cons</span> <span style="color:#ae81ff">2</span> (<span style="color:#a6e22e">cons</span> <span style="color:#ae81ff">3</span> <span style="color:#66d9ef">nil</span>)))
</span></span></code></pre></div><p>Visualized as pairs:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>(1 . (2 . (3 . nil)))
</span></span></code></pre></div><p>This implicit <code>nil</code> at the end is crucial - it&rsquo;s what defines a &ldquo;proper list&rdquo; in Lisp. Without this nil termination, you would have a different data structure. The presence of this nil terminator is what allows functions like <code>length</code> to work properly and what lets Lisp know where a list ends.</p>
<p>You can extract elements from lists using these functions:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(setq numbers <span style="color:#f92672">&#39;</span>(<span style="color:#ae81ff">1</span> <span style="color:#ae81ff">2</span> <span style="color:#ae81ff">3</span> <span style="color:#ae81ff">4</span>))
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">car</span> numbers)       <span style="color:#75715e">; =&gt; 1</span>
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">cdr</span> numbers)       <span style="color:#75715e">; =&gt; (2 3 4)</span>
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">car</span> (<span style="color:#a6e22e">cdr</span> numbers)) <span style="color:#75715e">; =&gt; 2</span>
</span></span></code></pre></div><p>Elisp provides convenient shorthand functions like <code>cadr</code> (car of cdr) for common combinations:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(cadr numbers)      <span style="color:#75715e">; =&gt; 2 (same as (car (cdr numbers)))</span>
</span></span><span style="display:flex;"><span>(caddr numbers)     <span style="color:#75715e">; =&gt; 3 (car of cdr of cdr)</span>
</span></span></code></pre></div><h2 id="the-dot-syntax-in-pairs">The Dot Syntax in Pairs</h2>
<p>In Emacs Lisp, you might encounter constructs with dot notation like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(add-to-list <span style="color:#e6db74">&#39;auto-mode-alist</span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;\\.md\\&#39;&#34;</span> <span style="color:#f92672">.</span> markdown-mode))
</span></span></code></pre></div><p>This dot notation represents a &ldquo;cons cell&rdquo; or pair. In this example, we&rsquo;re creating a pair where the car is <code>&quot;\\.md\\'&quot;</code> and the cdr is <code>markdown-mode</code>.</p>
<p>The following expressions are equivalent:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span><span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;\\.md\\&#39;&#34;</span> <span style="color:#f92672">.</span> markdown-mode)
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">cons</span> <span style="color:#e6db74">&#34;\\.md\\&#39;&#34;</span> <span style="color:#e6db74">&#39;markdown-mode</span>)
</span></span></code></pre></div><p>The dot creates a direct pair between two values. This syntax is commonly used in alists (like <code>auto-mode-alist</code>), mode hooks, and other paired data structures in Emacs.</p>
<p>When you see a dot in the middle of a list, it means &ldquo;the rest of this list is the cdr of this cons cell&rdquo; rather than continuing the list structure with an implicit nil at the end.</p>
<p>To understand the difference clearly:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span><span style="color:#75715e">;; A list with two elements (has an implicit nil at the end)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#39;</span>(<span style="color:#ae81ff">1</span> <span style="color:#ae81ff">2</span>)  <span style="color:#75715e">; =&gt; equivalent to (cons 1 (cons 2 nil))</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">;; A single cons cell (a pair) - NOT a proper list</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#39;</span>(<span style="color:#ae81ff">1</span> <span style="color:#f92672">.</span> <span style="color:#ae81ff">2</span>)  <span style="color:#75715e">; =&gt; equivalent to (cons 1 2)</span>
</span></span></code></pre></div><p>The difference is significant:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(<span style="color:#a6e22e">length</span> <span style="color:#f92672">&#39;</span>(<span style="color:#ae81ff">1</span> <span style="color:#ae81ff">2</span>))     <span style="color:#75715e">; =&gt; 2</span>
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">length</span> <span style="color:#f92672">&#39;</span>(<span style="color:#ae81ff">1</span> <span style="color:#f92672">.</span> <span style="color:#ae81ff">2</span>))   <span style="color:#75715e">; =&gt; Error: Wrong type argument: listp, (1 . 2)</span>
</span></span></code></pre></div><p>This distinction is fundamental to understanding how Lisp data structures work.</p>
<h2 id="function-quoting--vs-">Function Quoting: <code>#'</code> vs <code>'</code></h2>
<p>In Elisp, you&rsquo;ll see both <code>'function-name</code> and <code>#'function-name</code> when referring to functions. The difference is important:</p>
<ul>
<li><code>'function-name</code> simply quotes the symbol</li>
<li><code>#'function-name</code> is shorthand for <code>(function function-name)</code>, which specifically tells Elisp that the symbol represents a function</li>
</ul>
<p>When should you use <code>#'</code>? Best practice is to use it whenever you&rsquo;re referring to a function as a function, especially with higher-order functions:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span><span style="color:#75715e">;; Good practice</span>
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">mapcar</span> <span style="color:#a6e22e">#&#39;1+</span> <span style="color:#f92672">&#39;</span>(<span style="color:#ae81ff">1</span> <span style="color:#ae81ff">2</span> <span style="color:#ae81ff">3</span>))  <span style="color:#75715e">; =&gt; (2 3 4)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">;; Works but less explicit</span>
</span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">mapcar</span> <span style="color:#e6db74">&#39;1+</span> <span style="color:#f92672">&#39;</span>(<span style="color:#ae81ff">1</span> <span style="color:#ae81ff">2</span> <span style="color:#ae81ff">3</span>))
</span></span></code></pre></div><p>Using <code>#'</code> helps the byte-compiler optimize your code and makes your intent clearer to other programmers.</p>
<h2 id="association-lists-alists">Association Lists (alists)</h2>
<p>Association lists (alists) are lists of key-value pairs used for simple lookups:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(setq my-alist <span style="color:#f92672">&#39;</span>((name <span style="color:#f92672">.</span> <span style="color:#e6db74">&#34;John&#34;</span>)
</span></span><span style="display:flex;"><span>                 (age <span style="color:#f92672">.</span> <span style="color:#ae81ff">30</span>)
</span></span><span style="display:flex;"><span>                 (city <span style="color:#f92672">.</span> <span style="color:#e6db74">&#34;Boston&#34;</span>)))
</span></span></code></pre></div><p>You can access values using functions like <code>assoc</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(<span style="color:#a6e22e">cdr</span> (<span style="color:#a6e22e">assoc</span> <span style="color:#e6db74">&#39;age</span> my-alist))  <span style="color:#75715e">; =&gt; 30</span>
</span></span></code></pre></div><p>Alists are frequently used in Emacs for configuration options, especially when the list is relatively small and frequently modified. They&rsquo;re simple but not as efficient for large datasets.</p>
<h2 id="property-lists-plists">Property Lists (plists)</h2>
<p>Property lists are another key-value structure in Elisp, but with a different syntax:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(setq my-plist <span style="color:#f92672">&#39;</span>(:name <span style="color:#e6db74">&#34;John&#34;</span> :age <span style="color:#ae81ff">30</span> :city <span style="color:#e6db74">&#34;Boston&#34;</span>))
</span></span></code></pre></div><p>Notice how the keys are prefixed with colons. These are called keywords, similar to Ruby&rsquo;s symbols. You can access values using <code>plist-get</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(<span style="color:#a6e22e">plist-get</span> my-plist :age)  <span style="color:#75715e">; =&gt; 30</span>
</span></span></code></pre></div><p>Other languages with similar concepts include:</p>
<ul>
<li>Ruby with its symbols (<code>:symbol</code>)</li>
<li>Clojure with keywords (<code>:keyword</code>)</li>
<li>Elixir with atoms (<code>:atom</code>)</li>
</ul>
<p>Plists are often used for function arguments that have default values or are optional.</p>
<h2 id="summary">Summary</h2>
<p>Understanding these fundamental Emacs Lisp concepts will help you:</p>
<ol>
<li>Write more effective Elisp code</li>
<li>Understand existing Emacs configurations</li>
<li>Create your own Emacs extensions</li>
</ol>
<p><img alt="summary" loading="lazy" src="/post/emacs-list-introduction/summary.png"></p>
<p>Emacs Lisp&rsquo;s power comes from its simplicity and consistency. Once you grasp these basic concepts, you&rsquo;ll find that the language follows logical patterns that make learning advanced features much easier.</p>
<p>Happy hacking!</p>
]]></content:encoded>
    </item>
    <item>
      <title>The Essential Emacs Hotkeys Every User Should Know</title>
      <link>https://blog.0x17.de/post/essential-emacs-hotkeys/</link>
      <pubDate>Fri, 28 Mar 2025 20:00:00 +0100</pubDate>
      <guid>https://blog.0x17.de/post/essential-emacs-hotkeys/</guid>
      <description>&lt;p&gt;For over four decades, Emacs has stood as a pillar in the text editing world, beloved by programmers, writers, and power users alike. What makes Emacs particularly powerful is its extensive keyboard shortcut system that allows users to perform complex operations without ever touching the mouse.&lt;/p&gt;
&lt;p&gt;Emacs comes with an excellent built-in tutorial that can be accessed with &lt;code&gt;C-h t&lt;/code&gt; (Control-h followed by t). I highly recommend all new users complete this tutorial to get comfortable with Emacs&amp;rsquo; fundamentals. That said, the tutorial is comprehensive and takes time to complete.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>For over four decades, Emacs has stood as a pillar in the text editing world, beloved by programmers, writers, and power users alike. What makes Emacs particularly powerful is its extensive keyboard shortcut system that allows users to perform complex operations without ever touching the mouse.</p>
<p>Emacs comes with an excellent built-in tutorial that can be accessed with <code>C-h t</code> (Control-h followed by t). I highly recommend all new users complete this tutorial to get comfortable with Emacs&rsquo; fundamentals. That said, the tutorial is comprehensive and takes time to complete.</p>
<p><img alt="hotkeys" loading="lazy" src="/post/essential-emacs-hotkeys/hotkeys.png"></p>
<p>This guide serves as a TL;DR and quick reference of the most essential hotkeys you should memorize. Consider it a short recap of what&rsquo;s worth knowing by heart to be immediately productive in Emacs, whether you&rsquo;re new to the editor or just need a refresher.</p>
<h2 id="understanding-emacs-notation">Understanding Emacs Notation</h2>
<p>Before diving into the hotkeys themselves, let&rsquo;s decode how to read Emacs key notation:</p>
<ul>
<li><strong>C-</strong> represents the Control key. For example, <code>C-a</code> means &ldquo;hold Control and press a&rdquo;.</li>
<li><strong>M-</strong> represents the Meta key, which on modern keyboards is typically the Alt key. So <code>M-f</code> means &ldquo;hold Alt and press f&rdquo;.</li>
<li><strong>C-x</strong> followed by another key represents a two-key sequence. Press Control and x together, release, then press the next key.</li>
<li><strong>M-x</strong> similarly starts a command sequence where you type the command name after pressing Alt and x.</li>
</ul>
<p>Multiple modifier keys can be combined. For example, <code>C-M-f</code> means holding both Control and Alt while pressing f.</p>
<p>With this foundation, let&rsquo;s explore the essential hotkeys that will dramatically improve your Emacs efficiency.</p>
<h2 id="essential-emacs-hotkeys-by-category">Essential Emacs Hotkeys by Category</h2>
<h3 id="text-navigation">Text Navigation</h3>
<p>Efficient text navigation is the foundation of productive editing. These shortcuts let you move through your document with precision:</p>
<table>
  <thead>
      <tr>
          <th>Hotkey</th>
          <th>Action Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>C-a</code></td>
          <td>Move to beginning of line</td>
      </tr>
      <tr>
          <td><code>C-e</code></td>
          <td>Move to end of line</td>
      </tr>
      <tr>
          <td><code>C-f</code></td>
          <td>Move forward one character</td>
      </tr>
      <tr>
          <td><code>C-b</code></td>
          <td>Move backward one character</td>
      </tr>
      <tr>
          <td><code>M-f</code></td>
          <td>Move forward one word</td>
      </tr>
      <tr>
          <td><code>M-b</code></td>
          <td>Move backward one word</td>
      </tr>
      <tr>
          <td><code>C-n</code></td>
          <td>Move to next line</td>
      </tr>
      <tr>
          <td><code>C-p</code></td>
          <td>Move to previous line</td>
      </tr>
      <tr>
          <td><code>C-v</code></td>
          <td>Page down</td>
      </tr>
      <tr>
          <td><code>M-v</code></td>
          <td>Page up</td>
      </tr>
      <tr>
          <td><code>M-&lt;</code></td>
          <td>Move to beginning of buffer</td>
      </tr>
      <tr>
          <td><code>M-&gt;</code></td>
          <td>Move to end of buffer</td>
      </tr>
      <tr>
          <td><code>C-l</code></td>
          <td>Recenter buffer around cursor</td>
      </tr>
  </tbody>
</table>
<p>The navigation keys follow a pattern: <code>f</code> for forward, <code>b</code> for backward, <code>p</code> for previous, and <code>n</code> for next. Once you internalize these patterns, they become second nature.</p>
<h3 id="text-editing">Text Editing</h3>
<p>These shortcuts handle the core editing operations that you&rsquo;ll use hundreds of times daily:</p>
<table>
  <thead>
      <tr>
          <th>Hotkey</th>
          <th>Action Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>C-d</code></td>
          <td>Delete character at point</td>
      </tr>
      <tr>
          <td><code>M-&lt;backspace&gt;</code></td>
          <td>Delete word backward</td>
      </tr>
      <tr>
          <td><code>M-d</code></td>
          <td>Delete word forward</td>
      </tr>
      <tr>
          <td><code>C-k</code></td>
          <td>Kill (cut) from cursor to end of line</td>
      </tr>
      <tr>
          <td><code>C-w</code></td>
          <td>Kill (cut) selected region</td>
      </tr>
      <tr>
          <td><code>M-w</code></td>
          <td>Copy selected region</td>
      </tr>
      <tr>
          <td><code>C-y</code></td>
          <td>Yank (paste) most recently killed text</td>
      </tr>
      <tr>
          <td><code>M-y</code></td>
          <td>Cycle through kill ring after yanking</td>
      </tr>
      <tr>
          <td><code>C-/</code> or <code>C-_</code></td>
          <td>Undo</td>
      </tr>
  </tbody>
</table>
<p>A unique aspect of Emacs is its &ldquo;kill ring&rdquo; - a clipboard system that remembers multiple deleted items. After using <code>C-y</code> to paste the most recent item, you can press <code>M-y</code> repeatedly to cycle through previously killed text.</p>
<h3 id="region-and-selection">Region and Selection</h3>
<p>Working with selections in Emacs involves understanding the concept of the &ldquo;mark&rdquo; and &ldquo;point&rdquo;:</p>
<table>
  <thead>
      <tr>
          <th>Hotkey</th>
          <th>Action Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>C-space</code></td>
          <td>Set mark (start selection)</td>
      </tr>
      <tr>
          <td><code>C-x C-x</code></td>
          <td>Exchange point and mark (swap selection endpoints)</td>
      </tr>
      <tr>
          <td><code>C-x h</code></td>
          <td>Select entire buffer</td>
      </tr>
  </tbody>
</table>
<p>The mark is where a selection begins, and the point is your cursor position. Together they define the &ldquo;region&rdquo; - Emacs&rsquo; term for a selection.</p>
<h3 id="file-operations">File Operations</h3>
<p>These commands handle file management tasks:</p>
<table>
  <thead>
      <tr>
          <th>Hotkey</th>
          <th>Action Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>C-x C-f</code></td>
          <td>Find (open) file</td>
      </tr>
      <tr>
          <td><code>C-x C-s</code></td>
          <td>Save current buffer</td>
      </tr>
      <tr>
          <td><code>C-x s</code></td>
          <td>Save all buffers</td>
      </tr>
      <tr>
          <td><code>C-x C-c</code></td>
          <td>Exit Emacs</td>
      </tr>
      <tr>
          <td><code>C-x d</code></td>
          <td>Open directory (dired)</td>
      </tr>
  </tbody>
</table>
<p>The <code>C-x C-f</code> command is particularly powerful as it allows you to create new files by entering paths that don&rsquo;t exist yet.</p>
<h3 id="buffer-management">Buffer Management</h3>
<p>In Emacs, a buffer is essentially an open file or space for editing:</p>
<table>
  <thead>
      <tr>
          <th>Hotkey</th>
          <th>Action Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>C-x b</code></td>
          <td>Switch buffer</td>
      </tr>
      <tr>
          <td><code>C-x k</code></td>
          <td>Kill (close) buffer</td>
      </tr>
  </tbody>
</table>
<p>Efficient buffer navigation is crucial when working with multiple files.</p>
<h3 id="window-management">Window Management</h3>
<p>Emacs allows for sophisticated window layouts:</p>
<table>
  <thead>
      <tr>
          <th>Hotkey</th>
          <th>Action Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>C-x 2</code></td>
          <td>Split window horizontally (one above the other)</td>
      </tr>
      <tr>
          <td><code>C-x 3</code></td>
          <td>Split window vertically (side by side)</td>
      </tr>
      <tr>
          <td><code>C-x o</code></td>
          <td>Switch to other window</td>
      </tr>
      <tr>
          <td><code>C-x 0</code></td>
          <td>Close current window</td>
      </tr>
      <tr>
          <td><code>C-x 1</code></td>
          <td>Close all windows except current</td>
      </tr>
      <tr>
          <td><code>C-x 5 2</code></td>
          <td>Create new frame (GUI window)</td>
      </tr>
  </tbody>
</table>
<p>The ability to split the editor into multiple windows, each showing different buffers, is one of Emacs&rsquo; most powerful features.</p>
<h3 id="search-and-replace">Search and Replace</h3>
<p>Finding and replacing text efficiently is essential for editing:</p>
<table>
  <thead>
      <tr>
          <th>Hotkey</th>
          <th>Action Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>C-s</code></td>
          <td>Incremental search forward</td>
      </tr>
      <tr>
          <td><code>C-r</code></td>
          <td>Incremental search backward</td>
      </tr>
      <tr>
          <td><code>M-%</code></td>
          <td>Query replace</td>
      </tr>
  </tbody>
</table>
<p>Emacs&rsquo; incremental search updates as you type, making it quick to locate specific text.</p>
<h3 id="help-system">Help System</h3>
<p>When you inevitably need guidance, Emacs has built-in help:</p>
<table>
  <thead>
      <tr>
          <th>Hotkey</th>
          <th>Action Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>C-h f</code></td>
          <td>Describe function</td>
      </tr>
      <tr>
          <td><code>C-h k</code></td>
          <td>Describe key</td>
      </tr>
      <tr>
          <td><code>C-h t</code></td>
          <td>Start tutorial</td>
      </tr>
  </tbody>
</table>
<p>The self-documenting nature of Emacs means help is always just a few keystrokes away.</p>
<h3 id="macros">Macros</h3>
<p>Macros are powerful tools for automating repetitive tasks:</p>
<table>
  <thead>
      <tr>
          <th>Hotkey</th>
          <th>Action Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>F3</code></td>
          <td>Start recording a keyboard macro</td>
      </tr>
      <tr>
          <td><code>F4</code></td>
          <td>Stop recording or execute the most recent keyboard macro</td>
      </tr>
  </tbody>
</table>
<p>To use macros: press F3, perform the sequence of actions you want to repeat, press F4 to finish recording, then press F4 again each time you want to replay those exact keystrokes. This is incredibly useful for mass operations on text.</p>
<h3 id="command-execution">Command Execution</h3>
<p>Finally, the gateway to thousands of Emacs commands:</p>
<table>
  <thead>
      <tr>
          <th>Hotkey</th>
          <th>Action Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>M-x</code></td>
          <td>Execute command by name</td>
      </tr>
  </tbody>
</table>
<p>This shortcut unlocks Emacs&rsquo; full potential, giving you access to any command by name.</p>
<h2 id="building-your-muscle-memory">Building Your Muscle Memory</h2>
<p>Learning these hotkeys will take time, but the productivity payoff is immense. Start by mastering the navigation and basic editing commands, then gradually incorporate the others. Consider printing this list and keeping it near your workspace until the keystrokes become automatic.</p>
<p>Remember that Emacs is highly customizable - once you&rsquo;re comfortable with these basics, you can create your own keybindings for commands you use frequently.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The beauty of Emacs lies in how it becomes an extension of your thinking process once you&rsquo;ve internalized these commands. Text manipulation becomes effortless, allowing you to focus on your actual work rather than the mechanics of editing.</p>
<p><img alt="emacs-mind" loading="lazy" src="/post/essential-emacs-hotkeys/emacs-mind.png"></p>
<p>While this guide covers the essential hotkeys, it barely scratches the surface of what Emacs can do. As you grow more comfortable with these basics, explore specialized modes for your particular work, whether that&rsquo;s programming in specific languages, writing prose, managing projects, or organizing your life.</p>
<p>What began as a seemingly steep learning curve will transform into a powerful skillset that follows you throughout your computing life. Happy editing!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Lessons Learned from Journaling with Emacs org-journal-mode</title>
      <link>https://blog.0x17.de/post/lessons-org-journaling/</link>
      <pubDate>Fri, 28 Mar 2025 00:00:00 +0100</pubDate>
      <guid>https://blog.0x17.de/post/lessons-org-journaling/</guid>
      <description>&lt;p&gt;As I delve into the intricacies of Emacs and its powerful org-mode ecosystem, I&amp;rsquo;ve discovered that org-journal has transformed my daily note-taking and task management workflow. Looking at the &lt;a href=&#34;https://github.com/0x17de/emacs-config&#34;&gt;configuration shared&lt;/a&gt;, there are several valuable insights worth highlighting for anyone looking to enhance their personal knowledge management system.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Journaling with org-mode&#34; loading=&#34;lazy&#34; src=&#34;https://blog.0x17.de/post/lessons-org-journaling/org-mode.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-power-of-daily-granularity&#34;&gt;The Power of Daily Granularity&lt;/h2&gt;
&lt;p&gt;One of the most impactful lessons I&amp;rsquo;ve learned is the importance of splitting journals into smaller, more manageable chunks. The configuration sets up org-journal with daily entries rather than maintaining one massive file for an entire year&amp;rsquo;s worth of thoughts and tasks. This approach offers several benefits:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>As I delve into the intricacies of Emacs and its powerful org-mode ecosystem, I&rsquo;ve discovered that org-journal has transformed my daily note-taking and task management workflow. Looking at the <a href="https://github.com/0x17de/emacs-config">configuration shared</a>, there are several valuable insights worth highlighting for anyone looking to enhance their personal knowledge management system.</p>
<p><img alt="Journaling with org-mode" loading="lazy" src="/post/lessons-org-journaling/org-mode.png"></p>
<h2 id="the-power-of-daily-granularity">The Power of Daily Granularity</h2>
<p>One of the most impactful lessons I&rsquo;ve learned is the importance of splitting journals into smaller, more manageable chunks. The configuration sets up org-journal with daily entries rather than maintaining one massive file for an entire year&rsquo;s worth of thoughts and tasks. This approach offers several benefits:</p>
<ul>
<li><strong>Improved Performance</strong>: Smaller files load faster and are less likely to cause Emacs to slow down</li>
<li><strong>Better Organization</strong>: Daily or weekly files create natural boundaries for your thoughts</li>
<li><strong>Easier Navigation</strong>: Finding specific entries becomes simpler when they&rsquo;re organized by date</li>
</ul>
<p>My configuration explicitly sets <code>org-journal-dir</code> to &ldquo;~/org/journal&rdquo; and uses the format (YYYYMMDD) for consistency and easy sorting.</p>
<h2 id="task-migration-never-lose-track-again">Task Migration: Never Lose Track Again</h2>
<p>A game-changing feature in org-journal is its ability to automatically move unfinished tasks to the next day&rsquo;s entry. This prevents tasks from being forgotten in past journal entries and keeps your current day&rsquo;s focus on what still needs attention.</p>
<h2 id="effective-agenda-management">Effective Agenda Management</h2>
<p>The configuration reveals a crucial insight: simply journaling isn&rsquo;t enough—you need to leverage org&rsquo;s scheduling and deadline functions to create an effective overview of your commitments. The custom function <code>_0x17de/org-highlight-todays-deadlines</code> applies special highlighting to items due today, creating visual urgency for time-sensitive tasks.</p>
<h2 id="enhanced-task-states-with-custom-keywords">Enhanced Task States with Custom Keywords</h2>
<p>The standard TODO/DONE paradigm often feels inadequate for complex workflows. This configuration expands the vocabulary of task states:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(setq org-todo-keywords <span style="color:#f92672">&#39;</span>((sequence <span style="color:#e6db74">&#34;TODO&#34;</span> <span style="color:#e6db74">&#34;WAITING&#34;</span> <span style="color:#e6db74">&#34;DOING&#34;</span> <span style="color:#e6db74">&#34;|&#34;</span> <span style="color:#e6db74">&#34;DONE&#34;</span> <span style="color:#e6db74">&#34;CANCELLED&#34;</span>)))
</span></span></code></pre></div><p>Adding intermediate states like &ldquo;WAITING&rdquo; and &ldquo;DOING&rdquo; provides more context about where each task stands without requiring additional notes. The vertical bar separates active states from terminal states, a subtle but important distinction.</p>
<h2 id="visual-differentiation-through-custom-styling">Visual Differentiation Through Custom Styling</h2>
<p>The configuration goes beyond mere keywords by defining custom faces for different task states:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-elisp" data-lang="elisp"><span style="display:flex;"><span>(org-modern-todo-faces <span style="color:#f92672">&#39;</span>((<span style="color:#e6db74">&#34;TODO&#34;</span> :foreground <span style="color:#e6db74">&#34;white&#34;</span> :background <span style="color:#e6db74">&#34;darkgreen&#34;</span> :weight bold)
</span></span><span style="display:flex;"><span>                        (<span style="color:#e6db74">&#34;DOING&#34;</span> :foreground <span style="color:#e6db74">&#34;white&#34;</span> :background <span style="color:#e6db74">&#34;orange&#34;</span> :weight bold)
</span></span><span style="display:flex;"><span>                        (<span style="color:#e6db74">&#34;WAITING&#34;</span> :foreground <span style="color:#e6db74">&#34;white&#34;</span> :background <span style="color:#e6db74">&#34;blue&#34;</span>)))
</span></span></code></pre></div><p>This color-coding creates immediate visual feedback, making it easy to scan a journal page and instantly understand what&rsquo;s in progress versus what&rsquo;s waiting on external factors.</p>
<h2 id="modern-interface-enhancements">Modern Interface Enhancements</h2>
<p>The use of <code>org-modern-mode</code> suggests an appreciation for clean, contemporary styling. This package enhances the visual appeal of org files with improved typography and modern design elements, making the journaling experience more pleasant.</p>
<h2 id="exploring-new-frontiers-org-node">Exploring New Frontiers: org-node</h2>
<p>The configuration hints at exploration of <code>org-node</code>, a powerful package that enables treating org headings as nodes in a graph. This approach opens up interesting possibilities for knowledge management and connecting ideas across different journal entries and documents.</p>
<h2 id="convenient-keybindings-for-quick-capture">Convenient Keybindings for Quick Capture</h2>
<p>Setting up a global keybinding (<code>C-M-S-j</code>) for creating new journal entries reduces friction in the journaling process. The fewer barriers to capturing thoughts, the more likely you are to maintain the practice consistently.</p>
<h2 id="integration-with-the-agenda">Integration with the Agenda</h2>
<p>The configuration enables agenda integration with <code>org-journal-enable-agenda-integration</code>, ensuring that tasks and events from journal entries appear in your org-agenda views. This creates a unified system where your journal and task management seamlessly work together.</p>
<h2 id="whats-next">What&rsquo;s Next?</h2>
<p>For those inspired to explore this setup further, my complete Emacs configuration is available at <a href="https://github.com/0x17de/emacs-config">https://github.com/0x17de/emacs-config</a>. It offers additional insights into how these journaling practices fit into a broader productivity system.</p>
<p>As my own journey with org-journal continues, I&rsquo;m particularly interested in diving deeper into <code>org-node</code> and exploring how graph-based knowledge management might enhance connections between journal entries over time.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
