<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>GNU Emacs on Free Range Bits</title>
    <link>https://freerangebits.com/tags/emacs/</link>
    <description>Recent content in GNU Emacs on Free Range Bits</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 24 Feb 2025 12:23:47 +0100</lastBuildDate>
    <atom:link href="https://freerangebits.com/tags/emacs/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Automatic Theme Switching in Emacs</title>
      <link>https://freerangebits.com/posts/2025/02/emacs-light-dark/</link>
      <pubDate>Mon, 24 Feb 2025 12:23:47 +0100</pubDate>
      <guid>https://freerangebits.com/posts/2025/02/emacs-light-dark/</guid>
      <description>&lt;img alt=&#34;Screenshot showing both a light and dark theme applied.&#34; src=&#34;light-dark.png&#34;&gt;&#xA;&lt;p&gt;I&amp;rsquo;m a dark theme nerd.  Partially because of the hacker aesthetic, but&#xA;mostly because I prefer to work in dark environments and light themes&#xA;turn computer screens into floodlights.&lt;/p&gt;&#xA;&lt;p&gt;However, in well lit rooms (or when working outdoors) dark themes&#xA;become completely unreadable.  Such is the case in my office during&#xA;the morning hours.  Naturally, I figured out how to change the system&#xA;theme from the command line, immediately updating running GTK and Qt&#xA;applications.  The next step was getting Emacs to respond to the same&#xA;event.&lt;/p&gt;&#xA;&lt;h2 id=&#34;theme-switching-and-d-bus&#34;&gt;Theme Switching and D-Bus&lt;/h2&gt;&#xA;&lt;p&gt;Linux and other Unix-like operating systems use &lt;a href=&#34;https://www.freedesktop.org/wiki/Software/dbus/&#34; target=&#34;_blank&#34;&gt;D-Bus&lt;/a&gt; for&#xA;interprocess communication.  Applications can use D-Bus to register&#xA;methods and properties which can be accessed and monitored from any&#xA;D-Bus client.  For example, to find out whether the system is&#xA;currently using a light or dark theme, call the&#xA;&lt;code&gt;org.freedesktop.portal.Settings.Read&lt;/code&gt; method from the command line&#xA;using the &lt;code&gt;dbus-send&lt;/code&gt; tool:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dbus-send --session --print-reply &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;  --dest&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;org.freedesktop.portal.Desktop &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;  /org/freedesktop/portal/desktop &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;  org.freedesktop.portal.Settings.Read &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;  string:org.freedesktop.appearance string:color-scheme&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This command will print &lt;code&gt;1&lt;/code&gt; when the system is using a dark theme and&#xA;&lt;code&gt;2&lt;/code&gt; when using a light theme (plus some other stuff you can ignore).&lt;/p&gt;&#xA;&lt;p&gt;With that information in hand we need to get Emacs to do two things:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Call this method when starting up and set its theme to match the&#xA;system, and&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Monitor the &lt;code&gt;color-scheme&lt;/code&gt; property and change its theme&#xA;automatically when the system theme changes.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;emacs-groundwork&#34;&gt;Emacs Groundwork&lt;/h2&gt;&#xA;&lt;p&gt;In order to get Emacs to change its theme we&amp;rsquo;ll need a way to store&#xA;our preferred dark and light themes, and a way to change the current&#xA;theme based on the results of a D-Bus call:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(defvar pjones:dark-theme &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ef-maris-dark&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Default dark theme.&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(defvar pjones:light-theme &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ef-maris-light&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Default light theme.&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(defun pjones:theme-from-dbus (value)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Change the theme based on a D-Bus property.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;VALUE should be an integer or an arbitrarily nested list that&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;contains an integer.  When VALUE is equal to 2 then a light theme&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;will be selected, otherwise a dark theme will be selected.&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (load-theme (&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;car&lt;/span&gt; (flatten-list value)))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  pjones:light-theme&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                pjones:dark-theme)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#66d9ef&#34;&gt;t&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You might be wondering what &lt;code&gt;flatten-list&lt;/code&gt; is for.  It turns out that&#xA;D-Bus gives two different types of answers depending on how you&#xA;requested a property.  When invoking a D-Bus method, the result comes&#xA;back to Emacs as a list.  For example, when requesting the current&#xA;color scheme using the &lt;code&gt;Read&lt;/code&gt; method the response will be &lt;code&gt;(1)&lt;/code&gt; or&#xA;&lt;code&gt;(2)&lt;/code&gt; depending on whether the current system theme is dark or light.&lt;/p&gt;&#xA;&lt;p&gt;However, when the property changes and D-Bus notifies clients that are&#xA;listening for change events, Emacs sees the property as a nested list.&#xA;In this case the color scheme value will be &lt;code&gt;((1))&lt;/code&gt; or &lt;code&gt;((2))&lt;/code&gt;.  The&#xA;call to &lt;code&gt;flatten-list&lt;/code&gt; ensures that both of these situations look the&#xA;same to the callback function (&lt;code&gt;pjones:theme-from-dbus&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;p&gt;The only thing left is to convince Emacs to set its theme using&#xA;information from D-Bus.&lt;/p&gt;&#xA;&lt;h2 id=&#34;using-d-bus-from-within-emacs&#34;&gt;Using D-Bus from within Emacs&lt;/h2&gt;&#xA;&lt;p&gt;It should come as no surprise that Emacs ships with its own D-Bus&#xA;library.  To find out what the current color scheme is we can call the&#xA;&lt;code&gt;Read&lt;/code&gt; method using &lt;code&gt;dbus-call-method-asynchronously&lt;/code&gt;.  And then to be&#xA;notified when the system theme changes we can use&#xA;&lt;code&gt;dbus-register-signal&lt;/code&gt; to be notified when the &lt;code&gt;SettingChanged&lt;/code&gt; event&#xA;is emitted.  The arguments to these functions are a bit crazy but they&#xA;mirror those given to the &lt;code&gt;dbus-send&lt;/code&gt; tool.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;dbus&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;;; Set the current theme based on what the system theme is right now:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(dbus-call-method-asynchronously&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#e6db74&#34;&gt;:session&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;org.freedesktop.portal.Desktop&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/org/freedesktop/portal/desktop&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;org.freedesktop.portal.Settings&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Read&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#a6e22e&#34;&gt;#&amp;#39;&lt;/span&gt;pjones:theme-from-dbus&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;org.freedesktop.appearance&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;color-scheme&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;;; Register to be notified when the system theme changes:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(dbus-register-signal&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#e6db74&#34;&gt;:session&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;org.freedesktop.portal.Desktop&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/org/freedesktop/portal/desktop&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;org.freedesktop.portal.Settings&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;SettingChanged&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (lambda (path var value)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (when (and (&lt;span style=&#34;color:#a6e22e&#34;&gt;string-equal&lt;/span&gt; path &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;org.freedesktop.appearance&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#a6e22e&#34;&gt;string-equal&lt;/span&gt; var &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;color-scheme&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (pjones:theme-from-dbus value))))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it.  Switching the system color scheme should now cause Emacs&#xA;to update its theme too.  And when Emacs starts it should&#xA;automatically set its theme to match the system theme.&lt;/p&gt;&#xA;&lt;h2 id=&#34;command-line-theme-switching&#34;&gt;Command Line Theme Switching&lt;/h2&gt;&#xA;&lt;p&gt;I mentioned earlier that I figured out how to change the system theme&#xA;using the command line.  The most reliable way that I have found so&#xA;far is to use &lt;code&gt;gsettings&lt;/code&gt;, which also emits the &lt;code&gt;SettingChanged&lt;/code&gt; event&#xA;via D-Bus:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsettings set org.gnome.desktop.interface color-scheme prefer-dark&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsettings set org.gnome.desktop.interface gtk-theme Adwaita-dark&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# or&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsettings set org.gnome.desktop.interface color-scheme prefer-light&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsettings set org.gnome.desktop.interface gtk-theme Adwaita&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second invocation of &lt;code&gt;gsettings&lt;/code&gt; (changing the GTK theme) isn&amp;rsquo;t&#xA;strictly necessary.  However, I configured Qt to use the GTK theme and&#xA;this is the only way I could get Qt applications to also change their&#xA;color scheme as they don&amp;rsquo;t appear to respect the &lt;code&gt;color-scheme&lt;/code&gt;&#xA;setting.&lt;/p&gt;&#xA;&lt;p&gt;I also wrapped these commands up in XDG desktop entries so I could&#xA;invoke them from tools like Rofi.&lt;/p&gt;&#xA;&lt;h2 id=&#34;appendix-gtk-and-qt-themes&#34;&gt;Appendix: GTK and Qt Themes&lt;/h2&gt;&#xA;&lt;p&gt;It probably matters how I configured GTK and Qt, although these don&amp;rsquo;t&#xA;have anything to do with Emacs.  Basically, GTK is set to use the&#xA;&lt;code&gt;Adwaita-dark&lt;/code&gt; theme, and Qt is configured to use its &lt;code&gt;gtk3&lt;/code&gt; engine&#xA;which should follow the current GTK theme.  This works for almost all&#xA;Qt applications, although some refuse to update to the light theme.&lt;/p&gt;&#xA;&lt;p&gt;All of my GTK/Qt settings are done using &lt;a href=&#34;https://github.com/nix-community/home-manager&#34; target=&#34;_blank&#34;&gt;Home Manager&lt;/a&gt; in &lt;a href=&#34;https://github.com/pjones/desktop-scripts/blob/trunk/home/theme.nix&#34; target=&#34;_blank&#34;&gt;this&#xA;file&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Patching Instead of Pinning</title>
      <link>https://freerangebits.com/posts/2024/01/patch-instead-of-pin/</link>
      <pubDate>Sat, 06 Jan 2024 11:44:19 -0700</pubDate>
      <guid>https://freerangebits.com/posts/2024/01/patch-instead-of-pin/</guid>
      <description>&lt;p&gt;In &lt;a href=&#34;https://freerangebits.com/posts/2023/12/gnupg-broke-emacs&#34;&gt;a previous post&lt;/a&gt; I showed how to work around a deadlock&#xA;between GnuPG and Emacs.  As a brief recap, GnuPG 2.4.1 introduced a&#xA;change in its output which breaks a protocol that Emacs relied on, so&#xA;I pinned GnuPG to version 2.4.0 on my system to avoid the bug.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/DamienCassou&#34; target=&#34;_blank&#34;&gt;Damien Cassou&lt;/a&gt; reached out to me and expressed a&#xA;preferred way of dealing with this issue: patch the current version of&#xA;GnuPG so it doesn&amp;rsquo;t contain the bug.  This means we get to keep any&#xA;bug fixes and security updates in the most recent version without&#xA;having to suffer with the deadlock bug.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m going to demonstrate how to apply a patch to GnuPG in nixpkgs, but&#xA;before that let&amp;rsquo;s review the Nix code for pinning GnuPG to version&#xA;2.4.0.&lt;/p&gt;&#xA;&lt;h2 id=&#34;pinning-the-gnupg-package&#34;&gt;Pinning the GnuPG Package&lt;/h2&gt;&#xA;&lt;p&gt;In the last post we looked at three different options for pinning&#xA;GnuPG:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;A nixpkgs overlay to replace GnuPG globally&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Replace the version of GnuPG that shows up in the system &lt;code&gt;PATH&lt;/code&gt;&#xA;via the NixOS module&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Replace the version of GnuPG that shows up in the user&#xA;environment via the Home Manager module&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;My preference was for the last option, using Home Manager:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{ pkgs }:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  programs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gpg&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;package &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; pkgs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gnupg&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;overrideAttrs (orig: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    version &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.4.0&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    src &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; pkgs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;fetchurl {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      url &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mirror://gnupg/gnupg/gnupg-2.4.0.tar.bz2&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      hash &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256-HXkVjdAdmSQx3S4/rLif2slxJ/iXhOosthDGAPsMFIM=&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, I didn&amp;rsquo;t really explain what was going on in that Nix code.&#xA;I&amp;rsquo;d like to give that a try now.&lt;/p&gt;&#xA;&lt;h2 id=&#34;overriding-nix-packages&#34;&gt;Overriding Nix Packages&lt;/h2&gt;&#xA;&lt;p&gt;One way to think about a package written in Nix is as a set of&#xA;attributes.  (Of course, this isn&amp;rsquo;t true, but it&amp;rsquo;s a useful analogy&#xA;and allows us to continue without having to talk about lazy evaluation&#xA;and fixpoints.)  These attribute sets are immutable so we can&amp;rsquo;t change&#xA;them.  But what we can do is build new packages from existing ones.&lt;/p&gt;&#xA;&lt;p&gt;This is done with the &lt;code&gt;overrideAttrs&lt;/code&gt; function, which allows us to&#xA;create a new package by replacing attributes in an existing package.&#xA;The argument to &lt;code&gt;overrideAttrs&lt;/code&gt; is a function that is given the&#xA;existing attributes and should return replacement attributes.&lt;/p&gt;&#xA;&lt;p&gt;In the Nix code above that pins GnuPG to version 2.4.0, I replaced the&#xA;&lt;code&gt;version&lt;/code&gt; and &lt;code&gt;src&lt;/code&gt; attributes.  The result is a new package based on&#xA;the existing GnuPG 2.4.1 package, except that the upstream source code&#xA;is now coming from the GnuPG 2.4.0 tarball.&lt;/p&gt;&#xA;&lt;p&gt;This won&amp;rsquo;t always work, but it does in this case because GnuPG 2.4.0&#xA;and 2.4.1 are so similar.  If I tried to update the GnuPG package by&#xA;replacing its source code with that of the Linux kernel things&#xA;wouldn&amp;rsquo;t turn out so nicely.&lt;/p&gt;&#xA;&lt;p&gt;The most interesting thing about &lt;code&gt;overrideAttrs&lt;/code&gt; is that we can&#xA;replace &lt;em&gt;any&lt;/em&gt; package attribute we want.  I&amp;rsquo;ve used this to great&#xA;effect over the years: adding shell commands to the end of install&#xA;scripts, changing compiler flags, installing files that were missed by&#xA;&lt;code&gt;make install&lt;/code&gt;, to name a few.&lt;/p&gt;&#xA;&lt;p&gt;And of course, we can use this to apply patches to the source code&#xA;before building.&lt;/p&gt;&#xA;&lt;h2 id=&#34;patching-the-package-instead&#34;&gt;Patching the Package Instead&lt;/h2&gt;&#xA;&lt;p&gt;Nix packages have an optional &lt;code&gt;patches&lt;/code&gt; attribute which is a list of&#xA;patch files to apply to the source code before building.  And thanks&#xA;to &lt;code&gt;overrideAttrs&lt;/code&gt; we can add patches to that list:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;final: prev:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gnupg_plus_960877b &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; prev&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gnupg&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;overrideAttrs (orig: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    patches &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (orig&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;patches or [ ]) &lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (prev&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;fetchurl {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        url &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://github.com/gpg/gnupg/commit/960877b10f42ba664af4fb29130a3ba48141e64a.diff&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sha256 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;0pa7rvy9i9w16njxdg6ly5nw3zwy0shv0v23l1mmi0b7jy7ldpvf&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This example is an overlay and is straight &lt;a href=&#34;https://github.com/pjones/tilde&#34; target=&#34;_blank&#34;&gt;out of my Nix&#xA;configuration&lt;/a&gt;.  It creates a &lt;a href=&#34;https://github.com/pjones/tilde/blob/4fb2d93c2fc475e48b457dd3b4ddda9f18fa0ea8/pkgs/overlay.nix#L31&#34; target=&#34;_blank&#34;&gt;new package&lt;/a&gt;&#xA;(&lt;code&gt;gnupg_plus_960877b&lt;/code&gt;) from the exiting &lt;code&gt;gnupg&lt;/code&gt; package by replacing&#xA;the &lt;code&gt;patches&lt;/code&gt; attribute with one that includes the fix for the&#xA;deadlock bug.&lt;/p&gt;&#xA;&lt;p&gt;I ensure that I&amp;rsquo;m including patches from the package I&amp;rsquo;m modifying by&#xA;using the original patches list (&lt;code&gt;orig.patches&lt;/code&gt;), or if that&amp;rsquo;s&#xA;missing, an empty list.  Then I append (&amp;quot;&lt;code&gt;++&lt;/code&gt;&amp;quot;) a list with one&#xA;element which uses &lt;code&gt;fetchurl&lt;/code&gt; to get the patch I want.&lt;/p&gt;&#xA;&lt;p&gt;The only thing left to do is tell Home Manager to use this new&#xA;package:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{ pkgs }:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  programs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gpg&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;package &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; pkgs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gnupg_plus_960877b;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;Nix and nixpkgs make it very easy to alter an existing package thanks&#xA;to the &lt;code&gt;overrideAttrs&lt;/code&gt; function.  Using nixpkgs overlays we can even&#xA;replace a package globally throughout the package set.&lt;/p&gt;&#xA;&lt;p&gt;Sometimes we may want to alter a package&amp;rsquo;s &lt;code&gt;src&lt;/code&gt; attribute to&#xA;downgrade (or upgrade) it to another version.  In this case we took&#xA;&lt;a href=&#34;https://github.com/DamienCassou&#34; target=&#34;_blank&#34;&gt;Damien Cassou&amp;rsquo;s&lt;/a&gt; advice and applied a patch to the&#xA;exiting GnuPG package.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;&lt;strong&gt;Update (February 23, 2024)&lt;/strong&gt;: GnuPG 2.4.4 has been released and it&#xA;contains the patch mentioned in this post.  In other words, GnuPG&#xA;2.4.4 and Emacs work nicely together once again.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Archiving in Org Mode</title>
      <link>https://freerangebits.com/posts/2024/01/archiving-in-org-mode/</link>
      <pubDate>Thu, 04 Jan 2024 12:45:09 -0700</pubDate>
      <guid>https://freerangebits.com/posts/2024/01/archiving-in-org-mode/</guid>
      <description>&lt;p&gt;As some of you may know, I practically live inside &lt;a href=&#34;https://freerangebits.com/tags/emacs/&#34;&gt;Emacs&lt;/a&gt;.&#xA;And like a lot of Emacs users a good portion of that time is spend in&#xA;&lt;a href=&#34;https://orgmode.org/&#34; target=&#34;_blank&#34;&gt;org-mode&lt;/a&gt;, a package that is hard to describe due to its&#xA;overwhelming large number of features.&lt;/p&gt;&#xA;&lt;p&gt;One of the many ways I use org-mode is to implement a Getting Things&#xA;Done (GTD) workflow.  That is, managing all of the projects that I&amp;rsquo;m&#xA;trying to push forward as well as all of the routine recurring tasks&#xA;that I have to deal with on a daily basis.&lt;/p&gt;&#xA;&lt;p&gt;The issue that every org-mode user eventually has to wrestle with is&#xA;what to do with all those completed projects and obsolete tasks.  For&#xA;some projects the obvious answer is to simply delete them.  This is&#xA;especially true if you&amp;rsquo;re using a version control system to track your&#xA;org-mode files.  But if you regularly need to refer to completed&#xA;projects/tasks (i.e. &amp;ldquo;what was that crazy query I ran last time?&amp;rdquo;)&#xA;then archiving is a better option.&lt;/p&gt;&#xA;&lt;h2 id=&#34;archiving-options-in-org-mode&#34;&gt;Archiving Options in org-mode&lt;/h2&gt;&#xA;&lt;p&gt;In org-mode, archiving is the process of moving a subtree somewhere&#xA;else when it&amp;rsquo;s no longer needed&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.  The destination for an&#xA;archived subtree is taken from the &lt;code&gt;org-archive-location&lt;/code&gt; variable.&lt;/p&gt;&#xA;&lt;p&gt;By default, org-mode will move the subtree to another file whose name&#xA;is derived from the name of the current file by appending &amp;ldquo;&lt;code&gt;_archive&lt;/code&gt;&amp;rdquo;&#xA;to the name, but before the extension.  That said, like everything in&#xA;Emacs, the options for configuring the archive destination are&#xA;virtually limitless.&lt;/p&gt;&#xA;&lt;p&gt;A really common way to configure archiving is to use a dedicated file,&#xA;usually &lt;code&gt;archive.org&lt;/code&gt;.  Whether you use a single archive file or the&#xA;default strategy of using a file named after the current one, you will&#xA;ultimately run into the same problem, huge unwieldy org-mode files.&lt;/p&gt;&#xA;&lt;p&gt;I think there&amp;rsquo;s a better way to archive projects and tasks: use a lot&#xA;of small files.  Specifically, when I archive a subtree in org-mode I&#xA;send the subtree to the current day&amp;rsquo;s journal entry.&lt;/p&gt;&#xA;&lt;h2 id=&#34;using-the-org-roam-journal&#34;&gt;Using the org-roam Journal&lt;/h2&gt;&#xA;&lt;p&gt;I maintain my personal knowledge base in org-mode thanks to&#xA;&lt;a href=&#34;https://www.orgroam.com/&#34; target=&#34;_blank&#34;&gt;org-roam&lt;/a&gt;.  One of its features is the ability to manage&#xA;journal entries.  The journal system in org-roam is simply a&#xA;collection of subtrees in a one-file-per-day organization scheme.  In&#xA;other words, each day gets a new org-mode file and throughout the day&#xA;I add headings to the file in order to record certain events.&lt;/p&gt;&#xA;&lt;p&gt;When I archive a subtree from somewhere in my vast collection of&#xA;notes, org-mode stores it in one of my journal files.  The specific&#xA;journal file used is based on the date chosen from a prompt when I run&#xA;the following archiving function:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(defun pjones:org-archive-subtree-to-daily (&lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;optional&lt;/span&gt; _find-done)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Arhive the current subtree to the roam daily file.&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (interactive)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (require &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;org-roam&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (when-let* ((today (save-excursion&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       (org-roam-dailies-goto-date &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;d&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       (&lt;span style=&#34;color:#a6e22e&#34;&gt;buffer-file-name&lt;/span&gt;)))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (org-archive-location&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               (&lt;span style=&#34;color:#a6e22e&#34;&gt;concat&lt;/span&gt; today &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;::* Archived From %s&amp;#34;&lt;/span&gt;)))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (org-archive-subtree &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can tell org-mode that you want this to be your archiving function&#xA;by setting &lt;code&gt;org-archive-default-command&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(custom-set-variables&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;&lt;/span&gt;(org-archive-default-command &lt;span style=&#34;color:#a6e22e&#34;&gt;#&amp;#39;&lt;/span&gt;pjones:org-archive-subtree-to-daily))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After which you can archive the current subtree with the normal key&#xA;binding &amp;ldquo;&lt;code&gt;C-c C-x C-a&lt;/code&gt;&amp;rdquo;.  This leaves &amp;ldquo;&lt;code&gt;C-c C-x C-s&lt;/code&gt;&amp;rdquo; alone if you&#xA;want to use the built in system which relies on&#xA;&lt;code&gt;org-archive-location&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;(Note: I have both daily and monthly journal files.  To avoid being&#xA;asked which one I want to archive to I pass &amp;ldquo;&lt;code&gt;d&lt;/code&gt;&amp;rdquo; as the second&#xA;argument to &lt;code&gt;org-roam-dailies-goto-date&lt;/code&gt;.  This bypasses the prompt&#xA;and goes directly to the daily journal file.)&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;I find it easier to manage many small files verses a small number of&#xA;huge files.  To avoid a massive &lt;code&gt;archive.org&lt;/code&gt; file I archive subtrees&#xA;into my org-roam journal.  This makes it a lot easier to find what I&amp;rsquo;m&#xA;looking for and provides a bit of context when found.  And it pairs&#xA;perfectly with &lt;a href=&#34;https://github.com/dajva/rg.el&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;rg-project&lt;/code&gt;&lt;/a&gt; and&#xA;&lt;a href=&#34;https://github.com/minad/consult&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;consult-ripgrep&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;You can also tag the current subtree with the &lt;code&gt;ARCHIVE&lt;/code&gt;&#xA;tag which darkens the heading and keeps the tree collapsed.  This can&#xA;be done with the &lt;code&gt;org-toggle-archive-tag&lt;/code&gt; function or the &amp;ldquo;&lt;code&gt;C-c C-x a&lt;/code&gt;&amp;rdquo; key binding.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Pinning GnuPG with nixpkgs</title>
      <link>https://freerangebits.com/posts/2023/12/gnupg-broke-emacs/</link>
      <pubDate>Sun, 31 Dec 2023 10:49:30 -0700</pubDate>
      <guid>https://freerangebits.com/posts/2023/12/gnupg-broke-emacs/</guid>
      <description>&lt;p&gt;GnuPG 2.4.1 was released all the way back in May but I failed to&#xA;notice until I upgraded to NixOS 23.11 a few weeks ago.  And I only&#xA;noticed because Emacs froze when I tried to save an encrypted file.&#xA;It didn&amp;rsquo;t take me long to realize it was due to a &lt;a href=&#34;https://dev.gnupg.org/T6481&#34; target=&#34;_blank&#34;&gt;change in&#xA;GnuPG&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;emacs-and-encrypted-files&#34;&gt;Emacs and Encrypted Files&lt;/h2&gt;&#xA;&lt;p&gt;When working with encrypted files Emacs goes to great lengths to&#xA;ensure the unencrypted cleartext is never written to the file system.&#xA;It does this by invoking GnuPG directly and communicating with it&#xA;using pipes.  Thus, to write to an encrypted file, Emacs sends the&#xA;cleartext down the pipe and GnuPG writes the encrypted contents to a&#xA;file.&lt;/p&gt;&#xA;&lt;p&gt;Just before Emacs sends the cleartext down the pipe to GnuPG it waits&#xA;for GnuPG to signal that it&amp;rsquo;s ready to read cleartext.  The problem&#xA;with GnuPG (versions 2.4.1 through 2.4.3) is that it sends this signal&#xA;&lt;em&gt;after&lt;/em&gt; it reads from standard input.  In other words, both Emacs and&#xA;GnuPG are waiting for one another at the same time, resulting in a&#xA;classic I/O deadlock.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-workaround&#34;&gt;The Workaround&lt;/h2&gt;&#xA;&lt;p&gt;The Emacs maintainers &lt;a href=&#34;https://debbugs.gnu.org/cgi/bugreport.cgi?bug=63256&#34; target=&#34;_blank&#34;&gt;consider this situation&lt;/a&gt; a bug in GnuPG.&#xA;And after a few days the GnuPG maintainers &lt;a href=&#34;https://dev.gnupg.org/rG960877b10f42ba664af4fb29130a3ba48141e64a&#34; target=&#34;_blank&#34;&gt;fixed the bug&lt;/a&gt;.  It&#xA;will be part of GnuPG 2.4.4 release.  Until then the solution is to&#xA;downgrade GnuPG.  The Emacs &lt;code&gt;PROBLEMS&lt;/code&gt; file says:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The only known workaround is to downgrade to a version of GnuPG&#xA;older than 2.4.1 (or, in the future, upgrade to a newer version&#xA;which solves the problem, when such a fixed version becomes&#xA;available).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;pinning-packages-in-nixpkgs&#34;&gt;Pinning Packages in nixpkgs&lt;/h2&gt;&#xA;&lt;p&gt;This presents the perfect opportunity to demonstrate several ways that&#xA;nixpkgs ecosystem allows us to solve the problem of downgrading a&#xA;package, sometimes called package pinning.&lt;/p&gt;&#xA;&lt;p&gt;The easiest solution is to use an &lt;em&gt;overlay&lt;/em&gt;, a function that takes the&#xA;current package set and returns a new package set.  The overlay below&#xA;replaces the &lt;code&gt;gnupg&lt;/code&gt; package with one pinned at version 2.4.0:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;final: prev:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gnupg &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; prev&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gnupg&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;overrideAttrs (orig: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    version &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.4.0&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    src &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; prev&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;fetchurl {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      url &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mirror://gnupg/gnupg/gnupg-2.4.0.tar.bz2&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      hash &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256-HXkVjdAdmSQx3S4/rLif2slxJ/iXhOosthDGAPsMFIM=&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice that the overlay function actually takes two arguments.  The&#xA;second argument (&lt;code&gt;prev&lt;/code&gt;) is the previous package set, the one we want&#xA;to alter.  Since overlays can be chained together we may be&#xA;manipulating the original package set or one from a previous overlay.&lt;/p&gt;&#xA;&lt;p&gt;Sometimes we need access to the package set the way it will be after&#xA;all overlays have been applied.  For example, wanting to use a&#xA;dependency from a later overlay in the current overlay.  In this case&#xA;the first argument (&lt;code&gt;final&lt;/code&gt;) comes in handy, it&amp;rsquo;s the final package&#xA;set after all overlays have been applied.  (This is possible thanks to&#xA;Nix being a lazy language and the use of &lt;a href=&#34;https://en.wikipedia.org/wiki/Fixed-point_combinator&#34; target=&#34;_blank&#34;&gt;fixpoints&lt;/a&gt;.)&lt;/p&gt;&#xA;&lt;h2 id=&#34;livin-la-vida-gentoo&#34;&gt;Livin&amp;rsquo; La Vida Gentoo&lt;/h2&gt;&#xA;&lt;p&gt;Unfortunately, using an overlay to pin GnuPG comes at a cost.  It&#xA;turns out that GnuPG is a dependency in &lt;em&gt;a lot&lt;/em&gt; of packages.  This&#xA;means that after applying the overlay, nixpkgs will determine that all&#xA;of those packages need to be rebuilt, and we won&amp;rsquo;t be able to take&#xA;advantage of the binary cache (because the cache was built with GnuPG&#xA;2.4.1).&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t have the patience of a Gentoo user and compiling a ton of&#xA;packages from source isn&amp;rsquo;t my idea of a good time.  Besides, it&amp;rsquo;s a&#xA;terrible use of the power grid.  Thankfully, we have other options.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-nixos-module&#34;&gt;The NixOS Module&lt;/h2&gt;&#xA;&lt;p&gt;If you use NixOS then the easiest way to install and configure GnuPG&#xA;is via the NixOS module:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  programs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gnupg&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;enable &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The NixOS module also has a &lt;a href=&#34;https://search.nixos.org/options?query=programs.gnupg&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;package&lt;/code&gt; option&lt;/a&gt; so users&#xA;can override the GnuPG package.  Taking the overlay code from above we&#xA;can write our own NixOS module and load it into our system&#xA;configuration (via the normal &lt;code&gt;imports&lt;/code&gt; list mechanism):&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{ pkgs }:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  programs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gnupg&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;package &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; pkgs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gnupg&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;overrideAttrs (orig: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    version &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.4.0&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    src &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; pkgs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;fetchurl {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      url &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mirror://gnupg/gnupg/gnupg-2.4.0.tar.bz2&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      hash &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256-HXkVjdAdmSQx3S4/rLif2slxJ/iXhOosthDGAPsMFIM=&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Similar to the overlay method, pinning GnuPG through the NixOS module&#xA;affects the version of GnuPG in the system &lt;code&gt;PATH&lt;/code&gt;.  But unlike with&#xA;overlays, other packages still see the original version of GnuPG.&#xA;Since we&amp;rsquo;re not infecting other packages with a changed GnuPG, nothing&#xA;needs to be recompiled.&lt;/p&gt;&#xA;&lt;p&gt;Now, I&amp;rsquo;m &lt;a href=&#34;https://github.com/pjones/tilde&#34; target=&#34;_blank&#34;&gt;a very happy user of NixOS&lt;/a&gt;, but this isn&amp;rsquo;t my&#xA;preferred solution.  And, of course, it doesn&amp;rsquo;t work at all for&#xA;non-NixOS users.  The last way we&amp;rsquo;ll look at pinning GnuPG works for&#xA;any nixpkgs user and also doesn&amp;rsquo;t suffer from the overhead of the&#xA;overlay technique.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-home-manager-module&#34;&gt;The Home Manager Module&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;m a huge fan of &lt;a href=&#34;https://github.com/nix-community/home-manager&#34; target=&#34;_blank&#34;&gt;Home Manager&lt;/a&gt;.  It allows nixpkgs&#xA;users take all the awesomeness of NixOS to other Linux distributions&#xA;and even to closed operating systems like &lt;a href=&#34;https://github.com/LnL7/nix-darwin/tree/master&#34; target=&#34;_blank&#34;&gt;macOS&lt;/a&gt;,&#xA;&lt;a href=&#34;https://github.com/nix-community/nix-on-droid&#34; target=&#34;_blank&#34;&gt;Android&lt;/a&gt;, and even &lt;a href=&#34;https://github.com/nix-community/NixOS-WSL&#34; target=&#34;_blank&#34;&gt;Windows&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The Home Manager module for GnuPG is very similar to the NixOS module&#xA;and also includes a &lt;a href=&#34;https://nix-community.github.io/home-manager/options.xhtml#opt-programs.gpg.package&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;package&lt;/code&gt; option&lt;/a&gt;.  That means we&#xA;can pin GnuPG in our user environment similar to how the NixOS module&#xA;allowed us to pin it at the system level.  The following Nix code can&#xA;be loaded into your Home Manager configuration through the normal&#xA;&lt;code&gt;imports&lt;/code&gt; list mechanism, just like with NixOS modules:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{ pkgs }:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  programs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gpg&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;package &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; pkgs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gnupg&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;overrideAttrs (orig: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    version &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.4.0&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    src &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; pkgs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;fetchurl {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      url &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mirror://gnupg/gnupg/gnupg-2.4.0.tar.bz2&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      hash &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256-HXkVjdAdmSQx3S4/rLif2slxJ/iXhOosthDGAPsMFIM=&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;a-warning-about-other-workarounds&#34;&gt;A Warning About Other Workarounds&lt;/h2&gt;&#xA;&lt;p&gt;It&amp;rsquo;s important to point out that the correct solution to this problem&#xA;between Emacs and GnuPG is to fix &lt;em&gt;GnuPG&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve seen people on social media sites like Reddit suggesting a hack&#xA;to Emacs to resolve the problem.  Specifically, people are putting the&#xA;following in their Emacs configuration:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;fset&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;epg-wait-for-status&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ignore&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Don&amp;rsquo;t do this!&lt;/strong&gt;  This is not a valid fix and may lead to file&#xA;corruption when reading/writing encrypted files.&lt;/p&gt;&#xA;&lt;p&gt;This bit of hackery replaces the &lt;code&gt;epg-wait-for-status&lt;/code&gt; function with&#xA;one that ignores its arguments and always returns &lt;code&gt;nil&lt;/code&gt;.  That&#xA;function is used throughout the EPG library in Emacs, not just when&#xA;writing files through GnuPG.  Again, &lt;em&gt;please don&amp;rsquo;t do this&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;We&amp;rsquo;ve looked at three different ways of pinning a package in&#xA;nixpkgs:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Using an overlay function.&lt;/p&gt;&#xA;&lt;p&gt;This is usually my go-to solution.  But in this case GnuPG is&#xA;used in so many other packages that it caused massive rebuilds.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Pinning via the NixOS &lt;a href=&#34;https://search.nixos.org/options?query=programs.gnupg&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;programs.gnupg.package&lt;/code&gt;&lt;/a&gt;&#xA;option.&lt;/p&gt;&#xA;&lt;p&gt;This works by only changing the version of GnuPG installed in the&#xA;system &lt;code&gt;PATH&lt;/code&gt;.  If you use NixOS (and not Home Manager) this is&#xA;the way to go.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Pinning via the Home Manager&#xA;&lt;a href=&#34;https://nix-community.github.io/home-manager/options.xhtml#opt-programs.gpg.package&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;programs.gpg.package&lt;/code&gt;&lt;/a&gt; option.&lt;/p&gt;&#xA;&lt;p&gt;This is my preferred solution because it works nearly everywhere&#xA;thanks to Home Manager.  It replaces the version of GnuPG in your&#xA;user &lt;code&gt;PATH&lt;/code&gt;, leaving the system &lt;code&gt;PATH&lt;/code&gt; and the rest of nixpkgs&#xA;alone.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.latacora.com/blog/2019/07/16/the-pgp-problem/&#34; target=&#34;_blank&#34;&gt;Like many others&lt;/a&gt;, my frustration with GnuPG is nearing&#xA;its breaking point.  Over the last 20 years I&amp;rsquo;ve sent/received no more&#xA;than a handful of encrypted emails.  My use of GnuPG at this point is&#xA;limited to encrypting files in my &lt;a href=&#34;https://www.passwordstore.org/&#34; target=&#34;_blank&#34;&gt;password store&lt;/a&gt; and signing&#xA;Git commits.  It&amp;rsquo;s becoming less clear why I put up with the burden of&#xA;managing my GnuPG key and the occasional upgrade problem.&lt;/p&gt;&#xA;&lt;p&gt;Perhaps I&amp;rsquo;ll finally switch to &lt;a href=&#34;https://github.com/FiloSottile/age/&#34; target=&#34;_blank&#34;&gt;age&lt;/a&gt; over the next major holiday&#xA;break.  (I probably won&amp;rsquo;t find the time, but here&amp;rsquo;s hoping for the&#xA;best.)&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;&lt;strong&gt;Update (January 6, 2024)&lt;/strong&gt;: A better solution may be to patch the&#xA;current version of GnuPG so it doesn&amp;rsquo;t have the deadlock bug.  I&#xA;explore that option &lt;a href=&#34;https://freerangebits.com/posts/2024/01/patch-instead-of-pin&#34;&gt;in this post&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Update (February 23, 2024)&lt;/strong&gt;: GnuPG 2.4.4 has been released and&#xA;fixes the problems mentioned in this post.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Don&#39;t be affraid to learn vi or emacs</title>
      <link>https://freerangebits.com/posts/2011/11/learn-vi/</link>
      <pubDate>Wed, 23 Nov 2011 00:00:00 -0700</pubDate>
      <guid>https://freerangebits.com/posts/2011/11/learn-vi/</guid>
      <description>&lt;p&gt;Over at the &lt;a href=&#34;http://robots.thoughtbot.com/&#34; target=&#34;_blank&#34;&gt;thoughtbot blog&lt;/a&gt; there&amp;rsquo;s an article about the&#xA;&lt;a href=&#34;http://robots.thoughtbot.com/post/13164810557/the-vim-learning-curve-is-a-myth&#34; target=&#34;_blank&#34;&gt;myth of the vim learning curve&lt;/a&gt;.  I think everything said&#xA;about &lt;a href=&#34;https://freerangebits.com/tags/vim/&#34;&gt;vi/vim&lt;/a&gt; can equally be applied to &lt;a href=&#34;https://freerangebits.com/tags/emacs/&#34;&gt;Emacs&lt;/a&gt;.  The path to&#xA;getting up and running isn&amp;rsquo;t as daunting as you might think:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Go to your shell and type &lt;code&gt;vimtutor&lt;/code&gt;. The tutorial that&amp;rsquo;s presented&#xA;is excellent and you&amp;rsquo;ll be through it in no time. Once you&amp;rsquo;re done,&#xA;you&amp;rsquo;ll have the rudiments needed to get your work done. You won&amp;rsquo;t be&#xA;fast yet, no; but you&amp;rsquo;ll be competent.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a similar feature in Emacs.  To start the tutorial just type&#xA;&lt;code&gt;C-h t&lt;/code&gt; (that&amp;rsquo;s Control-h and then t).&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Fun stuff for Friday Nov. 18</title>
      <link>https://freerangebits.com/posts/2011/11/fun-friday-18/</link>
      <pubDate>Fri, 18 Nov 2011 00:00:00 -0700</pubDate>
      <guid>https://freerangebits.com/posts/2011/11/fun-friday-18/</guid>
      <description>&lt;p&gt;This past week has been a blur for me so I&amp;rsquo;m totally ready for the&#xA;weekend.  The kids and I have been making our way through the Alien&#xA;films and tonight we&amp;rsquo;re on number 3.  I don&amp;rsquo;t have fond memories of&#xA;the movie but I&amp;rsquo;m sure we&amp;rsquo;ll have fun.&lt;/p&gt;&#xA;&lt;p&gt;Hopefully you have some fun planned yourself and the links below will&#xA;help you kick off the weekend.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Anders Evenrud has released what he&amp;rsquo;s calling &lt;a href=&#34;http://anderse.wordpress.com/os-js/&#34; target=&#34;_blank&#34;&gt;OS.js&lt;/a&gt;, or what I&amp;rsquo;d&#xA;call an operating system emulator.  It almost looks like you VNC&#xA;into his Linux box, but nope, it&amp;rsquo;s all JS.  It even has apps&#xA;written for it.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://freerangebits.com/tags/emacs/&#34;&gt;Emacs&lt;/a&gt; users who want to start using version 24 (to be released&#xA;this spring) should take a look at Bozhidar Batsov&amp;rsquo;s&#xA;&lt;a href=&#34;https://github.com/bbatsov/emacs-prelude&#34; target=&#34;_blank&#34;&gt;Emacs Prelude&lt;/a&gt;.  It&amp;rsquo;s a set of configuration files and&#xA;packages sort of like the &lt;a href=&#34;https://github.com/technomancy/emacs-starter-kit&#34; target=&#34;_blank&#34;&gt;Emacs starter kit&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Itching to write code nobody can read?  Back after a rather long&#xA;hiatus is the &lt;a href=&#34;http://www.ioccc.org/&#34; target=&#34;_blank&#34;&gt;International Obfuscated C Code Contest&lt;/a&gt;!&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Looking for a geeky way to put your keys away for the night?  Why&#xA;not build an &lt;a href=&#34;http://www.instructables.com/id/RJ-45-key-chain-and-rack&#34; target=&#34;_blank&#34;&gt;RJ45 key chain&lt;/a&gt;.  I recommend wiring it so you&#xA;can plug it right into a hub or switch.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Videos: Astronauts &lt;a href=&#34;http://www.youtube.com/watch?v=LEdYf4SGhuI&#34; target=&#34;_blank&#34;&gt;tripping and falling&lt;/a&gt; on the moon (via&#xA;&lt;a href=&#34;http://www.wired.com/geekdad/2011/11/astronauts-falling-on-the-moon/&#34; target=&#34;_blank&#34;&gt;GeekDad&lt;/a&gt;) and &lt;a href=&#34;http://www.youtube.com/watch?v=PNln_me-XjI&#34; target=&#34;_blank&#34;&gt;Simultaneous time lapse&lt;/a&gt; video of the&#xA;sky over 360 days (via &lt;a href=&#34;http://kottke.org/11/11/year-long-sky-time-lapse&#34; target=&#34;_blank&#34;&gt;kottke&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Have a fun weekend!&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Remote pair programming in a terminal</title>
      <link>https://freerangebits.com/posts/2011/11/remote-pairing/</link>
      <pubDate>Mon, 14 Nov 2011 00:00:00 -0700</pubDate>
      <guid>https://freerangebits.com/posts/2011/11/remote-pairing/</guid>
      <description>&lt;p&gt;Pair programming is becoming more popular due to the good old&#xA;terminal.  Instead of having to sit next to your coworker who had an&#xA;onion sandwich for lunch you can use terminal sharing from across the&#xA;office or the country.  And with services like &lt;a href=&#34;http://rubypair.com/&#34; target=&#34;_blank&#34;&gt;Ruby Pair&lt;/a&gt; that&#xA;connect people who want to pair program, knowing how to use a terminal&#xA;multiplexer is worth a few minutes of your time.&lt;/p&gt;&#xA;&lt;p&gt;The venerable choice for a terminal multiplexer is &lt;a href=&#34;http://www.gnu.org/s/screen/&#34; target=&#34;_blank&#34;&gt;GNU Screen&lt;/a&gt;.&#xA;Dalibor Nasevic has written an article with instructions on how to&#xA;&lt;a href=&#34;http://blog.siyelo.com/remote-pair-programming-with-screen&#34; target=&#34;_blank&#34;&gt;configure SSH and Screen&lt;/a&gt; to allow remote pair programming.  In&#xA;my opinion, a huge downside to using Screen is having to setuid the&#xA;process to enable multiuser mode.  A much better option is &lt;a href=&#34;http://tmux.sourceforge.net/&#34; target=&#34;_blank&#34;&gt;tmux&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re looking for a more modern terminal multiplexer that is much&#xA;easier to configure, tmux is the answer.  Joe Moore has &lt;a href=&#34;http://remotepairprogramming.com/remote-pair-programming-with-tmux-and-vim-the&#34; target=&#34;_blank&#34;&gt;an&#xA;article&lt;/a&gt; about using tmux with &lt;a href=&#34;https://freerangebits.com/tags/vim/&#34;&gt;Vim&lt;/a&gt; for pair programming, but&#xA;it&amp;rsquo;s really just a few simple commands:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;# Host&#xA;tmux -S /tmp/pairprog&#xA;&#xA;# Client&#xA;ssh pair-host&#xA;tmux -S /tmp/pairprog attach&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Remote pair programming with Screen or tmux is also a great excuse to&#xA;polish your &lt;a href=&#34;https://freerangebits.com/tags/vim/&#34;&gt;Vim&lt;/a&gt; or &lt;a href=&#34;https://freerangebits.com/tags/emacs/&#34;&gt;Emacs&lt;/a&gt; skills.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Write HTML/XML faster with Zen Coding</title>
      <link>https://freerangebits.com/posts/2011/10/zen-coding/</link>
      <pubDate>Thu, 20 Oct 2011 00:00:00 -0700</pubDate>
      <guid>https://freerangebits.com/posts/2011/10/zen-coding/</guid>
      <description>&lt;p&gt;If you find yourself writing a lot of opening and closing tags by hand&#xA;you really should check out &lt;a href=&#34;http://code.google.com/p/zen-coding/&#34; target=&#34;_blank&#34;&gt;Zen Coding&lt;/a&gt;:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Zen Coding is an editor plugin for high-speed HTML, XML, XSL (or any&#xA;other structured code format) coding and editing. The core of this&#xA;plugin is a powerful abbreviation engine which allows you to expand&#xA;expressions&amp;ndash;similar to CSS selectors&amp;ndash;into HTML code.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;A very large variety of text editors are supported by the plug-in,&#xA;with alternative implementations for editors like Emacs and Vim.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Challenge your text editor fu</title>
      <link>https://freerangebits.com/posts/2011/10/editor-golf/</link>
      <pubDate>Mon, 17 Oct 2011 00:00:00 -0700</pubDate>
      <guid>https://freerangebits.com/posts/2011/10/editor-golf/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://www.igvita.com/&#34; target=&#34;_blank&#34;&gt;Ilya Grigorik&lt;/a&gt; has put together an excellent site called&#xA;&lt;a href=&#34;http://vimgolf.com/&#34; target=&#34;_blank&#34;&gt;VimGolf&lt;/a&gt; where developers host challenges to see who can complete&#xA;a task in &lt;a href=&#34;http://www.vim.org/&#34; target=&#34;_blank&#34;&gt;Vim&lt;/a&gt; with the fewest keystrokes.  Here&amp;rsquo;s an&#xA;&lt;a href=&#34;http://vimgolf.com/challenges/4d28637c4bcd032f1c00003d&#34; target=&#34;_blank&#34;&gt;example&lt;/a&gt; challenge:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Reformat long lines. Rearrange this ruby method call to put each&#xA;parameter on its own line. Could become a useful macro.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;You are given an input file and an output file with the goal to&#xA;provide the minimum number of keystrokes to convert the input file to&#xA;the output file.&lt;/p&gt;&#xA;&lt;p&gt;Vim not your cup of tea? &lt;a href=&#34;http://blog.twonegatives.com/&#34; target=&#34;_blank&#34;&gt;Tim Visher&lt;/a&gt; goes through the VimGolf&#xA;challenges with &lt;a href=&#34;http://www.gnu.org/s/emacs/&#34; target=&#34;_blank&#34;&gt;Emacs&lt;/a&gt; and posts &lt;a href=&#34;http://vimeo.com/timvisher&#34; target=&#34;_blank&#34;&gt;the results&lt;/a&gt; on Vimeo.  His&#xA;videos are great to watch if you want to improve your Emacs skills.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Behind the code: project planning</title>
      <link>https://freerangebits.com/posts/2008/07/project-planning/</link>
      <pubDate>Thu, 24 Jul 2008 00:00:00 -0700</pubDate>
      <guid>https://freerangebits.com/posts/2008/07/project-planning/</guid>
      <description>&lt;p&gt;In this new series of articles, Behind the Code, I&amp;rsquo;ll be looking at&#xA;the tools and processes that I&amp;rsquo;ve put into place to make me a more&#xA;efficient and effective developer.  I&amp;rsquo;m hoping to share my&#xA;experiences, and while doing that, refine the way I work using your&#xA;feedback.&lt;/p&gt;&#xA;&lt;p&gt;Today, I&amp;rsquo;ll be talking about project planning, the process of breaking&#xA;a project into tasks, and estimating the effort to complete those&#xA;tasks.  The artifacts generated during this process can then be used&#xA;to create a proposal for a client, cost estimations for your boss, or&#xA;even the start of your project documentation.&lt;/p&gt;&#xA;&lt;h2 id=&#34;file-formats-and-tools-matter&#34;&gt;File Formats and Tools Matter&lt;/h2&gt;&#xA;&lt;p&gt;If there&amp;rsquo;s one thing I&amp;rsquo;ve definitely learned the hard way, it&amp;rsquo;s that&#xA;the tools I use today aren&amp;rsquo;t necessarily the tools I&amp;rsquo;ll be using&#xA;tomorrow.  A better tool might come along, or I might be forced to use&#xA;another operating system where my preferred tools aren&amp;rsquo;t available.&lt;/p&gt;&#xA;&lt;p&gt;I avoid binary proprietary file formats like used car salesmen.  It&amp;rsquo;s&#xA;so important to me that it&amp;rsquo;s my first rule:&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Rule 1: Use plain text files when possible.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;No matter which platform you&amp;rsquo;re using, you can read and work with text&#xA;files.  If you happen to use a platform with good command line&#xA;tools (anything Unix based), you have a powerful system available for&#xA;finding, searching, and transforming text files.&lt;/p&gt;&#xA;&lt;p&gt;Text files rock, and what&amp;rsquo;s the best tool to edit them?  Being a&#xA;developer, using a text editor shouldn&amp;rsquo;t be unfamiliar to you.  As a&#xA;matter of fact, it should be the tool that you&amp;rsquo;re most comfortable and&#xA;efficient with.  If there&amp;rsquo;s only one thing you can call yourself an&#xA;expert in, it should be in using your text editor.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tools-for-project-planning&#34;&gt;Tools for Project Planning&lt;/h2&gt;&#xA;&lt;p&gt;There are several tools you can use to do project planning, all while&#xA;working with nothing more than plain text files.  My tool of choice is&#xA;&lt;a href=&#34;http://www.gnu.org/software/emacs/&#34; target=&#34;_blank&#34;&gt;Emacs&lt;/a&gt;, using the amazing &lt;a href=&#34;http://orgmode.org/&#34; target=&#34;_blank&#34;&gt;Org-Mode&lt;/a&gt; package.&lt;/p&gt;&#xA;&lt;p&gt;The tools that you pick will depend completely on you.  In this case,&#xA;the process is slightly more important than the tools.  Don&amp;rsquo;t get me&#xA;wrong though, a good tool can make a big difference in your workflow.&lt;/p&gt;&#xA;&lt;p&gt;I like &lt;a href=&#34;http://orgmode.org/&#34; target=&#34;_blank&#34;&gt;Org-Mode&lt;/a&gt; because it provides a lot of functionally, yet at&#xA;the end of the day everything is just plain text.  I can easily keep&#xA;my project files in a &lt;a href=&#34;http://git.or.cz/&#34; target=&#34;_blank&#34;&gt;revision control system&lt;/a&gt;, and use tools&#xA;like &lt;a href=&#34;http://www.ruby-lang.org&#34; target=&#34;_blank&#34;&gt;Ruby&lt;/a&gt; and &lt;a href=&#34;http://www.FreeBSD.org/cgi/man.cgi?query=grep&amp;amp;apropos=0&amp;amp;sektion=0&amp;amp;manpath=FreeBSD&amp;#43;7.0-RELEASE&amp;amp;format=html&#34; target=&#34;_blank&#34;&gt;grep&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;breaking-a-project-into-features-and-tasks&#34;&gt;Breaking a Project Into Features and Tasks&lt;/h2&gt;&#xA;&lt;p&gt;The first step for planning a project is breaking it into smaller&#xA;pieces.  I like to create a shallow hierarchy, where I break a project&#xA;into features, and then take those features and break them down into&#xA;tasks.&lt;/p&gt;&#xA;&lt;p&gt;Features are usually the bigger chunks that your client or boss would&#xA;know by name.  Since features are big chucks, you can&amp;rsquo;t estimate them&#xA;correctly, or think clearly about their dependencies without breaking&#xA;them down further.&lt;/p&gt;&#xA;&lt;p&gt;By breaking a feature down into tasks, you virtually walk though the&#xA;implementation of that feature, thinking about dependencies and&#xA;potential problems that you&amp;rsquo;ll have along the way.&lt;/p&gt;&#xA;&lt;p&gt;While breaking a project into features and tasks, don&amp;rsquo;t think about&#xA;time estimates, &lt;em&gt;only process&lt;/em&gt;.  Work through the steps you would&#xA;actually perform to implement a feature in your mind, recording them&#xA;in your project plan as tasks.&lt;/p&gt;&#xA;&lt;p&gt;Below is screenshot from Emacs, showing the outline I&amp;rsquo;ve created for&#xA;a fictional social networking application.  Org-Mode allows me to fold&#xA;the outline at any level.  Here I&amp;rsquo;m viewing just the outline headings&#xA;that show two features, broken down into tasks.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;folded.jpg&#34; alt=&#34;Folded&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;While I&amp;rsquo;m creating the feature and task breakdown, I leave myself&#xA;little notes just in case the headings are too vague and a few weeks&#xA;later I&amp;rsquo;m not sure what the hell I was talking about.&lt;/p&gt;&#xA;&lt;p&gt;Below is a fully expanded version of the outline from above, so you&#xA;can see the notes.  Later, these notes can be expanded and used as&#xA;project documentation or a client proposal.&lt;/p&gt;&#xA;&lt;p&gt;In Org-Mode, the tab key is used to expand or fold an outline.  This&#xA;makes it very easy to see just the part of the project plan that&#xA;you&amp;rsquo;re interested in.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;expanded.jpg&#34; alt=&#34;Expanded&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;estimating-the-tasks&#34;&gt;Estimating the Tasks&lt;/h2&gt;&#xA;&lt;p&gt;As I mentioned before, a feature by itself is too vague to estimate.&#xA;But now that you&amp;rsquo;ve broken each of the features down into tasks, you&#xA;should have enough information to estimate the effort of actually&#xA;implementing those features.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m not going to dive too deeply into the art of estimating in this&#xA;article.  That said, put your estimating cap on and let&amp;rsquo;s get to it.&lt;/p&gt;&#xA;&lt;p&gt;The best way to estimate your tasks is to begin with the first task,&#xA;and work through them one at a time.  I prefer to break my tasks down&#xA;into hours and minutes, usually in 30-minute increments.&lt;/p&gt;&#xA;&lt;p&gt;If you come across a task that will take more than a workday to&#xA;complete, you need to break the task down into more tasks.  It&amp;rsquo;s&#xA;important that your tasks are granular enough, I personally don&amp;rsquo;t like&#xA;my tasks to take more than 5-hours.  Along the same lines, any task&#xA;that takes less than 30-minutes, however, should be reviewed to ensure&#xA;it has been thought through enough.&lt;/p&gt;&#xA;&lt;p&gt;Below is a screenshot showing estimates assigned to each task.  I like&#xA;to switch Org-Mode into column view.  Org-Mode makes it easy to see&#xA;summations of task estimates using its handy column view mode, which&#xA;turns your hierarchical outline into a table.&lt;/p&gt;&#xA;&lt;p&gt;In this screenshot, I&amp;rsquo;ve assigned estimates to each task.  The&#xA;features now show the total estimates for their respective tasks,&#xA;leaving the top headline (the project name) with a total estimate for&#xA;the project.  Org-Mode automatically summed the time estimates for me,&#xA;I only assigned estimates to the tasks themselves (in purple below).&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;columns.jpg&#34; alt=&#34;Columns&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;presenting-the-project-plan&#34;&gt;Presenting the Project Plan&lt;/h2&gt;&#xA;&lt;p&gt;With your task estimates completed, you&amp;rsquo;ve collected enough&#xA;information to present a proposal to a client, or a project plan to&#xA;your boss.&lt;/p&gt;&#xA;&lt;p&gt;If you&amp;rsquo;ve been using a software tool to create your project plan, it&#xA;probably has an export feature.  Org-Mode can export your document to&#xA;HTML, LaTeX, and even a cleaned up ASCII text file.&lt;/p&gt;&#xA;&lt;p&gt;Even if you&amp;rsquo;re not using a tool with an export feature, you&amp;rsquo;re a&#xA;software developer right?  Write a script that will transform your&#xA;text file to something useful for your situation.&lt;/p&gt;&#xA;&lt;p&gt;As an example of a client proposal, I&amp;rsquo;ve exported the project file&#xA;into a cleaner &lt;a href=&#34;project-planning.pdf&#34;&gt;PDF file&lt;/a&gt; for my fictional client.  If&#xA;this were a real proposal, I would add additional notes, along with&#xA;details about the cost of the implementation.&lt;/p&gt;&#xA;&lt;h2 id=&#34;using-the-project-plan-during-implementation&#34;&gt;Using the Project Plan During Implementation&lt;/h2&gt;&#xA;&lt;p&gt;Why do all the work of creating a proposal, only to let it collect&#xA;dust?  When it comes time to implement the features that you created a&#xA;spec for, why not turn them into a to-do list?&lt;/p&gt;&#xA;&lt;p&gt;Using the Org-Mode ability to manage to-do lists, I turned the&#xA;estimated tasks into to-do items.  With Org-Mode I can &amp;ldquo;clock in&amp;rdquo; to a&#xA;task, which starts a timer.  When a task is complete, I mark it as&#xA;being done, and then I can compare the time I spent working to my&#xA;estimates.&lt;/p&gt;&#xA;&lt;p&gt;Below is a screenshot where I&amp;rsquo;ve completely expanded a finished task&#xA;so that you can see the meta-data that Org-Mode was adding to it when&#xA;I used the timer on a task and then marked it as complete.  You can&#xA;also see how a headline can be turned into a to-do item.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;tasks.jpg&#34; alt=&#34;Tasks&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s much more useful to switch back into column view for the&#xA;comparisons between my estimates and the clocked time.  The below&#xA;screenshot shows my outline back in column view, this time also&#xA;showing clock time summaries.&lt;/p&gt;&#xA;&lt;p&gt;This is a good example of how Org-Mode can collect the meta-data in&#xA;your text file and then present it to you in a more efficient way.&#xA;You can even edit the data in this table-like view, and Org-Mode will&#xA;do the right thing.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;clocked.jpg&#34; alt=&#34;Clocked&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;In addition to column view, Org-Mode has several ways to generate&#xA;reports from your data.  I especially like the agenda view.&lt;/p&gt;&#xA;&lt;p&gt;With the agenda view, you can see which tasks you&amp;rsquo;ve scheduled for&#xA;specific days.  I find it very useful to spend a little bit of time at&#xA;the end of my day, and schedule which tasks I&amp;rsquo;ll be working on for the&#xA;following day.&lt;/p&gt;&#xA;&lt;p&gt;In the morning, I can review my agenda and start working with a clear&#xA;idea of what I should be doing.  This really helps with any tendency&#xA;to stall or procrastinate during the first hours of the day.&lt;/p&gt;&#xA;&lt;h2 id=&#34;article-artifacts-and-further-reading&#34;&gt;Article Artifacts and Further Reading&lt;/h2&gt;&#xA;&lt;p&gt;I chose to show screenshots above so you could get a feel for how a&#xA;good tool like Org-Mode can provide a nice interface for project&#xA;planning.  The nice thing about Org-Mode is that you&amp;rsquo;re just working&#xA;with a text file, and if you open that file in any other text editor,&#xA;it doesn&amp;rsquo;t look foreign.&lt;/p&gt;&#xA;&lt;p&gt;Below are links to files I created while writing this article.  Open&#xA;the project plan in your favorite text editor and compare it to the&#xA;screenshots above.  Try opening it in Emacs and see what happens.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;project-planning.org&#34;&gt;The Plain Text Org-Mode File&lt;/a&gt; (Project File)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;project-planning.pdf&#34;&gt;A PDF Client Proposal&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re looking for more information about Org-Mode, the main web&#xA;site is a great resource.  There is a fantastic manual, and a very&#xA;responsive mailing list if you have any questions.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://orgmode.org&#34; target=&#34;_blank&#34;&gt;Org-Mode Web Site&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.youtube.com/watch?v=oJTwQvgfgMM&#34; target=&#34;_blank&#34;&gt;Org-Mode GoogleTalk&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
  </channel>
</rss>
