<?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>hi, it&#39;s mike</title>
    <link>https://mike.puddingtime.org/tags/emacs/</link>
    <description>Recent content on hi, it&#39;s mike</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>mike@puddingtime.org (mike)</managingEditor>
    <webMaster>mike@puddingtime.org (mike)</webMaster>
    <copyright>© 2026, mike</copyright>
    <lastBuildDate>Mon, 21 Apr 2025 11:10:53 -0700</lastBuildDate>
    <atom:link href="https://mike.puddingtime.org/tags/emacs/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>By-host configs in Doom. Custom starting window sizes. </title>
      <link>https://mike.puddingtime.org/posts/2025-04-21-by-host-configs-in-doom-custom-starting-window-sizes-/</link>
      <pubDate>Mon, 21 Apr 2025 11:10:53 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2025-04-21-by-host-configs-in-doom-custom-starting-window-sizes-/</guid>
      <description>Removed a little conditional logic from config.org</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve got a few Macs and a few Linux machines and they all respond differently to some basic font size stuff and starting window dimensions. For the laptops, I don&rsquo;t mind if they start Emacs maximized. For the desktops, their screen geometries differ enough that I end up fiddling around. On the Macs I&rsquo;ve got <a href="https://rectangleapp.com/pro">Rectangle Pro</a> to make a preset and keyboard shortcut, but even that&rsquo;s a little annoying.</p>
<p>I used to have a bunch of conditional logic in <code>config.org</code> to manage all this, but it was sort of a pain to pick through when adding a machine, so I wanted to isolate the individual machine configurations a little. I&rsquo;m guessing it could be useful for other stuff in the future, but for now it handles some appearance stuff.</p>
<p>For by-host configs, I added this to my <code>config.org</code>:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">hostname</span> <span class="p">(</span><span class="nv">system-name</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">hostname-file</span> <span class="p">(</span><span class="nv">expand-file-name</span> <span class="p">(</span><span class="nv">concat</span> <span class="nv">hostname</span> <span class="s">&#34;.el&#34;</span><span class="p">)</span> <span class="nv">doom-private-dir</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nv">file-exists-p</span> <span class="nv">hostname-file</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">load-file</span> <span class="nv">hostname-file</span><span class="p">))))</span></span></span></code></pre></div>
<p>That just looks for a file in my Doom directory with the <code>hostname.el</code> naming convention.</p>
<p>A sample <code>hostname.el</code> file looks like this:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">doom-font</span> <span class="p">(</span><span class="nv">font-spec</span> <span class="ss">:family</span> <span class="s">&#34;Fira Code&#34;</span> <span class="ss">:size</span> <span class="mf">14.0</span> <span class="ss">:weight</span> <span class="ss">&#39;medium</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">mixed-pitch-set-height</span> <span class="mi">15</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">&#39;default</span> <span class="no">nil</span> <span class="ss">:family</span> <span class="s">&#34;Fira Code&#34;</span> <span class="ss">:height</span> <span class="mi">140</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">&#39;fixed-pitch</span> <span class="no">nil</span> <span class="ss">:family</span> <span class="s">&#34;Fira Code&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">&#39;variable-pitch</span> <span class="no">nil</span> <span class="ss">:family</span> <span class="s">&#34;Helvetica Neue&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">initial-frame-alist</span>
</span></span><span class="line"><span class="cl">      <span class="o">&#39;</span><span class="p">((</span><span class="nv">width</span> <span class="o">.</span> <span class="mi">171</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">height</span> <span class="o">.</span> <span class="mi">66</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">left</span> <span class="o">.</span> <span class="mi">728</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">top</span> <span class="o">.</span> <span class="mi">166</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span>
</span></span><span class="line"><span class="cl">      <span class="o">&#39;</span><span class="p">((</span><span class="nv">width</span> <span class="o">.</span> <span class="mi">171</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">height</span> <span class="o">.</span> <span class="mi">66</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">left</span> <span class="o">.</span> <span class="mi">728</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">top</span> <span class="o">.</span> <span class="mi">166</span><span class="p">)))</span></span></span></code></pre></div>
<p>The <code>initial-frame-alist</code> and <code>default-frame-alist</code> dimensions came from this function:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">my/print-frame-setup-snippet</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Print a config snippet for setting the current frame size and position.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">w</span> <span class="p">(</span><span class="nv">frame-width</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">h</span> <span class="p">(</span><span class="nv">frame-height</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">pos</span> <span class="p">(</span><span class="nv">frame-position</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">l</span> <span class="p">(</span><span class="nf">car</span> <span class="nv">pos</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">top-pos</span> <span class="p">(</span><span class="nf">cdr</span> <span class="nv">pos</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">with-temp-buffer</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">insert</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;(setq initial-frame-alist\n      &#39;((width . %d)\n        (height . %d)\n        (left . %d)\n        (top . %d)))\n\n&#34;</span>
</span></span><span class="line"><span class="cl">                      <span class="nv">w</span> <span class="nv">h</span> <span class="nv">l</span> <span class="nv">top-pos</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">insert</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;(setq default-frame-alist\n      &#39;((width . %d)\n        (height . %d)\n        (left . %d)\n        (top . %d)))&#34;</span>
</span></span><span class="line"><span class="cl">                      <span class="nv">w</span> <span class="nv">h</span> <span class="nv">l</span> <span class="nv">top-pos</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">kill-new</span> <span class="p">(</span><span class="nv">buffer-string</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">message</span> <span class="s">&#34;!!! Frame setup snippet copied to clipboard! Paste it into your config.el.&#34;</span><span class="p">))))</span></span></span></code></pre></div>
<p>So, set the Emacs frame up the way you want, then run that function, and paste it into <code>hostname.el</code>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Hugo posting in Emacs</title>
      <link>https://mike.puddingtime.org/posts/2025-04-21-hugo-posting-in-emacs/</link>
      <pubDate>Mon, 21 Apr 2025 08:37:39 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2025-04-21-hugo-posting-in-emacs/</guid>
      <description>ox-hugo is nice and all</description>
      <content:encoded><![CDATA[<p>I dug a bunch of stuff out of archived configs to get the Hugo blog going again, including my old <a href="https://ox-hugo.scripter.co/">ox-hugo</a> setup.</p>
<p><code>ox-hugo</code> lets you keep a monolithic org file where each post is an org heading:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="nv">**</span> <span class="nv">SyncTrain</span> <span class="nv">for</span> <span class="nv">Syncthing</span> <span class="nv">on</span> <span class="nv">iOS</span> <span class="ss">:syncthing:ios:iphone:</span>
</span></span><span class="line"><span class="cl"><span class="ss">:PROPERTIES:</span>
</span></span><span class="line"><span class="cl"><span class="ss">:EXPORT_FILE_NAME:</span> <span class="nv">2025-04-20-synctrain-for-syncthing-on-ios</span>
</span></span><span class="line"><span class="cl"><span class="ss">:EXPORT_HUGO_DATE:</span> <span class="nv">&lt;2025-04-20&gt;</span>
</span></span><span class="line"><span class="cl"><span class="ss">:EXPORT_DATE:</span> <span class="nv">2025-04-20</span>
</span></span><span class="line"><span class="cl"><span class="ss">:EXPORT_HUGO_SECTION:</span> <span class="nv">blog</span>
</span></span><span class="line"><span class="cl"><span class="ss">:EXPORT_HUGO_CUSTOM_FRONT_MATTER+:</span> <span class="ss">:cover</span> <span class="o">&#39;</span><span class="p">((</span><span class="nv">image</span> <span class="o">.</span><span class="s">&#34;&#34;</span> <span class="p">)</span> <span class="p">(</span><span class="nv">caption</span> <span class="o">.</span> <span class="s">&#34;&#34;</span> <span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="ss">:EXPORT_HUGO_CUSTOM_FRONT_MATTER+:</span> <span class="ss">:images</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">/mph-logo.png</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="ss">:EXPORT_DESCRIPTION:</span>
</span></span><span class="line"><span class="cl"><span class="ss">:END:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">A</span> <span class="nv">few</span> <span class="nv">years</span> <span class="nv">ago</span> <span class="nv">I</span> <span class="nv">gave</span> <span class="nv">Mobius</span> <span class="nv">Sync</span> <span class="nv">a</span> <span class="nv">try</span> <span class="nv">as</span> <span class="nv">a</span> <span class="nv">Syncthing</span> <span class="nv">client</span> <span class="nv">on</span> <span class="nv">my</span> <span class="nv">iPhone</span> <span class="nb">and</span> <span class="nv">iPad.</span> <span class="nv">That</span> <span class="nv">went</span> <span class="nv">about</span> <span class="nv">as</span> <span class="nv">well</span> <span class="nv">as</span> <span class="nv">you</span><span class="ss">&#39;d</span> <span class="nv">expect</span> <span class="nv">for</span> <span class="nv">an</span> <span class="nv">iOS</span> <span class="nv">adaptation</span> <span class="nv">of</span> <span class="nv">something</span> <span class="nv">that</span> <span class="nv">wants</span> <span class="nv">to</span> <span class="nv">be</span> <span class="nv">an</span> <span class="nv">always-on</span> <span class="nv">filesystem-watching</span> <span class="nv">daemon.</span> <span class="nv">It</span> <span class="nv">wasn</span><span class="ss">&#39;t</span> <span class="nv">really</span> <span class="nv">worth</span> <span class="k">the</span> <span class="nv">stress</span> <span class="nv">of</span> <span class="nv">wondering</span> <span class="nv">what</span> <span class="nv">quantum</span> <span class="nv">state</span> <span class="nv">of</span> <span class="nv">sync</span> <span class="nv">everything</span> <span class="nv">is</span> <span class="nv">in,</span> <span class="nb">and</span> <span class="nv">I</span> <span class="nv">hated</span> <span class="nv">having</span> <span class="nv">to</span> <span class="nv">explicitly</span> <span class="nf">open</span> <span class="nv">it</span> <span class="nv">up</span> <span class="nv">to</span> <span class="nv">nudge</span> <span class="nv">it</span> <span class="nv">to</span> <span class="nv">sync.</span></span></span></code></pre></div>
<p>If a heading is marked as <code>TODO</code>, that translates to &ldquo;draft&rdquo; for Hugo. If you use org tags in the heading <code>:tag1:tag2:</code> those become post tags.</p>
<p>If you set up <code>org-capture</code> and a few hooks correctly, it takes a lot of friction away by exporting the Markdown files when you save the file.</p>
<p>Something has changed since I was last using it regularly, and some bugs crept into my setup. I was willing to live with a few of them, but last night I came across some goofy thing where Hugo&rsquo;s Markdown renderer (goldmark) and ox-hugo were interacting strangely, and the org-to-markdown conversion was indenting unordered lists enough that goldmark picked them up as indented code blocks. I did some poking around and saw that a lot of people have been vexed by that: goldmark uses the <a href="https://commonmark.org/">CommonMark</a> specification, which includes indented code blocks, and goldmark offers no toggle for it as a workaround.</p>
<p>How many seconds do we have of this precious life?</p>
<p>I do like working out of Emacs and not switching around to do stuff, so I found an old Ruby script I wrote to make generating a Hugo post with all the stuff particular to my setup and worked with a co-pilot to convert it to a lisp package.</p>
<p>When you invoke <code>hpost-new</code> it prompts for whether to follow the &ldquo;daily&rdquo; or regular post style, then asks for title, tags, and description, then plops the new file into the right place and opens it for editing.</p>
<p>This goes in <code>~/.config/doom/lisp</code>:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;; hpost.el --- Create new Hugo posts from Emacs  -*- lexical-binding: t; -*-</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">;; Adjust this to point at your Hugo or ox‑hugo content directory.</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defcustom</span> <span class="nv">hpost-posts-dir</span> <span class="s">&#34;~/blog/content/posts/&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Directory where new Hugo posts are written.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="ss">:type</span> <span class="ss">&#39;directory</span> <span class="ss">:group</span> <span class="ss">&#39;hpost</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">hpost--slugify</span> <span class="p">(</span><span class="nv">title</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Convert TITLE to a URL‑friendly slug.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">s</span> <span class="p">(</span><span class="nv">downcase</span> <span class="nv">title</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">s</span> <span class="p">(</span><span class="nv">replace-regexp-in-string</span> <span class="s">&#34;[^a-z0-9]+&#34;</span> <span class="s">&#34;-&#34;</span> <span class="nv">s</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">s</span> <span class="p">(</span><span class="nv">replace-regexp-in-string</span> <span class="s">&#34;^-\|-$&#34;</span> <span class="s">&#34;&#34;</span> <span class="nv">s</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">truncate-string-to-width</span> <span class="nv">s</span> <span class="mi">60</span> <span class="no">nil</span> <span class="no">nil</span> <span class="s">&#34;&#34;</span><span class="p">)))</span> <span class="c1">; hard cap at 60 chars</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">hpost--today</span> <span class="p">()</span> <span class="p">(</span><span class="nv">format-time-string</span> <span class="s">&#34;%Y-%m-%d&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">hpost--now</span>   <span class="p">()</span> <span class="p">(</span><span class="nv">format-time-string</span> <span class="s">&#34;%Y-%m-%dT%H:%M:%S%z&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">;;;###autoload</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">hpost-new</span> <span class="p">(</span><span class="nv">title</span> <span class="nv">tags</span> <span class="nv">summary</span> <span class="k">&amp;optional</span> <span class="nv">daily</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Create a new Hugo post.
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">Interactively prompts for TITLE, TAGS (comma‑delimited), and SUMMARY.
</span></span></span><span class="line"><span class="cl"><span class="s">With prefix arg, treat it as a daily note (pre‑sets title and tags).&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">interactive</span>
</span></span><span class="line"><span class="cl">   <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">daily</span> <span class="p">(</span><span class="nf">y-or-n-p</span> <span class="s">&#34;Daily note? &#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nv">title</span> <span class="p">(</span><span class="k">if</span> <span class="nv">daily</span>
</span></span><span class="line"><span class="cl">                     <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;Daily notes for %s&#34;</span> <span class="p">(</span><span class="nv">hpost--today</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">                   <span class="p">(</span><span class="nv">read-string</span> <span class="s">&#34;Title: &#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nv">tags</span>  <span class="p">(</span><span class="k">if</span> <span class="nv">daily</span> <span class="s">&#34;journal&#34;</span>
</span></span><span class="line"><span class="cl">                   <span class="p">(</span><span class="nv">read-string</span> <span class="s">&#34;Tags (comma): &#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nv">summary</span> <span class="p">(</span><span class="nv">read-string</span> <span class="s">&#34;Summary: &#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">     <span class="p">(</span><span class="nc">list</span> <span class="nv">title</span> <span class="nv">tags</span> <span class="nv">summary</span> <span class="nv">daily</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">slug</span>    <span class="p">(</span><span class="k">if</span> <span class="nv">daily</span> <span class="s">&#34;daily-notes&#34;</span> <span class="p">(</span><span class="nv">hpost--slugify</span> <span class="nv">title</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">fname</span>   <span class="p">(</span><span class="nv">concat</span> <span class="p">(</span><span class="nv">hpost--today</span><span class="p">)</span> <span class="s">&#34;-&#34;</span> <span class="nv">slug</span> <span class="s">&#34;.md&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">path</span>    <span class="p">(</span><span class="nv">expand-file-name</span> <span class="nv">fname</span> <span class="nv">hpost-posts-dir</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nv">file-exists-p</span> <span class="nv">path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">user-error</span> <span class="s">&#34;File %s already exists&#34;</span> <span class="nv">fname</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">with-temp-buffer</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">insert</span> <span class="p">(</span><span class="nf">format</span>
</span></span><span class="line"><span class="cl"><span class="s">&#34;---
</span></span></span><span class="line"><span class="cl"><span class="s">title: \&#34;%s\&#34;
</span></span></span><span class="line"><span class="cl"><span class="s">date: %s
</span></span></span><span class="line"><span class="cl"><span class="s">draft: true
</span></span></span><span class="line"><span class="cl"><span class="s">tags:%s
</span></span></span><span class="line"><span class="cl"><span class="s">summary: \&#34;%s\&#34;
</span></span></span><span class="line"><span class="cl"><span class="s">---
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">&#34;</span> <span class="nv">title</span> <span class="p">(</span><span class="nv">hpost--now</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">mapconcat</span> <span class="p">(</span><span class="nb">lambda</span> <span class="p">(</span><span class="no">t</span><span class="p">)</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;\n- %s&#34;</span> <span class="p">(</span><span class="nf">string-trim</span> <span class="no">t</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">                   <span class="p">(</span><span class="nv">split-string</span> <span class="nv">tags</span> <span class="s">&#34;,&#34;</span><span class="p">)</span> <span class="s">&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nv">summary</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">write-region</span> <span class="p">(</span><span class="nv">point-min</span><span class="p">)</span> <span class="p">(</span><span class="nv">point-max</span><span class="p">)</span> <span class="nv">path</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">find-file</span> <span class="nv">path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">message</span> <span class="s">&#34;New post created: %s&#34;</span> <span class="nv">path</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">provide</span> <span class="ss">&#39;hpost</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1">;;; hpost.el ends here</span></span></span></code></pre></div>
<p>&hellip; and the config:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; --- Hugo post helper ---------------------------------------</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-package!</span> <span class="nv">hpost</span>
</span></span><span class="line"><span class="cl">  <span class="ss">:load-path</span> <span class="s">&#34;lisp/&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="ss">:defer</span> <span class="no">t</span>
</span></span><span class="line"><span class="cl">  <span class="ss">:custom</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">hpost-posts-dir</span> <span class="s">&#34;~/blog/content/posts/&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="ss">:config</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; Optional keybinding:  &lt;leader&gt; n h</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">map!</span> <span class="ss">:leader</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="ss">:prefix</span> <span class="p">(</span><span class="s">&#34;n&#34;</span> <span class="o">.</span> <span class="s">&#34;notes&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">         <span class="ss">:desc</span> <span class="s">&#34;New Hugo post&#34;</span> <span class="s">&#34;h&#34;</span> <span class="nf">#&#39;</span><span class="nv">hpost-new</span><span class="p">)))</span></span></span></code></pre></div>
<p>It goes well with a few helpers I made to fire up or shut down the Hugo preview server within Emacs:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-start-hugo-server</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Run Hugo server with live reloading.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">root</span> <span class="p">(</span><span class="nv">projectile-project-root</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">default-directory</span> <span class="nv">root</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">compile</span> <span class="s">&#34;hugo server -D --navigateToChanged&#34;</span> <span class="no">t</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-stop-hugo-server</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Stop Hugo server.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">kill-compilation</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">map!</span> <span class="ss">:leader</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="ss">:prefix</span> <span class="p">(</span><span class="s">&#34;H&#34;</span> <span class="o">.</span> <span class="s">&#34;Hugo&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">       <span class="ss">:desc</span> <span class="s">&#34;Start Hugo Server&#34;</span> <span class="s">&#34;S&#34;</span> <span class="nf">#&#39;</span><span class="nv">my-start-hugo-server</span>
</span></span><span class="line"><span class="cl">       <span class="ss">:desc</span> <span class="s">&#34;Stop Hugo Server&#34;</span> <span class="s">&#34;s&#34;</span> <span class="nf">#&#39;</span><span class="nv">my-stop-hugo-server</span><span class="p">))</span></span></span></code></pre></div>
<p>So, <code>SPC H S</code> to start the test server, and <code>SPC n h</code> to start a new post. When I save the buffer, the preview server jumps to the newly written page in the browser.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Solving the Denote/Gollum links quandary</title>
      <link>https://mike.puddingtime.org/posts/2025-04-20-solving-the-denote-gollum-links-quandary/</link>
      <pubDate>Sun, 20 Apr 2025 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2025-04-20-solving-the-denote-gollum-links-quandary/</guid>
      <description>&lt;p&gt;My whole &amp;ldquo;thing I wish Denote would just do&amp;rdquo; issue has been around its custom linking format: If you use Denote&amp;rsquo;s kind of awesome org-mode dblocks, you get &lt;code&gt;denote:&lt;/code&gt; formatted links. Prot is very careful to say custom links are perfectly legal and supported by Emacs, but that leaves out the reality that there&amp;rsquo;s an ecosystem of non-Emacs org-mode tools (e.g. &lt;a href=&#34;https://plainorg.com/&#34;&gt;Plain Org&lt;/a&gt;) that don&amp;rsquo;t understand custom link formats.&lt;/p&gt;
&lt;p&gt;So I had this very cool thing going on with &lt;a href=&#34;https://github.com/gollum/gollum&#34;&gt;Gollum&lt;/a&gt; running on my Synology. Gollum is mostly the same engine GitHub uses for its own wikis, and it can understand a variety of plaintext formats (including Markdown and org). With Gollum you&amp;rsquo;ve got a web front-end with search, version control, and inline editing if you&amp;rsquo;re away from an Emacs-capable machine or just want to look a note up on a phone.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>My whole &ldquo;thing I wish Denote would just do&rdquo; issue has been around its custom linking format: If you use Denote&rsquo;s kind of awesome org-mode dblocks, you get <code>denote:</code> formatted links. Prot is very careful to say custom links are perfectly legal and supported by Emacs, but that leaves out the reality that there&rsquo;s an ecosystem of non-Emacs org-mode tools (e.g. <a href="https://plainorg.com/">Plain Org</a>) that don&rsquo;t understand custom link formats.</p>
<p>So I had this very cool thing going on with <a href="https://github.com/gollum/gollum">Gollum</a> running on my Synology. Gollum is mostly the same engine GitHub uses for its own wikis, and it can understand a variety of plaintext formats (including Markdown and org). With Gollum you&rsquo;ve got a web front-end with search, version control, and inline editing if you&rsquo;re away from an Emacs-capable machine or just want to look a note up on a phone.</p>
<p>And Denote has its very cool org-mode dblocks: You can use a regexp to pull files matching a certain pattern into a dynamically updating block to create things the Zettelkasten folks might call a MOC, Prot refers to as &ldquo;metanotes,&rdquo; etc. I have made a set of index files on high-level areas I tagged with &ldquo;topic,&rdquo; so a Denote dblock with this syntax:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="err">#</span><span class="nv">+BEGIN:</span> <span class="nv">denote-links</span> <span class="nb">:regexp</span> <span class="s">&#34;_topic&#34;</span> <span class="nb">:not-regexp</span> <span class="no">nil</span> <span class="nb">:excluded-dirs-regexp</span> <span class="no">nil</span> <span class="nb">:sort-by-component</span> <span class="no">nil</span> <span class="nb">:reverse-sort</span> <span class="no">nil</span> <span class="nb">:id-only</span> <span class="no">nil</span> <span class="nb">:include-date</span> <span class="nv">nil</span></span></span></code></pre></div>
<p>&hellip; will dynamically create an index of links to all my &ldquo;topic&rdquo; notes, and within each of them I can make Denote dblocks that pull in notes with their tag.</p>
<p>In the context of Gollum, or even just an entry point into my notes collection, that means my Home page can provide a dynamic index of topic notes as I create them. <em>Except</em>, of course, the whole problem that a Denote dblock uses its custom <code>denote:</code> link scheme, and Gollum can&rsquo;t understand that.</p>
<p>You can manually use Denote&rsquo;s <code>denote-org-convert-links-to-file-type</code> command to convert those links to standard <code>file:</code> links, but I&rsquo;m forgetful and hate the thought of having to remember to do it. So I fixed it with a <code>.dir-locals.el</code> file that does it for me with a pre-save hook:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">((</span><span class="nv">org-mode</span> <span class="o">.</span> <span class="p">((</span><span class="nf">eval</span> <span class="o">.</span> <span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;before-save-hook</span>
</span></span><span class="line"><span class="cl">                                <span class="nf">#&#39;</span><span class="nv">denote-org-convert-links-to-file-type</span>
</span></span><span class="line"><span class="cl">                                <span class="no">nil</span> <span class="no">t</span><span class="p">)))))</span></span></span></code></pre></div>
<p>So I can update my topic pages, save them, the hook runs for me, and I can push into the Gollum repo. I get to keep all of Denote&rsquo;s convenience features around link-making, backlink lists, etc, and Gollum knows what to do with it all.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The notes bakeoff</title>
      <link>https://mike.puddingtime.org/posts/2024-02-21-the-notes-bakeoff/</link>
      <pubDate>Wed, 21 Feb 2024 12:28:55 -0800</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2024-02-21-the-notes-bakeoff/</guid>
      <description>The agonized ego is a ring of defense around nothing. And should not interfere with note tool selection.</description>
      <content:encoded><![CDATA[<p>I wrote a few days ago about impermanence and how it is, perhaps, desirable for our identities to be at least a bit ephemeral, the better to grow. There&rsquo;s gray in all that. We should always be clear on who we are, what matters to us, what our values are. But we should also be ready to let bits of our identities go.</p>
<p>I know that is easier said than done.</p>
<p>&ldquo;Bits of our identities&rdquo; are conversation starters, signifiers, hints, badges, clues to deeper things about us, personal reminders, and anchors.</p>
<p>&ldquo;Anchors.&rdquo;</p>
<p>&ldquo;That was a very anchoring conversation.&rdquo;</p>
<p>&ldquo;This is a real anchor around my neck.&rdquo;</p>
<p>Which is a weird way to start a post about note-taking apps, but here we are.</p>
<p>Like, Emacs is part of my &ldquo;Unix person&rdquo; origin story. I can&rsquo;t name another software tool I&rsquo;ve used as consistently for 33 years. I suppose the Unix paradigm itself edges Emacs out for personal longevity, but not by much.  And when I think about everything I was doing with that first Ultrix account in 1991, &ldquo;running Emacs&rdquo; is the only thing that remains from the list. No more Netrek, I don&rsquo;t use USENET in a way that would be recognizable to Past Me, and if the work I did on the Landsraad assembly hall for the DUNE MUD remains &ndash; getting cones of silence to work felt like a real triumph &ndash; I haven&rsquo;t been around to visit it for a few decades.</p>
<p>It is a bit of an anchor in the putatively good sense of the word &ldquo;anchor.&rdquo; Technological comfort food. One of the first things that goes on any new machine, and one of the first server-side things I test when I&rsquo;m trying out a new remote access tool. But also a bit of an anchor in the not-great sense of the word, in that I will pay the &ldquo;figure out how to express this in elisp&rdquo; tax for hours, well beyond practicality or reason.</p>
<p>Most recently, I was ignoring some excellent advice from Prot regarding people who want to use his excellent Denote for task tracking:</p>
<blockquote>
<p>“If you want my opinion though, be more forceful with the separation of concerns. Decouple your knowledge base from your ephemeral to-do list: Denote (and others) can be used for the former, while you let standard Org work splendidly for the latter—that is what I do, anyway. &hellip; “Do not mix your knowledge base with your to-do items.”</p>
</blockquote>
<p>&hellip; and the complexity was piling up and up, the tradeoffs were getting worse, and there was simply no joy in the experience because I had gotten myself into that bitter &ldquo;make this problem yield&rdquo; mindset that eventually leads to less understanding and more hacked-up, suboptimal stuff.</p>
<p>I just don&rsquo;t have time for it right now.</p>
<p>So it makes sense that my fallback position was &ldquo;maybe Logseq would be fine,&rdquo; because it&rsquo;s got the whole &ldquo;supports org-mode syntax&rdquo; thing going on &ndash; leave the door open for a return to Emacsland once I have more time &ndash; and perhaps because it is just odd enough to tickle another bit of my self-image. Mercifully, the second I tried to solve a problem of moderate complexity I realized how much time I&rsquo;d have to invest to do anything besides pick code samples up off the sidewalk and pop them in my mouth. So I backed away slowly.</p>
<p>And after that it makes sense that Tiddlywiki got a look because it has been around forever and there is a sort of cheerfully prosaic attitude among its users. But the plugins started creeping in and I was trying to get it to do stuff it doesn&rsquo;t really want to do without a lot of third party assistance, so the whole &ldquo;it&rsquo;s very simple&rdquo; thing was not allowed to find much expression.</p>
<p>So there I was, and I&rsquo;m sort of glad that I chased my tail over the past few weeks because it tired me out a little, but left me with an idea of what I wanted to do: Take notes in a connected manner, blend a little of PARA with space for a slipbox approach, and have inline todos, <em>and</em> I wanted it to sync across a few devices.</p>
<p>Obsidian does all that very well. There is always the risk of plugin creep, but in past Obsidian experiments that has been less about extending the core feature set and more about removing repetitive work. The simple mission of &ldquo;write notes, link between them, keep track of tasks&rdquo; doesn&rsquo;t take much, with mobile and sync managed competently. It runs on every platform I&rsquo;d care to run it on.</p>
<p>It&rsquo;s a little dull. But after a few days of &ldquo;just using it&rdquo; and adding little affordances here and there from past vaults as I&rsquo;ve remembered them, it has the benefit of just working in a non-dramatic, non-head-desking, simple way.  I haven&rsquo;t had to really think about it much. I haven&rsquo;t inadvertently broken it or misconfigured it in such a way that I&rsquo;m scrambling around a minute before a meeting trying to get back into my own notes.  It&rsquo;s of sufficient maturity that you can look up the answers to things and they are often in written form, which minimizes the whole &ldquo;if I see one more YouTube poster frame of a slack-jawed influencer taking 30 minutes to explain something I could have copied and pasted in ten seconds I&rsquo;m going to do a murder&rdquo; thing.</p>
<p>I was inclined to say &ldquo;and it says nothing about me, at all.&rdquo;</p>
<p>But it does say a few things: &ldquo;Doesn&rsquo;t want to think about this problem he created for himself in any more detail,&rdquo; &ldquo;will settle on Markdown even though it is inferior to org,&rdquo; &ldquo;can stand being associated with people who think a graph of their notes is interesting and useful if it means not having to think about this any longer,&rdquo; &ldquo;will pay for sync,&rdquo; &ldquo;considers seven plugins normal and reasonable, would not admit to nine,&rdquo; and &ndash; most likely and eventually &ndash; &ldquo;always seems to creep back to Emacs even though it seemed like he knew better last time he did this.&rdquo;</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2024-02-14</title>
      <link>https://mike.puddingtime.org/posts/2024-02-14-daily-notes/</link>
      <pubDate>Wed, 14 Feb 2024 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2024-02-14-daily-notes/</guid>
      <description>The Org Borg.</description>
      <content:encoded><![CDATA[<h2 id="the-org-borg">The Org Borg</h2>
<p>I like the ideas I get from taking a tour of a tool like Logseq, even if I don&rsquo;t think the whole thing is going to work for me. It&rsquo;s a chance to fold ideas into what is practically my forever tool, which is org-mode/Emacs, or at least rethink things I thought were more bothersome to fix than they sometimes end up being.</p>
<p>The last few weeks I&rsquo;ve been intrigued by <a href="https://fortelabs.com/blog/para/">PARA</a> as a simple organizing principle, I&rsquo;ve wanted to continue to mesh prose and tasks in the way org-mode excels, and I&rsquo;ve wanted to de-gunk my Denote setup.</p>
<p>I gave Logseq a try, looked at Workflowy again, and briefly dusted off my last Obsidian setup. Logseq and Obsidian are pretty good at surfacing tasks from all over your notes collection. org-mode can manage that but it is very oriented around the org agenda as a way to see your tasks, and the agenda doesn&rsquo;t scale well with large collections of notes.</p>
<p>There are a few ways of coming at that problem, ranging from &ldquo;just be selective about which files go into the agenda&rdquo; to functions that pre-scan your corpus cheaply then assemble a list of agenda files only from things with active todos.</p>
<p>I am still a long way away from having a notes collection large enough to slow the agenda down, but it&rsquo;s growing.</p>
<p>So, in the midst of poking around and trying to decide whether or not to add one of several possible lumps of lisp to my config, I came across <a href="https://baty.blog/2022/keeping-my-org-agenda-updated/">Jack Baty&rsquo;s post on his own solution,</a> which is limiting your agenda files to just project files, based on Denote&rsquo;s naming convention.</p>
<p>My own Denote hierarchy has a bunch of little atomic notes, then a collection of <kbd>project</kbd> files, <kbd>area</kbd> files, and <kbd>people</kbd> files. It also has a <kbd>home</kbd> file that indexes the project and area files, and an <kbd>inbox</kbd> file. I&rsquo;ve been experimenting with a <kbd>foundations</kbd> type that I use to define core concepts. For instance, my team&rsquo;s work a specific tool migration might be a <kbd>project</kbd> file; while portfolio management generally is an <kbd>area</kbd> file. Defining what even is the portfolio, what it means for someone on the team to own a piece of the portfolio, and what expectations are for portfolio owners is a piece of <kbd>foundation</kbd> thinking.</p>
<p>I can see putting tasks in those special-purpose files, and will tend to avoid putting them in tinier atomic or fragmentary notes files. Feels like a reasonable compromise that discourages littering my notes with tasks, keeps org&rsquo;s agenda efficient, and provides a little bit of structure that I feel can go missing in a strictly anti-hierarchical note setup.</p>
<p>The code Jack shared defines <kbd>denote-to-agenda-regexp</kbd> to make a decision on whether or not some supporting functions should include a file in the agenda. He limits his to files with <kbd>_project</kbd> in the name (derived from having <kbd>project</kbd> somewhere in the filetags). I wanted to include <kbd>area</kbd> and <kbd>people</kbd>, too, so I expanded the regexp (inelegantly):</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defvar</span> <span class="nv">my-denote-to-agenda-regexp</span> <span class="s">&#34;_project\\|_area\\|_people\\|_inbox&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="s">&#34;Denote file names that are added to the agenda.
</span></span></span><span class="line"><span class="cl"><span class="s">    See </span><span class="ss">`my-add-denote-to-agenda&#39;</span><span class="s">.&#34;</span><span class="p">)</span></span></span></code></pre></div>
<p>I&rsquo;ve also added the project/area/person name as the <kbd>#+category:</kbd> property in my agenda-ready files, since that cleans up the far-left column on the agenda, which is the (very long in Denote) filename by default.</p>
<h2 id="forsaking-mobile">Forsaking mobile</h2>
<p>I guess the other development of all the cleanup and fussing was choosing to not care about the mobile use case for this stuff <em>at all</em>.</p>
<p>I think I have shared elsewhere that one of my formative work experiences included being handed the keys to a portfolio of websites with zero supporting staff and being expected to keep comment moderation going seven days a week. I developed a small fixation around mobile work that predated useful technology for mobile work by a good number of years. It made sense because it allowed me to be out and about and doing little moderation micro-tasks whenever.</p>
<p>Since then, I&rsquo;ve had this scar or kink or crease in my brain about making sure the mobile bases are covered, but the more I think about it the more I think it&rsquo;s a bad idea. It&rsquo;s bad enough that I let Slack or Gmail on my phone, let alone wanting all my work notes and tasks available wherever I am. I suppose in a truly, truly dire situation I could use <a href="https://blink.sh/">Blink</a> to sign in to the desktop machine and run an agenda or look up a note, but that&rsquo;s a ridiculous scenario and the better answer is probably &ldquo;yeah, sorry, away from my computer rn.&rdquo;</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2024-01-11</title>
      <link>https://mike.puddingtime.org/posts/2024-01-11-daily-notes/</link>
      <pubDate>Thu, 11 Jan 2024 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2024-01-11-daily-notes/</guid>
      <description>Secrets of the ancients.</description>
      <content:encoded><![CDATA[<h2 id="secrets-of-the-ancients">Secrets of the Ancients</h2>
<p>I felt a little nostalgic for my old <a href="https://github.com/kaushalmodi/ox-hugo">ox-hugo setup</a> today. What was so great about it?</p>
<ul>
<li>One big org file.</li>
<li>Your stuff ends up in a regular Markdown file for portability.</li>
<li>Pretty nicely wired up in Doom&rsquo;s menu structure: <code>SPC X b d</code> and a daily post is underway.</li>
</ul>
<p>I took a look in <code>config.org</code> and it looked like all the config was still there, so I started a daily post. type type type type type &hellip; saaaaave? What was supposed to happen next? Whatever it was, it didn&rsquo;t happen. I tried the whole &ldquo;close your eyes and start typing&rdquo; thing to see if muscle memory would take over, but no &hellip; I hadn&rsquo;t used this setup since last June and it was gone from my fingers.</p>
<p>More fiddling and fussing &ndash; it turned out there was no muscle memory to forget because I&rsquo;d had it set up to autopublish on save. One of the cool things about <code>ox-hugo</code> is that if you leave a post heading in <code>TODO</code> state, it&rsquo;s a draft, so saving and auto-publishing is safe, even if you forget and wander off and push another commit somewhere.</p>
<p>But saving availed me nothing &hellip; huh &hellip; more poking.</p>
<p>Oh, right &hellip; I took <code>ox-hugo</code> out of my <code>packages.el</code> when I stopped using it to keep things light.</p>
<p>Now it&rsquo;s working again.</p>
<p>And wow did I just elide a ton of stuff I had so step back through to get it to where it &ldquo;just worked&rdquo; again. My <code>config.org</code> was full of helpful notes like:</p>
<blockquote>
<p>Of particular interest: <code>org-hugo-auto-set-lastmod</code>, which is set <code>'t</code> in a lot of examples. This one is pesky because when set <code>'t</code> it will bump the date on posts that don&rsquo;t have a <code>date:</code> property set (in favor of org-hugos <code>EXPORT_HUGO_DATE</code>). You don&rsquo;t get bit until you have <code>org-hugo-auto-export-on-save</code> set, at which point fat-fingering a save in the wrong post will change its mod date and hence its published date, teleporting it into the future.</p>
</blockquote>
<p>&hellip; but the whole setup was still littered with stuff I couldn&rsquo;t understand. Like &hellip;</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"> <span class="nv">COMMENT</span> <span class="nv">Local</span> <span class="nv">Variables</span> <span class="ss">:ARCHIVE:</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="nv">Local</span> <span class="nv">Variables:</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="nv">eval:</span> <span class="p">(</span><span class="nv">org-hugo-auto-export-mode</span> <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="nv">End:</span></span></span></code></pre></div>
<p>Why the COMMENT thing? Why the ARCHIVE thing? Why &ldquo;End:&rdquo;  I don&rsquo;t remember how I learned that stuff or why it is what it is. I am pretty sure there were 10th century Saxon peasants who understood more about how ancient Roman highways were engineered than I was able to understand about my own setup.</p>
<p>I don&rsquo;t think, the day before I was let go from, er, &ldquo;Puppet by Perforce&rdquo; that I imagined I&rsquo;d spend as much time as I did doinking around with org-mode blogging, but wow did I. It was fun. I can tell it was fun because I was leaving myself paragraph-long notes on minor configuration issues.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-12-29</title>
      <link>https://mike.puddingtime.org/posts/2023-12-29-daily-notes/</link>
      <pubDate>Fri, 29 Dec 2023 15:08:36 -0800</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-12-29-daily-notes/</guid>
      <description>kitty and denote. Terminal maximalism? A few fun CLI app directories. Autojump for better CLI fs navigation. More Vampire Survivors.</description>
      <content:encoded><![CDATA[<h2 id="vampire-survivors-again">Vampire Survivors, again</h2>
<p>I used to play this tower defense game on the Mac called <em>Hordes of Orcs.</em>  Orcs would enter a maze, you&rsquo;d build towers of all kinds to murder them. After playing for a while, I came to pick out a certain aural signature. As you built more and more elaborate orc-murdering capabilities, you could begin to hear a rhythm emerge &ndash; the sound of a tower spraying hot death, the sounds the orcs made. It was not a rhythm game, but it invoked a similar feeling.  I came to think of a session of HoO as &ldquo;firing up the murder factory.&rdquo;</p>
<p>Well, Vampire Survivors sort of does that, too. I didn&rsquo;t really notice until I turned the music off, but as a level progresses and gets more intense and your character is surrounded by a number of orbiting weapons (boomerang axes, a lethal garlic aura, puddles of holy water dropping from the sky, two orbiting birds that rain death, etc.) you can hear the rhythm of all those things interacting.</p>
<p>It also occurred to me that Vampire Survivors reminds me a lot of <em><a href="https://en.wikipedia.org/wiki/Robotron%3A_2084">Robotron: 2084</a></em>.</p>
<p>Anyhow, it&rsquo;s an awful lot of fun for such a simple game.</p>
<h2 id="kitty-and-denote">kitty and denote</h2>
<p>Okay.</p>
<ol>
<li>Emacs as a systemd service? <a href="/posts/2023-12-25-daily-notes/">Check</a>.</li>
<li>Launching useful stuff in kitty? <a href="/posts/2023-12-27-daily-notes/">Check</a>.</li>
<li>Making a quick Denote note in kitty &hellip; ?</li>
</ol>
<p>Sure.</p>
<p>Make an org capture template like this:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">with-eval-after-load</span> <span class="ss">&#39;org-capture</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;org-capture-templates</span>
</span></span><span class="line"><span class="cl">               <span class="o">&#39;</span><span class="p">(</span><span class="s">&#34;n&#34;</span> <span class="s">&#34;New note (with Denote)&#34;</span> <span class="nv">plain</span>
</span></span><span class="line"><span class="cl">                 <span class="p">(</span><span class="nv">file</span> <span class="nv">denote-last-path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                 <span class="nf">#&#39;</span><span class="nv">denote-org-capture</span>
</span></span><span class="line"><span class="cl">                 <span class="ss">:no-save</span> <span class="no">t</span>
</span></span><span class="line"><span class="cl">                 <span class="ss">:immediate-finish</span> <span class="no">nil</span>
</span></span><span class="line"><span class="cl">                 <span class="ss">:kill-buffer</span> <span class="no">t</span>
</span></span><span class="line"><span class="cl">                 <span class="ss">:jump-to-captured</span> <span class="no">t</span><span class="p">)))</span></span></span></code></pre></div>
<p>&hellip; then add this to <code>kitty.conf</code>:</p>
<p><code>map kitty_mod+d launch emacsclient -t &quot;org-protocol:///capture?template=n&quot;</code></p>
<p>That launches an emacsclient instance in a new kitty window teed up to enter the title and tags for a denote note.</p>
<p>There&rsquo;s another way to do this, using kitty&rsquo;s startup sessions capabilities.</p>
<p>You can make a session file with something like this in your config directory:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">launch emacsclient -t &#34;org-protocol:///capture?template=n&#34;
</span></span><span class="line"><span class="cl">focus_os_window`</span></span></code></pre></div>
<p>&hellip; name it something like <code>denote.conf</code></p>
<p>&hellip; and launch it with <code>kitty --session denote.conf</code>.</p>
<p>Which isn&rsquo;t really what you want to do. You really want to use that for a custom keybinding out in your window manager.</p>
<h2 id="terminal-maximalism">terminal maximalism?</h2>
<p>Seeing my agenda for the day in a terminal &hellip; getting my upcoming todos in a terminal &hellip; denote notes in a terminal &hellip;</p>
<p>Is this all some sort of terminal maximalism thing?</p>
<p>Maybe, I guess?</p>
<p>I don&rsquo;t know about the rest of the world, but I go through moods with this stuff. Some days I feel supremely unfussed about the assorted UIs imposed on us by web app designers. Some days I feel very resistant to messing around with a browser or mouse. It&rsquo;s nice to sit down to a text editor in a terminal, start writing, and be able to quickly orient on where I&rsquo;m at in the day with a glance at my agenda or the day&rsquo;s todos. There are some days I don&rsquo;t feel put upon doing that in a browser window.</p>
<p>Looking at <a href="https://github.com/xwmx/nb">nb</a> is what got me thinking about doing more in a text shell, but I couldn&rsquo;t figure out a good way to solve for the mobile use case and I didn&rsquo;t want to live in it as my task manager. Sometimes it is handy to be able to manage or just review todos with a GUI. Its notes tool is fine, but I spent a lot of time setting up Denote and really appreciate it, plus I have a way to review my Denote notes via the web and create them on the go with Drafts.</p>
<p>And when I think about my little 11&quot; MacBook Air, that&rsquo;s a machine that would benefit from not having a lot of GUI clutter and not having a lot of open apps. It&rsquo;s a great candidate for spending more time in a terminal.</p>
<p>So &hellip; less terminal maximalism and more terminal optionality. For days when pointy-clicky feels really burdensome.</p>
<p>Anyhow, I did find a few good collections of CLI app links:</p>
<ul>
<li><a href="https://github.com/agarrharr/awesome-cli-apps">awesome-cli-apps</a></li>
<li><a href="https://github.com/alebcay/awesome-shell">awesome-shell</a></li>
</ul>
<p>I think my favorite discovery from both of them at this point is probably <a href="https://github.com/alebcay/awesome-shell#readme">autojump</a>, which watches where you visit and lets you go there from anywhere else, rather than having to descend and ascend a directory hierarchy. If you want to give it a try, the documentation is missing one key thing, at least if you pull it down from Fedora: You need to source a file it sticks in <code>/usr/share/autojump</code> in your shell&rsquo;s <code>.rc</code> file. The core package in Fedora supplies that file for bash, and you have to install the <code>autojump-zsh</code> package to get it for zsh.</p>
<h2 id="the-working-world">the working world</h2>
<p>Today I feel very annoyed with what I have come to think of as &ldquo;Businessing,&rdquo; which is to say &ldquo;all the things people do in the course of working in a business, but especially the ones that involve things nobody will say and rules nobody will articulate.&rdquo;</p>
<p>I don&rsquo;t think I have much more to say about it than that, so consider this me quietly whispering discontent into a hole in the side of a stump in the middle of an empty field under a new moon at midnight.</p>
<p>Okay. I have a little more to say.</p>
<p>Years and years ago I read Paul Fussel&rsquo;s <em><a href="https://www.goodreads.com/book/show/60044.Class">Class</a></em>. I was at something of a personal low point: Recently out of the army, a very different person on the other side of the experience, and feeling exiled in a small southern university town. <em>Class</em> gave me a lens for observing other people that my feelings of unbelonging and insecurity hadn&rsquo;t ever allowed through. It&rsquo;s a light, biting book that would pair nicely with Barbara Ehreneich&rsquo;s <em><a href="https://www.goodreads.com/book/show/24457.Fear_of_Falling">Fear of Falling</a></em>.</p>
<p>Once I saw the thing <em>Class</em> calls out when it&rsquo;s at its most empathetic &ndash; the constant and pervasive atmosphere of insecurity middle class people occupy and perpetuate &ndash; it made some things about work a little easier.  But just a little.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-12-11</title>
      <link>https://mike.puddingtime.org/posts/2023-12-11-daily-notes/</link>
      <pubDate>Mon, 11 Dec 2023 11:24:37 -0800</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-12-11-daily-notes/</guid>
      <description>Pop!_OS redux. Bad company in Emacs. You are not my spin doctor. A fun documentary about the Star Wars Holiday Special. Hugo previews in Emacs.</description>
      <content:encoded><![CDATA[<h2 id="pop_os-redux">Pop!_OS redux</h2>
<p>I set up a Linux PC over the weekend, and I&rsquo;m going to give Pop!_OS a try on it. I want to be able to use this machine for work sometimes, and there are a few desktop-y things that work better under Pop! than they do Fedora, maybe owing to Pop! remaining on xorg. Screen sharing in Zoom, for instance, works like you&rsquo;d expect on xorg and does not under Wayland. Apps with taskbar icons also work without the need for an extension.</p>
<p>You can tell Pop! is a little behind Fedora 39, but I&rsquo;m not sure it&rsquo;s that big a deal. I found <a href="https://launchpad.net/~ubuntuhandbook1/+archive/ubuntu/emacs">a PPA for Emacs 29.1</a>, but don&rsquo;t worry about much else: The stuff that moves with any speed is coming from a Flatpak. My <code>~/bin</code>, <code>~/.fonts</code>, and <code>~/.config/doom</code> are all handled via SyncThing.</p>
<p>What else?</p>
<ul>
<li>I noticed that my Elgato CamLink 4k + FujiFilm X-T2 work with a little less lag. I think there still is some, but it&rsquo;s pretty smooth.</li>
<li><a href="https://github.com/mikebrady/shairport-sync">shairplay-sync</a> has some permissions issues as a service, but works fine when I start it in daemon mode, so I&rsquo;ve moved my bookshelf speakers over to this machine: It acts like an AirPlay 2 endpoint for all my other stuff, and I can use Cider to get at my Apple Music stuff when I&rsquo;m working on this machine.</li>
<li>There&rsquo;s less font weirdness than under Fedora, meaning most apps show most fonts at a normal size out of the box and don&rsquo;t require passing environmental variables along or messing with config files.</li>
<li>My Jabra Engage 75 works fine with this thing, so no more messing around with AirPods: I just plugged it into an open port and I&rsquo;m back to reliable audio.</li>
<li>The rbenv and ruby-build that ship with Jammy don&rsquo;t have any of Ruby 3.x available. I just installed that on my own and added ruby-build as a plugin. Problem solved.</li>
</ul>
<p>Otherwise &hellip; I got through a day with it and it worked great: No weird glitches, crashes, or whatever. Multiple Zoom calls. Oh, and I&rsquo;m down to my last possum sticker, but the wireless scanning stuff works great, too: I managed to get a hi-res scan of my last sticker so I can make more.</p>
<h2 id="bad-company">Bad company</h2>
<p>I like <code>company-mode</code> in Emacs when I&rsquo;m coding, I hate it when I&rsquo;m writing prose. It slows everything down to suggest words I do not need suggested. This incantation fixed it:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">company-global-modes</span> <span class="o">&#39;</span><span class="p">(</span><span class="nf">not</span> <span class="nv">text-mode</span> <span class="nv">markdown-mode</span> <span class="nv">org-mode</span><span class="p">))</span></span></span></code></pre></div>
<h2 id="dont-spin-me">Don&rsquo;t spin me</h2>
<p>I enjoyed the most recent episode of <a href="https://www.patreon.com/badfaithpodcast/posts">Bad Faith</a>, &ldquo;Vibecession?&rdquo;, partly for the analysis and partly because one of the guests got to the thing that has been bothering me the most about the discourse around the economy:</p>
<blockquote>
<p>&ldquo;&hellip; as to why people are so heated in the first place I think you have a few things going on. One you do have people who are just kind of concerned about Biden&rsquo;s electoral prospects they&rsquo;re worried about Trump and they&rsquo;re worried about [&hellip;] a negative narrative.</p>
</blockquote>
<blockquote>
<p>&ldquo;You&rsquo;ve always got people out there who although they [&hellip;] appear to be kind of making objective arguments about this or that topic they&rsquo;re really mostly worried about trying to kind of steer the discourse in one way or another to to be more favorable to Democrats or less favorable to Democrats or whatever so there&rsquo;s that aspect [&hellip;] of the election worrying &hellip;&rdquo;</p>
</blockquote>
<p>I posted about it a few days ago:</p>
<iframe src="https://social.lol/@mph/111547466665352579/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe><script src="https://social.lol/embed.js" async="async"></script>
<p>&hellip; and then:</p>
<iframe src="https://social.lol/@mph/111547498854213817/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe><script src="https://social.lol/embed.js" async="async"></script>
<p>&hellip; and then I favorably boosted this:</p>
<iframe src="https://mastodon.social/@tess/111545872352995486/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe><script src="https://mastodon.social/embed.js" async="async"></script>
<p>&hellip; because if there&rsquo;s one word I have worn some grooves into over the past four years, it is &ldquo;precarity.&rdquo;</p>
<p>I don&rsquo;t know. We can either speak truthfully or we cannot, and I am not responding well to progressives or leftists or whatever who do not want to speak truthfully because they believe that are actually unpaid press secretaries for the Biden administration.</p>
<p>I&rsquo;m not telling anyone what to do with their spare time, I&rsquo;m just saying that if you&rsquo;re talking to me, leave me out of the four-dimensional chess game. I show up every election and vote exactly as you&rsquo;d expect. It is <em>okay</em> if, in December of the year before an election, I say &ldquo;I wish we had a better alternative than Biden.&rdquo; And it is super okay if I say, &ldquo;you know what, I wish we had a better alternative than this entire way of being we&rsquo;ve landed on.&rdquo;</p>
<h2 id="a-disturbance-in-the-force">A Disturbance in The Force</h2>
<p><em><a href="https://www.disturbanceintheforce.com/">A Disturbance in the Force</a></em> is a documentary about the 1978 <em>Star Wars Holiday Special</em>.</p>
<p>Al and I went to see it at the Hollywood Theater several years ago. I managed to win a cool Boba Fett poster (the cartoon version, from the special). It truly is wretched, but the documentary does a nice job of explaining that actually <em>everything</em> in 1978 was at least a little wretched, including the entire variety show genre.</p>
<p>And it does a nice job of explaining why the silly thing even mattered to anyone.</p>
<p>I had just turned nine when <em>Star Wars</em> came out. My family went to the theater to see a 6 p.m. showing on opening weekend in 1977, and ended up waiting around for a special 10 p.m. showing the theater added. It stayed in that theater for the better part of a year, and it became a way to just get me out of the house: Mom would give me ticket money, I&rsquo;d walk across the field and hop a ditch to get into the loading dock area of the mall, then walk around to the theater. When we visited relatives that year, &ldquo;what would Mike like to do&rdquo; was always &ldquo;go see <em>Star Wars</em>.&rdquo;</p>
<p>I was completely saturated in anything <em>Star Wars</em> I could get my hands on. Magazines, copies of <em>People</em> featuring any of the cast, the novelization, the comic books, <em>aaaaanything.</em> So the Holiday Special was a huge deal because it was gonna be more actual <em>Star Wars</em> and not just stuff <em>about</em> <em>Star Wars</em>.</p>
<p>And, as someone points out in the documentary, <em>Star Wars</em> was a very wild property at that point. Like, there were hints of deep lore and all, but the only &ldquo;canon&rdquo; you had to work with was the movie itself and wild theorizing. Some heretics thought Darth Vader was actually a robot. There were rumors that there would be a whole movie about Wookies. It was just this crazy thing that had landed in our pop culture lives and nothing was ever going to be the same again. So we were ripe for whatever George Lucas wanted to churn off the assembly line, including, apparently, a superannuated Wookie grandfather perving out to VR porn with Dianne Carroll.</p>
<p>Anyhow, the documentary is a fun 90-minute diversion. Not super heavy, but cool to hear from people who actually worked on it, and fun to see a lot of period clips, like the bonkers Donnie and Marie episode with Kris Kristofferson Han Solo and Paul Lynde Imperial officer.</p>
<h2 id="hugo-previews-in-emacs">Hugo Previews in Emacs</h2>
<p>I made this function to spin up the Hugo preview server while still working in Emacs:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-start-hugo-server</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Run Hugo server with live reloading.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">root</span> <span class="p">(</span><span class="nv">projectile-project-root</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">default-directory</span> <span class="nv">root</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">compile</span> <span class="s">&#34;hugo server -D --navigateToChanged&#34;</span> <span class="no">t</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-stop-hugo-server</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Stop Hugo server.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">kill-compilation</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">map!</span> <span class="ss">:leader</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="ss">:prefix</span> <span class="p">(</span><span class="s">&#34;H&#34;</span> <span class="o">.</span> <span class="s">&#34;Hugo&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">       <span class="ss">:desc</span> <span class="s">&#34;Start Hugo Server&#34;</span> <span class="s">&#34;S&#34;</span> <span class="nf">#&#39;</span><span class="nv">my-start-hugo-server</span>
</span></span><span class="line"><span class="cl">       <span class="ss">:desc</span> <span class="s">&#34;Stop Hugo Server&#34;</span> <span class="s">&#34;s&#34;</span> <span class="nf">#&#39;</span><span class="nv">my-stop-hugo-server</span><span class="p">))</span></span></span></code></pre></div>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-07-03</title>
      <link>https://mike.puddingtime.org/posts/2023-07-03-daily-notes/</link>
      <pubDate>Mon, 03 Jul 2023 08:54:41 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-07-03-daily-notes/</guid>
      <description>John Gruber might be Satan. magit-wip-mode. I can never tell when NYT is being obtuse or unintentionally helpful. New Himalayan loom &amp;ndash; fingers crossed.</description>
      <content:encoded><![CDATA[<h2 id="john-gruber-might-be-satan">John Gruber might be Satan.</h2>
<p><a href="https://johnmacfarlane.net/beyond-markdown.html">Reader, I lol&rsquo;d</a>.</p>
<h2 id="magit-wip-mode">magit-wip-mode</h2>
<p><a href="https://magit.vc/manual/magit/Wip-Modes.html">magit WIP modes</a>:</p>
<blockquote>
<p>&ldquo;Git keeps committed changes around long enough for users to recover changes they have accidentally deleted. It does so by not garbage collecting any committed but no longer referenced objects for a certain period of time, by default 30 days.</p>
</blockquote>
<blockquote>
<p>&ldquo;But Git does not keep track of uncommitted changes in the working tree and not even the index (the staging area). Because Magit makes it so convenient to modify uncommitted changes, it also makes it easy to shoot yourself in the foot in the process.</p>
</blockquote>
<blockquote>
<p>&ldquo;For that reason Magit provides a global mode that saves tracked files to work-in-progress references after or before certain actions. (At present untracked files are never saved and for technical reasons nothing is saved before the first commit has been created).&rdquo;</p>
</blockquote>
<p>I wander back and forth machines a lot and this seems like useful insurance, so I turned it on.</p>
<h2 id="accurate-but-not-good">accurate but not good</h2>
<p>Luke prompted a half-response this morning:</p>
<iframe src="https://hachyderm.io/@lkanies/110648795495111994/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe>
<p>I replied in a spirit appropriate to me, which is to say &ldquo;disappointed idealist who should learn to either quit being disappointed, or give up on being an idealist, or get a new sense of humor.&rdquo;</p>
<p>Because <a href="https://www.nytimes.com/2023/07/02/style/rethinking-july-4th-celebrations.html">that article</a> feels like a bookending, illustrative underscore of <a href="https://www.nytimes.com/2023/06/29/opinion/college-admissions-affirmative-action.html">this column</a>, which I went into sort of nodding along in a &ldquo;checks out&rdquo; sort of way, then sitting up straight when it got to:</p>
<blockquote>
<p>&ldquo;Expect more antiracist action plans, more vaporous decolonization, more mandated training, more huckster consultants, more vacuous reports, more administrators whose jobs no one can explain, more sleazy land acknowledgments (“Sorry I stole your house!”), more performative white self-flagellation, more tokenization of minority faculty members.</p>
</blockquote>
<blockquote>
<p>&ldquo;And amid this great tornado of race chatter, if you take a moment to plug your ears and look around, you will probably begin to notice fewer and fewer brown and Black kids reading on the quad and, down the line, fewer and fewer brown and Black doctors in the maternity wards. It will turn out that all those initiatives will have next to nothing to do with actually combating structural racism. We may well find ourselves teaching Toni Morrison to rooms that get whiter and richer by the year.&rdquo;</p>
</blockquote>
<p>The biggest change I noticed at my job from 2019 to 2022 was that HR managed to edge everyone out of anti-racist work, and suddenly anything that seemed like it could be meaningful and engage senior managers was ruled &ldquo;performative.&rdquo; Mentorship programs? Performative. Sponsorship programs? Performative. I came to realize that &ldquo;we don&rsquo;t want to be performative&rdquo; was just a thought-terminating cliché meant to shut down the conversation.</p>
<p>What were you supposed to do? Basically, fill low-stakes associate positions, maaaaaybe send a manager out to specific recruiting events, but otherwise just hand the entire hiring process over to recruitment and forget about it. If you looked at any demographic information that suggested perhaps the lenses you were supposed to use &mdash; ratios that ignored role or level &mdash; were problematic, you were asked how you got the information you were using because they thought they&rsquo;d locked it all up. And I watched a good leader driven out by someone who weaponized the whole topic.</p>
<p>When I helped interview HR business partners, it suggested to me that what I was seeing wasn&rsquo;t just local. One of them got uncomfortable when I asked about their experience with ERGs, and preferred to discuss how happy people were with a local soccer team ERG they&rsquo;d sponsored. I honestly didn&rsquo;t know what to do with that, but just marked &ldquo;strong no,&rdquo; explained why, and was relieved the hiring team went another direction. For all I know they thought that &mdash; as an older, white, male interviewer &mdash; I <em>wanted</em> to hear about a soccer ERG instead of an identity-based one, but I didn&rsquo;t feel like playing eight-dimension chess. <em>Including</em> soccer fans seemed like an odd DEI triumph.</p>
<p>So if I&rsquo;m coming off a little mordant about an NYT piece that manages to both report <em>and</em> perform a certain weird forgetfulness in the summer of 2023, it&rsquo;s because I&rsquo;m struggling to understand what we <em>got</em> besides a new consultant class, a new slice of territory for HR departments, and vague commitments to &ldquo;work on ourselves.&rdquo; I can&rsquo;t get mad about the reporting itself, because it seems <em>accurate.</em> It&rsquo;s where we all are. What do we want to do about that?</p>
<h2 id="new-loom-on-the-himalayan">New loom on the Himalayan</h2>
<p>I stuck <a href="https://accessories.hitchcocksmotorcycles.com/accessory-shop/Charging/46817">the new loom</a> on the RE Himalayan today. It was a 20-minute process, from taking off the side plate to figuring out where everything was, to disconnecting and reconnecting all the connectors.</p>
<p>The net effect is that it puts the gear detector behind the ignition instead of straight to the battery, which I hope will stop the parasitic drain I&rsquo;ve been dealing with. It&rsquo;s a weird thing to have to do, but I read a few rumors online that some dealers have been putting them on at sale. It&rsquo;s just a bad design decision with a $25 fix.</p>
<p>Al and I took a ride for groceries this evening. When we got home I took a reading off the battery then set a reminder to myself to check back in 24 hours to see whether the drain seems reasonable. Since I put an <a href="https://antigravitybatteries.com/products/starter-batteries/restart-oem/atz10-rs/">Antigravity battery</a> in there the stakes are a little lower if it drains too much while I observe.</p>
<p>Not related to the loom, the bike is running really well now.  It sounds good, feels smooth, and I&rsquo;ve appreciated how manageable it is. I had it out twice today and just enjoyed driving it through a few curvy parts of southeast Portland in the sun. We&rsquo;re thinking about taking a camping trip down in Clackamas County and going out separately so we can bring the Himalayan along and enjoy some forest service roads and rides along the river.</p>
<p>Still considering trading it in or selling it, but it&rsquo;s growing on me again. I just wish RE was just better at QA overall. I&rsquo;ve got $125 worth of dongles hanging off the thing to get it to just do what it should have done out of the factory, I&rsquo;ve spent four hours sitting around the dealership while the mechanics grudgingly fixed stuff like pinched vacuum hoses and weirdly tuned electrics, and I spent a bunch of my own time hand-tightening connections and digging overpacked grease out of connectors.</p>
<p>With all that time and effort invested, it&rsquo;s behaving. I don&rsquo;t know if I&rsquo;d recommend these bikes to a newbie. I have some patience and don&rsquo;t mind having to do a little work &mdash; it&rsquo;s sort of educational and interesting. Someone new to the hobby shouldn&rsquo;t have to think about that stuff when they&rsquo;re trying to just learn the basics and wondering if stalls or glitches are their fault.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-07-02</title>
      <link>https://mike.puddingtime.org/posts/2023-07-02-daily-notes/</link>
      <pubDate>Sun, 02 Jul 2023 10:38:55 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-07-02-daily-notes/</guid>
      <description>First Thorns match. A little more on Lemmy. Secret Invasion. Tagging Hugo posts in Emacs. Looking for monitor recommendations. Ben in France.</description>
      <content:encoded><![CDATA[<h2 id="first-thorns-match">First Thorns match</h2>
<p>Al and I went to our first Portland Thorns match last night. I think this is maybe the third soccer match I&rsquo;ve ever been to. The two previous were Timbers games for company parties and one of them got rained on pretty hard.</p>
<p>Since this was my first &ldquo;go sit in the regular seating, pay attention for 90 minutes&rdquo; match I wasn&rsquo;t sure what to expect. It was pretty fun. Our hosts are on their first season passes and newly energized about the sport, so their enthusiasm rubbed off. I think the other thing I kept coming back to was that watching requires patience similar to watching high-level jiu jitsu grapplers, but the other fans do a lot to contribute to your sense of the ebb, flow, rising and falling tension.</p>
<h2 id="more-lemmy">More Lemmy</h2>
<p>I have three accounts on assorted Lemmy instances, with a fourth pending. I learned about <a href="http://wefwef.app">wefwef</a> yesterday, which is a PWA that provides a nice client you can save to your phone homescreen same as Elk for Mastodon. I also have the beta of <a href="https://github.com/gkasdorf/memmy">memmy</a> on my phone.</p>
<p>There&rsquo;s not a ton of interaction on many of the communities I&rsquo;ve subscribed to so far. There&rsquo;s <a href="https://lemmy.ml/c/portland">a portland one</a> where people are swearing to be nicer, less hostile, and less censorious than /r/portland, which is a super low bar; and also less reactionary and goonish than /r/PortlandOR, which &mdash; again &mdash; low bar.</p>
<p>You can subscribe to communities in Mastodon by adding their address sans the <code>!</code> lemmy convention. I added a few but there&rsquo;s the usual &ldquo;now your instance needs to start pulling their stuff in&rdquo; lag.</p>
<h2 id="secret-invasion">Secret Invasion</h2>
<p>I&rsquo;m two episodes into the Skrull/Nick Fury espionage series <em>Secret Invasion</em>. Not sure. It feels like in terms of size, scale, and texture it&rsquo;s maybe a step down from <em>The Falcon and The Winter Soldier</em>, which felt pretty slick; and maybe a step up from <em>She-Hulk Attorney at Law</em>, which felt like it was made on a shoestring budget. None of those three have the charm of <em>Hawkeye</em>.</p>
<p>The dialog&rsquo;s sort of flat, there are &ldquo;big scenes&rdquo; that feel small. Samuel L. Jackson is doing something different and I&rsquo;m not sure it always works. There&rsquo;s a reason to not involve the Avengers that &hellip; it&rsquo;s going to always be a problem when there are any issues going on of a sub-Thanos scale where you&rsquo;re not just sending a group of second-string probationary Avengers to fix it.</p>
<p>But, you know, let&rsquo;s see where it goes.</p>
<h2 id="emacs-function-for-tagging-posts-in-hugo">Emacs function for tagging posts in Hugo</h2>
<p>I seem to be sticking to just blogging in Markdown, <a href="https://gist.github.com/pdxmph/9271cbb22d90f7e73a4b88664e0eaadd">using the Ruby script I wrote</a>. I didn&rsquo;t realize how much I missed reference links, or Markdown link notation in general. Tags are a little different story. I like the way <code>ox-hugo</code> uses org-mode&rsquo;s heading tags (<code>:foo:bar:baz:</code>) instead of Markdown/YAML&rsquo;s key tags (<code>tags: [&quot;foo&quot;,&quot;bar&quot;,&quot;baz&quot;]</code>).</p>
<p>So I made <code>mph/replace-tags-in-frontmatter</code> and stuck it in my growing Hugo submenu. You just invoke it and enter a comma-delimited set of tags and it replaces that frontmatter key. My script asks for tags up front, which is fine for single-topic posts where I know the tags up front. Doesn&rsquo;t work as well for daily posts, where it takes a day to know what&rsquo;s going in.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/replace-tags-in-frontmatter</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Replace the &#39;tags&#39; line in YAML frontmatter with user input.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let*</span> <span class="p">((</span><span class="nv">frontmatter-start-regexp</span> <span class="s">&#34;^---\n&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">frontmatter-end-regexp</span> <span class="s">&#34;\n---\n&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">tags-regexp</span> <span class="s">&#34;^\\s-*tags:\\s-*\\[.*\\]&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">input</span> <span class="p">(</span><span class="nf">read-string</span> <span class="s">&#34;Enter new tags (comma-separated): &#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">new-tags</span> <span class="p">(</span><span class="nf">mapcar</span> <span class="p">(</span><span class="nb">lambda</span> <span class="p">(</span><span class="nv">tag</span><span class="p">)</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;\&#34;%s\&#34;&#34;</span> <span class="p">(</span><span class="nv">string-trim</span> <span class="nv">tag</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">                           <span class="p">(</span><span class="nv">split-string</span> <span class="nv">input</span> <span class="s">&#34;,&#34;</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">save-excursion</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">goto-char</span> <span class="p">(</span><span class="nf">point-min</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">re-search-forward</span> <span class="nv">frontmatter-end-regexp</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">backward-char</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">re-search-backward</span> <span class="nv">frontmatter-start-regexp</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">forward-char</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">re-search-forward</span> <span class="nv">tags-regexp</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">replace-match</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;tags: [%s]&#34;</span> <span class="p">(</span><span class="nf">mapconcat</span> <span class="nf">#&#39;identity</span> <span class="nv">new-tags</span> <span class="s">&#34;,&#34;</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">message</span> <span class="s">&#34;Tags replaced successfully.&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">map!</span> <span class="nb">:leader</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">:prefix</span> <span class="p">(</span><span class="s">&#34;H&#34;</span> <span class="o">.</span> <span class="s">&#34;Hugo&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">       <span class="nb">:desc</span> <span class="s">&#34;Set tags for Hugo post&#34;</span> <span class="s">&#34;t&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/replace-tags-in-frontmatter</span><span class="p">))</span></span></span></code></pre></div>
<h2 id="ben-in-france">Ben in France</h2>
<p>Ben watched the Apple store in Strasbourg get smashed and looted, avoided a tear-gassing, and was briefly separated from his bike. He finally made it to the train after missing the first one out of town. Now he&rsquo;s on to the Netherlands.</p>
<p>When I was almost his exact age I went to Europe and then the then-Soviet Union as part of a student group. Our professor gave us a lot of advice on how to avoid local trouble, and since it was winter things were pretty much on rails anyhow: Cologne was mild, Copenhagen was wintry but okay, Stockholm was extremely cold, then Leningrad and Moscow were where I learned that -40 is the same on both the Fahrenheit and Celsius scales. Hungary: Cold and snowbound. Zurich: Not so bad but we were staying near a park known for aggressive cop sweeps. So there were opportunities for a little bit of mischief, but the overall vibe was &ldquo;travel in groups, don&rsquo;t go off alone.&rdquo; So we mostly didn&rsquo;t except for one guy who made himself sort of the group pariah.</p>
<p>When I think about my year in Korea, I&rsquo;m surprised nothing happened. I was there during a summer with some violent anti-US protests thanks to high-profile brawls between soldiers and Korean civilians. We were locked down on post for several weekends straight because the risk of violent altercation was high. I was a little bit of a loner over there, so it wasn&rsquo;t unusual for me to be out in the ville on my own, and a few times when I had to drive command staff up to Seoul for overnighters I just wandered around on my own after they cut me loose for the day. My <a href="https://en.wikipedia.org/wiki/Korean_Augmentation_To_the_United_States_Army">KATUSA</a> friend said my lonerish-ness made him nervous. I was in a weird frame of mind at that point &mdash; fresh out of jump school and hence invulnerable, more physically capable than I&rsquo;d ever been &mdash;  but he had a list of places I wasn&rsquo;t supposed to ever go and said the stakes would be higher than a beating or a black eye,  so I didn&rsquo;t go to those places. I got followed a few times other places, did the whole &ldquo;demonstrate situational awareness&rdquo; thing, and nothing ever happened.</p>
<p>Ben&rsquo;s over there with two other kids just roaming around, with the itinerary seeming to change as whims take them. It continues to make me incredibly happy for him. It took me a while to gain the confidence he has, his street savvy is a lot higher than mine was at his age, and his confidence comes from knowing how to get away from whatever it is, not steer into it.</p>
<h2 id="typography">typography</h2>
<p>I saw a blog go by with a really nice serifed body type. I spent 30 minutes messing around with Google Fonts trying to dial in something similar and ended up not liking anything I saw, so I picked something completely different to freshen up headings and nav but otherwise left everything alone.  I&rsquo;m not sure how much of not liking things was not liking them and how much was not being sure of my own typographical taste. Part of me thought &ldquo;oh! well! Go learn!&rdquo; and the rest of me outvoted that part.</p>
<p>Anyhow, day two of a four-day weekend. Nothing on the agenda for the next two days besides visiting a friend for a walk through Oaks Bottom tomorrow, and having some friends over for dinner for the Fourth. The park across the street is going to go completely bananas with the usual impromptu fireworks show, and there&rsquo;s a  better-than-even chance of the show more or less ending with a drunken brawl, so we tend to stick close to the house every year to make sure nothing catches on fire. This will be the 14th year we&rsquo;ve enjoyed this particular experience. This year I&rsquo;m anticipating it with less dread than normal, and maybe even a little amusement.</p>
<p>Somehow our little park became the place a lot of people go to set off their illegal fireworks. People start showing up in the early afternoon to set up chairs and blankets at the edge of the treeline. Within an hour of sundown everything is parked in and there are two rows of picnic chairs around the perimeter of the park, which is a block square minus maybe 50 or 75 yards of treeline on our end of it.</p>
<p>On the one hand, wow it can be annoying, especially when people block your driveway, set fireworks off next to your car, or set things on fire. And nobody packs out their trash, so the park is strewn with trash and expended fireworks the next morning. But it&rsquo;s also just &hellip; this thing that happens. People get a lot of joy from it. It&rsquo;s not official or sanctioned. It&rsquo;s seems to be a spontaneous thing and it happens every year. When we had a rescue dog who was terrorized by the whole thing it was the absolute worst. Now that we don&rsquo;t, I feel bad for all the other dogs and people in the neighborhood who are suffering, but it doesn&rsquo;t feel <em>personal</em>, and the cops and fire department have zero interest in doing anything to curtail something they come around and watch every year. So there&rsquo;s not much to do but watch it unfold and people watch.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-07-01</title>
      <link>https://mike.puddingtime.org/posts/2023-07-01-daily-notes/</link>
      <pubDate>Sat, 01 Jul 2023 08:24:29 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-07-01-daily-notes/</guid>
      <description>Swapping Zoom for Golden Ratio (Emacs window resizing). Life after reddit. First poke at Lemmy. Himalayan Day. Thorns game.</description>
      <content:encoded><![CDATA[<h2 id="zoom-swapped-in-for-golden-ratio">Zoom swapped in for Golden Ratio</h2>
<p>I mentioned a few weeks ago that I was trying out Golden Ratio, an Emacs package that dynamically resizes windows inside the frame as you switch between them. I saw a few warnings here and there that it had a few bugs, but for the past few weeks it seemed fine. I finally came across one a few days ago that I couldn&rsquo;t quite isolate &mdash; it broke the way <code>org-insert-structure-template</code> worked &mdash; and finally took the time to narrow it down this morning.</p>
<p>Golden Ratio isn&rsquo;t being maintained anymore, so I decided &ldquo;not enough time in the day,&rdquo; marked that part of my config <code>:tangle no</code> and installed <a href="https://github.com/cyrus-and/zoom">Zoom,</a>, which does much the same thing.</p>
<p>Minimum config:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">custom-set-variables</span>
</span></span><span class="line"><span class="cl"> <span class="o">&#39;</span><span class="p">(</span><span class="nv">zoom-mode</span> <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="o">&#39;</span><span class="p">(</span><span class="nv">zoom-size</span> <span class="o">&#39;</span><span class="p">(</span><span class="mf">0.618</span> <span class="o">.</span> <span class="mf">0.618</span><span class="p">)))</span></span></span></code></pre></div>
<h2 id="post-reddit">Post-reddit</h2>
<p>Golden Ratio made me think about reddit for a bit. I learned about that package from one of the Emacs subreddits. I don&rsquo;t recall a ton of discussion about it, so it must have been one of the quiet link aggregator subs, like /r/planetemacs. That was the other half of my reddit experience: Grazing steady feeds of interesting stuff. I&rsquo;ve learned a lot about assorted interests &mdash; motorcycling, longboarding, Emacs, ruby &mdash; from watching a subreddit scroll by and just grabbing links.</p>
<p>That part of my experience is largely unaffected by the third-party app shutdown. I don&rsquo;t follow or participate in discussions much, so I can do that from a browser or reddit&rsquo;s own, terrible app.</p>
<p>But while I&rsquo;m not, like, <em>boycotting</em> mad, I&rsquo;m irritated. I don&rsquo;t know how spez managed to press so many buttons at once with me &mdash; ordinarily tech dude stuff rolls off my back, and C-level tech dude stuff barely registers as language or thought, but the combination of smarm, Ralph-Wiggum-esqe &ldquo;I&rsquo;m a <em>business man</em> <code>&lt;eats paste&gt;</code>&rdquo; posturing, deceit, and bizarre turn into trying to make the whole thing some sort of identity politics issue just &hellip; wow.</p>
<p>Like, look: Even at my most business-like &mdash; my most &ldquo;jacked director&rdquo; &mdash; I&rsquo;m pretty much just one of those vintage-looking prints you see at mall restaurants of little kids dressed in adult clothing sitting at a desk on an old-timey phone or whatever.  If I have a philosophy of business communication or governing principle for &ldquo;how I show up,&rdquo; it is probably &ldquo;best to keep your mouth shut and be thought a fool &hellip;&rdquo; etc.</p>
<p>But when I read the clown-like attempts at businessing going on over the Apollo debacle &mdash; the appalling, <em>weak</em> blithered  promises that everyone was gonna be cool here &mdash; I was sort of appalled and a little embarrassed for them. It was like when you ask one of your managers &ldquo;so did you give them that feedback about promotion?&rdquo; and they swear to God they laid down the law but their report took it like a champ, then you actually read the check-in and it&rsquo;s, like, &ldquo;Joe Grudd was stellar this year. Recommending for immediate promotion. Top notch ace contributor. Indispensable.&rdquo;</p>
<p>And <em>then</em>, after dithering around and failing to just sit up straight and deliver the damn message, they let themselves get clowned. <em>Nobody</em> covered themselves in glory in whatever negotiations were going on, but table stakes for people who&rsquo;re busy ruining the customer experience on a beloved website because They Are Serious Business People Who Get How This Works is pretty much &ldquo;don&rsquo;t look worse than the one-man cottage industrialists who&rsquo;re hoping you&rsquo;ll get them to go peacefully if you just buy them out <em>ha ha only serious</em>.&rdquo;</p>
<p>But somehow they couldn&rsquo;t even do that.</p>
<p>Anyhow.</p>
<p>It just sort of shades the whole experience now. Perfectly nice, sometimes emotionally violent shitposters just getting on with their days, the occasional incel breaking cover and going down in a hail of gunfire under the helicopter spotlights of the moderation team, no longer ad free, forcing you to remember that when someone says &ldquo;have some gold, kind stranger&rdquo; that gold was sold to them by the Ed Rooney of web publishing. There&rsquo;s just this lingering fart smell wafting through it all. Where do you go from here?</p>
<h2 id="lemmy">Lemmy</h2>
<p>Well, I decided to look around at Lemmy.</p>
<p>I get it, more or less, and am assuming that all the weirdness I&rsquo;m seeing is down to the same thing that happened with Mastodon last fall: Lots of little instances struggling to keep up with the newbies, plus different configurations, plus the codebase itself. Most of the instances I skipped through were either slow or glitchy. The most solid Lemmy instance I&rsquo;ve seen &mdash; sometimes slow but usable &mdash; is the unfederated hexbear.net, and I don&rsquo;t think it counts.</p>
<p>So I signed up for a couple of more normal ones and will revisit as things calm down.</p>
<h2 id="himalayan-day">Himalayan Day</h2>
<p>Today is &ldquo;work on the Himalayan day.&rdquo; My new Antigravity self-jumping battery is here, the mounting base and passenger back pad for our Givi topcase are here (which will make it easier for Al to ride pillion), and I did some reading about how to test for that parasitic drain. So I&rsquo;m going to give it all a few hours out in the driveway with a wrench and a multimeter. It&rsquo;s sunny and beautiful, so I&rsquo;m looking forward to the ride after I&rsquo;m done.</p>
<p>I&rsquo;m kind of wondering if this small round of &ldquo;get ready for sale, but also make it a little nicer&rdquo; investment will change my mind about selling it.</p>
<p>My strong impression of Himalayans in general is that the user base is split between people who just drive them off the lot and love them, never really having much trouble that doesn&rsquo;t get addressed during early service; and people like me, who get a badly QA&rsquo;d one and more than their share of glitchy components.</p>
<p>I like riding the thing. It&rsquo;s a manageable size for city riding, and it does really well anywhere you&rsquo;d want to go in the Portland metro area. Holds its own on 205/84, fine for runs up to St. Johns or Sauvie Island, great down to Estacada. With the panniers and topcase it&rsquo;s fine for groceries. There&rsquo;s just enough power to two-up in town on date nights. I don&rsquo;t think I&rsquo;d ever take for a run down I5, but I could see running downstate on the back highways.</p>
<p>I&rsquo;ve done so much to it at this point that there&rsquo;s some sweat equity I don&rsquo;t want to part with. If I could nail down the parasitic drain I&rsquo;d have a bike that I feel more than a little attached to, because I&rsquo;ve put a lot of time into getting it dialed in. Knowing there&rsquo;s a dealership up in St. Johns that spends most of its time selling RE&rsquo;s, vs. the sort of crappy &ldquo;RE&rsquo;s are a weird loss-leader for broke Harley wannabes&rdquo; dealership out on the west side I had to get early service from, makes me a little more hopeful, too. It was frustrating having to go do my own research about assorted RE glitches then convince the service team to try fixes. I get the impression the St. Johns people are a little more into REs and would be a little more proactive.</p>
<p>We&rsquo;ll see. If I get it into a place where it just feels good and I don&rsquo;t have that &ldquo;poorly shimmed table leg&rdquo; feeling every time I turn the key, maybe we continue another season.</p>
<p>Anyhow, that&rsquo;s the plan for today, so I&rsquo;m gonna save and ship this.</p>
<h2 id="thorns-game">Thorns game</h2>
<p>Oh &hellip; going to a Thorns game tonight. Our first. Kathleen and Amy had extra tickets, so off we go.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-06-22</title>
      <link>https://mike.puddingtime.org/posts/2023-06-22-daily-notes/</link>
      <pubDate>Thu, 22 Jun 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-06-22-daily-notes/</guid>
      <description>Alright, sweethearts, you heard the man and you know the drill: Assholes and elbows!</description>
      <content:encoded><![CDATA[<h2 id="remarkable-sync-seems-faster">reMarkable sync seems faster</h2>
<p>It shows up as a thing in the latest release notes and it seemed to be true when I looked for it this morning: Sync on the reMarkable between desktop app and device is a lot faster. Not sure it&rsquo;s &ldquo;instantaneous,&rdquo; but it&rsquo;s in the range of &ldquo;wrote a note on the device downstairs, it was on my desktop by the time I got upstairs,&rdquo; which is a vast improvement. No idea if it will be consistent.</p>
<p>I sort of wonder about reMarkable, generally:</p>
<p>They just dropped 25 percent off the cost of their expensive keyboard accessory, and they&rsquo;re trying to herd users into annual plans. There are a lot of similar devices on the market, including stuff from Amazon and Kobo that combine note-taking with ebook reading. If I&rsquo;m doing the tradeoffs, the things that might count as &ldquo;nice&rdquo; on a reMarkable have to compete against the combined utility of a device that lets me read all my stuff from their respective stores, <em>and</em> take notes.</p>
<p>Personally, if I could make the thing go away and pocket $200 for it without dealing with assorted Craigslist randos who&rsquo;d try to trade me for a kayak with a hole in it and a moldy bag of weed I&rsquo;d take that deal. It has never really found a place in my workflow that has lasted. I won&rsquo;t say I <em>regret</em> it, but it just doesn&rsquo;t work for me.</p>
<h2 id="obsidian-again">Obsidian, again</h2>
<p>I knew that once I had a new job things would begin to change for me. Stuff I previously felt like messing around with would seem less fun to mess around with, and my assessment of a given tool would take a harder edge.</p>
<div style="text-align:center;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/IUkKkWAREFg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div>
<p>This week was my first week at work where I was in &ldquo;full engagement&rdquo; mode for the balance of the week: Back-to-back days, ad hoc meetings, just needing to get stuff done quickly. I wanted to do stuff like &ldquo;take this free 15 minutes to go downstairs, drink a glass of water, and look at the four todos I just added to my list before starting the next call.&rdquo;</p>
<p>It was all very clarifying. For instance, these general things about writing notes all occurred to me:</p>
<ul>
<li>Mobile matters, both for writing and reading.</li>
<li>If I have a spare few minutes to hack in a feature, I&rsquo;d rather do it in JavaScript than elisp.</li>
<li>I prefer sync infrastructure be somebody else&rsquo;s problem.</li>
<li>It turns out that if life were a Richard Scarry book, for eight hours of the day I would be, like, a bear with spectacles and a neck tie who does business stuff. Markdown is sufficient for &ldquo;businessman notes.&rdquo;</li>
<li>Future-proofing matters to me.</li>
</ul>
<p>These things about Emacs occurred to me:</p>
<ul>
<li>I like sitting down and writing longer-form stuff with it.</li>
<li>I am grateful for it as my daily driver text editor for programming.</li>
<li>Given Doom and very modest customizations, Emacs &ldquo;just works&rdquo; for me.</li>
<li>I am better off as a &ldquo;slow Emacs&rdquo; person, not a &ldquo;fast Emacs&rdquo; person.</li>
</ul>
<p>On that last, it means that I do better with Emacs when I am doing things that I tend to configure once and never mess with again. Like, it&rsquo;s enough to have Rubocop and LSP working for my Ruby coding. Done. It&rsquo;s enough to know how to preview a Markdown file, and I don&rsquo;t care about any other stuff I could do with Markdown mode. Done. Electric modes for the things where I care? Great. Done and done. That&rsquo;s all &ldquo;slow Emacs.&rdquo; Figure it out once, take your time doing so, then never think about it again.</p>
<p><em>Fast</em> Emacs stuff tends to be whole workflows, and I am constantly tweaking those. I can&rsquo;t stop. I hate wasted motion, I hate having to remember three words separated by hyphens when I can remember two letters led by a spacebar. If I can turn on a preview server <em>and</em> open a tab to it in Safari in a single command, I&rsquo;ll figure out how to make that work. If I get an idea in my head about how to optimize something, or come to believe that something is taking more time than it absolutely should, I can&rsquo;t quit worrying at it. Fast Emacs. Constant, rapid iteration on little things meant to shave seconds or keystrokes or conserve brain storage.</p>
<p>When I am using Slow Emacs stuff, I am in a very focused, calm place. Emacs feels steady underfoot, stuff &ldquo;just works,&rdquo; I quit noticing the tool.</p>
<p>When I am using Fast Emacs stuff, it doesn&rsquo;t feel as steady. More stuff goes wrong. I end up dropping a paren and blowing everything up when I restart. Weird little things go wrong because I missed an edge case. It&rsquo;s over-automation, and I know something about that because I did two IT tours and one engineering services tour dealing with over-automated teams. I&rsquo;m not, like, Rock-Ribbed Business Guy on the job, but the waste of constantly getting bit in the ass by things someone made to make work easier and more efficient that become sources of mysterious failures and lost days of refactoring and debugging sort of grinds me. When I&rsquo;m doing Fast Emacs stuff, I&rsquo;m doing that to myself.</p>
<p>So that&rsquo;s Emacs. These things about Obsidian occurred to me:</p>
<ul>
<li>When I took away some things I liked about Denote and implemented them in Obsidian, it took very little time and four community plugins (one of which is just there to provide an API for another one).</li>
<li>Setting up capture templates for my common use cases involved 30 minutes of reading and poking and then maybe five minutes per use case.</li>
<li>When your plugin loadout is light, Obsidian feels very sturdy. With a decent theme, it feels pleasant.</li>
<li>Trying to do Fast Obsidian &mdash; heavily automated workflows &mdash; feels so self-evidently wrong that I don&rsquo;t even bother. I see people doing it, it seems janky.</li>
<li>Slow Obsidian &ndash; simple little keyboard shortcuts, macros, etc. is dead simple to do quickly. Those kinds of quality of life plugins are usually pretty good.</li>
<li>I cannot imagine writing long-form stuff in Obsidian. I&rsquo;m glad you wrote your book in it, but there is something about it &mdash; probably the busyness of the UI &mdash; that prevents me from considering it.</li>
</ul>
<p>And these things about my free time occurred to me:</p>
<ul>
<li>Tool-specific subreddits are Satanic. Obsidian and Emacs both invite an endless wander among the plugins and packages interspersed by the occasional dipshit trying to pick a fight by complaining about their inability to learn something new, triggering both the hardened Tool Warriors and the soft-hearted, enabling evangelists. You&rsquo;d think by now I&rsquo;d be resigned to the whole &ldquo;baby newbie with a broken wing&rdquo; cycle, but any kind of brand or consumer identification is grotesquely fascinating to me, and the ability of someone wandering in off the street crying about how hard elisp is to suck all the air out of the room never ceases to amaze.</li>
<li>I like my new job, but I knew going in that parts of it were going to be a challenge, and that&rsquo;s proving out. So during the day I want to do the easiest possible thing to do things that are helpful but are not the core value I provide (like taking notes, storing information for later, and connecting <em>this</em> thing over here to <em>that</em> task over there). I don&rsquo;t want to mess with those things. They need to just work. And at the end of the day, I want to be done with things that would remind me of work, which I am enjoying but want to keep in its place so I can keep enjoying it.</li>
</ul>
<p>So after a week of living the Obsidian-but-configured-to-make-files-like-Denote life, I got into my <code>config.org</code> file, disabled large swaths of the configuration that have to do with Fast Emacs, and reconfigured Denote to produce <code>markdown-yaml</code> files in my Obsidian vault, so if Obsidian ends up bothering me, my fallback position is already in place.</p>
<ul>
<li>Plain text</li>
<li>A little more future-proofed than Obsidian&rsquo;s loose default behavior thanks to Denote conventions</li>
<li>Solid mobile experience with reliable sync</li>
<li>Markdown&rsquo;s spare markup</li>
<li>Fewer moving pieces</li>
</ul>
<p>As long as a certain software company from Minneapolis doesn&rsquo;t come and buy this place, too, I&rsquo;ll reclaim my free time to screw around with something else.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Templating Denote-style naming in Obsidian</title>
      <link>https://mike.puddingtime.org/posts/2023-06-16-templating-denote-style-naming-in-obsidian/</link>
      <pubDate>Fri, 16 Jun 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-06-16-templating-denote-style-naming-in-obsidian/</guid>
      <description>Still on the how-to-make-Denote-more-mobile kick from another direction.</description>
      <content:encoded><![CDATA[<p>I really do like the Denote file naming convention as a sort of future-proofed forever format, and I&rsquo;ve been fussing at this idea that Obsidian could make a good mobile Denote file browser. There are some things around how internal links work I haven&rsquo;t dug into yet, but it&rsquo;s something to play with.</p>
<p>This morning over tea I applied myself to learning how <a href="https://github.com/SilentVoid13/Templater">Templater</a> works. It&rsquo;s an Obsidian plugin that lets you run JavaScript on notes, with access to stuff like the data in the YAML frontmatter and the ability to build your own functions and make them globally reusable. With Templater, you can do the automation needed to produce Denote-style filenames with a very Denote-style &ldquo;name the directory, name the file, name the tags, start editing&rdquo; workflow. It sounds sort of Rube-Goldbergy, but if JavaScript is to Obsidian as elisp is to Emacs, it&rsquo;s just &ldquo;extensible tools require code.&rdquo;</p>
<p>So this is a Templater template to make a new note with YAML frontmatter and user-input tags. You can see that it&rsquo;s just template + a few strftime variations + a prompt:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="o">---</span>
</span></span><span class="line"><span class="cl"><span class="nx">title</span><span class="o">:</span> <span class="o">&lt;%</span> <span class="nx">tp</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">title</span> <span class="o">%&gt;</span> <span class="c1">// title comes from user input using the QuickAdd plugin
</span></span></span><span class="line"><span class="cl"><span class="nx">date</span><span class="o">:</span> <span class="o">&lt;%</span> <span class="nx">tp</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">creation_date</span><span class="p">(</span><span class="s2">&#34;YYYY-MM-DDTHH:mm:ssZ&#34;</span><span class="p">)</span> <span class="o">%&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nx">tags</span><span class="o">:</span> <span class="o">&lt;%*</span> <span class="kd">let</span> <span class="nx">tags</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">tp</span><span class="p">.</span><span class="nx">system</span><span class="p">.</span><span class="nx">prompt</span><span class="p">(</span><span class="s2">&#34;Enter tags, space delimited&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">)</span><span class="o">%&gt;&lt;%</span> <span class="nx">tags</span> <span class="o">%&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nx">identifier</span><span class="o">:</span> <span class="s2">&#34;&lt;% tp.file.creation_date(&#34;</span><span class="nx">YYYYMMDDTHHmmss</span><span class="s2">&#34;) %&gt;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">---</span></span></span></code></pre></div>
<p>(There&rsquo;s a small bootstrapping problem of how a new note can have a title to drop into the frontmatter &mdash; that&rsquo;s solved with a plugin that prompts for the title before creating the note.)</p>
<p>So &hellip; invoke that template and you get a note that has the characteristics of a Denote note with <code>markdown-yaml</code> content. Its actual filename, however, will be following Obsidian conventions: <code>Whatever the name is.md</code> on the filesystem.</p>
<p>That&rsquo;s not okay, because Denote&rsquo;s also a file-naming convention, and one I prefer because it includes tags in the filename along with date and title. If you just keep your filenames proper, <em>most</em> of what you care about for long-term portability is just sitting right there in the filename, easily extractable for export/migration/etc.</p>
<p>Templater is able to run scripts that suck in the data in the frontmatter, and it&rsquo;s able to manipulate filenames and locations. So, this is a user function that takes title, ident, and tags params and spits out a Denote-compatible filename:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">slugify</span><span class="p">(</span><span class="nx">title</span><span class="p">,</span><span class="nx">ident</span><span class="p">,</span><span class="nx">tags</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">title</span> <span class="o">=</span> <span class="nx">title</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/^\s+|\s+$/g</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">);</span> <span class="c1">// trim leading/trailing white space
</span></span></span><span class="line"><span class="cl">  <span class="nx">title</span> <span class="o">=</span> <span class="nx">title</span><span class="p">.</span><span class="nx">toLowerCase</span><span class="p">();</span> <span class="c1">// convert string to lowercase
</span></span></span><span class="line"><span class="cl">  <span class="nx">title</span> <span class="o">=</span> <span class="nx">title</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/[^a-z0-9 -]/g</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="c1">// remove any non-alphanumeric characters
</span></span></span><span class="line"><span class="cl">           <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\s+/g</span><span class="p">,</span> <span class="s1">&#39;-&#39;</span><span class="p">)</span> <span class="c1">// replace spaces with hyphens
</span></span></span><span class="line"><span class="cl">           <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/-+/g</span><span class="p">,</span> <span class="s1">&#39;-&#39;</span><span class="p">);</span> <span class="c1">// remove consecutive hyphens
</span></span></span><span class="line"><span class="cl">  <span class="nx">tags</span> <span class="o">=</span> <span class="nx">tags</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/ /g</span><span class="p">,</span><span class="s2">&#34;_&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">ident</span> <span class="o">+</span> <span class="s2">&#34;--&#34;</span> <span class="o">+</span> <span class="nx">title</span> <span class="o">+</span> <span class="s2">&#34;__&#34;</span> <span class="o">+</span> <span class="nx">tags</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="nx">slugify</span></span></span></code></pre></div>
<p>Once you know what the filename should be, you have to actually change it on the filesystem. This is a second Templater &ldquo;template&rdquo; of JavaScript you can run on a note once it has been created:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="o">&lt;%*</span>
</span></span><span class="line"><span class="cl">	<span class="nx">identifier</span> <span class="o">=</span>  <span class="nx">tp</span><span class="p">.</span><span class="nx">frontmatter</span><span class="p">[</span><span class="s2">&#34;identifier&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">	<span class="nx">title</span> <span class="o">=</span> <span class="nx">tp</span><span class="p">.</span><span class="nx">frontmatter</span><span class="p">[</span><span class="s2">&#34;title&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">	<span class="nx">tags</span> <span class="o">=</span> <span class="nx">tp</span><span class="p">.</span><span class="nx">frontmatter</span><span class="p">[</span><span class="s2">&#34;tags&#34;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">	<span class="nx">slugged</span> <span class="o">=</span>  <span class="nx">tp</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">slugify</span><span class="p">(</span><span class="nx">title</span><span class="p">,</span> <span class="nx">identifier</span><span class="p">,</span> <span class="nx">tags</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="nx">tp</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">rename</span><span class="p">(</span><span class="nx">slugged</span><span class="p">);</span> <span class="o">-%&gt;</span></span></span></code></pre></div>
<p>(Looking at the <code>slugify</code> function and that Templater code, I think you can just pass the <code>tp</code> object into the function to move some busy-ness into the function and away from your file template. I dunno. I&rsquo;m just trying to get ping right now.)</p>
<p>So at that point, you have a Markdown note sitting in your Obsidian vault with a filename that conforms to Denote&rsquo;s naming convention. If you visit your vault directory in Emacs using dired, the files are all fontified for Denote-browsing goodness.</p>
<p>And that&rsquo;s where I ran out of tea and needed to go do some paying work.</p>
<p>I don&rsquo;t yet know how to get that last function to run at the point of note creation. There&rsquo;s surely some way to get Templater code to hold off on firing the next step in a script until you can get all the data in place, but I don&rsquo;t know what it is. So I have the renaming template bound to a hotkey and just tap <code>Ctrl-Cmd-r</code> to trigger the rename once the note is ready. It&rsquo;s good to have it exposed as its own command, because part of the Denote workflow involves keeping good file naming hygiene when you change note metadata, I&rsquo;d just like to automate that part at time of creation, too.</p>
<p>The last ingredient I&rsquo;m using for all this is the Obsidian <a href="https://github.com/snezhig/obsidian-front-matter-title">front-matter title</a> plugin. It just consults the YAML frontmatter for the <code>title:</code> property and uses that to display note names instead of the filesystem name. That makes directories of files a little more legible, makes tab names less noisy, etc. It does for you in Obsidian some of what <a href="https://github.com/namilus/denote-menu">Denote Menu</a> and similar do in Emacs, pulling Denote&rsquo;s useful but visually cluttered naming convention more firmly in the &ldquo;human-readable&rdquo; direction. It&rsquo;s optional to this exercise, but preferred, especially when on mobile, where there&rsquo;s less real estate to burn on long filenames.</p>
<p>If you visit the file in Denote, you can mess with the frontmatter and use Denote&rsquo;s <code>denote-rename-file-using-front-matter</code> command to update the file name. If you mess around with it in Obsidian, you can run that Templater template to do the same.</p>
<p>If you run <a href="https://github.com/licht1stein/obsidian.el">obsidian.el</a> on top of all of this, it becomes possible to navigate your notes in Emacs, insert links from Emacs, etc. etc. You can&rsquo;t just tap a link from the keyboard &mdash; you have to use obsidian.el&rsquo;s navigation commands &mdash; but that&rsquo;s not terrible.</p>
<p>So to solve the mobile thing, you&rsquo;ve got this approach &mdash; customizing Obsidian with a few plugins and some light code to make your vault look like a Denote corpus &mdash; and you&rsquo;ve got <a href="/posts/2023-06-11-daily-notes/">the thing I did to provide a searchable web interface</a>.</p>
<p>The Obsidian route gives you a more complete mobile experience. You can make notes on the go, you have more flexibility for searching your notes, etc.</p>
<p>The web approach is more compact: Do some Emacs configuration, use some commodity infra with Tailscale and a Synology, then just use Denote in its native form, which is org- and desktop-centric.</p>
<p>Given my usage patterns, either seems fine?</p>
<p>Switching to Markdown for Denote satisfies a part of my brain that doesn&rsquo;t like trying to script org-mode migrations and that also understands &ldquo;org-mode vs. Markdown&rdquo; is another one of those &ldquo;Beta vs. VHS&rdquo; situations I need to just accept. Commensurately, it irritates the part of my brain that completely got it when my tech writing team told me they wanted to migrate from Markdown to <a href="https://en.wikipedia.org/wiki/Darwin_Information_Typing_Architecture">DITA</a>, maybe a little before we were really there on the maturity curve.</p>
<p>Anyhow, it&rsquo;s a hobby.</p>
<h2 id="espanso">espanso</h2>
<p>I don&rsquo;t know what on Earth happened to TextExpander but wow it isn&rsquo;t good.</p>
<p>Looking around for a text expansion tool of some kind I came across <a href="https://espanso.org">espanso</a>. It&rsquo;s a snippet tool. It behaves about like yasnippet or TextMate snippets: Start typing a trigger phrase and it expands it for you.</p>
<p>Most of these things are wrapped in a GUI. espanso is configurable with a YAML file. It also has some cool stuff for handling regexps that allow you to use variables to your snippets. For instance:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;:tml\\((?P&lt;tag&gt;.*)\\)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">replace</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;[Items tagged `{{tag}}` in Things](things:///search?query=%23{{tag}})&#34;</span></span></span></code></pre></div>
<p>If you type <code>:tml(foo)</code> it&rsquo;ll expand to a Markdown link using <code>foo</code>.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">[<span class="nt">Items tagged `foo` in Things</span>](<span class="na">things:///search?query=%23foo</span>)</span></span></code></pre></div>
<p>(I&rsquo;m not sure, btw, how to do that in yasnippet and need to figure that out.)</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-06-15</title>
      <link>https://mike.puddingtime.org/posts/2023-06-15-daily-notes/</link>
      <pubDate>Thu, 15 Jun 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-06-15-daily-notes/</guid>
      <description>Excruciating Multiplicity of Approaches to Cat-Skinning. I slay me. Denote-org-to-Denote-Markdown. Golden Ratio window management.</description>
      <content:encoded><![CDATA[<h2 id="golden-ratio">Golden ratio</h2>
<p>This is kind of cool. The <a href="https://github.com/roman/golden-ratio.el">golden-ratio</a> package dynamically resizes Emacs windows within frames as they become the active window. It works <em>okay</em> on a desktop machine, and I really like it on my laptop. Opening up a window for LSP output, for instance, kept the code buffer at a better size while still being able to track the LSP to the side.</p>
<p>It doesn&rsquo;t work out of the box with Doom Emacs &mdash; it needs an incantation:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-package!</span> <span class="nv">golden-ratio</span>
</span></span><span class="line"><span class="cl">  <span class="nb">:after-call</span> <span class="nv">pre-command-hook</span>
</span></span><span class="line"><span class="cl">  <span class="nb">:config</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">golden-ratio-mode</span> <span class="mi">+1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; Using this hook for resizing windows is less precise than</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; `doom-switch-window-hook&#39;.</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">remove-hook</span> <span class="ss">&#39;window-configuration-change-hook</span> <span class="nf">#&#39;</span><span class="nv">golden-ratio</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;doom-switch-window-hook</span> <span class="nf">#&#39;</span><span class="nv">golden-ratio</span><span class="p">))</span></span></span></code></pre></div>
<p>Demo/tutorial video:</p>
<div style="text-align:center;">
  <iframe width="560" height="315" src="https://www.youtube.com/embed/k5Nwwo4QTmI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen>
  </iframe>
</div>
<p>I understand that Golden Ratio is no longer maintained. Some people say <a href="https://github.com/cyrus-and/zoom">Zoom</a> is as good, so maybe I&rsquo;ll try it if I hit any of those bugs people talk about.</p>
<h2 id="when-you-feel-the-heat-coming-around-the-corner-dot-dot-dot">&ldquo;When you feel the heat coming around the corner &hellip;&rdquo;</h2>
<p>I think I lost an hour to figuring out how to take a batch of existing Denote notes in org format and move them into Markdown, so I got very, very patient
with ChatGPT and together we came up with this:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">re</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">argparse</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">pypandoc</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">shutil</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">org_dir</span> <span class="o">=</span> <span class="s1">&#39;/Users/mph/org/notes&#39;</span>  <span class="c1"># Replace with your directory path</span>
</span></span><span class="line"><span class="cl"><span class="n">md_dir</span> <span class="o">=</span> <span class="s1">&#39;/Users/mph/org/notes-md&#39;</span>  <span class="c1"># Replace with the desired directory path for markdown files</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">convert_org_to_md</span><span class="p">(</span><span class="n">org_file</span><span class="p">,</span> <span class="n">org_path</span><span class="p">,</span> <span class="n">md_dir</span><span class="p">,</span> <span class="n">with_hashtags</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Recreate the directory structure in the markdown directory</span>
</span></span><span class="line"><span class="cl">    <span class="n">org_relative_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">relpath</span><span class="p">(</span><span class="n">org_path</span><span class="p">,</span> <span class="n">org_dir</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">md_relative_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">org_relative_path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">md_output_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">md_dir</span><span class="p">,</span> <span class="n">md_relative_dir</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">md_output_dir</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">md_file</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">org_file</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">&#39;.md&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="n">md_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">md_output_dir</span><span class="p">,</span> <span class="n">md_file</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Copy org file to markdown directory</span>
</span></span><span class="line"><span class="cl">    <span class="n">shutil</span><span class="o">.</span><span class="n">copy2</span><span class="p">(</span><span class="n">org_path</span><span class="p">,</span> <span class="n">md_path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">md_path</span><span class="p">,</span> <span class="s1">&#39;r&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">org_content</span> <span class="o">=</span> <span class="n">file</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Extract frontmatter variables from org file</span>
</span></span><span class="line"><span class="cl">    <span class="n">title_match</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;#\+title:\s+(.+)&#39;</span><span class="p">,</span> <span class="n">org_content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">identifier_match</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;#\+identifier:\s+(.+)&#39;</span><span class="p">,</span> <span class="n">org_content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">tags_match</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;#\+filetags:\s+(.+)&#39;</span><span class="p">,</span> <span class="n">org_content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">frontmatter</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">title_match</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">frontmatter</span><span class="p">[</span><span class="s1">&#39;title&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">title_match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">identifier_match</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">frontmatter</span><span class="p">[</span><span class="s1">&#39;identifier&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">identifier_match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">tags_match</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">tags_string</span> <span class="o">=</span> <span class="n">tags_match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">tags_list</span> <span class="o">=</span> <span class="p">[</span><span class="n">tag</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s1">&#39;:&#39;</span><span class="p">)</span> <span class="k">for</span> <span class="n">tag</span> <span class="ow">in</span> <span class="n">tags_string</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;:&#39;</span><span class="p">)</span> <span class="k">if</span> <span class="n">tag</span><span class="o">.</span><span class="n">strip</span><span class="p">()]</span>
</span></span><span class="line"><span class="cl">        <span class="n">frontmatter</span><span class="p">[</span><span class="s1">&#39;tags&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39; &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">tags_list</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Update date stamp format</span>
</span></span><span class="line"><span class="cl">    <span class="n">org_content</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\[(\d</span><span class="si">{4}</span><span class="s1">-\d</span><span class="si">{2}</span><span class="s1">-\d</span><span class="si">{2}</span><span class="s1">) (\w</span><span class="si">{3}</span><span class="s1"> \d</span><span class="si">{2}</span><span class="s1">:\d</span><span class="si">{2}</span><span class="s1">)\]&#39;</span><span class="p">,</span> <span class="sa">r</span><span class="s1">&#39;\1T\2:00-07:00&#39;</span><span class="p">,</span> <span class="n">org_content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Convert org to markdown using Pandoc</span>
</span></span><span class="line"><span class="cl">    <span class="n">md_content</span> <span class="o">=</span> <span class="n">pypandoc</span><span class="o">.</span><span class="n">convert_text</span><span class="p">(</span><span class="n">org_content</span><span class="p">,</span> <span class="s1">&#39;gfm&#39;</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="s1">&#39;org&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Generate new frontmatter content</span>
</span></span><span class="line"><span class="cl">    <span class="n">updated_frontmatter</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;title&#39;</span><span class="p">:</span> <span class="n">frontmatter</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;title&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;date&#39;</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;%Y-%m-</span><span class="si">%d</span><span class="s1">T%H:%M:%S-07:00&#39;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;identifier&#39;</span><span class="p">:</span> <span class="n">frontmatter</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;identifier&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;tags&#39;</span><span class="p">:</span> <span class="n">frontmatter</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;tags&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Generate the new frontmatter string</span>
</span></span><span class="line"><span class="cl">    <span class="n">frontmatter_string</span> <span class="o">=</span> <span class="s1">&#39;---</span><span class="se">\n</span><span class="s1">&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">updated_frontmatter</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">        <span class="n">frontmatter_string</span> <span class="o">+=</span> <span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">key</span><span class="si">}</span><span class="s1">: </span><span class="si">{</span><span class="n">value</span><span class="si">}</span><span class="se">\n</span><span class="s1">&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="n">frontmatter_string</span> <span class="o">+=</span> <span class="s1">&#39;---</span><span class="se">\n</span><span class="s1">&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Add updated frontmatter to the markdown content</span>
</span></span><span class="line"><span class="cl">    <span class="n">md_content</span> <span class="o">=</span> <span class="n">frontmatter_string</span> <span class="o">+</span> <span class="n">md_content</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Insert tags as hashtags on the last line if enabled</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">with_hashtags</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">tags_line</span> <span class="o">=</span> <span class="s1">&#39; &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="sa">f</span><span class="s1">&#39;#</span><span class="si">{</span><span class="n">tag</span><span class="si">}</span><span class="s1">&#39;</span> <span class="k">for</span> <span class="n">tag</span> <span class="ow">in</span> <span class="n">frontmatter</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;tags&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">()])</span>
</span></span><span class="line"><span class="cl">        <span class="n">md_content</span> <span class="o">+=</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span> <span class="o">+</span> <span class="n">tags_line</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Save the markdown file</span>
</span></span><span class="line"><span class="cl">    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">md_path</span><span class="p">,</span> <span class="s1">&#39;w&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">md_content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">convert_directory</span><span class="p">(</span><span class="n">org_dir</span><span class="p">,</span> <span class="n">md_dir</span><span class="p">,</span> <span class="n">with_hashtags</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">org_files</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">root</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">files</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">org_dir</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">files</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">file</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;.org&#39;</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">                <span class="n">org_files</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">file</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">org_path</span> <span class="ow">in</span> <span class="n">org_files</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">org_file</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">org_path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">convert_org_to_md</span><span class="p">(</span><span class="n">org_file</span><span class="p">,</span> <span class="n">org_path</span><span class="p">,</span> <span class="n">md_dir</span><span class="p">,</span> <span class="n">with_hashtags</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Parse command-line arguments</span>
</span></span><span class="line"><span class="cl"><span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s1">&#39;Convert org files to markdown.&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--with-hashtags&#39;</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s1">&#39;store_true&#39;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">&#39;Insert tags as hashtags on the last line&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Convert org files to markdown</span>
</span></span><span class="line"><span class="cl"><span class="n">convert_directory</span><span class="p">(</span><span class="n">org_dir</span><span class="p">,</span> <span class="n">md_dir</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">with_hashtags</span><span class="p">)</span></span></span></code></pre></div>
<p>I thiiiink that&rsquo;s according to the Denote spec for Markdown, and I <em>think</em> that makes it good enough for Hugo, too, excepting links in the
<code>[[denote:12345678]]</code> format.</p>
<p>So, what is it good for? Mostly just getting from an org-mode-based Denote corpus to a Markdown-based one. At least, it seems to &ldquo;just work&rdquo; to do that.</p>
<p>If you&rsquo;re not heavily cross-linked and don&rsquo;t mind cleaning up <code>denote:</code>-style links I suppose you could drop the whole thing into Obsidian. In fact, I did. Works well minus, again, <code>denote:</code> links. I was also personally curious about whether the whole mess would work well with <a href="https://github.com/artempyanykh/marksman">Marksman</a> &mdash; an LSP server for Markdown that has some interesting &ldquo;make a wiki out of simple Markdown&rdquo; features &mdash; but I&rsquo;m missing something about Marksman. It doesn&rsquo;t work well with the stock LSP under Doom, and while it doesn&rsquo;t crash using Eglot, I&rsquo;m still not sure of its utility.</p>
<p>I also tossed in a command line switch that adds the tags as hashtags at the bottom of the file, which is where I tend to put them, and also what I thought I needed to do until I realized that Obsidian actually understands the <code>tags: [&quot;foo&quot;,&quot;bar&quot;,&quot;baz&quot;]</code> notation in YAML frontmatter if you do a <code>tag:#foo</code> search in its search tool. So &mdash; if you&rsquo;re a frontmatter person, just run it plain. If you&rsquo;re not then <code>--with-hashtags</code> is your friend.</p>
<h2 id="obsidian-dot-el">Obsidian.el</h2>
<p>Another option, I guess, is <a href="https://github.com/licht1stein/obsidian.el">obsidian.el</a>, which is meant to provide a way to get around an Obsidian vault within Emacs. You point it at your vault directory, designate an inbox folder, and it provides ways to search by tag, etc.</p>
<p>I dunno. At this point it&rsquo;s all just messing around and seeing how all this stuff hangs together (or doesn&rsquo;t.) Fun.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-06-13</title>
      <link>https://mike.puddingtime.org/posts/2023-06-13-daily-notes/</link>
      <pubDate>Tue, 13 Jun 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-06-13-daily-notes/</guid>
      <description>Figuring out connection points between Denote and non-Emacs apps like Things with custom links and elbow grease. Automating org dblock rendering. Making org-export output more amenable to SimpleCSS. Text expansion with espanso.</description>
      <content:encoded><![CDATA[<h2 id="making-links-to-pages-in-my-denote-web-export">Making links to pages in my Denote web export</h2>
<p>I&rsquo;m back and forth on whether to stick to org-gtd or to start using Things again. I wanted to re-tag some actions on the fly this morning and it took some extra typing I didn&rsquo;t want to do.  So far, my org-gtd and Denote usage haven&rsquo;t intersected, and there is no way I can think of that any of the existing mobile tools could do anything for me at all if they did.  So as I think about my Emacs/Denote/org estate, and how to decompose it and remix different pieces, there&rsquo;s a pretty clean perforated line between written notes and tasks, provided I can find a way to bridge the two.</p>
<p>One thing I used to do when I was a regular Bear user was create a Things project for all the people I had regular 1:1s with. I set up section headings for each person in the project under which I dropped actions I owed or had delegated. At the top of that project, I had a list of links to my 1:1 notes with each person to make it easier to get to past notes during a meeting without looking them up in Bear &ndash; just save the URL to their 1:1 file,  click the link, Bear opens to where I need it. This felt like a clean way to let two tools do what they&rsquo;re best at: Things does have some basic Markdown editing, but I don&rsquo;t generally want to embed writing/thinking in actions.</p>
<p>Unlike Bear, Emacs has the disadvantage of not being everywhere I would use Things, but since I&rsquo;m exporting my Denote stuff to the web, my notes do have a permanent URL, and it&rsquo;s derived from the filename of a given note, so it&rsquo;s easy to convert the file path to the URL.</p>
<p>This function copies that URL to the clipboard when I&rsquo;m in a note. No error- or sanity-checking: The results will be nonsense if I invoke it outside my Denote hierarchy, but I bound it to my Denote menu in Doom Emacs so it&rsquo;ll only come up when it&rsquo;s contextually appropriate:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/convert-to-skyhook-url</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Converts the current buffer&#39;s path to a URL for the Skyhook notes.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let*</span> <span class="p">((</span><span class="nv">buffer-path</span> <span class="p">(</span><span class="nf">buffer-file-name</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">notes-directory</span> <span class="s">&#34;/Users/mph/org/notes/&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">relative-path</span> <span class="p">(</span><span class="nv">file-relative-name</span> <span class="nv">buffer-path</span> <span class="nv">notes-directory</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">html-path</span> <span class="p">(</span><span class="nf">concat</span> <span class="p">(</span><span class="nv">file-name-sans-extension</span> <span class="nv">relative-path</span><span class="p">)</span> <span class="s">&#34;.html&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">url-prefix</span> <span class="s">&#34;http://skyhook:8888/&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">url</span> <span class="p">(</span><span class="nf">concat</span> <span class="nv">url-prefix</span> <span class="nv">html-path</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">kill-new</span> <span class="nv">url</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">message</span> <span class="s">&#34;Skyhook URL: %s&#34;</span> <span class="nv">url</span><span class="p">)))</span></span></span></code></pre></div>
<p>Then it&rsquo;s just dropping it into a Things project page and wrapping it in Markdown link markup.</p>
<p>There&rsquo;s a converse linking relationship between todos and notes, and I made something to address that, too:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="c1">;; updated to de-hard-code the # symbol -- any symbol is sanitized for use in a URL now</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">after!</span> <span class="nv">org</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">org-link-set-parameters</span> <span class="s">&#34;things&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">:follow</span> <span class="p">(</span><span class="nb">lambda</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span> <span class="p">(</span><span class="nv">browse-url</span> <span class="p">(</span><span class="nf">concat</span> <span class="s">&#34;things:///search?query=&#34;</span> <span class="p">(</span><span class="nv">url-hexify-string</span> <span class="nv">label</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">    <span class="nb">:export</span> <span class="p">(</span><span class="nb">lambda</span> <span class="p">(</span><span class="nv">path</span> <span class="nv">desc</span> <span class="nv">backend</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">              <span class="p">(</span><span class="nb">cond</span>
</span></span><span class="line"><span class="cl">               <span class="p">((</span><span class="nf">eq</span> <span class="ss">&#39;html</span> <span class="nv">backend</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;&lt;a href=\&#34;things:///search?query=%s\&#34;&gt;Things: %s&lt;/a&gt;&#34;</span>
</span></span><span class="line"><span class="cl">                        <span class="p">(</span><span class="nv">url-hexify-string</span> <span class="nv">path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                        <span class="p">(</span><span class="nv">org-html-encode-plain-text</span> <span class="nv">path</span><span class="p">)))))))</span></span></span></code></pre></div>
<p>It&rsquo;s a custom org external link for Things. Enter a link of this format:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-org" data-lang="org"><span class="line"><span class="cl">[[<span class="na">things:#foo</span>]]</span></span></code></pre></div>
<p>&hellip; and it will link to a Things search for <code>#foo</code>.</p>
<p>The <code>:export</code> section insures that when I publish the site, the <code>things://</code> URL scheme survives. When org-mode comes across protocols it doesn&rsquo;t recognize it mangles them. This ensures that <code>things:</code> URLs show up in the rendered HTML.</p>
<p>So if I&rsquo;m sitting down to a 1:1 with &ldquo;Joe Grudd,&rdquo; I&rsquo;ve got a link to the web version of his metanote from Things on a computer or phone. If I&rsquo;m looking at Joe Grudd&rsquo;s metanote in Emacs or on the web, I&rsquo;ve got a link that shows a search for anything tagged <code>#joeg</code> in Things.</p>
<h2 id="automating-dblock-driven-metanote-updates">Automating dblock-driven metanote updates</h2>
<p>I have metanotes set up in my Denote hierarchy for frequent people and topic tags. The metanotes are semi-automated at this point using <a href="https://protesilaos.com/emacs/denote#h:8b542c50-dcc9-4bca-8037-a36599b22779">Denote&rsquo;s dynamic blocks</a>.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-org" data-lang="org"><span class="line"><span class="cl"><span class="c">#+BEGIN: </span><span class="cs">denote-links</span><span class="c"> :regexp &#34;_rfc&#34;
</span></span></span><span class="line"><span class="cl"><span class="c">#+END:</span></span></span></code></pre></div>
<p>Just <code>C-c C-c</code> in that block and it expands to something like:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-org" data-lang="org"><span class="line"><span class="cl"><span class="c">#+BEGIN: </span><span class="cs">denote-links</span><span class="c"> :regexp &#34;_rfc&#34;
</span></span></span><span class="line"><span class="cl">- [[<span class="na">denote:20230613T083549</span>][<span class="nt">RFC - Crosstraining</span>]]
</span></span><span class="line"><span class="cl">- [[<span class="na">denote:20230613T083700</span>][<span class="nt">RFC - IT Portfolio</span>]]
</span></span><span class="line"><span class="cl">- [[<span class="na">denote:20230613T083726</span>][<span class="nt">RFC - Status and progress</span>]]
</span></span><span class="line"><span class="cl"><span class="c">#+END:</span></span></span></code></pre></div>
<p>All those Denote links are translated by org-publish during conversion to HTML, so a link to a metanote on the web server gets me to the HTML version of all the linked notes.</p>
<p>If I&rsquo;m on a laptop, getting to the metanotes is pretty easy: They&rsquo;re all in a metanote at the top of my Denote hierarchy, so that&rsquo;s easy enough to get to in &ldquo;full computer&rdquo; contexts.</p>
<p>The biggest hole in this workflow is that that dynamic blocks have to be updated. I semi-automated it yesterday with a save hook in my Denote directory that updates any dblocks in a file before it saves, but you have to be in a metanote for that to happen.</p>
<p>Not sure if there&rsquo;s a more efficient way to do it, but this automates the update process:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/update-meta-dblocks</span> <span class="p">(</span><span class="nv">directory</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Update dynamic blocks, save, and publish HTML for files with &#39;_meta&#39; in the name in the given DIRECTORY.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span> <span class="s">&#34;DSelect directory: &#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">files</span> <span class="p">(</span><span class="nf">directory-files</span> <span class="nv">directory</span> <span class="no">nil</span> <span class="s">&#34;\\.org$&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">dolist</span> <span class="p">(</span><span class="nv">file</span> <span class="nv">files</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nv">string-match-p</span> <span class="s">&#34;_meta&#34;</span> <span class="nv">file</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">org-file</span> <span class="p">(</span><span class="nf">concat</span> <span class="nv">directory</span> <span class="s">&#34;/&#34;</span> <span class="nv">file</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nb">with-current-buffer</span> <span class="p">(</span><span class="nv">find-file-noselect</span> <span class="nv">org-file</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="c1">;; Suspend hooks temporarily</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nf">run-hooks</span> <span class="ss">&#39;no-hooks</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nv">org-update-all-dblocks</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nv">save-buffer</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">))))))</span></span></span></code></pre></div>
<p>(The <code>run-hooks 'no-hooks</code> business is there to keep my post-save publishing hooks from running with each touch, which I <em>think</em> will make this safe to use as a pre-processing hook.) I think I&rsquo;m going to just use it as I remember it for a few days until I can see how much time it chews up. Maybe it&rsquo;s better run as a scheduled batch thing now and then.</p>
<h2 id="cleaning-up-org-publishing-exports">Cleaning up org publishing exports</h2>
<p>I also took the time to clean up HTML publishing last night. Emacs documentation ftw: I used the <a href="https://orgmode.org/manual/Publishing-options.html">publishing options page</a> to run down settings/variables and what they do. In particular:</p>
<h3 id="org-html-divs">org-html-divs</h3>
<p>I use SimpleCSS to save a few steps. <code>org-html-divs</code> lets you set the preamble, content, and postamble element types and id&rsquo;s,  so:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">org-html-divs</span>
</span></span><span class="line"><span class="cl">    <span class="o">&#39;</span><span class="p">((</span><span class="nv">preamble</span> <span class="s">&#34;header&#34;</span> <span class="s">&#34;preamble&#34;</span><span class="p">)</span> <span class="c1">;; set the preamble div to a &lt;header&gt; element with an id of &#34;preamble&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">content</span> <span class="s">&#34;main&#34;</span> <span class="s">&#34;content&#34;</span><span class="p">)</span> <span class="c1">;; etc.</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">postamble</span> <span class="s">&#34;footer&#34;</span> <span class="s">&#34;postamble&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">org-export-with-author</span> <span class="no">nil</span><span class="p">)</span></span></span></code></pre></div>
<p>I kept the id&rsquo;s so I could have a reference for debugging and keep sight of org&rsquo;s nomenclature.</p>
<h3 id="org-html-preamble">org-html-preamble</h3>
<p>To get a SimpleCSS nav into place, markup has to go into the export&rsquo;s preamble:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">org-html-preamble</span> <span class="s">&#34;&lt;nav&gt;&lt;ul&gt;
</span></span></span><span class="line"><span class="cl"><span class="s">                           &lt;li&gt;&lt;a href=\&#34;/\&#34; class=\&#34;home\&#34;&gt;Home&lt;/a&gt;
</span></span></span><span class="line"><span class="cl"><span class="s">                           &lt;li&gt;&lt;a href=\&#34;/sitemap.html\&#34;&gt;All Notes&lt;/a&gt;
</span></span></span><span class="line"><span class="cl"><span class="s">                           &lt;/ul&gt;
</span></span></span><span class="line"><span class="cl"><span class="s">                         &lt;/nav&gt;
</span></span></span><span class="line"><span class="cl"><span class="s">                         &#34;</span><span class="p">)</span></span></span></code></pre></div>
<h3 id="org-html-head">org-html-head</h3>
<p>To pull in SimpleCSS, FuseJS, and a local style sheet:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span>
</span></span><span class="line"><span class="cl">      <span class="nv">org-html-head</span> <span class="s">&#34;&lt;link rel=\&#34;stylesheet\&#34; href=\&#34;https://cdn.simplecss.org/simple.min.css\&#34; /&gt;
</span></span></span><span class="line"><span class="cl"><span class="s">                     &lt;link rel=\&#34;stylesheet\&#34; href=\&#34;/local.css\&#34; /&gt;
</span></span></span><span class="line"><span class="cl"><span class="s">                     &lt;script src=\&#34;https://cdn.jsdelivr.net/npm/fuse.js@6.6.2\&#34;&gt;&lt;/script&gt;&#34;</span><span class="p">)</span></span></span></code></pre></div>
<h2 id="espanso">espanso</h2>
<p>I don&rsquo;t know what on Earth happened to TextExpander but wow it isn&rsquo;t good.</p>
<p>Looking around for a text expansion tool of some kind I came across <a href="https://espanso.org">espanso</a>. It&rsquo;s a snippet tool. It behaves about like yasnippet or TextMate snippets: Start typing a trigger phrase and it expands it for you.</p>
<p>Most of these things are wrapped in a GUI. espanso is configurable with a YAML file. It also has some cool stuff for handling regexps that allow you to use variables to your snippets. For instance:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;:tml\\((?P&lt;tag&gt;.*)\\)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">replace</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;[Items tagged `{{tag}}` in Things](things:///search?query=%23{{tag}})&#34;</span></span></span></code></pre></div>
<p>If you type <code>:tml(foo)</code> it&rsquo;ll expand to a Markdown link using <code>foo</code>.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">[<span class="nt">Items tagged `foo` in Things</span>](<span class="na">things:///search?query=%23foo</span>)</span></span></code></pre></div>
<p>(I&rsquo;m not sure, btw, how to do that in yasnippet and need to figure that out.)</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-06-12</title>
      <link>https://mike.puddingtime.org/posts/2023-06-12-daily-notes/</link>
      <pubDate>Mon, 12 Jun 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-06-12-daily-notes/</guid>
      <description>A Drafts action to make Denote notes on the go. Fright Night 2011. Leica Q3, Fujifilm X100/X-Pro. Old man coos at clouds.</description>
      <content:encoded><![CDATA[<h2 id="denote-drafts-action">Denote Drafts action</h2>
<p>The other half of the &ldquo;get more mobile with Denote and Emacs&rdquo; conundrum &mdash; outside the stuff where you can read notes &mdash; is the capture part: Being able to get things into the system when you&rsquo;re out and about and maybe don&rsquo;t have a laptop along.</p>
<p>The glue for everything I&rsquo;m doing to address the mobile stuff is <a href="https://syncthing.net">Syncthing</a>, with all the nodes connected via <a href="https://tailscale.com">TailScale</a>. On my iOS devices, I use <a href="https://www.mobiussync.com">Mobius Sync</a> as my Syncthing client. Since I&rsquo;ve got Syncthing running on a Synology, that provides me with a central node to compensate for mobile or seldom-used desktop devices coming in and out on the TailScale network as they sleep and wake up.</p>
<p>To make my Denote setup more mobile, I&rsquo;ve got SyncThing updating my published notes folder more frequently than the default, and I&rsquo;ve got a save hook for my Denote directory that both publishes my Denote notes as HTML and runs the note indexer script that FusionJS depends on to make search fast. Since org publishing is incremental, there&rsquo;s not a big hit when I save a Denote file: It recreates the notes index and runs the Python script, which takes about a twentieth of a second to complete at this point because all it cares about is the filename and the tags (which are built into the filename.)</p>
<p>Over time, as my notes scale, that script might take longer, and that&rsquo;s fine: It is also running on the Synology where performance isn&rsquo;t as big of a deal. Running the indexer on the client nodes just means when SyncThing kicks in it is shipping an updated index along with the new files to the Synology.</p>
<p>Anyhow, that&rsquo;s the background infra stuff.</p>
<p>To handle the other part, capture, I turned to Drafts. It needed a little bit of Javascript to create a few variables for the output template, and it can write out to on-device storage, so it was trivial to <a href="https://directory.getdrafts.com/a/2Kb">create a Drafts action</a> that takes this:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Some note about agriculture
</span></span><span class="line"><span class="cl">fruits vegetables
</span></span><span class="line"><span class="cl">I am going to write today about fruits and vegetables and how important they are to our way of life.</span></span></code></pre></div>
<p>&hellip; and turns it into a file called <code>20230612T121326--some-note-about-agriculture__fruits_vegetables.org</code> with the content</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-org" data-lang="org"><span class="line"><span class="cl"><span class="cs">#+title</span><span class="c">:      Some note about agriculture</span>
</span></span><span class="line"><span class="cl"><span class="cs">#+date</span><span class="c">:       [2023-06-12 Mon 12:13]</span>
</span></span><span class="line"><span class="cl"><span class="cs">#+filetags</span><span class="c">:   :fruits:vegetables:</span>
</span></span><span class="line"><span class="cl"><span class="cs">#+identifier</span><span class="c">: 20230612T121326</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">I am going to write today about fruits and vegetables and how important they are to our way of life.</span></span></code></pre></div>
<p>&hellip; and then deposits it into the on-device storage path for Mobius Sync and ingestion into the Syncthing network.</p>
<p>The use case for something like this is pretty small: I&rsquo;d like to be able to make Denote notes on a phone or iPad when I&rsquo;m not near a laptop or desktop machine, and it was easier to automate that up front even if Denote&rsquo;s naming and formatting convention is pretty simple. Following the &ldquo;convention over configuration&rdquo; mindset of Denote, the top level of my notes hierarchy is empty, so it becomes the de facto inbox for when I&rsquo;m back in front of a &ldquo;real computer&rdquo; for triaging incoming notes captured while mobile &ndash; moving them into the right folders, updating metadata, etc.</p>
<p>The action writes to a Drafts &ldquo;bookmark,&rdquo; so you can use whatever storage back end you like: If you keep your Denote notes in Dropbox, Box, Google Drive or whatever, the action will prompt you the first time you use it (on Mac or iOS/iPadOS) and you can choose the right thing for you.  I suppose for Git people something like Working Copy will probably also work.</p>
<p>Anyhow, seems to be a fine v1.</p>
<p>And I guess, going wide for a few seconds, another comment on what I like about Denote generally: It&rsquo;s a good convention!  As I was working on the search stuff over lunch, I realized that the Python script that creates the <code>index.json</code> file that Fuse.js has to consume was using file creation times to record the date of a given note in the index. That&rsquo;d be fine if those notes were never regenerated, but they are. But whatever! The Denote naming convention embeds the date in the filename. So I just parse that to create the date entry for each file in the index.</p>
<p>If all my plaintext notes were saved with that naming convention for all eternity, it wouldn&rsquo;t be the worst thing. If the space goat comes and eats Emacs, the convention-over-configuration approach means that if you understand regular expressions and any commodity scripting language, you can pipe your stuff through pandoc and be on your way in a new tool. It&rsquo;s not much more complex a lift than, say, switching from Jekyll to Hugo. If you&rsquo;re willing to use a tool you have to use lisp to configure, this isn&rsquo;t a big thing.</p>
<p>The one &ldquo;looking over my shoulder&rdquo; question I have is around markup and future-proofing. There&rsquo;s a case to be made for using Denote with its Markdown-and-YAML format and not its org-mode format. That would provide close to perfect portability into something like Obsidian without needing to run anything through pandoc first. There&rsquo;s an argument to be made that parsing that format is easier, too, because YAML is a thing and &ldquo;org mode file variables&rdquo; are kind of not.</p>
<p>Eh. Whatevs.</p>
<p>I might need to write a script. Please don&rsquo;t throw me in the briar patch.</p>
<h2 id="a-bit-more-on-the-leica-q3-and-the-fujifilm-roadmap">A bit more on the Leica Q3 and the Fujifilm roadmap</h2>
<p>I loaned my Leica Q2 out, which prompted some comments from the lendee, which made me think about the Q3 in clearer terms. It sounds like actual general availability will be quite delayed, and I&rsquo;m in no hurry to buy new gear anyhow, but I think I&rsquo;m more curious about what&rsquo;s next for Fujifilm&rsquo;s X100 lineup and the eventual X100 &ndash; VI? 6? Whatever it is.</p>
<p>I&rsquo;d love to see IBIS and I&rsquo;d love for it to have the X-T5&rsquo;s sensor. It feels like a faster lens is probably too much to hope for: The size difference between Fujifilm&rsquo;s two faster 23mm lenses &mdash; the original XF23/1.4 and the WR remake &mdash; and the lenses you find in the X100 series and the XF23/2 WR is pretty drastic. I think an f1.8 or 1.4 would bulk the X100 up considerably.</p>
<p>I&rsquo;m also curious about whether there&rsquo;s any life left in the X-Pro series. I thought the &ldquo;no chimping&rdquo; design of the X-Pro 3 was a gimmick, and I am not sure what the real audience even is for an optical viewfinder. I read someone recently who put the X-Pro OVF in the context of early mirrorless technology, pointing out that it helped people get around the performance problems with early EVFs. Personally, I feel an aesthetic connection with it but prefer to just shoot with the EVF. The one exception to that is when I&rsquo;m out with my little Funleader fixed-focus pancake: I use the EVF now and then to spot-check exposure, but it&rsquo;s fun shooting super lo-fi with a toy lens and an OVF.</p>
<figure><img src="/img/statuary.jpg"
    alt="A pseudo-classical yard statue in the shadow of a gray house. Strong shadows."><figcaption>
      <h4>Shot with a Funleader 18/f8 fixed-focus lens</h4>
    </figcaption>
</figure>

<p>It feels to me like the X100 line could be coming close to rounding out a phase: Get IBIS squeezed in there, break the f2 barrier on the lens, and what else do you do besides iterate on the sensor as it makes sense to do so, selling it as a travel/street compact all-rounder? They added WR last go-round. There&rsquo;s not much left to do if it is to stay a fixed-lens kinda-rangefinder. If they killed the OVF to make room for IBIS, and bulked it up a little for a faster lense, I think I&rsquo;d take that deal. It&rsquo;d just be an APS-C Leica Q-series at that point.</p>
<h2 id="fright-night--2011">Fright Night (2011)</h2>
<p>We watched the 2011 <em>Fright Night</em> remake last night after a weekend conversation about vampire movies. I wouldn&rsquo;t call it a paragon of the form, but by the time we were able to settle down for a movie it was a little late and we wanted something fizzy. I &hellip; didn&rsquo;t remember Colin Farrell having so much fun the first time I saw it, which must have been in the theater or not long after its run. But he does have fun. And it left us wanting to go back to the &lsquo;85 original, because the remake raised a few questions we couldn&rsquo;t answer. It was nice of them to let Chris Sarandon turn up long enough to get eaten.</p>
<p>That conversation also has me wanting to do a few more pairs/trios. Like, Murnau&rsquo;s <em>Nosferatu</em> along with <em>Shadow of the Vampire</em>, but also <em>Cabinet of Dr. Caligari</em> to get a good dose of German Expressionism.</p>
<h2 id="old-man-coos-at-cloud">Old man coos at cloud</h2>
<p>Possibly lost in the Denote shuffle because I&rsquo;m using them and they seem to just work:</p>
<p>Syncthing, NextDNS, and TailScale are really doing it for me.</p>
<p>There&rsquo;s the occasional glitch with Syncthing, but nothing too bad and probably because I have some things writing to the sync folders a little too often. But it works really well for how I&rsquo;m using it:</p>
<ul>
<li>Syncing org files</li>
<li>Syncing the HTML output of org publishing to the Synology</li>
<li>Syncing back end for Mackup (configuration syncing)</li>
<li>Syncing back end for my Doom Emacs configuration</li>
<li>Syncing <code>~/bin</code></li>
</ul>
<p>I haven&rsquo;t been using it quite long enough to rule on whether it&rsquo;s as good as Dropbox, but it&rsquo;s not nearly as <em>needy</em> as Dropbox, and it works great over &hellip;</p>
<p>TailScale. I came <em>this</em> close to setting up a VPN on my Synology when I remembered that I meant to look into TailScale. I went in expecting I&rsquo;d bounce off something about it, and didn&rsquo;t expect to be able to connect iOS/iPadOS devices to it, but it&rsquo;s almost magical in its just-works-ness. I&rsquo;ve got a few things on Heroku I could probably pull back to the Synology at this point.</p>
<p>Another bonus is that I can use my NextDNS account with it, which spares me conflicting profiles on my Apple devices and hence removes the need to keep separate ad blockers going on anything: I&rsquo;m subscribed to a few filters on NextDNS and it is more than adequate.</p>
<p>I need to take one last pass at making sure I don&rsquo;t have something syncing its config on Dropbox, and get all my Dropbox stuff out, but I think that&rsquo;s one more account I can kill thanks to Syncthing and TailScale.</p>
<p>I&rsquo;m remembering back to when my world was NFS mounts and DynDNS, and this is all so much better.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-06-11</title>
      <link>https://mike.puddingtime.org/posts/2023-06-11-daily-notes/</link>
      <pubDate>Sun, 11 Jun 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-06-11-daily-notes/</guid>
      <description>First week at my new job. How I made a searchable web interface for my Denote notes with FuseJS, a Synology, and TailScale.</description>
      <content:encoded><![CDATA[<h2 id="first-week-at-iterable">First week at Iterable</h2>
<p>Well, after a lot of hinting and oblique mentions, it&rsquo;s okay to finally say I started a new job this week, as director of IT at Iterable, thus ending about seven months of rest and a relatively easy job search.</p>
<p>Here&rsquo;s the LinkedIn version:</p>
<blockquote>
<p>I remember being 1200 feet over a Ft. Benning drop zone: My parachute risers had twisted up, my helmet had fallen off, and I was airsick. I thought to myself, &ldquo;well, you brought this on yourself.&rdquo;</p>
<p>Years and years later, I read Pema Chödrön, who said, &ldquo;to be fully alive, fully human, and completely awake is to be continually thrown out of the nest.&rdquo;</p>
<p>I finished my first day at Iterable today. I&rsquo;m very happy to be starting this new role with a warm, welcoming team that includes a few familiar faces.</p>
<p>Reflecting on my time off after Puppet:</p>
<p>It is easier said than done to go still, rest, and find some quiet. I think I lost two months to assorted writing and photography projects and other busy-making stuff until someone close to me finally said, &ldquo;I thought you were supposed to be resting. This doesn&rsquo;t seem like resting.&rdquo;</p>
<p>I did finally manage to go still and rest. When I decided to start looking for work again, I knew I had to sift through 10 amazing years at Puppet and figure out when I was happiest and helping the most people. Having the time to discern meant I was able to set a few things aside I would have sworn I most wanted to do as I realized I was probably just trying to replace something I&rsquo;d lost. I felt more focused with each recruiter screen or interview, and my list of job alerts got shorter as I shifted from &ldquo;what can I do&rdquo; to &ldquo;what do I want to do.&rdquo;</p>
<p>It&rsquo;s easy to euphemize: During my time out I got a lot of really unfortunate advice about covering up gaps, and trying to talk around things, so I&rsquo;ll just say that yes, it sucked to get laid off — to get thrown out of the nest.</p>
<p>It wasn&rsquo;t a world-ending shock, I was treated with respect and generosity, and it was a genuine gift to know that I could spend a few months helping my team transition once I knew I wasn&rsquo;t going to continue. But it was still tough. So I&rsquo;m also grateful to friends I got to spend time with over the past several months. There were a few times I felt at sea and unsure of myself, and all the coffees, lunches, and texts helped so much. I had a lot more friends on this jump than I did over that drop zone, and I&rsquo;m very grateful for all of them.</p>
</blockquote>
<p>There is a ton more to say about the past seven months, and it feels like the right thing to do is to think more deeply about big themes. But there are some little things to say:</p>
<p>First, I caught a lot of great breaks going into my time off, and saw my layoff coming far enough out that I could prepare. I spent a lot of my early career under the shadow of layoffs, with a completely different mindset. I think the person who smiled and told his layer-offer that he hoped they had an okay time with all their other layoffs last August would be completely alien to the person who wouldn&rsquo;t take a weekend off for nine straight months in 2001.</p>
<p>There are lots of ways you can &ldquo;figure out what&rsquo;s next&rdquo; that don&rsquo;t have to involve getting laid off or quitting your job, but &ldquo;figuring out what&rsquo;s next&rdquo; takes work. It&rsquo;s probably <em>easiest</em> if you know and start acting on it while you have a job, but if you&rsquo;re in a place where you have a ton of things to sort out and you&rsquo;re just enervated from keeping the lights on wherever you are, it&rsquo;s still kind of hard. I&rsquo;m glad I had the resources, and hence the time, to take a break and be methodical. There was risk and some anxiety, but it got the best result.</p>
<p>Second, depending on how you want to manage the reckoning, this is my first new job in almost 11 years. I did so much growing during that time. There are some moments I wish I could go back to and get a do-over on, but that&rsquo;s part of the whole &ldquo;growth&rdquo; thing &hellip; not getting things quite right the first time you encounter them.</p>
<p>Third, I&rsquo;m glad I structured the job search the way I did. During the intense &ldquo;cold call&rdquo; period of February through April I had a loose routine of taking three days a week to just go through job listings and two days a week of applying for the listings I had saved the other three days of the week. Breaking it up like that gave me space to think about each listing.</p>
<p>I learned a practice years ago of pausing and asking if an opportunity or request elicits a &ldquo;whole body yes,&rdquo; &mdash; positive reactions from head, heart, and gut. I found that spending some time looking through job posts and quickly capturing the ones where my first response was &ldquo;sure, I could do that,&rdquo; then coming back to them a few days later to look a second time elicited a slightly different response. Sometimes it was &ldquo;wow, why am I delaying the application here?&rdquo; and other times it was &ldquo;I don&rsquo;t know why I thought that was a good idea.&rdquo; The third test was the actual application &mdash; filling out whatever forms and writing a cover letter, and that was when I could tell whether my heart was really in it. If I couldn&rsquo;t write a compelling cover letter &mdash; didn&rsquo;t feel sincere or engaged &mdash; it was a signal from head and heart.</p>
<p>I started out looking at several kinds of jobs &mdash; IT, engineering, operations &mdash; and then a few categories within each. I had some good early signal from the operational roles (chief of staff and similar), extremely positive signal on IT, and really uneven signal on engineering. I was also looking at organizational size/maturity.  Part of me went in thinking &ldquo;man, I wish I could do a &lsquo;Puppet in 2012, but everything I know now.&rsquo;&rdquo;</p>
<table>
  <thead>
      <tr>
          <th>Role</th>
          <th>Org maturity</th>
          <th>Feels</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Chief of staff</td>
          <td>low</td>
          <td>Exciting, frustrating.</td>
      </tr>
      <tr>
          <td>Chief of staff</td>
          <td>medium</td>
          <td>Sure, I could do that. I&rsquo;d have some growth opportunities, you&rsquo;d get some shit done better.</td>
      </tr>
      <tr>
          <td>Chief of staff</td>
          <td>high</td>
          <td>&ldquo;I would need to be this tall to ride and I&rsquo;m not there yet.&rdquo;</td>
      </tr>
      <tr>
          <td>Eng</td>
          <td>low</td>
          <td>Under certain, odd conditions; but your conception of &ldquo;my lane&rdquo; is too narrow.</td>
      </tr>
      <tr>
          <td>Eng</td>
          <td>medium/high</td>
          <td>North of &ldquo;zone of mediocrity&rdquo; or &ldquo;competence,&rdquo; nearing &ldquo;zone of excellence,&rdquo; but not &ldquo;zone of genius.&rdquo;</td>
      </tr>
      <tr>
          <td>IT</td>
          <td>low</td>
          <td>&ldquo;Well, you certainly have interesting notions; someone will enjoy disabusing you of them&rdquo;</td>
      </tr>
      <tr>
          <td>IT</td>
          <td>medium</td>
          <td>&ldquo;Yup. Put me in there. I have some lessons to apply.&rdquo;</td>
      </tr>
      <tr>
          <td>IT</td>
          <td>high</td>
          <td>&ldquo;Will you issue me a clipboard and legal pad or do I have to count all these beans on my fingers?&rdquo;</td>
      </tr>
  </tbody>
</table>
<p>Going in my enthusiasm and interest was highest around chief of staff roles. Over my time at Puppet I&rsquo;d been in and out of &ldquo;operational leader&rdquo; roles, and had to very disappointing experiences in that area. I wanted another bite at the apple. I got several interviews for that sort of thing, made it pretty far into a few processes, and came away with a few observations:</p>
<ul>
<li>The places where I would do the most good, that seemed the most exciting, and that were the most greenfield, were the worst conversations, and they happened early enough that my energy and patience for yet another baby CTO with a reflexive hatred for process were too low to even attempt to make a sale. <em>Or</em> they didn&rsquo;t actually want a chief of staff &mdash; they wanted an EA/office manager.</li>
<li>The places where I could be helpful and effective &mdash; the medium maturity organizations with enough introspection to know they needed help &mdash; were harder to find, and the few conversations I had there always left me uneasy. Like I was swapping the process resistance and insecurity of baby C-levels for the conditioned wariness of leadership teams that understand a chief of staff is a potential threat to the balance of power and their individual access and influence.</li>
<li>There was a third tier &ndash; medium or high maturity orgs who wanted someone very senior with much more hard-core business operations experience. Just isn&rsquo;t me, and I didn&rsquo;t bother.</li>
</ul>
<p>But I also had to come to grips with why I was looking at those roles to begin with, and it began to dawn on me that the things that made me a likely candidate to do that kind of thing at Puppet over the years involved a different mix of factors from what these places needed. I kept imagining doing these roles from the perspective of the person who&rsquo;d been at Puppet for ten years, had a solid network, had a basis for trust with people throughout the business, and an inventory of patterns we could pick up and dust off that had the ring of familiarity for the old-timers, but could be pivoted or spruced up a little for the skeptical newcomers.</p>
<p>I kept saving those roles when I got job alerts for them, though, kept applying, and kept tracking why I dropped out or decided not to finish the cover letters for everything, and finally formed a thought over my morning tea and listing review one morning:</p>
<p>&ldquo;You loved that place, loved being there, and loved even the people who drove you a little crazy. You wanted to make it better and knew how to get things unstuck. You understood what it needed on some emotional level. It&rsquo;s gone.&rdquo;</p>
<p>I quietly re-branded my LinkedIn page, turned off those job alerts, and narrowed my list to IT and engineering.</p>
<p>Engineering things weren&rsquo;t sparking much joy at any point in the process. One opportunity came along that seemed interesting, but in a very &ldquo;you&rsquo;ve got a very painful-sounding definition &lsquo;interesting&rsquo;&rdquo; sort of way. When you send your wife this gif to explain why you think you&rsquo;d be a good fit for a job:</p>
<figure><img src="/img/sith-speciality.gif"
    alt="Senator Palpatine, Sith Lords are our speciality ...">
</figure>

<p>&hellip; you should ask a second time if that&rsquo;s how you want to spend your days.</p>
<p>It kept coming back to <a href="https://themanagershandbook.com/coaching-and-feedback/zone-of-genius">which zone I&rsquo;m in</a> when I&rsquo;m leading in engineering, and I never really felt like I was in my &ldquo;Zone of Genius.&rdquo; I&rsquo;ve been around those people and know enough to understand the difference between us.</p>
<p>Ultimately the things that kept feeling the most right to me were the IT roles. I had a few processes go pretty far, so I had the chance to do a lot of personal writing and preparation, and I realized that the challenge I was having was less about thinking up a response, but organizing all the thoughts I had on any given part of the conversation. Over the course 30+ years in professional workplaces I held a lot of jobs in a lot of different kinds of businesses. I was never quite sure what skills would transfer in each role I held, but I knew that during my time in IT it felt I could tap the most of my experiences, and that my particular temperament worked the best.</p>
<p>By the time the Iterable opportunity presented itself, I felt primed and very clear.</p>
<p>I guess the last thing I want to say right now is that it was a pretty great couple of weeks of interviewing. I had no problem writing the customary followup note. The opportunity is at that intersection of &ldquo;oh, there&rsquo;s a lot to do&rdquo; and &ldquo;I know what I need to do.&rdquo; I want to be there.</p>
<h2 id="our-world-of-note-taking-compromises">Our world of note-taking compromises</h2>
<p>So part of Week One was having my new boss up from California for a kickoff and planning. We got a WeWork space. I didn&rsquo;t do anything to get a toolchain onto my new work laptop so I didn&rsquo;t have Emacs or any of my personal config stuff on it. It was a good opportunity to think about the compromises that have loomed the largest when it comes to living in the Emacs ecosystem but having the occasional mobile use case:</p>
<ul>
<li>Decent clients to read org-mode files.</li>
<li>Reliable sync.</li>
<li>Capture on the go.</li>
</ul>
<p>After a few days in a WeWork, seeing what would have been useful and how I was working by just putting stuff in native tools then moving them over, I realized I&rsquo;d be happiest working with these assumptions:</p>
<ul>
<li>Stick with Emacs/org-mode/Denote. They feel the best for just doing work on a laptop or desktop, and that&rsquo;s where I do most of my work.</li>
<li>Give up on any of the mobile options for managing org-mode. They&rsquo;re dancing bears. It&rsquo;s great that they can dance, and it feels uncharitable to complain that they don&rsquo;t dance well, but they&rsquo;re hindered by a lack of native sync. The best they can do is capture simple things and relate simple things. Put more weight on them and they&rsquo;ll frustrate me.</li>
<li>Make static notes available in a way that&rsquo;s easily readable by native tools and put extra effort into making sure that when the static notes are pushed out, they&rsquo;re truly pushed out.</li>
</ul>
<p>On that last point, the biggest pain point I&rsquo;ve come across using Denote/Emacs has been getting at stuff for reference when I&rsquo;m not near a real computer. One way tools like Obsidian and Things run rings around Emacs is in their native, bespoke, purpose-built sync capabilities. Capture is no big deal.</p>
<p>Yesterday I spent some time sussing out how org-publish works and:</p>
<ul>
<li>Got my notes set up to publish using <a href="https://simplecss.org">SimpleCSS</a>.</li>
<li>Connected the output directory to my Synology via SyncThing.</li>
<li>Set up the Synology&rsquo;s web server (it&rsquo;s just nginx).</li>
<li>I can connect to the saved notes via Tailscale, which is running on all my devices (and using NextDNS, which is sweet, since I was able to take out a whole layer of browser-based ad-blockers).</li>
<li>Set up an after-save-hook to kick off a publish whenever I save a file in the notes directory.</li>
<li>Set up a pre-save hook to update any Denote org-babel d-blocks, because I make meta note pages with those.</li>
</ul>
<p>I put SyncThing on an aggressive update schedule to make sure the HTML versions of notes will get pushed out after saves.</p>
<p>Today I started figuring out how to add search to my exported notes. <a href="https://fusejs.io">FuseJs</a> seems to be working fine for that. I  made a script that can walk the exported HTML notes and get them into a JSON index, and I added some HTML/JS to an <code>index.org</code> file in my notes directory. Here&rsquo;s a quick demo of a few searches on mobile:</p>
<p><video controls width="40%"><source src="/img/denote-fuse-search.mp4" type="video/mp4">
Your browser does not support the video tag.</video></p>
<p>For now the notes indexing script is just running from the Synology&rsquo;s Task Scheduler.</p>
<p>So, net:</p>
<ul>
<li>When I write or edit a note in Denote, save-hooks publish all my notes as HTML.</li>
<li>SyncThing makes sure the HTML is pushed over to my Synology.</li>
<li>The Synology periodically indexes the HTML for search.</li>
<li>nginx running on the Synology serves the notes.</li>
<li>Everything is happening over Tailscale.</li>
</ul>
<p>There&rsquo;s a very fair question, which is &ldquo;why on Earth do all this when Obsidian, Logseq, or a few other mobile-capable PKMs are sitting right there?&rdquo;</p>
<p>I guess the answer is, &ldquo;I don&rsquo;t like them as much.&rdquo;</p>
<p>I mean, they&rsquo;re fine and all &mdash; I would use Obsidian if there were no Emacs &mdash; but if I line up what they excel at with what Emacs/org-mode/Denote excel at, and ask myself &ldquo;how do I most often use these tools,&rdquo; the mobile access use case is relatively rare and mainly amounts to a question of access and very simple capture. I just want to know that if I save a piece of information on a laptop or desktop, it&rsquo;ll be there for review on a tablet or phone not long after.</p>
<p>For a few hours of work configuring some off-the-shelf tools and a little bit of fine-tuning of the underlying sync engine, all my notes are securely available to me with super-fast search, and I can author them in a decent environment to begin with, not some Electron-based Markdown editor</p>
<p>I&rsquo;m happy to share what I came up with but avoided my customary &ldquo;here&rsquo;s a few snippets.&rdquo; The stuff I have going right now feels alpha. It&rsquo;s working, but it&rsquo;s in that realm of &ldquo;I just got ping.&rdquo; The HTML output needs some polishing, I&rsquo;m not sure the search stuff is configured as well as it could, and it remains to be seen how it all works as I just get on with my day. I did as much as I could over a few sessions on the weekend so I could just get back to work tomorrow without any lingering &ldquo;just one more thing&rdquo; desire to fiddle.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-06-04</title>
      <link>https://mike.puddingtime.org/posts/2023-06-04-daily-notes/</link>
      <pubDate>Sun, 04 Jun 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-06-04-daily-notes/</guid>
      <description>Denote and encrypted notes plus the whole mobile angle.  Hugo preview server and ox-hugo. What happened to V.</description>
      <content:encoded><![CDATA[<h2 id="denote-and-encrypted-notes">Denote and encrypted notes</h2>
<p>I want to have access to my Denote notes via SyncThing on a machine I don&rsquo;t completely control (but is not, to be clear, operating in a hostile environment) and I want them to be encrypted, same as my <code>org-journal</code> files. I should probably just ask Prot, but as near as I can tell the <em>clean</em> way to encrypt notes in Denote is to add an &ldquo;org.gpg&rdquo; type to <code>denote-file-types</code>, like this:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;denote-file-types</span>
</span></span><span class="line"><span class="cl">             <span class="o">&#39;</span><span class="p">(</span><span class="nv">org-gpg</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:extension</span> <span class="s">&#34;.org.gpg&#34;</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:date-function</span> <span class="nv">denote-date-org-timestamp</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:front-matter</span> <span class="nv">denote-org-front-matter</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:title-key-regexp</span> <span class="s">&#34;^#\\+title\\s-*:&#34;</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:title-value-function</span> <span class="nf">identity</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:title-value-reverse-function</span> <span class="nv">denote-trim-whitespace</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:keywords-key-regexp</span> <span class="s">&#34;^#\\+filetags\\s-*:&#34;</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:keywords-value-function</span> <span class="nv">denote-format-keywords-for-org-front-matter</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:keywords-value-reverse-function</span> <span class="nv">denote-extract-keywords-from-front-matter</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:link</span> <span class="nv">denote-org-link-format</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:link-in-context-regexp</span> <span class="nv">denote-org-link-in-context-regexp</span><span class="p">))</span></span></span></code></pre></div>
<p>It looks like a lot to do a little, but it&rsquo;s just a clone of the <code>org</code> type that&rsquo;s already in that list, with the extension changed. I suppose one could just alter the <code>org</code> type, but then you don&rsquo;t have an unencrypted type if you want it.</p>
<p>With that in place, you can do:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">denote-file-type</span> <span class="ss">&#39;org-gpg</span><span class="p">)</span></span></span></code></pre></div>
<p>&hellip; and anything you create with the <code>denote</code> command uses that type, with the correct extension. Given the right general config:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;epa-file</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">epa-file-enable</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">org-crypt-key</span> <span class="s">&#34;foo@bar.baz&#34;</span><span class="p">)</span></span></span></code></pre></div>
<p>&hellip; it all &ldquo;just works,&rdquo; with decryption handled transparently provided the gpg agent is set up correctly, and I preserve the option to have unencrypted notes for whatever reason I might want them at some point.</p>
<p>To get my existing notes into an encrypted state, I used this script:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/zsh
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">encrypt_file<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">file_path</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">recipient</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$2</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">encrypted_file_path</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">file_path</span><span class="si">}</span><span class="s2">.gpg&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  gpg --encrypt --recipient <span class="s2">&#34;</span><span class="nv">$recipient</span><span class="s2">&#34;</span> --output <span class="s2">&#34;</span><span class="nv">$encrypted_file_path</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$file_path</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;File encrypted: </span><span class="nv">$encrypted_file_path</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">encrypt_files_in_directory<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">directory</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">recipient</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$2</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">for</span> file_path in <span class="s2">&#34;</span><span class="nv">$directory</span><span class="s2">&#34;</span>/*.org<span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    encrypt_file <span class="s2">&#34;</span><span class="nv">$file_path</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$recipient</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="k">done</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Usage: ./encrypt_files.sh directory recipient_email</span>
</span></span><span class="line"><span class="cl"><span class="nv">directory</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">recipient_email</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$2</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[[</span> -n <span class="s2">&#34;</span><span class="nv">$directory</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> -n <span class="s2">&#34;</span><span class="nv">$recipient_email</span><span class="s2">&#34;</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">  encrypt_files_in_directory <span class="s2">&#34;</span><span class="nv">$directory</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$recipient_email</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span>
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;Usage: ./encrypt_files.sh directory recipient_email&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span></span></span></code></pre></div>
<h2 id="the-mobile-problem">The mobile problem</h2>
<p>The tradeoff with that approach is that your mobile use case gets harder. I can still do something like mosh my way in to the Mac Studio with Tailscale, I guess.</p>
<p>I have the nagging feeling that Emacs-centric note taking wouldn&rsquo;t work great for me if I were dealing with a commute or other scenarios where mobile access is more important. Yes, there are beorg, <a href="https://plainorg.com">Plainorg</a>, and a few other options, but the syncing layer is the complicator. Some people seem to live fine just using git and maybe <a href="https://github.com/ryuslash/git-auto-commit-mode">git-auto-commit</a>, or just generally being more disciplined about their file use. I have generally felt better served by bespoke solutions, like you get with Obsidian, Things, and others. They&rsquo;re still subject to the occasional screwup, but I don&rsquo;t feel like I see them as often as I do with things that simply watch a file system and try to react appropriately.</p>
<p>I have been doing a little personal journaling about my preoccupations with mobile stuff. After tracing things back over the years, I recently realized that a lot of my fixation on getting stuff to work on a phone came from a pretty terrible time during the 2001 downturn.</p>
<p>All my teammates had been laid off and I was holding down a small network of Linux/open source sites that had previously involved a much larger team. If I didn&rsquo;t want things to get out of control I had to keep an eye on them over the weekend. That mentality caused a lot of lines to blur and it took years to unblur them. I was an early iPad enthusiast because I&rsquo;d internalized the idea that I should be able to do all kinds of work from anywhere at any time. Before that, I was really into the netbook thing because I could put an eeePC into a hip bag.</p>
<p>By the time I got to Puppet in 2012, working from home wasn&rsquo;t a novelty or an aspirational goal: I&rsquo;d been doing it for 13 or 14 years and was really glad to have an office to go to. Covid lockdown sparked a pretty bad reaction after the initial &ldquo;let&rsquo;s build a fire and sing songs while we wait for the drop ship&rdquo; phase because lines started blurring again.</p>
<div style="position: relative; width: 100%; padding-bottom: 56.25%;margin-bottom:20px;">
<iframe style="position:absolute; width:100%; height:100%;" src="https://getyarn.io/yarn-clip/1700a3aa-2d58-4411-a8cf-02cea98e8561/embed?autoplay=false&responsive=true"
frameborder="0">
</iframe>
</div>
<p>At the same time, just last week I had a pair of things to do in the afternoon and I&rsquo;d written some thoughts down about one of the events that I wanted to review while I was out of the house. Well &hellip; apparently SyncThing hadn&rsquo;t picked up on the changes before the machine I wrote them on went to sleep, so none of the other machines in the mesh &mdash; including a Synology I put SyncThing on for just these occasions &mdash; knew the notes existed.</p>
<p>At some point, &ldquo;oh, no problem, I&rsquo;ll just Tailscale in to the home network and WoL the Mac Studio so I can wake up SyncThing and then sync my changes down&rdquo; loses all its charm.</p>
<p>Ugh. Need to stop before I talk myself into doing something rash and disruptive.</p>
<h2 id="hugo-previews-while-working-in-ox-hugo">Hugo previews while working in ox-hugo</h2>
<p>I&rsquo;m not sure if there&rsquo;s a better way to do this, but this is working for me:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/start-hugo-server</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Run Hugo server with live reloading and open the server URL in a browser.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let*</span> <span class="p">((</span><span class="nv">root</span> <span class="p">(</span><span class="nv">projectile-project-root</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">default-directory</span> <span class="nv">root</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">compile</span> <span class="s">&#34;hugo server -D --navigateToChanged&#34;</span> <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">run-at-time</span> <span class="s">&#34;3 sec&#34;</span> <span class="no">nil</span> <span class="p">(</span><span class="nb">lambda</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">                              <span class="p">(</span><span class="nv">browse-url</span> <span class="s">&#34;http://localhost:1313&#34;</span><span class="p">)))))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/stop-hugo-server</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Stop Hugo server.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">kill-compilation</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">map!</span> <span class="nb">:leader</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">:prefix</span> <span class="p">(</span><span class="s">&#34;H&#34;</span> <span class="o">.</span> <span class="s">&#34;Hugo&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">       <span class="nb">:desc</span> <span class="s">&#34;Start Hugo Server&#34;</span> <span class="s">&#34;S&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/start-hugo-server</span>
</span></span><span class="line"><span class="cl">       <span class="nb">:desc</span> <span class="s">&#34;Stop Hugo Server&#34;</span> <span class="s">&#34;s&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/stop-hugo-server</span><span class="p">))</span></span></span></code></pre></div>
<p>I get a little <em>Compiling</em> treatment in the modeline while the preview server is running. My browser reloads any time I save my work.</p>
<h2 id="what-happened-to-v">What happened to V</h2>
<p>I always sort of wondered <a href="https://www.vanityfair.com/hollywood/2023/05/the-v-files-legacy">what happened to V</a> between the miniseries and the regular series. I had a vague sense it had gotten worse, but I was also a teenager and didn&rsquo;t have a lot of critical faculties beyond &ldquo;this seems sort of sucky and boring now.&rdquo; Well, now I know: They got rid of the person who created it, made it cheaper, and tossed out what someone thought were the dumb parts, which were actually the good parts.</p>
<p>Interesting factoid:</p>
<blockquote>
<p>V was watched in more than 33 million homes, which amounted to 40 percent of all TV viewership. (The most popular series in America today, Yellowstone, averages 13.1 million viewers per episode.)</p>
</blockquote>
<p>I recently tried to dig up what&rsquo;s considered &ldquo;good numbers&rdquo; in the streaming era and didn&rsquo;t get many satisfying answers. Seeing that a modern phenomenon like <em>Yellowstone</em> pulls about 40 percent of V&rsquo;s numbers is helpful. <em>V</em> was hyped all to hell at the time, so its &ldquo;television special event&rdquo; status probably skews things a little. (The <em>M*A*S*H</em> finale did 105.97 million total viewers, and that record may be impossible to break as streaming-driven atomization deepens.)</p>
<h2 id="the-phony-solidarity-of-the-american-pundit-class">&ldquo;The Phony Solidarity of the American Pundit Class&rdquo;</h2>
<p>I got to <a href="https://www.thenation.com/article/society/jordan-neely-pundits/">this post in The Nation</a> after it sat on the read later pile for a while.</p>
<p>It&rsquo;s very strange to see the post-2016 realignments continuing apace. This particular link targets the slice of the center-left-to-center-right commentariat that has learned to talk about &ldquo;working people.&rdquo;  That tic &mdash; the &ldquo;won&rsquo;t somebody think of the working people&rdquo; tic &mdash; feels symptomatic of a kind of <a href="/posts/2022-06-20-elite-capturehttpsmicroblogbooks-by/">elite capture</a> all its own.</p>
<p>I wrote a few years ago:</p>
<blockquote>
<p>&ldquo;I have a lot of time for some heterodox thinkers. I wish &lsquo;heterodox&rsquo; was narrow-able to something less broad than &lsquo;a coalition of middle class trolls, rebadged culture warriors, people who hate how much they get ratioed, and well-meaning independent thinkers.&rsquo;&rdquo;</p>
</blockquote>
<p>I think I may need to retract that. I was going through the podcast searching for an episode and saw a few descriptions here and there that tell me &ldquo;heterodox&rdquo; has stopped being a word one lands on after casting about for a better one, and has become a sort of branding exercise.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-06-03</title>
      <link>https://mike.puddingtime.org/posts/2023-06-03-daily-notes/</link>
      <pubDate>Sat, 03 Jun 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-06-03-daily-notes/</guid>
      <description>Poking at Mimestream. Picking at Emacs.</description>
      <content:encoded><![CDATA[<h2 id="poking-at-mimestream">Poking at Mimestream</h2>
<p>I started beta testing Mimestream last year because &ldquo;mail client.&rdquo; It flipped to v1 recently and is having one of those Mac Commentariat moments.</p>
<p>My initial take was &ldquo;oh, another <a href="https://mailplaneapp.com">Mailplane</a>,&rdquo; but that&rsquo;s not right. It&rsquo;s not a browser app. It&rsquo;s a real app, and it does some helpful things if you&rsquo;re a Gmail user, like making filters more accessible. Because it is using the Gmail API and not IMAP it also feels super quick and responsive.</p>
<p>I still don&rsquo;t completely understand the effusive enthusiasm for it: No plaintext options, no local URL scheme or scripting interface, and for whatever reason the URLs you can get out of it point back to the Gmail web app instead of Mimestream. (I think that&rsquo;s set to change.)</p>
<p>On plaintext: I prefer to start with the plaintext version of any message, and I prefer to send in plaintext. If I feel the need to flip into rich/HTML mail mode I will, and I don&rsquo;t mind having to hit a key to get the HTML version of a mail if it means getting to start with the more calming plaintext alternative.</p>
<p>On the local URL scheme: I don&rsquo;t like living out of my inbox, and I don&rsquo;t like making tasks out of mails that don&rsquo;t include a link back to the message. When I turn an email into an action, I want a link back to the message, I don&rsquo;t want to copy the entire mail into my todo system.</p>
<p>On the scripting interface: It looks like there&rsquo;s a single Shortcuts action available right now, which is promising in its own way.     Where there&rsquo;s one there could some day be more. Most days I&rsquo;d rather have an AppleScript dictionary, but I get that Shortcuts are sort of the populist middle way between AppleScript and Automator.</p>
<p>In any event, until the app has more ways to talk to the rest of my apps, I&rsquo;m a gentle no. I have the sense that the team behind it has correctly identified that email clients have a lot of baggage that needs to be left behind, but it&rsquo;s a little too spare for my tastes. I don&rsquo;t think &ldquo;step up from the native Gmail interface&rdquo; is what I am after.</p>
<p>Since <a href="/posts/2023-04-25-daily-notes/#mail-restlessness-alights-on-mailmate">discovering MailMate</a> and <a href="/posts/2023-05-02-finding-an-org-contact-record-s-emails-in-mailmate/">figuring out how to work it into plaintext workflows</a>, I&rsquo;ve been enjoying its whole &ldquo;GUI mutt for the 21st century&rdquo; vibe.</p>
<h2 id="quit-picking-at-it">&ldquo;Quit picking at it&rdquo;</h2>
<p>This morning I was working on the bit about Mimestream and did a quick save of my <code>blog.org</code> file. I&rsquo;m used to seeing the name of the Markdown version of the post flash by in the minibuffer as org-hugo exports the org markup to the posts directory. Huh. So I made a quick change to dirty the buffer and saved again. Still nothing.</p>
<p>Huh &hellip; huh. Oh &hellip; I did refactor my <code>config.org</code> file! Maybe &hellip; no. That wasn&rsquo;t it.</p>
<p>Well &hellip; maybe &hellip; no, restarting didn&rsquo;t help.</p>
<p>Around and around for, I dunno, 5-7 minutes before breaking down and Googling and realizing that at some point I&rsquo;d tidied away this business at the bottom of my blog file:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-org" data-lang="org"><span class="line"><span class="cl"><span class="gh">*</span><span class="ni"> COMMENT</span><span class="gs"> Local Variables :ARCHIVE:</span>
</span></span><span class="line"><span class="cl"><span class="c"># Local Variables:</span>
</span></span><span class="line"><span class="cl"><span class="c"># eval: (org-hugo-auto-export-mode -1)</span>
</span></span><span class="line"><span class="cl"><span class="c"># End:</span></span></span></code></pre></div>
<p>Just &hellip; the thing that puts the buffer in auto-export mode and I&rsquo;d fiddled with it and it broke.</p>
<p>And a few days ago I decided to play around with spell-checking engines. Why? I don&rsquo;t know. Somebody said one was better. It also tripled the amount of time it took to open files. Why? I don&rsquo;t know. I didn&rsquo;t even bother searching to figure out if that was <em>true</em>, because I just intuited what was going on by where the minibuffer was hanging when I opened a file, undid the change, and with the minor exception of losing some custom words got on with my newly re-accelerated file opening life.</p>
<p>I think this might be the most built up I&rsquo;ve ever had Emacs, but I&rsquo;m also doing much less with it that isn&rsquo;t just writing, coding, or managing todos. Brief experiments with mail, RSS, and Mastodon all went by the wayside pretty quickly, so maybe it makes sense that I&rsquo;m fiddling with the core functionality more.</p>
<p>I think I&rsquo;m also ready to just start working again. Like, the knife is plenty sharp. I&rsquo;ve settled into some core day-to-day tools that have been just great for doing the things I do to provide structure for myself during this period. I felt a little like a dog endlessly circling before lying down on the question of how to best take notes before taking a cue from something I figured out as I was working on my plaintext CRM, which was &ldquo;work out the convention, then scaffold it into the capture process such that you don&rsquo;t ever think about the convention again, but know it will be there for you.&rdquo; Note-taking being a current site of influencer struggle, it took parallel work in a different kind of workflow to get me to hear through the noise and pick out the analogies between worfklows.</p>
<p>But having gone through that process &mdash; having circled seemingly endlessly &mdash; when I sit with how I feel about all the fiddling and goofing around, I realize the last time I felt like this I was a tech journalist getting paid a decent amount of money to goof off with Linux. It&rsquo;s probably why I&rsquo;m so impatient with tech influencers and tech bloggers today:</p>
<p>You read a review for a camera or tool and the use cases feel like they&rsquo;re all &ldquo;how does this work for someone whose job it is to review things,&rdquo; vs. &ldquo;how does this work for someone who has to do other things.&rdquo; The obsessive quest to prove that iPads could be &ldquo;serious computers,&rdquo; for instance &mdash; with the benchmark for &ldquo;seriousness&rdquo; being &ldquo;I can automate the process of making screenshots that document how to automate making screenshots so I can blog about the iPad&rsquo;s fundamental seriousness&rdquo; &mdash; felt like a &ldquo;content person&rsquo;s&rdquo; obsession. That&rsquo;s not to say that tech journalists, bloggers, and influencers don&rsquo;t have work to do &hellip; it&rsquo;s just that they necessarily have a conception of &ldquo;usefulness&rdquo; that is derived from what they have to do all day, which is not what most people who have to use computers to get work done have to do all day.  <em>Most people</em> do not need to know how to make screenshots at scale. The fact that your niche blog about Mac automation is heavily dependent on scaled automation of screenshot production <em>and</em> is very successful does not make scaled screenshot production any more imperative for the rest of us.</p>
<p>But even still I sort of get it.</p>
<p>For a certain kind of person (me among them), there is something mesmerizing about the kind of hyper-competence good automation or tech mastery suggests. It&rsquo;s like watching a magic trick, or a longboard dancer, or a woodworking show. One of my favorite sysadmins was incredibly fun to watch at work: all the tmux panes on full-screened terminals on dual monitors, hand never straying to the mouse, sitting cross-legged on his tall chair in front of his elevated desk. It was like watching a levitating octopus in a hoodie running a nuclear power plant.</p>
<figure class="rt-img"><img src="/img/delta-cafe-table.jpg"
    alt="A wooden table in a cafe in partial shadows. Blue wall. Decorative red enamel plate." width="320"><figcaption>
      <h4>Delta Cafe</h4>
    </figcaption>
</figure>

<p>The past several months, bereft of much to do but the dull and repetitive administrivia demanded by recruitment automation, punctuated by hurry-up-and-wait interview processes, it was sort of fun to sit and watch tech magic tricks and obsess on the relative efficiency of assorted modes of interaction with computers.</p>
<p>But now, knowing that this period is finally winding down, I&rsquo;m trying to think about what it&rsquo;s like when I&rsquo;m just trying to use a computer to get things done when I&rsquo;m <em>not</em> being very pointed about just goofing off and resting.  Like, &ldquo;oh, it&rsquo;s time to join a meeting, and I just restarted Emacs but it&rsquo;s bombing because when I added the config change that worked perfectly fine live, I dropped a paren,&rdquo; or &ldquo;oh, I forget to make sure that all the config for that package I decided not to use is untangled.&rdquo; With enough picking, your carefully curated, meticulously optimized trusted system stops being trustworthy. It just becomes this thing that breaks when you really need it to just work, but thanks to all the picking and fiddling it isn&rsquo;t just working, so you end up punting and using Apple Notes. Or if you&rsquo;re me and are still living out patterns established when you were a for-real journalist in the time before there were laptops, you grab a reporter&rsquo;s notebook out of the box of them you keep on hand and start scribbling.</p>
<p>It&rsquo;s a little interesting to me that as I began to feel that mounting sense of unease about all the picking and fiddling and &ldquo;what did I just change that is making this previously reliable thing break&rdquo; and began to pare things down, archive experimental chunks of my config, and just generally sit on my hands until the urge to monkey around passed, I started grabbing my camera on the way out the door again, <a href="/posts/2023-05-14-daily-notes/#picture-taking-dot-i-m-not-doing-it-much-dot">after a long period of not doing that much</a>.</p>
<p>Huh. Maybe there&rsquo;s somewhere non-self-defeating my creative energy can go.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Leuven is more pleasant than I thought it would be.</title>
      <link>https://mike.puddingtime.org/posts/2023-05-29-leuven/</link>
      <pubDate>Mon, 29 May 2023 20:40:59 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-29-leuven/</guid>
      <description>I don&amp;rsquo;t want to be soothed any longer.</description>
      <content:encoded><![CDATA[<p>There are these corners of the computing world that sort of jump out at me now and then because they&rsquo;ve been around forever, seem immune to whatever is the current sensibility and feel very much to be products of their own &hellip; <em>thing</em>, whatever that is.</p>
<p>Like, all the Emacs themes that have been around for as long as Emacs has had themes &ndash; since Emacs 20? They have sort of odd names, and you get this sense that a lot of them predate the sort of web-driven popularization of color science. Like, someone thought it&rsquo;d be cool to make a theme where everything is just a shade of blue, and call it &ldquo;Dreams of Blue,&rdquo; or &ldquo;poindexter-blue&rdquo; or what have you. There&rsquo;s also some primitivism or nostalgia. The ones that are meant to remind you of amber monochrome monitors. Or WordPerfect 5.</p>
<p>They predate stuff that to my mind is sort of modern and seems scientific &ndash; Solarized and Dracula jump to mind, and catppuccin is big lately. Or the things that have come out of the UX departments at big tech companies, like all the variants on Material. You know where Material is coming from, because Google probably issued a press release about it to draw attention away from its latest EU privacy violation settlement.</p>
<p>Anyhow, there are a bunch of them and I&rsquo;ve been seeing them around forever, and sometimes they do things that strike me as perhaps <em>quaint</em>. Like, they use a shade I&rsquo;ve come to think of as &ldquo;commit pink&rdquo; or &ldquo;commit green,&rdquo; dowdy shades that predate modern sensibilities &hellip; that perhaps don&rsquo;t have the whiff of <em>scientific soundness</em>. Tones and choices that do a little more to introduce a sense of structure than is currently popular.</p>
<p>At the same time, there&rsquo;s this unmistakable aura of <em>authority</em> just because they&rsquo;ve been around forever. Or at least I feel like I&rsquo;ve been scrolling past them forever. And core to Unix culture is that crushing deference to the patriarchs. The same thing you feel when you learn about man pages for the first time and it begins to occur to you that it took a lot of people a very, very long time to write that much documentation. The fact that so much of it is written in a sort of assumptive, referential style just adds to the sense you&rsquo;re reading the day journals of an obscure contemplative order.</p>
<p>Which brings me to Leuven, which I read about because someone on reddit asked for a good starting point for themeing org-mode, but which I feel like I have been seeing around forever.</p>
<p>Ordinarily, not my thing:</p>
<ul>
<li>It&rsquo;s a light theme. I thought I was all in on dark ones.</li>
<li>It&rsquo;s sort of contrasty. I thought I wanted low contrast ones.</li>
<li>Not exactly a <em>contemporary</em> palette. I&rsquo;m not sure how to describe the modern emphasis on things that are both vibrant and low contrast &ndash; or maybe I just did by typing that. Leuven doesn&rsquo;t do that.</li>
<li>It draws lines and boxes around things, in a way that feels sort of like when someone writes a console app that has an ASCII GUI. It uses background colors for headings and spelling errors.</li>
</ul>
<p>But all of that adds up to something that makes some kind of sense to me.</p>
<p>Like, a lot of modern themes go to words like &ldquo;soothing,&rdquo; posing that <em>contra</em> things like &ldquo;strain,&rdquo; or &ldquo;fatigue.&rdquo;</p>
<figure><img src="/img/leuven.jpg"
    alt="A screen shot of Leuven, a bright, contrasty Emacs theme."><figcaption>
      <h4>Leuven.</h4>
    </figcaption>
</figure>

<p>Okay, fair. I definitely agree that there are color schemes out there that cause strain and fatigue thanks to bad color choices, bad typography, etc.</p>
<p>But you know, another thing that causes fatigue and strain is trying to discern structure in a document using a palette designed to eliminate contrast. Turns out a few stark lines here and there do an admirable job of guiding the eye, aiding quantification, providing boundaries, creating a sense of anchors and space.</p>
<p>Now, to be fair, one problem the lo-contrast themers face is probably that they aren&rsquo;t in complete control of white space and typography, which can do a lot to put that sense of structure back in place. Or they&rsquo;re just neglecting to do it because someone picked some tones that are appropriately uwu, done some color science, and called it a day thinking their work is done.</p>
<p>After trying Leuven for a day, I found myself feeling a little more situationally aware and much less washed out. When its whole &ldquo;black text on white background&rdquo; thing got a little much, I used the brightness buttons to dial it down and was happy that its essential contrastiness still worked. Worked even better, in fact, because less detail got lost with the dimness.</p>
<p>It kind of reminds me of when I screwed something up with the lighting in my office. I had a bunch of Hues and tried out some sort of automation but they got quietly stuck in a very amber-toned place on the spectrum. So for weeks my office was &ldquo;well lit,&rdquo; but with a permanent orange-ish sundown tint. I couldn&rsquo;t figure out why it just felt soporific to go in there, or why it felt like <em>effort</em> to carry on a conversation.</p>
<p>Then one day Ben tried out some disco light app without bothering to make sure he was only targeting the lights in his room. After a few perplexed seconds of figuring out what had happened (it wasn&rsquo;t that hard &ndash; we shared a wall and the lights started going bananas just after he started blasting a Sophie album) I got into the Home app and reset all the lights to the tone I&rsquo;d set as &ldquo;normal&rdquo; years ago, and immediately felt the difference.</p>
<p>So, Leuven. Seems to have been around forever. I thought it was going to be a bit much, but actually find it to be &hellip; bracing. Energizing.</p>
<p><a href="https://github.com/fniessen/emacs-leuven-theme">Screenshots and instrux</a>.</p>
<p>In a similar vein, Prot&rsquo;s <a href="https://github.com/protesilaos/modus-themes">modus-vivendi and modus-operandi</a> themes.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-05-29</title>
      <link>https://mike.puddingtime.org/posts/2023-05-29-daily-notes/</link>
      <pubDate>Mon, 29 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-29-daily-notes/</guid>
      <description>More writing about a camera I both covet and find unfathomable. All in on Denote. Keycast for influencing and debugging. Succession ended with integrity.</description>
      <content:encoded><![CDATA[<h2 id="leica-q3">Leica Q3</h2>
<p><a href="https://baty.net/journal/2023-05-27">Via Jack Baty</a>, here&rsquo;s <a href="https://om.co/2023/05/26/whats-wrong-with-leica-q3/">Om Malik on &ldquo;What&rsquo;s Wrong with Leica Q3,&rdquo;</a> which, okay: &ldquo;introducing the flippy-tilty screen takes away from Leica’s uniqueness. The company has been able to charge more for offering less.&rdquo; Citing their monochrome cameras as an example of that is &hellip; a take.</p>
<p>Tilting screens add to the versatility of the device. That&rsquo;s all. They make certain situations easier to manage, especially with the kinds of things you want to shoot macro, and they give you more flexibility in street shooting situations where you don&rsquo;t want to have a camera up to your face.</p>
<p>A camera like a Q3, I&rsquo;d argue, <em>should</em> be making some concessions on design austerity, because the machines themselves exist for the times you can&rsquo;t take everything with you that you wish you could, so you&rsquo;re compromising and taking just one thing.</p>
<p>Now, he goes on to <a href="https://www.theverge.com/2023/5/25/23736639/leica-q3-camera-28mm-fixed-lens-compact-8k-availability-price-specs">point to the Verge review</a>, where it sounds like the implementation is lacking:</p>
<blockquote>
<p>&ldquo;&hellip; the worst part of the screen, aside from it looking like it’s just been grafted on and makes the camera appear and feel bulkier, is that there’s no groove or grip on its left side to dig your nail into or grab with your finger. It has grooves on its top and bottom, meaning you have to make a much bigger reach to move it.&rdquo;</p>
</blockquote>
<p>That doesn&rsquo;t sound great. I do like the way the Fuji X100V and X-T5 are built. It&rsquo;s a simpler, easier motion, sort of planting your thumb and kind of twisting each hand to get the screen undogged and moving. I don&rsquo;t like anything I need to pry open.</p>
<p>Om&rsquo;s concern that the Q3 &ldquo;design disaster&rdquo; is going to infect other Leica product lines didn&rsquo;t ring great with me because I don&rsquo;t like the button layout on the Q2 as well as I like it on an X100, or X-T. The Q3 looks more like a Fujifilm camera in that regard this time around (well, now the Leica people are <em>really</em> gonna hate it). Yeah, you have an extra target to distinguish when the camera is up to your face, but you figure it out.</p>
<p>I&rsquo;ll also admit that when it comes to a Q-series camera &ndash; $6k just to get in the door, then close to another $1k to get it fully provisioned &ndash; it&rsquo;s a little harder to smile and say &ldquo;well, they&rsquo;ll get it right in the next rev.&rdquo; I did that with three generations of Fujfilm X100s, but they hold their value about as well as a Leica (I checked a few generations and used street prices for <a href="/posts/2023-05-25-daily-notes/#leica-q3-arrives">my last post on the Q3</a>) so that&rsquo;s less of a sting.</p>
<p>Anyhow, I welcome the addition even if it sounds like it&rsquo;s imperfect.</p>
<p>Every time I&rsquo;ve tried to compare the Q-series to the X100-series, I walk away with a sense that the X100s are inferior on every spec (except the hybrid viewfinder), but manage to stay in the ring because they&rsquo;re scrappier and looser cameras.</p>
<p>The thing that blunts my joy about the Q-series is pretty similar to what makes me unhappy about very early Apple products and tools: There&rsquo;s a bias toward the austere that sometimes stifles. It was an easy matter for me, for instance, to perambulate between OS X and Linux for a period, because Apple was doing the &ldquo;slow layering&rdquo; thing and the customization ecosystem hadn&rsquo;t caught up yet. Once people figured out how to leverage the BSD userland and third party people began to figure out the new APIs, we were off and running.</p>
<p>Even a not-perfectly-realized tilt screen, and a reconfiguration of the control scheme to introduce more flexibility and easier one-thumb use while shooting, feels less to me like Violation of Holiest Ascetic Precepts and more like an opening up and loosening appropriate to a camera that manages to be both shockingly expensive <em>and</em> be the thing you shrug and grab when you can&rsquo;t take everything you&rsquo;d like, or make up your mind about what you need.</p>
<h2 id="succession-ended-with-integrity">Succession ended with integrity</h2>
<p>Spoiler culture is out of control, but &hellip; spoiler.</p>
<p><a href="/posts/2023-05-26-succession-finale-hot-take/">I wrote that Succession was a tragicomedy</a> and therefore needed to end a particular way to keep its integrity. It ended about the way I felt it should have, and even smeared a little spit on the rims of select audience brandy snifters with its elevation of the closest thing to a lens character had to a kind of hollow power that nonetheless commands deference from people newly laid low.</p>
<p>Tom Wambsgans disgusted you all along? You felt a warm glow when Shiv perforated him with as a grasping climber? Reminded you of that one VP you worked for who never fooled you but somehow fooled everybody else? Well, he&rsquo;s here to put a sticker on your forehead, and he doesn&rsquo;t need you to mean it when you hold his hand.</p>
<p>Who will win? The cockroach won. But it isn&rsquo;t even winning.</p>
<p>A reviewer referred to Roman&rsquo;s final little smile as &ldquo;twisted.&rdquo;  I think he was the only one of the three who knew enough to feel liberated. The other three siblings were clowns masquerading as serious people. Roman was the clown who knew better than any of it. He drives Kendall to rip of his own mask, then quietly declares them all shit. His comedic aspect is reunion with himself. His tragic aspect is the relationship he lost one of the few times he tried to play things straight.</p>
<p>With a good ending, it joins <em>The Wire</em>, <em>Breaking Bad</em>, <em>Mad Men</em>, <em>Justified</em>, <em>Halt and Catch Fire</em>, <em>Six Feet Under</em>, and <em>The Sopranos</em> in the &ldquo;stuck the landing&rdquo; club.</p>
<h2 id="denote-just-makes-sense-to-my-brain">Denote just makes sense to my brain</h2>
<p>Well, after a few days of fiddling and trying this and that, I think I&rsquo;m all in on Denote:</p>
<ul>
<li>No external dependencies</li>
<li>Convention-based naming</li>
<li>Portable</li>
<li>Simple</li>
</ul>
<p>&hellip; and an ecosystem is forming around it that respects its conventions but smooths out its UI. So if you want to just manage Denote via <code>dired</code>, you&rsquo;re welcome to do that. The fontification of Denote directories is enough to make the titles and tags clear when you&rsquo;re looking at a simple directory listing.</p>
<p>But there are also packages like <a href="https://github.com/namilus/denote-menu#">denote-menu</a> and <a href="https://github.com/mclear-tools/consult-notes">consult-notes</a> that provide light wrappers and convenience functions if you&rsquo;d like a cleaner view, where, for instance, the title, keywords, and date are all displayed in their own columns; and there are features that help quickly filter down your view based on keyword, etc.</p>
<p>I sort of want to compare it to what I admire about Markdown: Fine on its own, able to support more, probably you could go a little nuts trying to do more with it. I appreciate that it participates in the broader org ecosystem, and equally admire that you&rsquo;re welcome to use Markdown/YAML if that suits you.</p>
<p>This is occurring to me because I spent a bunch of time fiddling around with a few Denote wrappers over the weekend and ended up in that weird &ldquo;why did I do this&rdquo; state of mind where all the single-minded optimizing and tweaking felt sort of like a high-carb meal. Then I just opened up my notes directory in dired and realized Denote is great at its most basic.</p>
<p>If you use zsh, this will give you a colorized <code>ls</code> for a Denote directory, btw:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">dls<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    ls -1 <span class="p">|</span> <span class="nv">GREP_COLORS</span><span class="o">=</span><span class="s1">&#39;mt=1;32&#39;</span> egrep --color<span class="o">=</span>always <span class="s1">&#39;[0-9]{8}T[0-9]{6}&#39;</span> <span class="p">|</span> <span class="nv">GREP_COLORS</span><span class="o">=</span><span class="s1">&#39;mt=1;34&#39;</span> egrep --color<span class="o">=</span>always <span class="s1">&#39;__.*$&#39;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span></span></span></code></pre></div>
<h2 id="keycast">keycast</h2>
<p>While I was watching Prot&rsquo;s Denote demo video I noticed his keystrokes and commands were echoed to the modeline, which seemed pretty cool, and was also helpful to me trying to figure out what on Earth he was doing.  Then it occurred to me this afternoon that one thing I&rsquo;ve been struggling with as I try to <a href="/posts/2023-05-24-daily-notes/#batteries-included-situations-and-their-discontents">untangle what&rsquo;s going on in Doom</a> with some of the stuff I&rsquo;ve wanted to fix, has been <em>what&rsquo;s going on in Doom</em> when I use certain commands.</p>
<p>Like &hellip; previewing a file under point, which you invoke with <code>CTRL SPC</code>.</p>
<p>The sort of low-rent debug method I&rsquo;ve observed is that people just ripgrep their <code>~/.emacs/</code> for any mention of <code>C-SPC</code> to see what&rsquo;s bound to that.</p>
<p>Well, joke was on me:</p>
<p>Maybe it was <code>ivy-call-and-recenter</code>, maybe <code>company-complete-common</code>, prolly not <code>org-agenda-show-and-scroll-up</code>. PROBABLY <code>+vertico/embark-preview</code>, but who can say in these troubled times?</p>
<p>So I went looking for whatever it is Prot was using, and found something called <a href="https://github.com/tarsius/keycast">keycast</a>.</p>
<p>Its obvious utility is for screencasting, but it also has <code>keycast-log-mode</code>, which sends all your commands to a buffer, and which helped me establish it was, indeed, <code>+vertico/embark-preview</code>.</p>
<p>To get it to work in Doom Emacs you need to add something to your config:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span> <span class="nv">keycast</span>
</span></span><span class="line"><span class="cl">  <span class="nb">:config</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">define-minor-mode</span> <span class="nv">keycast-mode</span>
</span></span><span class="line"><span class="cl">    <span class="s">&#34;Show current command and its key binding in the mode line (fix for use with doom-mode-line).&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">:global</span> <span class="no">t</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">if</span> <span class="nv">keycast-mode</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;pre-command-hook</span> <span class="ss">&#39;keycast--update</span> <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">remove-hook</span> <span class="ss">&#39;pre-command-hook</span> <span class="ss">&#39;keycast--update</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;global-mode-string</span> <span class="o">&#39;</span><span class="p">(</span><span class="s">&#34;&#34;</span> <span class="nv">keycast-mode-line</span><span class="p">)))</span></span></span></code></pre></div>
<p>There are a bunch of issues mentioning problems with Doom and Spacemacs all over the place, but this is what worked for me, here in late May, 2023.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-05-25</title>
      <link>https://mike.puddingtime.org/posts/2023-05-25-daily-notes/</link>
      <pubDate>Thu, 25 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-25-daily-notes/</guid>
      <description>The Leica Q3 and some absurd back-of-napkin X100v comparisons, Denote silos.</description>
      <content:encoded><![CDATA[<h2 id="leica-q3-arrives">Leica Q3 arrives</h2>
<p><a href="https://www.dpreview.com/reviews/leica-q3-initial-review">DPReview&rsquo;s initial review of the Leica Q3</a> says:</p>
<ul>
<li>Tilt screen</li>
<li>Actual ports (USB-C, micro-HDMI)</li>
<li>Bigger sensor</li>
<li>Some rearranged buttons</li>
<li>Option for wireless charging</li>
<li>Hybrid AF</li>
<li>$5995</li>
</ul>
<p>They stuck with the previous 28mm lens and are standing by digital crop if you want to get to tighter focal lengths. I&rsquo;d still prefer a native 35mm, but you&rsquo;d lose a little &ldquo;take anywhere&rdquo; versatility.</p>
<p>Anyhow:</p>
<p>The tilt screen is very welcome, and will make the lens&rsquo;s macro mode more useful/practical.</p>
<p>The rearranged buttons caught my eye, because the Q2&rsquo;s arrangement felt pretty unergonomic, and it was easy to accidentally press them with your face when shooting in portrait orientation. DPReview says it helps:</p>
<blockquote>
<p>In addition to the new tilting touch panel, the buttons for &lsquo;Menu&rsquo; and &lsquo;Play&rsquo; and a custom function button have been moved, now appearing on the right to join the four-way controller. Having used both cameras, within a few hours of shooting the new one I found the layout to be a marked improvement that let me reach all the buttons with just my right thumb while the left hand stayed on the lens ready for the next shot. It&rsquo;s a much faster and less cumbersome arrangement that let me get in and out of menus quicker.</p>
</blockquote>
<p>Having a USB-C port is welcome. The wireless charging part sounds like a nice-to-have that makes it a little nicer to just keep near the door.</p>
<p>All in all, sounds like a nice step forward for the Q series, and with the tilt screen it sort of does become the $5995 Fujifilm X100V you always wished would happen, with its 35mm digital crop still outresolving the X100V by a few megapixels.</p>
<p>Speaking of the X100V, <a href="/posts/2020-12-03-on-the-leica/">I did compare it with the Q2</a> a few years ago:</p>
<blockquote>
<p>I don’t think the Q2 is four times the camera an X100V is, and I can’t think of anyone I’d be in the position of recommending a camera to for whom I’d recommend it as the better choice: Dollar for dollar, the X100V is a much better camera for almost everybody interested in a premium compact camera. At the same time, now that I own the Q2 and have not returned it or sold it in a fit of guilt, I wouldn’t easily part with it: I love shooting with it, love what I get out of it, and expect to keep it for a long time. The only reason it is not my only camera comes down to its fixed, very wide lens, which makes portraits and some outdoor photography a relative challenge.</p>
</blockquote>
<p>One thing that changed a lot for me since writing that up was the arrival of IBIS in the Fujifilm ILC lineup. It wasn&rsquo;t something I weighted as heavily then, but definitely started weighting more heavily as I learned how much it expanded my horizons. With the changes showing up in the Q3, I&rsquo;ll just say that the gap between the X100 series and the Q series has narrowed. There&rsquo;s still 4,200 actual dollars of daylight between the two to account for, but the Q3 is a more flexible camera than its predecessor.</p>
<p>So:</p>
<ul>
<li>A bit shy of 2x the resolution, uncropped sensor</li>
<li>Faster, more versatile lens</li>
<li>Image stabilization</li>
</ul>
<p>I&rsquo;m not sure how to go about doing a parts list that would account for the differences and leave me with some objective calculation of the brand tax you&rsquo;re paying, but it&rsquo;s easy to imagine an X100 Pro series because we have that in the form of an X-Pro3 with the 23mm/f2 Fujicron, and MSRP on that rig is around $2,300. So, following this reasoning, we&rsquo;ve got about $3,300 to account for. You&rsquo;re still a stop shy on the lens and don&rsquo;t have a macro mode, you&rsquo;re still trading away depth of field and resolution thanks to the sensor difference, you still don&rsquo;t have image stabilization.</p>
<p>Okay &hellip; so maybe we stick the newer Fujiflm XF23mm/f1.4WR on our theoretical X100 Pro. That&rsquo;s $500 over the 23/f2. We&rsquo;re down to $2,800 difference. We&rsquo;re still contending with the sensor difference and IBIS. Tough to call.</p>
<p>On IBIS, the Fujifilm X-T4  was an incremental change over the X-T3, and it came in at $200 more MSRP, with IBIS being one of the larger differentiators. The X-T5 introduced a much larger (but still APS-C) sensor, but kept the MSRP. So &hellip; we&rsquo;re down to $2,600 difference, and still have to account for the sensor, which sort of throws the math on the lens, too. I&rsquo;m not sure how to square that. Call it $500.</p>
<p>So, we&rsquo;ve found about $1,300 in component differences (IBIS, lens, sensor)? Leaving us with around $3000 to account for.</p>
<p>I am assuming the red dot involves pigments mixed from the blood of unicorns.</p>
<p>I kid.</p>
<h2 id="silos-and-denote">Silos and Denote</h2>
<p>Last night I was finishing up some note cleanup in Denote and realized that a lot of the stuff I&rsquo;d atomized from my job search was sort of interesting and useful, but not in a day-to-day way. And that I wanted to have some way to segregate, eventually, &ldquo;work&rdquo; from &ldquo;personal.&rdquo;</p>
<p>Denote has a siloing feature that lets you keep separate directories of Denote notes that can&rsquo;t see each other. If you operate in one of those directories, all your Denote activities (creating a new note, etc.) treat that directory as home. Outside the context of any particular directory, your default Denote directory is home. There are a few other features related to suggested keywords in those silos, but for now it&rsquo;s enough to be able to make broad distinctions.</p>
<p>There&rsquo;s also a useful function for <a href="https://protesilaos.com/emacs/denote#h:0f72e6ea-97f0-42e1-8fd4-0684af0422e0">pre-selecting a silo then running a Denote command targeted at it</a>, so you can be out and about elsewhere in the filesystem and dispatch information to different silos as needed.</p>
<p>For now I&rsquo;m siloing by default/personal and &ldquo;career,&rdquo; which is what I am calling all the interview notes, work-oriented biographical stuff and generic management writing I&rsquo;ve had to do. I&rsquo;ll probably put my job search log, interview notes, and other stuff that&rsquo;s currently all in a monolith into that directory as well, for long-term storage. And eventually there will be a &ldquo;work&rdquo; silo for day-to-day work stuff.</p>
<p>I vacillated about the segregation of big-picture career-related writing from day-to-day work writing, but realized most of that career stuff is a prompt. Interesting to read through, and good grist for first-30-day planning and thinking, but not pertinent to the day-to-day. If I end up feeling like some part of it is, I&rsquo;ll just pull it into a metanote as a link.</p>
<p>I guess the other Denote thing of, er, note, was that Prot&rsquo;s whole &ldquo;this is also a good way to just learn Emacs&rdquo; direction with Denote got a workout tonight. I watched his demo video, where he marked a selection of files by regexp in dired, then made the unmarked ones disappear from view in the directory. It took three or four scrub-throughs to catch which commands he was using to make that happen, because he was just doing it the way you do when something is deep in your muscle memory.  But eventually I caught it all &ndash; <code>%m</code> to mark by regexp, <code>t</code> to invert the selection, then <code>k</code> to &ldquo;kill&rdquo; the lines (but not <em>kill</em> kill them, just hide them). It sounds like a lot, but most of my Doom menus are two or three keystrokes deep. Once I had it, it was a lot easier to narrow and triage my collection and get everything dispatched into a silo.</p>
<h3 id="update-on-that-dot-dot-dot">Update on that &hellip;</h3>
<p>One thing I didn&rsquo;t like so much about that &ldquo;just use the native commands&rdquo; approach was that in Doom, you&rsquo;ve got to switch in and out of evil mode to use all of dired&rsquo;s keystrokes. I ended up grabbing <a href="https://melpa.org/#/dired-narrow">dired-narrow</a>, which dynamically narrows a dired buffer, and then recorded a quick macro to restore the buffer view (using the native dired command, which would need a shift out of evil mode):</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/dired-unnarrow</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">evil-emacs-state</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">execute-kbd-macro</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">&#34;g C-z&#34;</span><span class="p">)))</span></span></span></code></pre></div>
<p>Then I added <code>dired-narrow</code> and my new macro to my Denote menu structure:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">map!</span> <span class="nb">:leader</span>
</span></span><span class="line"><span class="cl">      <span class="nb">:nv</span> <span class="s">&#34;n d&#34;</span> <span class="no">nil</span> <span class="c1">;; Doom has deft here, so we have to nil it out first</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">:prefix-map</span> <span class="p">(</span><span class="s">&#34;n&#34;</span> <span class="o">.</span> <span class="s">&#34;notes&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">:prefix</span> <span class="p">(</span><span class="s">&#34;d&#34;</span> <span class="o">.</span> <span class="s">&#34;Denote&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;ripgrep&#34;</span> <span class="s">&#34;/&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/denote-rg-search</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;Backlinks&#34;</span> <span class="s">&#34;b&#34;</span> <span class="nf">#&#39;</span><span class="nv">denote-link-backlinks</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;Move subtree&#34;</span> <span class="s">&#34;c&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/denote-org-copy-subtree</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;add keywords&#34;</span> <span class="s">&#34;k&#34;</span> <span class="nf">#&#39;</span><span class="nv">denote-keywords-add</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;remove keywords&#34;</span> <span class="s">&#34;K&#34;</span> <span class="nf">#&#39;</span><span class="nv">denote-keywords-remove</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;Move subtree&#34;</span> <span class="s">&#34;m&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/denote-org-move-subtree</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;New note&#34;</span> <span class="s">&#34;d&#34;</span> <span class="nf">#&#39;</span><span class="nv">denote</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;Rename with frontmatter&#34;</span> <span class="s">&#34;r&#34;</span> <span class="nf">#&#39;</span><span class="nv">denote-rename-file-using-front-matter</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;Pick silo, then command&#34;</span> <span class="s">&#34;s&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/denote-pick-silo-then-command</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;Narrow dired view&#34;</span> <span class="s">&#34;n&#34;</span> <span class="nf">#&#39;</span><span class="nv">dired-narrow</span>
</span></span><span class="line"><span class="cl">         <span class="nb">:desc</span> <span class="s">&#34;Unnarrow dired view&#34;</span> <span class="s">&#34;u&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/dired-unnarrow</span>
</span></span><span class="line"><span class="cl">         <span class="p">)))</span></span></span></code></pre></div>
<p><em>Technically</em> I guess those narrow/unnarrow commands belong in some other hierarchy, but I will tend to use them when I&rsquo;m doing stuff with Denote, and they can live in more than one context if I wish.</p>
<p>I have the sense there are other things I could be using, like Embark, but I am still struggling with the whole Vertico ecosystem, so one thing at a time.</p>
<h3 id="update-to-the-update">Update to the update</h3>
<p>With Vertico/Embark on Doom, I don&rsquo;t need dired narrow to get what I was after:</p>
<ul>
<li><code>SPC .</code> to start finding files</li>
<li>Once things are narrowed, <code>C-c ;</code> moves all the candidates into their own buffer</li>
<li>Do stuff</li>
<li><code>q</code> to quit the transient buffer</li>
</ul>
<p><video width="100%" controls><source src="/img/embark_collect.mp4" type="video/mp4">
Your browser does not support the video tag.</video></p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-05-24</title>
      <link>https://mike.puddingtime.org/posts/2023-05-24-daily-notes/</link>
      <pubDate>Wed, 24 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-24-daily-notes/</guid>
      <description>Cleaning up results in literate config files. Portland and the JOHS. Some Doom discontent.</description>
      <content:encoded><![CDATA[<h2 id="cleaning-up-my-literate-config-file">Cleaning up my literate config file</h2>
<p>I like keeping my Doom Emacs config file in config.org. I didn&rsquo;t like the <code>#RESULTS</code> drawers cluttering up the file, especially for longer functions with copious output.</p>
<p>The way to selectively disable that for a given src block is to append <code>:results output silent</code> to the block opener, e.g.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="err">#</span><span class="nv">+begin_src</span> <span class="nv">emacs-lisp</span> <span class="nb">:results</span> <span class="nv">output</span> <span class="nv">silent</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vertico-reverse-mode</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">vertico-count</span> <span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">vertico-resize</span> <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span><span class="nv">+end_src</span></span></span></code></pre></div>
<p>The way to do it for an entire file is to put <code>#+property: header-args :results silent</code> at the top.</p>
<p>You can still evaluate a given src block by tapping return on either the first or <code>#+end_src</code> lines, but the output goes to the minibuffer instead of a <code>#RESULTS</code> drawer. If you need to really read through the output, there&rsquo;s always the <code>*Messages*</code> buffer, or tacking <code>:results output replace</code> onto the src block opener to get your <code>#RESULTS</code> drawer back.</p>
<h2 id="johs-and-the-city">JOHS and the city</h2>
<p>The city and the county are <a href="https://www.wweek.com/news/city/2023/05/23/city-council-will-vote-to-extend-joint-office-agreement-with-multnomah-county-to-allow-for-further-negotiations-again/">again considering extending the JOHS for just a year</a>. I still don&rsquo;t understand the division of labor there. It&rsquo;s the worst of both worlds: The city drops a pallet of money on the county&rsquo;s dock, but remains on the hook for the tactical response. The county takes the money, claims the high ground of long-term, strategic perspective, then has an effective veto over elements of the city&rsquo;s tactical response even as it fails to allocate half its budget, and actual providers on the ground <a href="https://www.wweek.com/news/2023/04/05/joint-office-of-homeless-services-contracting-woes-create-instability-for-survivors-of-domestic-violence/">struggle to retain help with a living wage, or even get decent contracts through the JOHS</a>.</p>
<p>If the JOHS were a <em>joint</em> office, performing some actual coordinative role, maybe it&rsquo;d be different. But it&rsquo;s a county office: Its reporting structure roles up to the chair, it uses county administrative structures and processes, and it is beholden to county leadership. It&rsquo;s also profoundly dysfunctional, leaving millions and millions of dollars on the table, and failing in its most basic data-gathering, reporting, and contracting commitments.</p>
<p>But we&rsquo;re in one of those situations where the dysfunction seems to be politically expedient. The city and county are at fundamental odds on homelessness policy, and the people in this policy area at the county level view themselves as a sort of superego governing the city&rsquo;s id. Once one partner in a relationship predicates their participation on the notion that they&rsquo;re mostly there to keep their partner from doing something they don&rsquo;t like, the relationship is sunk. Burn it down and start over with a new charter.</p>
<h2 id="batteries-included-situations-and-their-discontents">Batteries-included situations and their discontents</h2>
<p>I think I&rsquo;ve hit the first thing using Doom Emacs that is not sitting well with me. Well, let&rsquo;s scope out a little: I think I&rsquo;ve hit the first time something <em>that is inevitable</em> with &ldquo;batteries-included&rdquo; situations has annoyed me as I&rsquo;ve used Doom in particular.</p>
<p>Emacs has a bunch of &ldquo;completion frameworks,&rdquo; which control what happens when you go to issue a command, open a file, look up a definition or whatever. The last time I used Emacs a lot <a href="https://github.com/emacs-helm/helm">Helm</a> was sort of the big deal, but since then plenty of others have come along. If you look in the part of Doom&rsquo;s config that offers pre-packaged completion frameworks, you get several choices:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="nb">:completion</span>
</span></span><span class="line"><span class="cl"><span class="nv">company</span>           <span class="c1">; the ultimate code completion backend</span>
</span></span><span class="line"><span class="cl"><span class="c1">;; helm              ; the *other* search engine for love and life</span>
</span></span><span class="line"><span class="cl"><span class="c1">;; ido               ; the other *other* search engine...</span>
</span></span><span class="line"><span class="cl"><span class="c1">;; ivy               ; a search engine for love and life</span>
</span></span><span class="line"><span class="cl"><span class="nv">vertico</span>           <span class="c1">; the search engine of the future</span></span></span></code></pre></div>
<p>Which, so far so good. As near as I can parse the conversation, newer completion frameworks like <a href="https://github.com/minad/vertico/blob/main/README.org">Vertico</a> are built around the idea that it&rsquo;s better to build off of core Emacs functionality and think in a more modular manner. So then you look up what happens when you enable Vertico, that involves a series of complementary packages:</p>
<ul>
<li>consult</li>
<li>consult-flycheck</li>
<li>embark</li>
<li>embark-consult</li>
<li>marginalia</li>
<li>orderless</li>
<li>vertico</li>
<li>vertico-posframe (maybe)</li>
<li>wgrep</li>
</ul>
<p>Because I do not want to make this about the problem I&rsquo;m dealing with at this particular moment, I just want to say <em>holy cow what a stew of possible starting points for solving a problem</em>.</p>
<p>I&rsquo;ve spent this morning trying to track down a UI annoyance and the mere act of changing word order in my searches has implicated four of the packages on that list.  Because the Emacs community is a relatively small one &mdash; at least by the time you get done subdividing it into &ldquo;Emacs users who also use Doom and who are using Vertico within Doom&rdquo; &mdash; you exhaust possible resolutions quickly, and begin to realize you&rsquo;ve seen the same configuration go by several different times as people in this relatively small subset share it around.</p>
<p>Anyhow, I&rsquo;m not here to bag on Doom or complain about copypasta configs. I&rsquo;m just noting that at a certain point in the world of batteries-included frameworks you are sorting through a metric ton of batteries, all tucked away behind a very smooth housing requiring a variety of Torx and jeweler&rsquo;s screwdrivers to get open. One of those paradoxes, I guess, where your lower-skilled people (me) get a ton of leverage from all the layers of abstraction and affordance, but then wander into situations where it would take a very highly skilled person (not me) to sort out where the magic is going wrong (or just not going the way you wished, since &ldquo;wrong&rdquo; is sort of fraught, here.)</p>
<p>And I fall on the maximizer end of <a href="https://www.psychologistworld.com/cognitive/maximizers-satisficers-decision-making">the satisficer/maximizer spectrum</a>, so it&rsquo;s hard to say of some UI glitch &ldquo;well, that&rsquo;s an annoyance I&rsquo;ll be living with,&rdquo; even if there are ample workarounds or even simple &ldquo;then quit moving your arm that way&rdquo; solutions.</p>
<p>Okay. I think I&rsquo;ve gotten that off my chest. Time to go to the Doom Discourse, <a href="https://discourse.doomemacs.org/t/trying-to-get-a-handle-on-fixing-file-preview-during-find-file/3896">mention the issue</a>, and see what I get.</p>
<h2 id="monodraw">Monodraw</h2>
<p>Even if you don&rsquo;t follow that link, I had an excuse to use <a href="https://monodraw.helftone.com">Monodraw</a> to illustrate my problem. Monodraw makes it super easy to make ASCII diagrams then copies them in a pre block to your clipboard.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">┌──────────────────────────┐  ┌──────────────────────────┐
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">│     Original window      │  │                          │
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">│                          │  │      Preview window      │
</span></span><span class="line"><span class="cl">├──────────────────────────┤  │                          │
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">│      Preview window      │  │                          │
</span></span><span class="line"><span class="cl">│                          │  ├──────────────────────────┤
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">├──────────────────────────┤  │                          │
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">│                          │  │      Vertico window      │
</span></span><span class="line"><span class="cl">│      Vertico window      │  │                          │
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">│                          │  │                          │
</span></span><span class="line"><span class="cl">└──────────────────────────┘  └──────────────────────────┘</span></span></code></pre></div>
<p>There is a world somewhere that I could use Monodraw in a business context and not have it be a complete distraction, but for anything other than &ldquo;a box with words in it,&rdquo; e.g. a more complex organizational diagram or flow chart, it is utterly distracting, either by people who want there to be boxes with colors or people who want to know how on Earth you made such a complex diagram with pipes and dashes.</p>
]]></content:encoded>
    </item>
    <item>
      <title>More plaintext primitivism with Denote</title>
      <link>https://mike.puddingtime.org/posts/2023-05-22-more-plaintext-primitivism-with-denote/</link>
      <pubDate>Mon, 22 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-22-more-plaintext-primitivism-with-denote/</guid>
      <description>Denote wants you to stick with the native tools you already have for a stripped-down PKM system.</description>
      <content:encoded><![CDATA[<p><a href="https://github.com/protesilaos/denote">Denote</a> is a note-taking package for Emacs I find sort of interesting because its creator is trying very hard to make something that is structured and can provide some of the affordances we&rsquo;re all coming to expect from <a href="https://www.reddit.com/r/PKMS/comments/nfef59/list_of_personal_knowledge_management_systems/">PKMs</a> without requiring a bunch of extra overhead: At the content level he wants you to use existing file types and markup languages (org, Markdown), and at the management/search level he wants you to use existing Emacs tools, like <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html">dired</a> in combination with a file naming scheme that incorporates title, date, and tags into the filename.</p>
<p>It doesn&rsquo;t toss you into the plaintext-n-filesystem primitivist deep end on your own. It comes with a dired mode that fontifies based on its own filenaming convention, so what seems like it could be super ungainly is actually pretty easy to scan in practice:</p>
<figure><img src="/img/denote_dired.jpg"
    alt="Screenshot of files colorized by their datestamp, title, and tags in Emacs dired"><figcaption>
      <h4>dired in denote-dired-mode</h4>
    </figcaption>
</figure>

<p>&hellip; and it has a collection of functions that let you add/remove keywords, rename files using its naming convention, etc.  There are even a few next-level sorts of things, such as the ability to create content &ldquo;silos,&rdquo; so you can set up a note directory for personal stuff, work stuff, etc. without clashing label namespaces and other things that come up when you have to manage a few discrete areas with the same tool.</p>
<p>As &ldquo;what would my exit plan be&rdquo; tools go, this one is pretty good, given It&rsquo;s All Just Text with no particularly difficult conventions.</p>
<p>It was trivial to move a bunch of notes into a directory, use Denote&rsquo;s built-in tools to convert them to the proper naming convention, and start using it. It took under a minute to convert a function I cribbed from org-roam&rsquo;s forums to use ripgrep to provide fulltext search:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/denote-rg-search</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Search denote directory using consult-ripgrep. With live-preview.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">consult-ripgrep-command</span> <span class="s">&#34;rg --null --smart-case --type org --line-buffered --color=always --max-columns=500 --no-heading --line-number . -e ARG OPTS&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">consult-ripgrep</span> <span class="nv">denote-directory</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">map!</span> <span class="nb">:leader</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">:prefix-map</span> <span class="p">(</span><span class="s">&#34;n&#34;</span> <span class="o">.</span> <span class="s">&#34;notes&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">:prefix</span> <span class="p">(</span><span class="s">&#34;D&#34;</span> <span class="o">.</span> <span class="s">&#34;Denote&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">       <span class="nb">:desc</span> <span class="s">&#34;ripgrep&#34;</span> <span class="s">&#34;/&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/denote-rg-search</span><span class="p">)))</span></span></span></code></pre></div>
<p>The obvious comparisons in the Emacs ecosystem are <a href="https://github.com/jrblevin/deft">Deft</a> and <a href="https://www.orgroam.com">org-roam</a>. I haven&rsquo;t given Deft much time. I&rsquo;ve used org-roam more. I like Denote&rsquo;s lack of a dependency on a database. I don&rsquo;t know how Denote will compare in terms of scale if it&rsquo;s all filesystem-and-native-tools.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-05-12</title>
      <link>https://mike.puddingtime.org/posts/2023-05-12-daily-notes/</link>
      <pubDate>Fri, 12 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-12-daily-notes/</guid>
      <description>Automation vs. Augmentation, ChatGPT and ideology, day one of the Things/org experiment.</description>
      <content:encoded><![CDATA[<h2 id="automation-vs-dot-augementation">Automation vs. Augementation</h2>
<p><a href="http://www.zephoria.org/thoughts/archives/2023/04/21/deskilling-on-the-job.html">This is a thoughtful piece by danah boyd</a> that gets to some things I&rsquo;ve been thinking about re: AI.</p>
<blockquote>
<p>Whether you are in Camp Augmentation or Camp Automation, it’s really important to look holistically about how skills and jobs fit into society. Even if you dream of automating away all of the jobs, consider what happens on the other side. How do you ensure a future with highly skilled people? This is a lesson that too many war-torn countries have learned the hard way. I’m not worried about the coming dawn of the Terminator, but I am worried that we will use AI to wage war on our own labor forces in pursuit of efficiency. As with all wars, it’s the unintended consequences that will matter most. Who is thinking about the ripple effects of those choices?</p>
</blockquote>
<p>There is a lot of commentary <a href="https://www.reddit.com/r/MetaFilterMeta/comments/13chd82/how_many_people_are_feeling_or_fearing_the_impact/">in this r/metafiltermeta thread about AI</a>, which was framed from a place of anxiety:</p>
<blockquote>
<p>I&rsquo;m reading about AI&rsquo;s impact on coding, graphic design, video, motion graphics, architecture and law. I hear proponents say that they think AI will change jobs, and that smart workers will learn how to use it as an assistant, but when I review Silicon Valley&rsquo;s contributions to labor in the U.S., mostly I see entire fields gutted, and folks moved over to poorly paying gig economy work.</p>
</blockquote>
<p>The more thoughtful responses pointed, I think correctly, to the eventual Gartner Hype Cycle state of equilibrium you get to once you get unrealistic expectations out of the way, trudge through the salty marshes of &ldquo;told you it was all bullshit,&rdquo; and get to &ldquo;how is this thing going to be used day-to-day?&rdquo;</p>
<p>The people at the Peak of Inflated Expectations do what they always do: Try to solve their problems in a manner ill suited to the tool in front of them, or in a manner that is not reflective of the limitations of the model. The chorus waiting for them down at the bottom of the Trough of Disillusionment has no single motivation: Some of it is wise realism, forward thinking, and experience; some of it is whistling past the graveyard or just missing that &ldquo;productivity gains,&rdquo; like many things in technology and business, are not a series of home runs and grand slams, but rather singles and the occasional double. Reframed more bleakly, grinding down labor&rsquo;s ability to resist induced precarity is a game of inches.</p>
<p>Which is the long way around to saying that if the people who are pointing to offshoring and content-farming mania of the naughts and tens are correct in saying they&rsquo;re the closest analogies we have, and if danah boyd is right that &ldquo;we tend to optimize towards more intense work schedules whenever we introduce new technologies while downgrading the status of the highly skilled person,&rdquo; then it&rsquo;s going to mean fewer people working in AI-effected systems that are biased toward always looking for one more headcount they can get away with removing. It&rsquo;ll look different from the &ldquo;prompt engineering&rdquo; everyone imagines today. It&rsquo;ll be software companies figuring out how to integrate existing &ldquo;dumb&rdquo; systems with generative AI systems acting as synthesizers, with a few humans acting as QA on top of that process, working from a weakened position.</p>
<h2 id="chatgpt-is-an-ideology-machine">&ldquo;ChatGPT Is an Ideology Machine&rdquo;</h2>
<p><a href="https://jacobin.com/2023/04/chatgpt-ai-language-models-ideology-media-production/">Jacobin last month</a>:</p>
<blockquote>
<p>A wide variety of Marxists have also seen ideology as a form of kitsch. First articulated by the Marxist art critic Clement Greenberg in 1937, the notion of kitsch is “pre-digested form.” Among all the things we might say or think, some pathways are better traveled than others. The form of those paths is given; we don’t need to forge them in the first place. The constant release of sequels now has this quality of kitsch — we know exactly where we are when we start watching a Marvel movie. For Greenberg, the avant-garde was the formal adventurer, creating new meaning by making new paths. Hegemony and kitsch are combined in the output of GPT systems’ semantic packages, which might miss aspects of “the world” but faithfully capture ideology.</p>
</blockquote>
<h2 id="my-things-link-to-org-stuff">My Things link to org stuff</h2>
<p>Today I started using the org-protocol stuff <a href="/posts/2023-05-11-daily-notes/#connecting-things-todos-to-org-headings">I talked about yesterday</a> with a set of regular todos I added to Things. For my daily writing and journaling todos, I captured links to the headings from the org documents and pasted them into the notes field of the Things todo before marking them done. Clicking on those links brings up a new Emacs frame that jumps straight to the heading in the correct file.</p>
<p>That pretty much recreates the workflow I had with Bear and Things for other kinds of task/notes combinations, and it shows me how to use org-protocol and org-capture to do similar kinds of workflows where Emacs participates in the rest of my tools ecosystem.</p>
<p>So, promising trial experience. I&rsquo;m a little becalmed on heavy-duty task/work tracking right now, so I&rsquo;m satisfied to just note that the idea works and that I&rsquo;ll keep using it to find out where the edge cases are: Something always comes up.</p>
<p>The idea that keeps popping up in my head is that a lot of my past &ldquo;emacsimalism&rdquo; &ndash; a recurring phase I&rsquo;ve experienced over several decades &ndash; was due to the fact that Emacs was pretty much a technology island. The Mac builds weren&rsquo;t always very good, and the ways in which it could speak to the system around it were sort of flaky. But things like org-protocol and a little bit of utility glue with osascript do a lot to make it easier to find your way into and out of Emacs. You don&rsquo;t <em>have</em> to make it your everything because it can work well <em>alongside</em> other things that might suit your individual style better. The idea I&rsquo;m sort of nibbling around right now is that I don&rsquo;t like org-mode for <em>organization of work and tasks</em> so much as I like it for <em>organization of text and ideas</em>. It&rsquo;s less &ldquo;a smarter Things, OmniFocus, or Reminders,&rdquo; and more &ldquo;what I wish Ulysses had been.&rdquo;</p>
<p>Maybe that&rsquo;s why assorted org syntax implementations in more modern text editors (e.g. BBEdit, Sublime, Atom, VSCode) are always disappointing: They&rsquo;re usually just syntax highlighting and no smarts. Might as well just be doing Markdown at that point, because the <em>smarts</em> of org-mode pretty much live in Emacs and lisp. Without that, you&rsquo;re just quibbling over whether a backslash or an asterisk is better <code>emph</code> notation.</p>
<p>Anyhow, we&rsquo;ll leave it at that until there&rsquo;s something new to say. I think I&rsquo;ve visited this topic plenty.</p>
<h2 id="twitter">Twitter</h2>
<p>I disabled my Twitter account late last month, so I think I have a bit under two weeks for it to fully deactivate. I think I will thread the needle between making an <em>announcement</em> and merely noting that I have embarked on the process of closing my account by making it the last heading of today&rsquo;s post, unmentioned in the summary.</p>
<p>There&rsquo;s a needle to thread because my strong preference would be for people to give up on Twitter. So if you&rsquo;re someone with whom I might have some influence, I&rsquo;m happy for you to read this and do the primate thing &ndash; &ldquo;Hm, Mike is a thoughtful, ethical person whose ideas I tend to take under advisement, and he sees Twitter as, on balance, negative and harmful, so I will take that idea under advisement, as well.&rdquo;</p>
<p>That&rsquo;s all.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-05-11</title>
      <link>https://mike.puddingtime.org/posts/2023-05-11-daily-notes/</link>
      <pubDate>Thu, 11 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-11-daily-notes/</guid>
      <description>BBEdit turns 30, Emacs update, Things, OmniFocus, etc.</description>
      <content:encoded><![CDATA[<h2 id="bbedit-turns-30">BBEdit turns 30</h2>
<p>Just after <a href="https://mike.puddingtime.org/posts/2023-05-10-daily-notes/">I was remembering it yesterday</a>, there&rsquo;s a <a href="https://news.ycombinator.com/item?id=35904320">nice appreciation of BBEdit going on over at HackerNews.</a> One comment captured my opinion pretty well:</p>
<blockquote>
<p>I read about BBEdit on HN a few months ago and realized it has one use-case where it excels: text transformation and regex search/replace across files. When it comes to this, no other editor I know can hold water: neither Sublime, nor VS Code, nor Vim. And forget about Emacs, as regexes need to be awkwardly double or triple backslashed.</p>
<p>Text transformations can be done via regex, predefined functions, or any scripting language, where the scripts will be listed in the menu.
Regex search/replace has a history of used patterns, so you can reuse them.</p>
<p>All in all, it is a very lightweight editor with excellent text transformation features that no other editor can offer.</p>
</blockquote>
<p>It is definitely my go-to for that kind of thing. I used to feel sort of guilty that I wasn&rsquo;t trying to get heavy-duty text transforms done from the shell, then I wised up: BBEdit makes it fast, reversible, repeatable, and visually discoverable. And it will plow through large files like nothing else. I keep a license around just for scenarios like &ldquo;need to do something to 2,000 Markdown files&rdquo; or what have you.</p>
<p>Also, my interactions with BareBones for support have been so amazingly helpful and cordial.</p>
<p>Thirty years old and still an evolving, high quality product that I reach for when &ldquo;I just need to get this task done.&rdquo;</p>
<h2 id="emacs-update">Emacs update</h2>
<p>The last few days I&rsquo;ve started getting reminders of a fundamental truth of Emacs life, which is that you will eventually push it a little too far with the new stuff and it starts getting punchy and stops feeling trustworthy.</p>
<p>I got a little excited about some tweaks, and I&rsquo;m glad I was applying them one at a time and seeing what happened, because when one of them hard-locked Emacs it was simple to just go back into my <code>config.org</code> file,  <code>:tangle no</code> the offending config, and comment out the problematic package in <code>packages.el</code>.</p>
<p>This is a part of Emacs life, though, that Doom Emacs has made better: It makes configuration simple. I love being able to organize config blocks under headings I can manage with org-mode structure editing, and I appreciate the simplicity of package management. There are a few more steps to get some things done, but they&rsquo;re simpler steps than how I used to manage Emacs.</p>
<p>When I hard-locked it yesterday it was a small bummer but it was also easy to undo the change and get back up and running. I&rsquo;ve felt the difference in how I feel when I sit down to use Emacs over the past while: It has gone from &ldquo;well, I wonder what sort of fatal self-own I&rsquo;m going to suffer from today&rdquo; to &ldquo;this is a stable tool I like using and don&rsquo;t worry about much.&rdquo;</p>
<p>It&rsquo;s such an open ecosystem, and extending it involves so much complexity, that the bits like &ldquo;oh, added that package and it crashed trying to open a file&rdquo; are just going to be part of it. But you deal with that by following a &ldquo;no new toys with an unsaved buffer of something that matters to you&rdquo; rule and making incremental changes.</p>
<h2 id="organizing-work-todo-apps">Organizing work &ndash; todo apps</h2>
<p>I spent a little time watching reviews and comparisons of Things and OmniFocus 3 today. Last night I started putting together a 90-day plan in org-mode and was enjoying the &ldquo;actions/prose&rdquo; hybrid of org-mode, but also thinking &ldquo;this is getting complex and these lists are pretty sequential and interdependent &hellip; I wonder if I want to put this weight on org-mode.&rdquo;</p>
<p>So I watched the videos, downloaded OmniFocus 3 again (I&rsquo;ve had a license for a few years), and took a stab at entering a few small chunks of work to see how it felt.</p>
<p>Not great.</p>
<p>I don&rsquo;t spend a lot of time worrying too much about how apps look, but OF is just sort of unappealing in that regard.</p>
<p>When I look at Things, there&rsquo;s a lot of visual appeal. You can&rsquo;t do much to control it, but you don&rsquo;t need to. The color scheme and roominess of the interface really work for me. When I look at an org-mode buffer, it is a very different aesthetic. I recently stopped doing mixed-mode and just live in good old Fira Code in a single size. But I&rsquo;ve got good light and dark themes and once I figured out how to control line-spacing it opened things up a little and made it feel less like a &hellip; like smelly ASCII cave. Looking over at MailMate, I can also exercise a little bit of control, so even though it is a visually simple app, the bit of decoration it does have is clean and I can pick my typefaces.</p>
<p>OmniFocus has some customization options, but I&rsquo;ve always struggled with its font sizes, sort of resenting the iOS-style &ldquo;small/medium/large/larger/very larger&rdquo; restriction on my choices, especially because there&rsquo;s a wide range of text size going on within the UI. It is also cramped. The UI is packed tight and even lists of project headings feel claustrophobic and closed in.</p>
<p>Things 3, one might respond, has next to no customization, either. Fewer choices than OF3, even. But it&rsquo;s just better done out of the box. It reminds me of something the UX designers at Puppet would have come up with in that it feels light and open.</p>
<p>That&rsquo;s a lot of time on looks, but if you have to look at the thing all day, they start mattering.</p>
<p>I think mostly I just managed to remind myself that I really loved the <em>idea</em> of OmniFocus years and years ago, but in practice it never stuck for long.</p>
<p>Things is harder to discard. It&rsquo;s just pleasant to work with, it&rsquo;s logically organized, the mobile apps are very good, and I really like the way you can organize a project with headings that are loose enough to have whatever meaning you care to give them: Milestones, themes, phases, or whatever. There&rsquo;s light Markdown sprinkled into the text areas, too. If you were not hung up on ultimate portability, the typography is clean and legible enough that you could manage prose notes in Things.</p>
<p>Back in the day, when I was using <a href="https://bear.app">Bear</a> a lot for note-taking in conjunction with Things as my task manager, I would just include a link to a Bear note in the notes field in Things. So, for instance, the Things project I had set up for my team had a heading for each member of the team where followup items went, and a link to the individual team member&rsquo;s note in Bear for prose. It worked pretty well.</p>
<h3 id="connecting-things-todos-to-org-headings">Connecting Things todos to org headings</h3>
<p>I wondered if I could do that with Emacs and an org-mode heading, and yes, I can.</p>
<p><a href="https://emacs.stackexchange.com/questions/47986/jump-to-org-mode-heading-from-external-application">This StackOverflow post</a> provided two bits of code to add navigation to a given org-mode heading using <code>org-protocol</code> and to yank the link from a given heading. It points to <a href="https://github.com/xuchunyang/setup-org-protocol-on-mac">this page</a> on how to make a simple little AppleScript app that registers <code>org-protocol</code> as a valid URL handler in macOS. I bound the link-grabbing function to <code>SPC n L</code> in Doom, and gave it a try by pasting the link into a Things note &hellip; yup &hellip; worked: Dropped me into a new Emacs GUI window with the point on the org-heading.</p>
<figure><img src="/img/things_emacs.jpg"
    alt="Screenshot of a Things todo with a link to a heading in an org-mode buffer"><figcaption>
      <h4>Things with an org-protocol link pointing to an org-mode blog post heading</h4>
    </figcaption>
</figure>

<p>Will I use it?</p>
<p>I don&rsquo;t know!</p>
<p>I remember my Things/Bear workflow being a very nice harmonization of two different kinds of work that lived in single-function apps. org-mode blurs those lines all on its own. I <a href="/posts/2023-05-02-daily-notes/#my-org-contacts-file-and-things">wrote a little about this several days ago</a> in relationship to my plaintext PRM.</p>
<p>I really like how clean Things is for capturing stuff from all sorts of places on my phone and computer. I like its seamless integration with existing macOS and iOS calendars and Reminders. I can do that stuff in org-mode and Emacs, but it takes a little extra work and feels more brittle. There are mobile apps for org-mode, like beorg, but they do feel a little clunkier than Things.</p>
<p>So I guess I&rsquo;ll take that small chunk of planning I was working on in Things, expand it to more stuff,  and see how it feels when I can link in to org-mode documents as easily as I can now.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-05-10</title>
      <link>https://mike.puddingtime.org/posts/2023-05-10-daily-notes/</link>
      <pubDate>Wed, 10 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-10-daily-notes/</guid>
      <description>org-babelified API noodling with verb, org-sticky-header, Amazon&amp;rsquo;s Citadel</description>
      <content:encoded><![CDATA[<h2 id="noodling-http-with-verb-and-emacs">Noodling http with verb and Emacs</h2>
<p>My traditional &ldquo;poke around an API&rdquo; tool is usually an irb session, because I&rsquo;m probably headed for Ruby once I understand what I&rsquo;m asking for. This morning <a href="https://www.reddit.com/r/emacs/comments/13dq9ew/emacs_as_rest_api_client/">a thread on r/emacs</a> led me to <a href="https://github.com/federicotdn/verb">verb</a>, an org-mode-aware http client. At its simplest, you give it an org heading like this, from the project page:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-org" data-lang="org"><span class="line"><span class="cl">       <span class="k">* </span>Example request :verb:
</span></span><span class="line"><span class="cl">       get https:/<span class="ge">/api.ipify.org/</span>?format=json</span></span></code></pre></div>
<p>Then <code>verb-send-request-on-point</code> to get a buffer with the json response.</p>
<p>But it also works with org-babel:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="err">#</span><span class="nv">+begin_src</span> <span class="nv">verb</span> <span class="nb">:wrap</span> <span class="nv">src</span> <span class="nv">ob-verb-response</span>
</span></span><span class="line"><span class="cl"><span class="nf">get</span> <span class="nv">https://api.ipify.org/?format=json</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span><span class="nv">+end_src</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span><span class="nv">+RESULTS:</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span><span class="nv">+begin_src</span> <span class="nv">ob-verb-response</span>
</span></span><span class="line"><span class="cl"><span class="nv">HTTP/1.1</span> <span class="mi">200</span> <span class="nv">OK</span>
</span></span><span class="line"><span class="cl"><span class="nv">Content-Length:</span> <span class="mi">23</span>
</span></span><span class="line"><span class="cl"><span class="nv">Content-Type:</span> <span class="nv">application/json</span>
</span></span><span class="line"><span class="cl"><span class="nv">Date:</span> <span class="nv">Wed,</span> <span class="mi">10</span> <span class="nv">May</span> <span class="mi">2023</span> <span class="nv">17:18:25</span> <span class="nv">GMT</span>
</span></span><span class="line"><span class="cl"><span class="nv">Vary:</span> <span class="nv">Origin</span>
</span></span><span class="line"><span class="cl">   <span class="nv">{</span>
</span></span><span class="line"><span class="cl">    <span class="s">&#34;ip&#34;</span><span class="o">:</span> <span class="s">&#34;97.115.5.6&#34;</span>
</span></span><span class="line"><span class="cl">   <span class="nv">}</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span><span class="nv">+end_src</span></span></span></code></pre></div>
<p>That&rsquo;s delightful.</p>
<p>As I&rsquo;ve leaned more and more into org-babel, I&rsquo;ve been trying to figure out why it feels both like a big discovery but also something I remembered doing, and it finally occurred to me this morning: I used to use BBEdit&rsquo;s &ldquo;<a href="https://www.barebones.com/products/bbedit/benefitsintegrate.html#worksheet">shell worksheets</a>&rdquo; all the time to test and model a suite of scripts I&rsquo;d written to help with my copyediting work.</p>
<p><video width="100%" controls><source src="/img/bbedit-worksheet.mp4" type="video/mp4">
Your browser does not support the video tag.</video></p>
<p>My main use case was &ldquo;here&rsquo;s a filter I wrote, I&rsquo;ve got some problematic HTML from some writer sitting here, paste it over in the worksheet, run the filter on it, see how it goes.&rdquo; It&rsquo;s been &hellip; wow, a little while &hellip; since I was doing that. I just did a quick spotlight search on the librarified version and it looks like the last time I edited it was 2009.</p>
<h2 id="org-sticky-header-mode">org-sticky-header-mode</h2>
<p>Sometimes, deep into an org-mode file, I get sort of lost and wondering where I am. <a href="https://github.com/alphapapa/org-sticky-header">org-sticky-header</a> is for those times, providing a breadcrumb line at the top of the window:</p>
<figure><img src="/img/org-sticky-header.jpg"
    alt="An Emacs screenshot showing breadcrumbs of org headings"><figcaption>
      <h4>org-sticky-header in my ox-hugo file.</h4>
    </figcaption>
</figure>

<h2 id="more-like-cit-a-dumb-amirite">More like cit-a-dumb, amirite?</h2>
<p>Al and I saw a trailer for Amazon&rsquo;s <em><a href="https://en.wikipedia.org/wiki/Citadel_(TV_series)">Citadel</a></em> in a movie theater and being the sort of people we are it seemed like catnip. Waiting around for it to arrive, I perused the reviews and was only mildly surprised that they were savage. We watched it anyhow, and I guess I think two things:</p>
<ol>
<li>
<p>It&rsquo;s a very expensive spy show by people who produced <em>Avengers</em> movies, so yes, it is something of a pastiche. A little <em>Mission Impossible</em>, a little <em>Bourne Identity</em>, a little <em>Black Widow</em>, a little <em>Agents of SHIELD</em>, a little <em>Kingsmen</em>.  There&rsquo;s a soapy element to it. You can MST3K the living hell out of it on the first watch.</p>
<p>Do I <em>like</em> it? I mean, yeah? It is not demanding, it&rsquo;s a little silly, you could even call it <em>dumb</em> in an endearing way. It is for sure trope-y, anyhow. I don&rsquo;t end an episode feeling resentful of the time lost &ndash; good sign! &ndash; and it is honest about how it intends to get you back each week: reveals, as opposed to more puzzles.</p>
</li>
<li>
<p>TV criticism is really tedious.</p>
</li>
</ol>
<p>This is not a &ldquo;let people like dumb things, critics!&rdquo; complaint.</p>
<p>It would be really weird to me if a big, expensive Amazon spy show&rsquo;s critics/audience enjoyment ratio skewed high on the critics side. Big, expensive, popular entertainments are miraculous constructions of cross-demographic box-checking and cynical cultural manipulation designed to do about as well in Topeka as they do in Atlanta. Television critics, on the other hand, come out of a narrower cultural milieu, and exist in uneasy tension with their reading audiences.</p>
<p>I&rsquo;d <em>hate</em> having to go review an <em>Avengers</em> movie, or a season of the new <em>Star Trek</em> show, or a new <em>Star Wars</em> thing, because the fandom for established properties is <em>right there</em>, waiting for you to not like their thing they like. It&rsquo;s sort of complicated by the occasional swerve: Gender-flip a property, play with elvish phenotypes, etc. and that makes it fraught in a different way and the calculation changes.</p>
<p>Something greenfield, though &ndash; a non-property &ndash; and I&rsquo;d guess critical instincts are on clearer display. Maybe the stars bring along a fandom, but it&rsquo;s just not as dangerous.</p>
<p>The reviews for <em>Citadel</em> felt a little like that. Like, sort of harsh over stuff that gets a pass when it&rsquo;s attached to a big franchise. And a lot of focus on inside baseball: Changing creative teams, the production cost, etc.</p>
<p>So, subhead aside, you know, <em>Citadel</em> seems better than the critical consensus. I&rsquo;d say its current &ldquo;middling C&rdquo; audience score is more fair than its &ldquo;high F&rdquo; critical average. If I had my thoughts completely in order around genre grade-curving, I might even go higher than &ldquo;middling C.&rdquo; Its Major Genre is &ldquo;spy thriller,&rdquo; and its Supporting Flavors are &ldquo;breezy&rdquo; &ldquo;romantic,&rdquo; &ldquo;light,&rdquo; and &ldquo;cross-demographically appealing.&rdquo; Your curve can do a lot of work with that.</p>
<p>My gut tells me it is not going to produce a lot of stans &ndash; It seems like the kind of thing I imagine <em>every</em> generation believes the next older generation would prefer a little more. But it&rsquo;s also an okay diversion. If I watched a <em>lot</em> of t.v. and really believed every minute of it needed to count, <em>Citadel</em> probably would not make the cut. But I tend to watch t.v. when I do not want to invest the time in a movie, and feel a little too tired to read a book. Things like <em>Citadel</em> work great for me.</p>
<h2 id="carrion-comfort">Carrion Comfort</h2>
<p>I don&rsquo;t know why Dan Simmons&rsquo; <em><a href="https://www.goodreads.com/en/book/show/11286">Carrion Comfort</a></em> burbled back up on social media, but it did, and I was fresh off a re-read of <em><a href="https://www.goodreads.com/en/book/show/18956">Homicide</a></em> that was sort of grueling this time, so I figured what the hell.</p>
<p>Which makes two books in a row that I picked up remember-expecting one thing and finding something harder.</p>
<p><em>Homicide</em> was one of the foundational texts of what became <em>The Wire</em>, which I recently re-watched. The book and series share characters (real people in <em>Homicide</em> thinly adapted for <em>The Wire</em>) and some scenes in <em>The Wire</em> are lifted straight from <em>Homicide</em>.</p>
<p><em>The Wire</em> holds up well today. The cast is diverse, and that softens some of its harder observations about racial politics in a one-party town, by which I guess I mean, &ldquo;which lets it get away with Clay Davis as a character.&rdquo; <em>Homicide</em> also holds up, despite being published in the late &rsquo;80s, but I think it probably enjoys something of a reverse pedigree, too, and I think it would bother a lot of people if it came out today: There&rsquo;s much less appetite for its rough irony, even if you have no problem locating where its heart is at, and even if you know to treat it like honest reporting.</p>
<p>But wow was it hard to read this time. It probably should be hard to read a book about a year in the life of a homicide squad in a city that averages better than a murder a day. It doesn&rsquo;t flinch. It took me forever to get through, because it was just hard to read it.</p>
<p>But it also felt important to read it. It reminded me a lot, this time, of David Grossman&rsquo;s amazing <em><a href="https://www.goodreads.com/book/show/78127.On_Killing?from_search=true&amp;from_srp=true&amp;qid=ZXALKmRbL7&amp;rank=2">On Killing</a></em>, which I read while I was in therapy for some military stuff. (For the record, because it comes up, no, I have never killed anybody, but <em>On Killing</em> had a ton of explanatory power for me trying to make sense of what had happened to me in the army nonetheless.) The two feel connected by an understanding of why some people become police (or join the army) that has gone completely missing in the popular discourse, and in the poignancy with which they consider the consequences of exposing a human to the things a homicide detective, or a soldier, are exposed to. I don&rsquo;t know how our society will find its way to moral balance between the cultural poles that give us law-n-order copaganda and &ldquo;ACAB,&rdquo; but <em>Homicide</em> could be an important text in the process.</p>
<p>Anyhow, I didn&rsquo;t like <em>Carrion Comfort</em> much when I read it in the early &rsquo;90s. I think my taste in horror was maybe more Lovecraftian, and it felt a little overstuffed. There are places where it tells and doesn&rsquo;t show. But there were a few scenes in it that stuck with me that weren&rsquo;t what you might expect to stick from a novel about mind-controlling vampires. So when it came back up again and I was in need of a cool-down, I loaded it up in the Kobo.</p>
<p>I&rsquo;m about a quarter of the way through it this time, and I appreciate it more. Like, the horror parts are more <em>horrible</em> to me. The parts I thought were maybe extraneous now feel like nice attention to detail. Some of it still feels a little tells-doesn&rsquo;t-show, but I feel a little more patient about them and I wonder if they were just a way to get the audience to sort of pay attention where it matters in the early going.</p>
<p>Anyhow, enjoying the re-read, but it&rsquo;s landing harder this time.</p>
<h2 id="i-m-not-saying-org-re-reveal-helped-me-win-the-presentation-dot-dot-dot">I&rsquo;m not saying org-re-reveal helped me win the presentation &hellip;</h2>
<p>&hellip; but I&rsquo;m not <em>not</em> saying it, either.</p>
<p>And, I guess, by &ldquo;win&rdquo; I mean that superstition forbids me to say much about some paperwork I signed, but I signed some today.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-05-08</title>
      <link>https://mike.puddingtime.org/posts/2023-05-08-daily-notes/</link>
      <pubDate>Mon, 08 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-08-daily-notes/</guid>
      <description>More on org-reveal - general goodness, custom CSS. Zoom and Mac display mirroring, scrum and kanban.</description>
      <content:encoded><![CDATA[<h2 id="more-on-org-reveal-custom-css">more on org-reveal, custom CSS</h2>
<p>I spent a chunk of the weekend working on a presentation using org-mode and org-reveal.
I kept getting reminded of why org-mode is so powerful, both as a paradigm and as an ecosystem.</p>
<p>The presentation itself just went faster freed of having to either operate inside presentation software, or working with an eye to moving things into presentation software. You&rsquo;re just outlining, which is efficient and fast with org-mode.</p>
<p>As you work in the early &ldquo;get it all out of your head&rdquo; stages, you can take advantage of org as a todo-inflected outliner, adding literal TODOs and tags to headings to remind you to follow up or help you find common themes/areas. It&rsquo;s simple to reorder headings, subheadings, and lists. You can make a kitchen sink area and mark it <code>:noexport:</code> and quickly refile dead-ends or reminders with no place to go into it. As you move into refining, those reordering and moving/refiling features make short work of small changes/adjustments. Unlike presentation software, you don&rsquo;t get caught up in positioning/layout hell.</p>
<p>That&rsquo;s not to say that there are no positioning concerns, and the way you address them is something a lot of people aren&rsquo;t going to tolerate, but works fine for me: If you want, e.g. columns &ndash; maybe two or three equally sized ones &ndash; you have to do it in CSS.</p>
<p>That raises a few usability questions: How much CSS, and how do you wedge it into the org format?</p>
<p>&ldquo;How much&rdquo; isn&rsquo;t much, at least if you know you have full control of the display environment for your presentation. I got away with a few lines:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">.</span><span class="nc">reveal</span> <span class="p">.</span><span class="nc">leftcol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">   <span class="k">float</span><span class="p">:</span> <span class="kc">left</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">   <span class="k">width</span><span class="p">:</span> <span class="mi">48</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">   <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">reveal</span> <span class="p">.</span><span class="nc">rightcol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">   <span class="k">float</span><span class="p">:</span> <span class="kc">right</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">   <span class="k">width</span><span class="p">:</span> <span class="mi">48</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">   <span class="p">}</span></span></span></code></pre></div>
<p>How to wedge it in isn&rsquo;t hard, either, at least with org-reveal:</p>
<p>You just put it in your org directory somewhere and pull it in at the top of the presentation file:</p>
<p><code>#+REVEAL_EXTRA_CSS: css/my-reveal.css</code></p>
<p>If you get tired of repeating yourself across multiple presentations, just customize it with <code>org-re-reveal-extra-css</code>.</p>
<p>There were a few things about the <code>revealjs</code> theme I am using that didn&rsquo;t quite work for me, and it was easy to use my <code>extra-css</code> file to override them after a quick session with the Web inspector.</p>
<p>The markup inside a doc is pretty simple, too:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-org" data-lang="org"><span class="line"><span class="cl"><span class="gh">*</span><span class="gs"> Slide Title</span>
</span></span><span class="line"><span class="cl"><span class="c">#+BEGIN_leftcol</span>
</span></span><span class="line"><span class="cl">*Left Heading*
</span></span><span class="line"><span class="cl">  - foo
</span></span><span class="line"><span class="cl">  - bar
</span></span><span class="line"><span class="cl">  - baz
</span></span><span class="line"><span class="cl"><span class="c">#+END_leftcol</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">#+BEGIN_rightcol</span>
</span></span><span class="line"><span class="cl">*Right Heading*
</span></span><span class="line"><span class="cl">  - foo
</span></span><span class="line"><span class="cl">  - bar
</span></span><span class="line"><span class="cl">  - baz
</span></span><span class="line"><span class="cl"><span class="c">#+END_rightcol</span></span></span></code></pre></div>
<p>The <code>BEGIN_</code> keyword just ouputs a div with the <code>rightcol</code> or <code>leftcol</code> class.</p>
<p>So, do I <em>like</em> doing this?</p>
<p>I mean, not in an absolute sense. The presentation I&rsquo;m working on right now is supposed to represent a work plan I hope I get a chance to actually start implementing. In my ideal world, I&rsquo;d have a way to hide the positioning/styling markup in a drawer so that it was there and out of the way, allowing the presentation to be a living document that flipped back and forth between a roadmap work document and a presentation.</p>
<p>If I wanted to make that sort of document &ldquo;code switching&rdquo; a priority, I&rsquo;d get rid of the positional stuff, and I&rsquo;d be in a pretty good place to pull it off. Good enough for my style of presenting.</p>
<p>And even if I&rsquo;d rather not have the wasted motion, it is not a bad amount of wasted motion. The separation of concerns between content and presentation is still balanced in a direction I like, and it&rsquo;s not a lot of work to take a practical working doc and turn it into a useful presentation. It reminds me a lot of early, pre-WYSIWYG word processors, like PaperClip III, and typesetting systems that needed &ldquo;dot commands&rdquo; to send formatting information to a spooled laser printer.</p>
<p>Here&rsquo;s a <a href="https://oer.gitlab.io/emacs-reveal-howto/howto.html">pretty good presentation on the stuff you can do with org-reveal</a> (as bundled into emacs-reveal). It&rsquo;s where I got the CSS stuff from after a little excavation.</p>
<h2 id="zoom-and-mac-display-mirroring">Zoom and Mac display mirroring</h2>
<p>Getting ready for that presentation, I wanted to do something really simple:</p>
<ul>
<li>Open my presentation in Safari.</li>
<li>Open RevealJS&rsquo;s presenter window (current slide, next slide, timer, speaker notes)</li>
<li>Put the presentation in fullscreen</li>
<li>Share the fullscreened presentation</li>
<li>Run the presentation from the presenter window</li>
</ul>
<p>Which &hellip; no. Not happening.</p>
<p>I could do everything but last part, because when I&rsquo;d move from the fullscreened Safari window to the presenter window, the thing shared on Zoom became Safari&rsquo;s placeholder &ldquo;ESC to exit fullscreen mode&rdquo; tab, and it paused sharing anyhow.</p>
<p>I fiddled around for a while, gave up, and decided maybe the best option was a Firefox plugin that makes a window look mostly fullscreen while not being actually fullscreen. I knew I&rsquo;d wake up this morning hating it, but also knew I had something I could live with, and that would allow me to turn back to polishing the actual content.</p>
<p>This morning I did, indeed, wake up hating the solution. So I went back into Zoom because I vaguely remembered that you can share classes of things besides &ldquo;apps,&rdquo; e.g. devices and displays. Sure enough, you can share devices, displays, and whole desktops (mostly, since full-screened Safari exists in some sort of desktop/screen netherworld, I think.)</p>
<p>I ended up grabbing my iPad Pro, connecting it to my Mac Studio, and using it as a secondary display/desktop. It was easy to drag the full-screened Safari presentation into the iPad Pro, full-screen it, open the presenter window, move that up to the primary desktop, and have it all work as expected.</p>
<p>I am positive I had the setup I thought of first  working in the past with just a single monitor, and I found evidence of people noticing that something changed at some point and offering frankly bizarre and counter-intuitive workarounds. I&rsquo;m glad I just have an iPad Pro to throw at the problem.</p>
<p>I&rsquo;m also glad that I&rsquo;ve fully embraced &ldquo;don&rsquo;t change anything on game day.&rdquo; It didn&rsquo;t take me long &ndash; maybe 30 minutes &ndash; to get from &ldquo;I&rsquo;m using a new presentation approach and I should test this&rdquo; to &ldquo;this isn&rsquo;t working how I remember&rdquo; to &ldquo;I tried everthing I know&rdquo; to &ldquo;settling on this workaround&rdquo; to &ldquo;oh, right &ndash; this might work.&rdquo; Just fine for 36 hours out. It would have sucked on game day.</p>
<h2 id="scrum-and-kanban">Scrum and kanban</h2>
<p>Interesting post: &ldquo;<a href="https://lucasfcosta.com/2022/10/02/scrum-versus-kanban.html">You don&rsquo;t need Scrum. You just need to do Kanban right.&rdquo;</a></p>
<p>As my friend Luke is fond of pointing out, most people don&rsquo;t know what Kanban even is, thinking it&rsquo;s more of a presentational approach than a whole methodology.</p>
<p>Regarding this post, which I have read once and have marked to read again more carefully, the one thing that stuck in my craw a little was the theme of &ldquo;making work visible,&rdquo; because &ndash; and I need to do that second read &ndash; it seems that visibility stops at the edge of &ldquo;the team.&rdquo;</p>
<p>Scrum may, indeed, be &ldquo;manager training wheels,&rdquo; and it can definitely become brittle in the face of &ldquo;a stochastic process such as software development.&rdquo; But it also makes a team (or organization&rsquo;s) work seem more legible to the rest of the business, which is busy trying to understand what&rsquo;s going into the next quarter&rsquo;s training offerings, messaging briefs, marketing plans, forecasts, etc.</p>
<p>One of the lessons the Fourth International took away from the failure of the 1917 Russian revolution (not the eventual &ldquo;Berlin wall comes down&rdquo; failure &ndash; the &ldquo;oh, did you intend for there to be Stalin?&rdquo; failure) was that you can&rsquo;t have socialism in one country. A friend of mine did his master&rsquo;s work on intentional communities such as the Amana Colonies, Harmony, etc. and found similar: Given a local system that is misaligned with its broader context, the broader context takes advantage of its encirclement and either forces compliance or increases pressure until internal contradictions destabilize the system and cause it to either fail, or betray its own principles in order to &ldquo;survive.&rdquo;</p>
<p>I&rsquo;d love to talk to someone who&rsquo;s &ldquo;done kanban&rdquo; as their agile methodology on an enterprise delivery footing. Not because I don&rsquo;t think it&rsquo;s possible, but because I&rsquo;m  curious about how it worked.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-05-06</title>
      <link>https://mike.puddingtime.org/posts/2023-05-06-daily-notes/</link>
      <pubDate>Sat, 06 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-06-daily-notes/</guid>
      <description>If you&amp;rsquo;re going to work on a deck on a Saturday, at least play with org; making catppuccin work with Doom&amp;rsquo;s helm; @andycarolan@social.lol reminds us longboarding season is here.</description>
      <content:encoded><![CDATA[<h2 id="turn-org-files-into-decks-with-org-reveal">Turn org files into decks with org-reveal</h2>
<p>It&rsquo;s Saturday afternoon and I am happy to be sitting here working on a presentation. Al&rsquo;s out of town, so she doesn&rsquo;t have to put up with me asking her how things sound, I can sit here in my bathrobe and monologue at myself, and only the cats are here to bear witness to me pacing around when I get too agitated to keep typing.</p>
<p>I was <em>not</em> happy to make a bunch of org notes then try to figure out how to get them into presentation software, and didn&rsquo;t like anything  available via the usual export options , but I remembered that Doom has a presentation package for org-mode, so I enabled it (<code>+present</code> in the org-section of <code>init.el</code>) .</p>
<p>That package provides you with a properly configured <a href="https://gitlab.com/oer/org-re-reveal">org-re-reveal</a>, which takes an org-mode document and turns it into a <a href="https://revealjs.com">reveal.js</a> presentation. reveal, in turn, provides you with a deck you can open in your browser with transition effects, a speaker window, and keyboard shortcuts.</p>
<p>I&rsquo;m seldom fond of the stuff that has to happen to get a bunch of HTML loaded into a simpler plaintext format, but the demands of org-re-reveal are pretty light.</p>
<p>I put this at the top of the document:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#+title: My Presentation
</span></span><span class="line"><span class="cl">#+REVEAL_THEME: league
</span></span><span class="line"><span class="cl">#+REVEAL_TRANS: fade
</span></span><span class="line"><span class="cl">#+OPTIONS: toc:nil num:nil
</span></span><span class="line"><span class="cl">#+OPTIONS: timestamp:nil</span></span></code></pre></div>
<ul>
<li><code>toc:</code> controls whether it has a table of contents slide</li>
<li><code>num:</code> controls whether it numbers the slide headings</li>
<li><code>timestamp:</code> controls whether it puts the creation date on the title slide</li>
</ul>
<p>Then for each list on a give slide, I add the first line below just over it:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#+ATTR_REVEAL: :frag (fade-in)
</span></span><span class="line"><span class="cl">- apples
</span></span><span class="line"><span class="cl">- pears
</span></span><span class="line"><span class="cl">- bananas</span></span></code></pre></div>
<p>&hellip; which causes each list item  to appear in sequence as I advance through the slide.</p>
<p>If you want speaker notes to show up in the speaker window they go in a little block as Markdown:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">#+BEGIN_NOTES
</span></span><span class="line"><span class="cl">Some speaker note
</span></span><span class="line"><span class="cl">#+END_NOTES</span></span></code></pre></div>
<p>That&rsquo;s about it. In Doom, you just <code>SPC m e v b</code>  and it opens the presentation in your default browser, ready to go. Tap <code>s</code> and it brings up the speaker window, with a timer, current slide, and next slide. <code>esc</code> gives you thumbnails of the presentation so you can go back to a slide by sight, or <code>g</code> to go to a given slide number.</p>
<p>The presentation itself is very simple and clean. You can choose from several themes, including low-contrast favorites Dracula and Solarized for the &ldquo;oh! My terminal looks like that!&rdquo; crowd, or some other generically named ones that just look &hellip; normal.</p>
<p>There are some presentation modes for org-mode that let you put your org-mode buffer itself into a specially styled mode. I did a trial run with one, but the theme choices were a little offputting, navigation was strange, and there&rsquo;s a little bit of &ldquo;<em>I am doing this in an Emacs buffer</em>&rdquo; nerd glee involved. Fine for Emacs influencer YouTubers, but a little distracting for my intended audience, whom I want to expose to my particular combination of charm, reason, and attentional issues  via the content, not the presentation. And I really liked that there was zero config file noodling to get it to work. It&rsquo;s one of Doom&rsquo;s finer &ldquo;batteries included&rdquo; moments.</p>
<p>I&rsquo;ve always, by the way,  liked Keynote&rsquo;s outliner mode when I&rsquo;ve been working on a presentation. It encourages a focus on structure, allows for iterative work as ideas come and go or shift around, and keeps you out of trying to do a bunch of custom work on each slide.  Had I not learned about org-re-reveal I would have just popped open Keynote and retyped my outline.  And at some point, when I&rsquo;m back in the world of &ldquo;we&rsquo;re all supposed to use this template you can download from Confluence&rdquo; I expect I will have to figure out how to use the pptx export options. For now, though, org-re-reveal provides an extremely simple, easy, direct path from &ldquo;outline&rdquo; to &ldquo;presentation.&rdquo;</p>
<h2 id="making-catppuccin-work-for-helm-in-doom">Making catppuccin work for helm in Doom</h2>
<p>I&rsquo;m a fan of the <a href="https://github.com/catppuccin/catppuccin">catppuccin palette family</a> and they&rsquo;re simple to add to Doom: just stick the <a href="https://github.com/catppuccin/emacs">theme file</a> in <code>~/.config/doom/themes</code> and then use them in <code>config.el</code>:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">doom-theme</span> <span class="ss">&#39;catppuccin</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">catppuccin-flavor</span> <span class="ss">&#39;frappe</span><span class="p">)</span></span></span></code></pre></div>
<p>They don&rsquo;t set any values for the selection highlight color, though, which means you can&rsquo;t really tell which completion line you&rsquo;re on as you move the cursor around. It&rsquo;s also an exercise in a very unique sort of frustration to try the usual &ldquo;what is this face called&rdquo; trick of <code>desc-face</code> (<code>SPC h F</code> in Doom ) in a buffer you can&rsquo;t run a command on.</p>
<p>My own search queries about it were just poorly formed enough that I stood on the precipice of saying &ldquo;sure, I&rsquo;ll just eat these 50 lines of lisp off the sidewalk to <em>number</em> the selection if that&rsquo;s what it takes,&rdquo; but I reframed one last time and finally found the answer.</p>
<p>The face to customize is <code>helm-selection</code>.  Just give it a background and it&rsquo;s fine.</p>
<h2 id="longboarding-season-is-here">Longboarding season is here</h2>
<p><video width="320" controls class="rt-img"><source src="/img/wipeout.mp4" type="video/mp4">
Your browser does not support the video tag.</video></p>
<p>Andy Carolan <a href="https://social.lol/@andycarolan/110316990998796991#.">reminded me</a> that longboarding season is here.</p>
<p>A few years ago Al and I decided we wanted to learn how to lonboard. I don&rsquo;t remember why. I think we just wanted to get out and do something together. So we bought some very cheap Amazon completes that looked cool &ndash; 42&quot; top-mount pintails &ndash; and spent weeks over at the nearby elementary school playground learning how to roll around on them like very upright mannequins on wheeled platforms.</p>
<p>Then we started watching videos and reading blogs and figuring out better choices. I finally settled on a Pantheon Trip &ndash; a little 33&quot; double-drop. Alison got a Loaded Icarus, a really nice composite deck with a bunch of spring to it.  I also had a Bustin&rsquo; Maestro, a 37&quot; dropthrough. I had several more boards for that matter, trying to get comfortable, and ended up <a href="/posts/2018-10-20-the-midlife-longboard/">writing a guide for fellow olds</a>.</p>
<p>We took the boards everywhere for a while: State parks sometimes have good accessible paths you can ride on, or just good asphalt around the campground for cruising. Also Saturday coffee runs and cruises down the Springwater. For a period, when I was riding the train to work, I used mine as a &ldquo;last-mile&rdquo; conveyance to the Lents Town Center station. A few times I did 10-mile solo rides down the Springwater.</p>
<figure class="rt-img"><img src="/img/subsonic.jpg"
    alt="Closeup of longboard trucks with light blue 90mm wheels attached and the Subsonic logotype on the deck" width="320"><figcaption>
      <h4>The Subsonic GT40. Best coffee cruiser ever</h4>
    </figcaption>
</figure>

<p>Cruising was fun, and the Pantheon Trip is a great deck for that because it has huge wheels and rides super low to the ground. It&rsquo;s low effort to push, and the giant wheels just roll over grit and rocks.</p>
<p>We stopped riding together when Al took her spill: She hit a seam that joined the Springwater to one of the overpasses and went over backwards. She threw her arm out and it dislocated the part of her elbow that didn&rsquo;t just shatter. We spent 40 minutes out on the Springwater while emergency responders from three jurisdictions argued over who should come get her. She&rsquo;s got titanium in that joint now, and exceeded the doctor&rsquo;s predictions, regaining full mobility. The only reminder is the bad-ass scar and some aches when the weather is cold and wet.</p>
<p>I kept riding, and absent the sort of mellow vibe we&rsquo;d established as a couple got interested in downhill, so I took a class from a local longboarding champion. We met every Wednesday night at Mt. Tabor. It was one of the most fun things I&rsquo;ve done in a while. Completely padded up, helmeted, and doing the hills we were doing, it was no big deal to wipe out, and it felt <em>great</em> to get knocked around a little. I&rsquo;d leave class feeling the same way I felt at the end of a day in the sawdust pits or the swing-landing trainer at jump school.</p>
<p><video width="100%" controls><source src="/img/slides.mp4" type="video/mp4">
Your browser does not support the video tag.</video></p>
<p>Anyhow, last season I traded in my hard pads for some nicer G-Form elbow and knee pads that go under my shirt and pants a little more easily, and I traded my Pantheon Trip in for a <a href="https://pantheonboards.com/product/pantheon-pranayama-complete-commuter-longboard/">Pantheon Pranayama</a>, which is pretty much the Trip except with traditional kingpin trucks, so it&rsquo;s a little more nimble. I went with the 7-ply deck, so it&rsquo;s also less stiff than my 8-ply trip. I thought that might have been a mistake, but I&rsquo;m down about 25 pounds from last season and I think it&rsquo;s going to be okay.</p>
<p>Anyhow, it&rsquo;s 10 a.m. and time to get back to that deck for a little while. Presenting Tuesday!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-05-03</title>
      <link>https://mike.puddingtime.org/posts/2023-05-03-daily-notes/</link>
      <pubDate>Wed, 03 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-03-daily-notes/</guid>
      <description>A Ruby/CLI-based plaintext PRM, Robert DeNiro on exporting org-mode to JSON, blogging with ox-hugo, that Royal Enfield Himalayan</description>
      <content:encoded><![CDATA[<h2 id="friends-a-plaintext-ruby-based-prm">&ldquo;friends&rdquo; - a plaintext, Ruby-based PRM</h2>
<p>Looking around for other people who have done CRM/PRM-ish things in plaintext, I found <a href="https://github.com/JacobEvelyn/friends">JacobEvelyn/friends</a>. It&rsquo;s written in Ruby, uses Markdown for its home format, and gives you a command line interface to a record of your friends and activities.  I appreciate how thoroughly it thinks about what it is trying to do, and I sense a set of concerns similar to mine about the &ldquo;keeping up with personal contacts&rdquo; challenge.</p>
<p>Some things I like about it:</p>
<ul>
<li>Simple CLI data entry syntax</li>
<li>Some &ldquo;habit tracking&rdquo; style reporting to help you understand if you&rsquo;re keeping up your practice.</li>
<li>Clean reporting with a lot of flexibility that would let you build more reporting.</li>
<li>Simple use of Markdown, with no elaborate syntactical overlay.  If you gave up on friends, your data would be easily readable.</li>
</ul>
<p>It&rsquo;s probably good to note that friends isn&rsquo;t a full contact management system. It&rsquo;s better to think of it as a sort of journaling and habit tracking tool with a tight focus on keeping up with people, not a way to manage all your contact details. If I could extend one thing about it, it would probably be to be able to store email addresses with contacts: Email addresses aren&rsquo;t <em>great</em> keys, but also they&rsquo;re fine keys sometimes, and they&rsquo;d open friends up to interacting with other tools.</p>
<h2 id="ox-json-and-the-wisdom-of-neil-mccauley">ox-json and the wisdom of Neil McCauley</h2>
<p>As I was looking through the docs for friends and waming up to it some I wondered how readily I could migrate my org-contacts information. My home language is Ruby, so I tend to start there when I&rsquo;m looking for a library. There&rsquo;s one org-mode gem I&rsquo;m aware of, but its primary preoccupation is converting org-mode to HTML or Textile for presentation purposes.</p>
<p>Another way to come at the problem is to get the org markup into something more universally parseable, which is where <a href="https://github.com/jlumpe/ox-json">ox-json</a> could help. Does what it says on the tin: Converts an org-mode file into JSON, including, crucially, the data stored in the  <code>:PROPERTIES:</code>  drawer. Currently it passes by the <code>:LOGBOOK:</code> drawer, so that limits what you can do with it, but it still opens up possibilities.</p>
<p>Why?</p>
<div style="text-align:center;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/rGPWW9Pjzto" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div>
<h2 id="ox-hugo-update">ox-hugo update</h2>
<p>I started blogging with <a href="https://github.com/kaushalmodi/ox-hugo">ox-hugo</a> several weeks ago, going into it a little warily.</p>
<p>Recap:</p>
<ul>
<li>You write all your posts in a monolithic org-mode file.</li>
<li>Each heading is a post.</li>
<li>Heading tags become post tags.</li>
<li>Headings in a <code>TODO</code> state are drafts.</li>
<li>Metadata can be stored in the <code>:PROPERTIES:</code> drawer (tidy, but the templating syntax gets cluttery if you&rsquo;re not a lisp native) or additional metadata src blocks (more visually cluttered when writing, but easier to read the template  if you&rsquo;re a YAML native)</li>
<li>You can set it up to automatically export the Markdown version into your Hugo content hierarchy whenever you save the buffer.</li>
</ul>
<p>Why would you want to do this?</p>
<p>As someone who does a lot of digest posts, I like having my pre-publication notes, links, etc. in the org-mode ecosystem, with all of its text manipulation affordances.  If a topic I&rsquo;m working on isn&rsquo;t ready when it&rsquo;s time to publish that day, I just <code>refile</code> the subheading under my <code>* Daily Post Overflow</code>  heading and keep going. I also like org-mode&rsquo;s structure editing features. It&rsquo;s simple to move headings and their content around within a post.</p>
<p>I thought the &ldquo;all-in-one-file&rdquo; thing would annoy me, and there is part of me that still doesn&rsquo;t like seeing all the surrounding context, but that&rsquo;s what <code>subtree to indirect buffer</code> is for. I drop into an indirect buffer for the long-haul writing, then pop back out of it if I need to pull things in from the overflow area or check on something from a previous post.</p>
<p>I did stub my toe on one thing, which was that the org-capture template I found to make the post setup simpler was setting <code>:EXPORT-HUGO-DATE:</code>, which updates dynamically when you save a post heading. I went back to make some edits to a post, saved my work, and it altered the date metadata in the Markdown output and jumbled my post order. The answer seemed to be to switch that to <code>:EXPORT_DATE:</code>, and now it behaves.</p>
<p>I also put off cleaning up my capture template so all the metadata could go in the <code>:PROPERTIES:</code> drawer. At first It was easier  to just embed some YAML at the top of the post body with <code>#+begin_src yaml :front_matter_extra t</code> rather than working out the Lispier syntax for post image and cover image in the context of writing a capture template.  It just took a few minutes to fix once I decided to bother with it, and the template now outputs <code>:PROPERTIES:</code> metadata:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-org" data-lang="org"><span class="line"><span class="cl">:EXPORT_HUGO_CUSTOM_FRONT_MATTER<span class="gd">+: :cover &#39;((image . &#34;&#34; ) (caption . &#34;&#34; ))
</span></span></span><span class="line"><span class="cl"><span class="gd">:EXPORT_HUGO_CUSTOM_FRONT_MATTER+</span>: :images &#39;(/momo-logo.jpg)
</span></span><span class="line"><span class="cl">:EXPORT_DESCRIPTION:</span></span></code></pre></div>
<p>I only sometimes use cover images, but I like to include my site logo in social posts, etc. when I don&rsquo;t have some other image to show, so the template defaults to an empty cover image and <code>image</code> metadata that Hugo&rsquo;s OpenGraph templating can pull in.</p>
<p>Several weeks in, I like the workflow. One tiny part of my soul is troubled that I have org source and Markdown output, but on the other hand the org source overwrites the Markdown output on edit, so the two don&rsquo;t drift. Realistically, the Markdown would be the more migratable content were I to shift off of Hugo, and it&rsquo;s simply better to author in org-mode.  So there&rsquo;s no associated toil and each format gets to be useful in the way it is best suited to be so.</p>
<h2 id="that-royal-enfield-himalayan">That Royal Enfield Himalayan</h2>
<p>I complained a little about my Royal Enfield Himalayan a few days ago: a little big for the power it has, and it had some QA problems that took some time to track down  I am pretty sure I am going to sell it to fund something similar.  But I did swap in a fresh battery and cleaned it up from winter storage, and rode it up to St. Johns for lunch yesterday, which meant a few dozen miles. It ran pretty well!</p>
<p>Last year, after dealing with rough idling and stalls, I finally broke down and installed a <a href="https://www.boosterplug.com/shop/frontpage.html">BoosterPlug</a>. Himalayans run too lean out of the factory, and the difference after installing one was pretty amazing. It was about a five-minute operation and it made the difference between a very rough first five minutes and &ldquo;let it idle for 30 seconds and it&rsquo;ll be fine.&rdquo; The machine never stalls now. I do think it still idles a little low, but that&rsquo;s a fine-tuning thing.</p>
<p>Anyhow, it was nice to ride around. Yeah, it&rsquo;s a little big, but it&rsquo;s not a big bike. There&rsquo;s plenty of pep for the city. Running up HWY 30, it did fine with the lunch crowd and there was plenty of power to overtake or squeeze out of spots at urban parkway speeds. I&rsquo;d do exit-to-exit on the Portland bypasses with it.</p>
<p>I was also glad to see <a href="https://www.sabatinomoto.com">an RE dealership up in St. John.</a>  Wasn&rsquo;t a fan of the Harley dealership I was getting service at and had to do a lot of research on my own to get help when it was suffering from factory QA problems.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-05-02</title>
      <link>https://mike.puddingtime.org/posts/2023-05-02-daily-notes/</link>
      <pubDate>Tue, 02 May 2023 00:00:00 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-02-daily-notes/</guid>
      <description>A Mackup/Dropbox glitch, integrating org-contacts and Things, conversations not interviews.</description>
      <content:encoded><![CDATA[<h2 id="mackup-and-dropbox">Mackup and Dropbox</h2>
<p>I recently recommended <a href="https://github.com/lra/mackup">Mackup</a>, a Mac config syncronization tool, but I&rsquo;m having a few issues with it now. In general, it does a pretty good job with most apps, but I ran into a weird bug with Mailmate where it kept forgetting all my settings. After a few go-rounds I opened up the Console and searched for Mailmate messages and found it wasn&rsquo;t able to write to its prefs file. I put Mailmate in Mackup&rsquo;s skip list, removed the symlinks and let it write its files again and all was well. Searching Mackup&rsquo;s issues, <a href="https://github.com/lra/mackup/issues/1891">I found someone experiencing a similar issue with Xcode</a> and learned it seems to be a thing with Dropbox and iCloud and certain apps. In the case of Dropbox, it has come with that app&rsquo;s move to the <code>CloudStorage</code> folder.</p>
<p>I&rsquo;m not sure this is enough to get me quit using it. It works quite well with my Emacs config, gpg, ssh, zsh, and other stuff. I also like using it for syncing my <code>~/bin</code>.  It doesn&rsquo;t work so well with Terminal.app, and gets a little weird now and then with a few other things.</p>
<p>Just &hellip; proceed with caution, I guess is the advice.  For now I&rsquo;ve got Mailmate, Terminal.app, karabiner, and Bartender on the skip list. That&rsquo;s fine for most of them: They&rsquo;re generally best configured a little different between laptop and desktop anyhow.</p>
<h2 id="my-org-contacts-file-and-things">My  org-contacts file and Things</h2>
<p>I stopped using mu4e. I was uncomfortable with the interplay between several different clients (both automated and user-facing) and my Maildir and IMAP. That left a a small hole in the functionality I&rsquo;d built into my org-mode PRM: being able to quickly mail a contact from a Doom Emacs menu. So I made a quick function that just turns the email address in the org-contacts record into a <code>mailto:</code> link and <code>open</code> call to the system that invokes my preferred mail client (Mailmate at this point). So if the point is over an org-contacts heading I can <code>SPC C m</code> (&ldquo;leader - CRM - mail&rdquo;)  and get a new message.</p>
<p>I&rsquo;m on the record somewhere about not liking the emphasis on URL schemes for Mac automation. I don&rsquo;t like the ins and outs of encoding values and cramming data into that format. At the same time, it <em>does</em> seem to have kept the idea of Mac end-user automation from fading away. So as I sat there looking at my new mailto function, I wondered about how all the contact data I&rsquo;m keeping could interact with the wider Mac ecosystem in a sort of &ldquo;if needed&rdquo; manner, hence this little thing.</p>
<p>It just provides an interactive menu for selecting a contact activity (ping, call, write, etc.) and an interactive date picker, then makes a Thing todo that includes the tags for the contact, with a &ldquo;start date.&rdquo; I can get at it with <code>SPC C g</code> (&ldquo;leader CRM thinGs&rdquo;).  I don&rsquo;t mean to use it? I was just curious. I&rsquo;m not sure.</p>
<p>What I am learning as I use org-mode day-to-day again is that there are things that come naturally to it and that do not come naturally to it. I&rsquo;ve got working integrations with my calendar, for instance, but calendar syncing is another one of those things that eats the one thread you have to work with when it runs, and sometimes it does mysterious things if you mess with a plaintext representation of a more complex data structure that was never written with direct human interaction in mind.</p>
<p>That&rsquo;s always the struggle with Emacs: What <em>can</em> it do, and what <em>should</em> it do?</p>
<p>The temptation is to crawl into a uni-environment and torture everything into some kind of alignment, but that&rsquo;s brittle. It might <em>feel</em> good if your temperament or proclivities lead you to feeling comfortable with that particular shape, but there are tradeoffs whether you acknowledge them or not. In this particular case, the line I am sensing is the line between &ldquo;getting things done&rdquo; in a very mixed, tactical, &ldquo;chores, obligations, and interrupts&rdquo; kind of way, and getting things done in a very &ldquo;life is an information problem&rdquo; kind of way.</p>
<p>I love org-mode as a way of organizing information and thoughts. In particular, I am very fond of all the refiling capabilities it offers, because ideas and information can be shuffled around between different contexts inside the broader org-mode context without lifting a hand from the keyboard. As a day-to-day &ldquo;chores and household projects&rdquo; tool, I&rsquo;m a little less certain about it, mainly because of the mobile piece. <a href="https://beorgapp.com">beorg</a> is great, but it is also a little bit of work to use, and its syncing model is borrowed, so it&rsquo;s not as good as a purpose-built solution. Further, it is not consistent with my desktop org-mode environments when it comes to things like the agenda views.</p>
<p>So, you know, the interesting thing to me becomes &ldquo;how can this sophisticated text manipulation environment fit into a broader toolkit?&rdquo; How can all these things interconnect and complement each other? What are the kinds of work that makes sense living in a purpose-built tool because their typical context favors less thinking and less complexity, vs. the kinds of work that are broadly the same thing (&ldquo;a thing I need to do&rdquo;) that benefit from more thinking and more complexity? What kinds of tasks can be &ldquo;dead&rdquo; and in a little purpose-built silo, and what kinds of tasks benefit from a little bit of added complexity to exist in a better context? How could a thing move from one environment to the other?</p>
<p>Interesting to me, anyhow, because my tendency, at rest &ndash; my unconscious tendency &ndash; is to want everything in one tool, but I continue to learn over time that the one-tool outlook breeds its own kinds of complexity.</p>
<p>Anyhow, here&rsquo;s that function. It works okay so far. The one glitch is that the Things URL scheme won&rsquo;t make a tag if it doesn&rsquo;t exist, so I had to go in and tag an existing todo with all my contact types (friend, network, recruiter, etc.) to get the function to properly tag a contact todo.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/org-contacts-to-things</span> <span class="p">(</span><span class="nv">contact-kind</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Create a Things to-do item based on the current Org Contacts record.
</span></span></span><span class="line"><span class="cl"><span class="s">   CONTACT-KIND is a string that specifies the kind of contact (&#39;ping&#39;, &#39;call&#39;, &#39;write&#39;, &#39;schedule&#39;, or &#39;follow up&#39;).&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span>
</span></span><span class="line"><span class="cl">   <span class="p">(</span><span class="nf">list</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">completing-read</span> <span class="s">&#34;Contact Kind: &#34;</span> <span class="o">&#39;</span><span class="p">(</span><span class="s">&#34;ping&#34;</span> <span class="s">&#34;call&#34;</span> <span class="s">&#34;write&#34;</span> <span class="s">&#34;schedule&#34;</span> <span class="s">&#34;follow up&#34;</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let*</span> <span class="p">((</span><span class="nv">name</span> <span class="p">(</span><span class="nv">org-entry-get</span> <span class="no">nil</span> <span class="s">&#34;Name&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">email</span> <span class="p">(</span><span class="nv">org-entry-get</span> <span class="no">nil</span> <span class="s">&#34;Email&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">phone</span> <span class="p">(</span><span class="nv">org-entry-get</span> <span class="no">nil</span> <span class="s">&#34;Phone&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">note</span> <span class="p">(</span><span class="nf">read-string</span> <span class="s">&#34;Note: &#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">notes</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;Email: %s\nPhone: %s\nNote: %s&#34;</span> <span class="nv">email</span> <span class="nv">phone</span> <span class="nv">note</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">start-date</span> <span class="p">(</span><span class="nv">org-read-date</span> <span class="no">nil</span> <span class="no">nil</span> <span class="no">nil</span> <span class="s">&#34;Start Date: &#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">start-date-string</span> <span class="p">(</span><span class="nf">format-time-string</span> <span class="s">&#34;%Y-%m-%d&#34;</span> <span class="p">(</span><span class="nv">org-time-string-to-time</span> <span class="nv">start-date</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">tags</span> <span class="p">(</span><span class="nv">org-get-tags</span> <span class="no">nil</span> <span class="no">t</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">tag-string</span> <span class="p">(</span><span class="nb">if</span> <span class="nv">tags</span> <span class="p">(</span><span class="nf">mapconcat</span> <span class="ss">&#39;identity</span> <span class="nv">tags</span> <span class="s">&#34;,&#34;</span><span class="p">)</span> <span class="s">&#34;&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">title</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;%s: %s&#34;</span> <span class="nv">contact-kind</span> <span class="nv">name</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">url</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;things:///add?title=%s&amp;notes=%s&amp;when=%s&amp;tags=%s&#34;</span>
</span></span><span class="line"><span class="cl">                      <span class="p">(</span><span class="nv">url-encode-url</span> <span class="nv">title</span><span class="p">)</span> <span class="p">(</span><span class="nv">url-encode-url</span> <span class="nv">notes</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                      <span class="p">(</span><span class="nv">url-encode-url</span> <span class="nv">start-date-string</span><span class="p">)</span> <span class="p">(</span><span class="nv">url-encode-url</span> <span class="nv">tag-string</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">start-process-shell-command</span> <span class="s">&#34;open&#34;</span> <span class="no">nil</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;open \&#34;%s\&#34;&#34;</span> <span class="nv">url</span><span class="p">))))</span></span></span></code></pre></div>
<h2 id="conversations-not-interviews">Conversations, not interviews</h2>
<p>Refreshing interview closer of the month:</p>
<p>&ldquo;We have a few minutes left, any questions of me?&rdquo;</p>
<p>&ldquo;No. I came into this thinking you&rsquo;d either say &lsquo;did you even read the job description? Now good day while I go fire the recruiter,&rsquo; or you&rsquo;d see something that would lead you to want a conversation, which I hope we&rsquo;ll continue so I can learn more.&rdquo;</p>
<p>And there we were, having a conversation.</p>
<p>I&rsquo;ve been very lucky to have had several <em>conversations</em> recently. It&rsquo;s reminding me of the times I had <em>interviews</em> and how those things went wrong down the road. It&rsquo;s great to end a conversation hearing the person you were conversing with say &ldquo;wow, the time flew by &hellip; but this felt so organic.&rdquo; You can enter a conversation with curiosity, and with a good conversational partner you can see where things go, make connections to your experience in the moment, change course or call up other experiences when they say &ldquo;well, that&rsquo;s not quite what we&rsquo;re dealing with here.&rdquo; That&rsquo;s much better than  pre-thinking a bunch of answers and poring over &ldquo;ten most common questions&rdquo; or (if Nigel or Chris are reading) &ldquo;you&rsquo;re trapped in a 20&rsquo; blender&rdquo; scenarios.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Finding an org-contact record&#39;s emails in MailMate and events in Google Calendar</title>
      <link>https://mike.puddingtime.org/posts/2023-05-02-finding-an-org-contact-record-s-emails-in-mailmate/</link>
      <pubDate>Tue, 02 May 2023 00:00:00 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-02-finding-an-org-contact-record-s-emails-in-mailmate/</guid>
      <description>Looking up email histories and past Google Calendar events from org-contacts, and a few ideas about how to schedule time with people.</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve been digging <a href="https://freron.com">MailMate</a>, but missing a function I&rsquo;d added to my Doom Emacs setup that let me search mu4e for mails from a contact in my <code>contacts.org</code> file.  I set out to fix that this evening thinking it&rsquo;d probably be an AppleScript thing, but <a href="https://manual.mailmate-app.com/extended_url_scheme">it turns out MailMate has its own URL scheme</a> (<code>mlmt:</code>) that includes queries. From the command line, for instance, you&rsquo;d just do something like <span class="inline-src language-sh" data-lang="sh"><code>open mlmt:quicksearch?string=&quot;foo@bar.com&quot;</code></span>  to search for that address.</p>
<p>(I learned about that from this post by James Sulak (another Emacs person, as it turns out), who shared <a href="https://boxkitemachine.net/posts/mailmate-and-alfred/">a set of helpful Alfred workflows for working with MailMate</a>.)</p>
<p>This function grabs the <code>EMAIL</code> property of a given org-contacts heading and runs the <code>open</code> shell command:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/open-mlmt-quicksearch</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Open a quicksearch URL for the email address at point.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">email</span> <span class="p">(</span><span class="nv">org-entry-get</span> <span class="p">(</span><span class="nf">point</span><span class="p">)</span> <span class="s">&#34;EMAIL&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">if</span> <span class="p">(</span><span class="nv">not</span> <span class="p">(</span><span class="nv">string-empty-p</span> <span class="nv">email</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">shell-command</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;open &#39;mlmt:quicksearch?string=%s&#39;&#34;</span> <span class="nv">email</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">message</span> <span class="s">&#34;No email address found&#34;</span><span class="p">))))</span></span></span></code></pre></div>
<p>MailMate search is very fast. The results are there in an eyeblink.</p>
<p>&hellip; and that sort of led to this, which searches Google Calendar for an email address from a contact:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/open-gcal-search-for-email</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Open a Google Calendar search page for the email address at point.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">email</span> <span class="p">(</span><span class="nv">org-entry-get</span> <span class="p">(</span><span class="nf">point</span><span class="p">)</span> <span class="s">&#34;EMAIL&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">search-url</span> <span class="s">&#34;https://calendar.google.com/calendar/u/0/r/search?q=%s&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">if</span> <span class="p">(</span><span class="nv">not</span> <span class="p">(</span><span class="nv">string-empty-p</span> <span class="nv">email</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nb">progn</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nf">message</span> <span class="s">&#34;Searching Google Calendar for events with email %s...&#34;</span> <span class="nv">email</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nv">browse-url</span> <span class="p">(</span><span class="nf">format</span> <span class="nv">search-url</span> <span class="nv">email</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">message</span> <span class="s">&#34;No email address found&#34;</span><span class="p">))))</span></span></span></code></pre></div>
<p>&hellip; and that suggested this one, which gets a date from the interactive org date picker and creates an all-day  Google Calendar event with the contact as an invitee:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/create-gcal-all-day-appointment-with-contact</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Create a new all-day appointment in Google Calendar and invite the contact at point.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let*</span> <span class="p">((</span><span class="nv">date</span> <span class="p">(</span><span class="nv">org-read-date</span> <span class="no">nil</span> <span class="no">t</span> <span class="no">nil</span> <span class="s">&#34;Date: &#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">formatted-date</span> <span class="p">(</span><span class="nf">format-time-string</span> <span class="s">&#34;%Y%m%d&#34;</span> <span class="nv">date</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">next-day</span> <span class="p">(</span><span class="nf">format-time-string</span> <span class="s">&#34;%Y%m%d&#34;</span> <span class="p">(</span><span class="nf">time-add</span> <span class="nv">date</span> <span class="p">(</span><span class="nf">*</span> <span class="mi">24</span> <span class="mi">60</span> <span class="mi">60</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">contact-email</span> <span class="p">(</span><span class="nv">org-entry-get</span> <span class="p">(</span><span class="nf">point</span><span class="p">)</span> <span class="s">&#34;EMAIL&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">url</span> <span class="p">(</span><span class="nf">concat</span> <span class="s">&#34;https://calendar.google.com/calendar/u/0/r/eventedit?dates=&#34;</span>
</span></span><span class="line"><span class="cl">                      <span class="nv">formatted-date</span>
</span></span><span class="line"><span class="cl">                      <span class="s">&#34;/&#34;</span>
</span></span><span class="line"><span class="cl">                      <span class="nv">next-day</span>
</span></span><span class="line"><span class="cl">                      <span class="s">&#34;&amp;pli=1&amp;sf=true&amp;action=TEMPLATE&amp;add=&#34;</span>
</span></span><span class="line"><span class="cl">                      <span class="nv">contact-email</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">browse-url</span> <span class="nv">url</span><span class="p">)))</span></span></span></code></pre></div>
<p>I preferred just setting it to all-day, because I&rsquo;ve learned a few things about scheduling time to catch up with people in a non-business context:</p>
<ol>
<li>It&rsquo;s usually gonna be a few weeks out. PTO, busy, etc.</li>
<li>Setting a day is pretty easy, but setting a good time can be hard when it&rsquo;s that far out. Schedules do things, or we know a given day is <em>usually</em> our good day, but specifics can shift around.</li>
<li>Setting an all-day item and a reminder to lock down the details several days out makes it easier to agree to <em>something</em> and work out the details when calendars are a little more clear. No constant shuffling if one party or the other isn&rsquo;t in complete control of their own calendar.</li>
</ol>
<p>I wonder if I should go read a book about how to stay in touch with people. I know there are several.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Exporting a DayOne commonplace book to org-roam</title>
      <link>https://mike.puddingtime.org/posts/2023-04-30-exporting-a-dayone-commonplace-book-to-org-roam/</link>
      <pubDate>Sun, 30 Apr 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-30-exporting-a-dayone-commonplace-book-to-org-roam/</guid>
      <description>A very cheap and cheerful DayOne-to-org-roam exporter and a link to a useful org-roam search function.</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve kept some quotes in DayOne for years, and I frequently find myself coming back to them when I&rsquo;m writing, either to actually use them or to just remember an idea. I thought it&rsquo;d be handy to have them in my writing tool, so I used ChatGPT to help me write a quick exporter.</p>
<p>I&rsquo;ll include that below, but the other thing to link to before your eyes glaze over with a hunk of Ruby is <a href="https://org-roam.discourse.group/t/using-consult-ripgrep-with-org-roam-for-searching-notes/1226/7">this useful post on using consult-ripgrep with org-roam for fulltext search from the org-roam Discourse.</a> I&rsquo;ve been careful to tag everything I&rsquo;ve put in so far, but I won&rsquo;t get to that with this batch of files, and I usually remember a keyword, anyhow. So they&rsquo;re just tagged  with &ldquo;quotes&rdquo; and &ldquo;commonplace&rdquo; for now.</p>
<p>The script just consumes the JSON that DayOne&rsquo;s export function provides and coughs out formatted org-roam nodes. It uses DayOne&rsquo;s uuid&rsquo;s, but tacks on a few words &ndash; just in case? Maybe over time I&rsquo;ll go clean up the titles but for now they&rsquo;re just there to provide a hint when I search.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="ch">#!/usr/bin/env ruby</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">require</span> <span class="s1">&#39;json&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">require</span> <span class="s1">&#39;date&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Set these up before running</span>
</span></span><span class="line"><span class="cl"><span class="n">src_json</span> <span class="o">=</span> <span class="s2">&#34;/path/to/file.json&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">destination_dir</span> <span class="o">=</span> <span class="s2">&#34;/path/to/export/dir&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Read the JSON file</span>
</span></span><span class="line"><span class="cl"><span class="n">json_str</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">src_json</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Parse the JSON string</span>
</span></span><span class="line"><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="no">JSON</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">json_str</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_json_to_org_roam_files</span><span class="p">(</span><span class="n">json_str</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="n">data</span> <span class="o">=</span> <span class="no">JSON</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">json_str</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="n">entries</span> <span class="o">=</span> <span class="n">data</span><span class="o">[</span><span class="s1">&#39;entries&#39;</span><span class="o">]</span>
</span></span><span class="line"><span class="cl">  <span class="n">entries</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">entry</span><span class="o">|</span>
</span></span><span class="line"><span class="cl">    <span class="n">created_date</span> <span class="o">=</span> <span class="no">DateTime</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">entry</span><span class="o">[</span><span class="s1">&#39;creationDate&#39;</span><span class="o">]</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;%Y%m%d%H%M%S&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">title</span> <span class="o">=</span> <span class="n">entry</span><span class="o">[</span><span class="s1">&#39;text&#39;</span><span class="o">].</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/^&#34;/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/&#34;$/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/[^a-zA-Z0-9 ]/</span><span class="p">,</span> <span class="s1">&#39; &#39;</span><span class="p">)</span><span class="o">.</span><span class="n">squeeze</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span> <span class="c1"># replace non-alphanumeric with space, remove extra spaces</span>
</span></span><span class="line"><span class="cl">    <span class="n">first_words</span> <span class="o">=</span> <span class="n">title</span><span class="o">.</span><span class="n">split</span><span class="o">.</span><span class="n">first</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/[^a-zA-Z0-9]/</span><span class="p">,</span> <span class="s1">&#39;-&#39;</span><span class="p">)</span> <span class="c1"># replace non-alphanumeric with dash</span>
</span></span><span class="line"><span class="cl">    <span class="n">uuid</span> <span class="o">=</span> <span class="n">first_words</span> <span class="o">+</span> <span class="s1">&#39;-&#39;</span> <span class="o">+</span> <span class="n">entry</span><span class="o">[</span><span class="s1">&#39;uuid&#39;</span><span class="o">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">content</span> <span class="o">=</span> <span class="no">JSON</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">entry</span><span class="o">[</span><span class="s1">&#39;richText&#39;</span><span class="o">]</span><span class="p">)</span><span class="o">[</span><span class="s1">&#39;contents&#39;</span><span class="o">].</span><span class="n">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">c</span><span class="o">|</span> <span class="n">c</span><span class="o">[</span><span class="s1">&#39;text&#39;</span><span class="o">]</span> <span class="p">}</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">filename</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">#{</span><span class="n">created_date</span><span class="si">}</span><span class="s2">-</span><span class="si">#{</span><span class="n">first_words</span><span class="si">}</span><span class="s2">.org&#34;</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/^-/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/-$/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/-{2,}/</span><span class="p">,</span><span class="s1">&#39;-&#39;</span><span class="p">)</span> <span class="c1"># remove leading/trailing dashes and collapse multiple dashes</span>
</span></span><span class="line"><span class="cl">    <span class="n">file_content</span> <span class="o">=</span> <span class="o">&lt;&lt;~</span><span class="no">ORG_NODE</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/^\s*/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="ss">:PROPERTIES</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="ss">:ID</span><span class="p">:</span> <span class="c1">#{uuid}</span>
</span></span><span class="line"><span class="cl">      <span class="ss">:END</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="c1">#+title: #{first_words}</span>
</span></span><span class="line"><span class="cl">      <span class="c1">#+filetags: :commonplace:quotes:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="c1">#{content}</span>
</span></span><span class="line"><span class="cl">    <span class="no">ORG_NODE</span>
</span></span><span class="line"><span class="cl">    <span class="n">file</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">filename</span><span class="p">),</span> <span class="s1">&#39;w&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">file_content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">file</span><span class="o">.</span><span class="n">close</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Iterate over each entry</span>
</span></span><span class="line"><span class="cl"><span class="n">data</span><span class="o">[</span><span class="s1">&#39;entries&#39;</span><span class="o">].</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">entry</span><span class="o">|</span>
</span></span><span class="line"><span class="cl">  <span class="n">write_json_to_org_roam_files</span><span class="p">(</span><span class="n">json_str</span><span class="p">,</span> <span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="n">destination_dir</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div>
]]></content:encoded>
    </item>
    <item>
      <title>plasticity and org-roam</title>
      <link>https://mike.puddingtime.org/posts/2023-04-30-plasticity-and-org-roam/</link>
      <pubDate>Sun, 30 Apr 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-30-plasticity-and-org-roam/</guid>
      <description>The more a thing tends to be permanent, the more it tends to be lifeless.</description>
      <content:encoded><![CDATA[<blockquote>
<p>&ldquo;The more a thing tends to be permanent, the more it tends to be lifeless.&rdquo;</p>
</blockquote>
<div class="src-block-caption">
<p>— Alan Watts</p>
</div>
<p>A few days ago <a href="https://mike.puddingtime.org/posts/2023-04-26-daily-notes/">I wrote about Zettelkasten</a>:</p>
<blockquote>
<p>In the end, it just wasn’t for me. I tried it, and Obsidian is an excellent tool for organizing your work that way, but I think the problem I had with it was that the ratio of “volume of stuff that’s just there in my head” to “volume of stuff I need to keep in a second brain” didn’t justify the existence of the second brain, or at least not one organized in classic Zettelkasten fashion.</p>
</blockquote>
<p>That remains true. However &hellip;</p>
<p>In the process of thinking about <a href="/posts/2023-02-28-about-old-posts/">what to make of old blog posts</a>  I realized that one of my bigger impediments to blogging at all was a little personal confusion about what a blog is. In the past year I had a small crisis around my personal domains and realized things had sprawled and gotten a little too tangled up, so I got a new domain that solved a few problems the old one caused, and I went to some effort to establish new email addresses and sites. It was time to do all that, because I was pretty sure I was about to get thrown out of my work nest, and I had some ideas about what I needed to do to be ready for that.</p>
<p>But solving one problem &ndash; correcting for a lack of intentionality in my web presence over years &ndash; led to another one I only recently figured out, which was about having the <em>wrong</em> intentions once I got more intentional.</p>
<h2 id="the-brochure-site-months">The brochure site months</h2>
<p>I got very into the &ldquo;personal branding&rdquo; aspects of my web presence. I had some ideas about a small book, I had done some writing about work, and I was feeling defensive about what exactly it was I said I did there. So as I sat down to think about why I wanted to have a website, there was a &ldquo;professional considerations&rdquo; piece to it that loomed larger than it ever had, and I was thinking in the direction of &ldquo;content marketing.&rdquo;</p>
<p>I built that site and really enjoyed doing it. It was a chance to stretch a few web development muscles, and I really loved the way I&rsquo;d managed to blend my photography and writing. And I liked the idea of positioning it as a slow-moving, professionally safe space where I could pull in work from past sites, but keep the focus on The Work Persona. I didn&rsquo;t discount the value of a more personal, faster-moving site, so I focused on fixing up my microblog, too.</p>
<p>Actually maintaining that sort of web presence turned out to be a drag. The second the site was up and running it became a gigantic, statically generated Blank Page Problem. Over on the microblog I was just being me; on the &ldquo;core&rdquo; site I was struggling with being the kind of writer I sort of hate to come across out in the real world, trying to sound <em>authoritative</em> and <em>opinionated</em> about <em>matters of professional import</em>. I completely get that some people manage to strike a very authentic balance with writing about what they care about, and what they care about happening to be, in part, their professional life. I couldn&rsquo;t make myself fill the page, so the site mostly sat.</p>
<p>Then I <em>did</em> get thrown out of the nest, and something I thought was kind of irritating but would eventually be surmountable when push came to shove actually became even more of an issue for me, because what had been a simple but misguided idea that I&rsquo;d just gradually fill that site up with stuff as it came to me felt inadequately urgent.</p>
<p>I am very lucky to have a supportive partner and some other good voices around me, because after I spent maybe six weeks last  fall using a period I&rsquo;d known for <em>months</em> was meant to be restful downtime doing anything but resting, thrashing around, coming up with Big Projects, I just settled down and actually rested. I just stopped. Or rather, I stopped doing anything I would ordinarily believe I was <em>supposed</em> to do, and <a href="https://mike.puddingtime.org/2023-01-17-oauth-rubocop-a/">let myself do</a> what I <em>wanted</em> to do as it occurred to me to do it:</p>
<blockquote>
<p>&hellip; I am feeling good because I realized at some point over the past couple of weeks that I am doing all this because it is playing. I used to do a lot of little utility scripts and silly gadgets because it was fun and absorbing, not because it was hugely practical or efficient. It was just playing. I stopped playing for a long while. It feels good to play again.</p>
</blockquote>
<p>Since January, I&rsquo;ve slowly turned back to what I <em>need</em> to be doing, and I&rsquo;ve been immensely grateful that my friends and network have been there for me as I find my way back to a job because there are parts of The Job Hunt that are a colossal drag &ndash; the grind of getting opportunities into the top of the funnel &ndash; and there are parts of it, once something works its way down the funnel that are hard in different ways.</p>
<p>The value of this site has played out a little differently than I imagined when I thought it was going to be a content marketing thing. It definitely <em>does</em> come up in interviews, because I&rsquo;ve done writing for it that is about work stuff, but less <code>HERE IS A BROCHURE OF MY THOUGHT LEADERSHIP</code> and more &ldquo;oh yeah, you know, I wrote about this very thing a few weeks ago, and found my thoughts changing a little once I thought it out more.&rdquo; A <em>few</em> people say &ldquo;oh, I&rsquo;d love to read that if you don&rsquo;t mind sending me the link,&rdquo; but not many. <em>But</em> when they&rsquo;ve asked there&rsquo;s been, in funnel terms, a 100 percent conversion rate from top-of-the-funnel to middle-of-the-funnel. That&rsquo;s great.</p>
<p>But the hidden half of that has been the very real struggle, after ten years in one place, of getting back into the swing of looking for my next thing to do, and shifting from that mode of sitting quietly with your hands folded politely in your lap answering questions as correctly as you can muster, to  finding the people who want to have actual conversations and <em>welcoming</em> the opportunity they present.</p>
<p>It took getting all the way to the end of one very mechanistic, flat, incurious hiring process to flip a switch in my brain.</p>
<p>One of the interviewers as good as said &ldquo;well, you&rsquo;re coming from this environment you were in so you probably are this certain way&rdquo; in the midst of a &ldquo;here are nine questions, prepare your three-minute responses, we are not permitted to have a conversation that deviates from you answering this question&rdquo; session. It was incredibly belittling and frustrating, and it finally sparked the thing that I guess you have to have sparked if you&rsquo;re going to continue the process of going around asking people to give you money in exchange for having to use Outlook or whatever, which was a sense that my background &ndash; the places I&rsquo;ve been, the things I&rsquo;ve seen, and the work I&rsquo;ve done &ndash; adds up to something more than a collection of self-published pamphlets about businessing.</p>
<p>Anyhow, the switch that flipped was, &ldquo;this could get harder before it gets easier, but it&rsquo;s going to suck hard and it&rsquo;s not going to end well if I keep looking over my shoulder.&rdquo; I, er, <em>contain multitudes</em>, and I have come to believe that the best way to get across who I am is to quit trying to draw a circle around me.</p>
<p>(I do not, by the way, have a &ldquo;so I told that guy to shove the job&rdquo; story to tell. I got declined, apparently very narrowly. I definitely would have taken the job, because I&rsquo;m fine working against expectations. You cannot go from &ldquo;studied philosophy&rdquo; to &ldquo;worked at a newspaper&rdquo; to &ldquo;administered UNIX systems&rdquo; to &ldquo;volunteered for airborne school&rdquo; without feeling comfortable being misunderstood by everyone around you.)</p>
<p>So this site is now the way it is, instead of the Brochure About Mike it was meant to be, because this, more or less and as much as I&rsquo;m willing to disclose, is <em>me</em>.</p>
<h2 id="okay-but-something-about-org-roam">Okay, but something about org-roam?</h2>
<p>Right. As I was saying. A few days ago I wrote about Zettelkasten, related some reasons I decided at the time it was not for me, and then gently defended what I took to be a mild challenge from someone who wished I&rsquo;d given it more of a chance.</p>
<p>But if the point of this site is less to <em>represent me as a unit of productive capacity</em> and more to <em>think out loud</em> about my preoccupations as they emerge (and hence become its own sort of representation), then it did its work in this case, because over the weekend that post ended up being just a thesis that I applied to what I thought I&rsquo;d want to use a Zettelkasten system for, flavored in part by my natural (and not always flattering) skepticism about why people get into these things.</p>
<p>But like all good theses, it is subject to dialectical forces &ndash; new contexts, conditions, or information.</p>
<p>In the process of trying to salvage something from hours of over-preparation, I realized I had a bunch of good material about what I think about certain things that was suffering from being stuffed into the mold of a very rigid and dysfunctional interview process that nevertheless had forced me to rethink my value proposition and set my sights a little higher than they were going in. And I also realized I have a few opportunities coming up &ndash; and will no doubt have more &ndash; to use that material very soon.</p>
<p>As I killed a little time waiting for Al to get home, my mind first went to &ldquo;well, turn it all into a couple of very thoughtful essays about IT, inclusion, etc. the better to stock your website with brochures.&rdquo;</p>
<p>Then I thought, &ldquo;we told ourselves we don&rsquo;t like doing that.&rdquo; Or as a friend put it, &ldquo;I thought you said you were over the idea of writing weird shit for LinkedIn.&rdquo;</p>
<p><em>Then</em> I thought, &ldquo;but wow, it can&rsquo;t stay in this form, because it&rsquo;ll always smell like the janitor&rsquo;s closet at the county jail when you try to get any good out of it.&rdquo;</p>
<p>I realized I wanted to do with it what I&rsquo;d sworn 48 hours earlier didn&rsquo;t really make sense to me, which was to sort of draw dashed lines on the surface of that big, strangely shaped accretion of thought, then go at it with a hammer until I had a bunch of chunks I could label and repurpose. So I took some time to re-read the org-roam manual, look at some half-understood config I&rsquo;d put in place when I was giving it a try post-Obsidian, and clear my head of the idea that I was going to some day write eight-dozen books about management thanks to Zettelkasten, or do anything particularly public at all, really.</p>
<p>Having done that, I started chunking out the ideas in that writing and  &ldquo;inserting nodes,&rdquo; in the org-roam parlance.</p>
<p>I didn&rsquo;t get too much into linking anything for now, preferring to start at the level of tagging. I once went to a talk then years later had an interesting exchange with the guy who invented the term &ldquo;folksonomy,&rdquo; and his ideas about free-tagging have stuck with me since. People often screw it up by assuming that free-tagging is somehow antithetical to &ldquo;categorization&rdquo; or other ways of making associations &hellip;  oh, <a href="http://www.ibiblio.org/hhalpin/homepage/notes/taggingcss.html">just read this for the problem with that</a>. Briefly, I have gotten hung up in the past with the advice to build <a href="https://justgage.github.io/moc.md">MoC pages,</a> etc. but was encouraged by that guy to think instead of tagging as  <a href="https://english.stackexchange.com/questions/44800/what-does-don-t-pave-the-cow-path-mean-in-this-context">cow-pathing</a>.  Eventually, you will want to put up lights and signs, and before that you may even want to make a map of the best ones. For now, I am just being careful to tag. When there is a nugget in something that I didn&rsquo;t manage to break down or separate from something close to it, I am giving it its own heading so I can make it a node with a tag.</p>
<p>Anyhow, I&rsquo;m giving the whole thing another try because I have a practical thing to do try it out on, and it is already helping me: I have a presentation coming up and it&rsquo;s great to go through that previous work shorn of a little of the original context.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-04-28</title>
      <link>https://mike.puddingtime.org/posts/2023-04-28-daily-notes/</link>
      <pubDate>Fri, 28 Apr 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-28-daily-notes/</guid>
      <description>Fixing mixed-pitch in Doom, Carlson&amp;rsquo;s fake populism, ethics in affiliate linking.</description>
      <content:encoded><![CDATA[<h2 id="mixed-pitch-in-doom">Mixed pitch in Doom</h2>
<p>Less a big thing to write about and more a thing I learned that was helpful after pounding my head against this wall:</p>
<p><code>mixed-pitch-mode</code>  allows for both variable and fixed pitches. It&rsquo;s nice for org-mode, where you&rsquo;ve got a mix of prose and more code-looking stuff &ndash; headings and body text look nicely typeset, property drawers and tags continue to use a fixed face.</p>
<p>My Doom font setting is pretty basic:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">doom-font</span> <span class="p">(</span><span class="nf">font-spec</span> <span class="nb">:family</span> <span class="s">&#34;Fira Code Retina&#34;</span> <span class="nb">:size</span> <span class="mi">15</span> <span class="nb">:weight</span> <span class="ss">&#39;regular</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="nv">doom-variable-pitch-font</span> <span class="p">(</span><span class="nf">font-spec</span> <span class="nb">:family</span> <span class="s">&#34;SF Pro&#34;</span> <span class="nb">:size</span> <span class="mi">16</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span></span></span></code></pre></div>
<p>&hellip; but for reasons that eluded me, when I entered <code>mixed-pitch</code> mode, my variable pitch font was way too small, except when it was way too big.</p>
<p>I did a lot of poking around, a lot of searching, and a lot of scrolling forums, then I broke down and asked ChatGPT, which told me to add this:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">mixed-pitch-set-height</span> <span class="mi">16</span><span class="p">)</span></span></span></code></pre></div>
<p>That did it.  Combined with the <code>doom-earl-grey</code> theme, I&rsquo;ve got a pleasant, low-contrast, paper-like display to work with.</p>
<h2 id="a-rare-political-link">A rare political link</h2>
<p>I was braced to hate this column, but ended up appreciating it a lot:</p>
<p><a href="https://www.thenation.com/article/society/tucker-carlson-fake-populism-fascism/">No, You Absolutely Do Not Have to Hand It To Tucker Carlson</a> (The Nation)</p>
<blockquote>
<p>&ldquo;&hellip; there’s every reason to view Carlson’s alleged anti-war politics and putative politics as a fraud. It’s true that Carlson worries about escalation in the Ukraine/Russia conflict and has pushed for diplomacy. But his position on that issue is based not on any aversion to militarism but a belief that the United States should focus its firepower on other enemies, notably Mexico and China. Rather like the late Gore Vidal (who, alas, made this argument in the pages of The Nation), Carlson wants an American-Russia alliance against the non-white hordes. International relations scholar Daniel Drezner observes, &lsquo;It&rsquo;s also hard to claim that Carlson was opposed to U.S. military adventurism; it’s more accurate to say Carlson preferred aggressive military adventurism closer to home. Carlson repeatedly called for using the military south of the border in Mexico.&rsquo;&rdquo;</p>
</blockquote>
<p>&hellip; and</p>
<blockquote>
<p>As for economic populism, Carlson is far more likely to criticize big corporations for “wokeness” (in other words trying to keep up with changing social mores) than union busting. His populism is the kind that worries about gender ambiguity in M&amp;Ms candy—not rampant inequality. He’s all too quick to revert to GOP business-class norms when there is a partisan battle. Business Insider reported on a telling moment in 2021 when Carlson “accused President Joe Biden of proposing a tax hike on wealthy Americans to ‘punish’ them.” This was a tax on people earning more than $400,000 per year—hardly a fitting target for proletarian outrage.</p>
</blockquote>
<p>In sum:</p>
<blockquote>
<p>His occasional populist and pacifist sentiments only exist in the context of a politics that aims to take justified anti-establishment outrage and harvest it for far-right ethnonationalism.</p>
</blockquote>
<p>Why was I braced to hate it?</p>
<p>Because one of my core theses about What is Going on Right Now is that formerly cherished political categories are disintegrating, but we&rsquo;re not doing a great job of understanding what that means, or allowing each other to explore what that means. So while it&rsquo;s good to call out a charlatan like Tucker Carlson or assorted other <em>faux</em> populists (<em>fauxpulists?</em>), it&rsquo;s not great when we just shoot on past that useful distinction-making and on into the territory of &ldquo;therefore, nothing they&rsquo;re saying should have any resonance with decent people.&rdquo;</p>
<p>The danger of Tucker Carlson and others like him is not, to me, that they think bad or dangerous things. It&rsquo;s that they are accomplished ideological entrepreneurs. They&rsquo;re good at catching scent of shifts in the popular mood, understanding the language of those shifts, and then folding those shifts into whatever their real political commitments are. I&rsquo;m not sure who you could name on the left that has shown the same acumen for that kind of political marketing. Bernie Sanders, AOC, Elizabeth Warren, and Katie Porter come to mind as politicians working the left populist beat. In terms of commentators? Not sure.</p>
<p>One bad side effect has been the rise of commentator who exist outside the mainstreams of conservative or liberal thought and engage in their own entrepreneurialism despite being badly confused about their own political commitments.</p>
<p>I&rsquo;m thinking of people like Batya Sargon Unghar, who wrote a snarling takedown of student loan forgiveness as a populist issue because, she said, it wasn&rsquo;t helping &ldquo;enough classes of people,&rdquo; implying that there couldn&rsquo;t be any working people with student loan debt. She has made some good observations about the cultural and class proclivities of the professional media &ldquo;class,&rdquo; but that&rsquo;s just it: She doesn&rsquo;t see a working reporter as a &ldquo;working class person.&rdquo; The top one percent of households in the US control a third of the wealth, the bottom half of US households control 2.6 percent of it,  but let&rsquo;s pit the nurse (or reporter, or software developer, or corporate recruiter, or technical writer) paying off their student loans against the person working a job that didn&rsquo;t require college.</p>
<p>And I&rsquo;m also thinking of the contrarian class &ndash; people who probably have some sort of left political commitment but respond poorly to reflexive rejection of an idea because the wrong person coopted it, and who end up contributing to a feedback loop: They become impatient with the echo chamber, they resent the lazy dunks and thoughtless inconsistencies of politics built around cultural antagonisms, and they get lumped, in turn, with &ldquo;the dark side,&rdquo; tainting anything <em>they&rsquo;ve</em> ever put forth regardless of its worthiness.</p>
<p>Anyhow, my point, I suppose, builds off this one:</p>
<blockquote>
<p>The strategy of selectively borrowing left-wing ideas in order to bolster a program of nationalism, racism, and gender conformity is not new. As Meyerson and Mavuram rightly observe, this is a familiar tactic of fascism, which typically emerges in a time where establishment politics are in crisis and the public is open to multiple solutions.</p>
</blockquote>
<p>I appreciate an article that can acknowledge that selective borrowing, and remind readers that Carlson and other fake populists like him are identifying &ldquo;what works&rdquo; about left political ideas. That doesn&rsquo;t mean we should spend our time understanding how we could rehabilitate Tucker Carlson: He does not want to be rehabilitated. He is a cynic whose commitments are not mine. But we should spend <em>some</em> time understanding what in there both resonates with our own politics and speaks to people who are suffering.</p>
<h2 id="affiliate-links-and-ethics">Affiliate links and ethics</h2>
<p>If you truly think a product is too bulky, pointlessly prods people toward buying a thing that replaces a shared good they probably already have, is hard to use, leaks water, takes forever, and <a href="https://www.theverge.com/23659598/steambox-electric-lunchbox-battery">is only worth a score of &ldquo;5/10&rdquo;</a> even though you couldn&rsquo;t even get your own spouse to try it out, I&rsquo;d propose that you not put affiliate links in your review.</p>
<p>I think this cuts to the core of my issue with modern review sites. The only way to get the reviews is to accept that they need affiliate link revenue; but you end up in situations like this, where the product is a sustainability nightmare about which the only nice things you can say are &ldquo;doesn&rsquo;t smell,&rdquo; &ldquo;looks cute,&rdquo; and &ldquo;good if you don&rsquo;t have an outlet&rdquo; (even though you also note it is too big and heavy to actually carry anywhere there are no outlets). They still feel okay tossing up the affiliate links, even though their review nets out to &ldquo;useless; do not buy.&rdquo;</p>
<p>I&rsquo;m just picking on this review because it went by in the news stream last week. There&rsquo;s much worse.</p>
<p>But man it could also be better. There is so much electronic junk in the world &ndash; drop-shipped ripoffs, poorly thought out Kickstarters, parts-bin garbage. There should be less of it. It should not be okay to make something out of plastic and toxic battery components <a href="https://www.macrumors.com/2023/04/26/amazon-discontinuing-halo-wristband/">then render it useless in six months</a>.</p>
<p>It&rsquo;s fine for the Verge to do its journalistic duty by fairly reviewing a bad product and saying it&rsquo;s bad. It&rsquo;s correct for the Verge to disclose the existence of affiliate links to better educate people on how they&rsquo;re incentivized.  It would be awesome if the Verge, and sites like it, would go one step further and say &ldquo;we&rsquo;re not going to help you buy this thing&rdquo; when they plainly don&rsquo;t think the thing is worth buying, and when that thing is going to be turning up in a landfill.</p>
<p>Okay.  That&rsquo;s it for today. This afternoon is spoken for.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Were you to attempt something like this in AppleScript</title>
      <link>https://mike.puddingtime.org/posts/2023-04-27-were-you-to-attempt-this-with-applescript/</link>
      <pubDate>Thu, 27 Apr 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-27-were-you-to-attempt-this-with-applescript/</guid>
      <description>&lt;p&gt;I started down the path of &lt;a href=&#34;https://mike.puddingtime.org/posts/20230413-making-a-plaintext-personal-crm-with-org-contacts/&#34;&gt;building some sort of PRM in org-mode&lt;/a&gt; because I couldn&amp;rsquo;t find anything that worked the way I wanted. I did briefly look at Apple&amp;rsquo;s Contacts app, and also at &lt;a href=&#34;https://flexibits.com/cardhop&#34;&gt;Cardhop&lt;/a&gt;, which builds on top of your Contacts database but still makes some assumptions about how good you are at all at remembering to reach out to people.&lt;/p&gt;
&lt;p&gt;I also looked at &lt;a href=&#34;https://monicahq.com&#34;&gt;Monica&lt;/a&gt;, an open source PRM. The promising part of Monica is its API. The web UI itself shows comprehensive data for each contact, but does not do anything in the way of bulk editing and has no automation at all. It&amp;rsquo;s laborious to bootstrap.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I started down the path of <a href="https://mike.puddingtime.org/posts/20230413-making-a-plaintext-personal-crm-with-org-contacts/">building some sort of PRM in org-mode</a> because I couldn&rsquo;t find anything that worked the way I wanted. I did briefly look at Apple&rsquo;s Contacts app, and also at <a href="https://flexibits.com/cardhop">Cardhop</a>, which builds on top of your Contacts database but still makes some assumptions about how good you are at all at remembering to reach out to people.</p>
<p>I also looked at <a href="https://monicahq.com">Monica</a>, an open source PRM. The promising part of Monica is its API. The web UI itself shows comprehensive data for each contact, but does not do anything in the way of bulk editing and has no automation at all. It&rsquo;s laborious to bootstrap.</p>
<p>In the process of trying to figure out how I could write some automation to move Contacts information beyond the basic vCard fields into Monica I did end up having to learn about how macOS Contacts work and realized you can create custom labels for date fields then add them to your card editing template in Contacts&rsquo; preferences.</p>
<p>The data entry widget for these fields expects a date and is tolerant of not entering a year (which helps it support, er, &ldquo;polite&rdquo; birthdays). You can, in turn, use it somewhat opaquely in a Contacts smart list: There&rsquo;s a generic &ldquo;Date&rdquo; field you can filter on that looks at date fields in the card.  Paired with a &ldquo;within/not within,&rdquo; or &ldquo;in the next&rdquo; parameter, you can make a smart list of &ldquo;people not contacted in the past 30 days,&rdquo; etc.</p>
<p>If Contacts smart lists could also use groups, you could do a lot by just setting a &ldquo;last contacted&rdquo; date field and making a set of smart lists based on group membership. Contacts smart lists <em>can&rsquo;t</em> use groups, though, which is a strange oversight.</p>
<p>As I was trying to figure out, though, how to get my contacts uploaded to Monica in a way that would let me use its API to add tags to them once they were imported, I worked out some AppleScript that let me prepend a contact&rsquo;s group into its note as a hashtag. Contacts smart lists <em>can</em> filter on the contents of notes.</p>
<p>As a solution goes, it&rsquo;s in the category of &ldquo;cheap and cheerful.&rdquo; If you wanted to use macOS Contacts to keep track of your most recent touchpoint with someone, and drive a little automation to surface contacts you haven&rsquo;t reached out to in a while, you could do it with one custom field and adopting a simple convention for notes. You&rsquo;re also well into the territory of things AppleScript can do to help out, too: It is trivial to write scripts that automate logging, etc. or even write reminders or make events in a contacts calendar. In fact, here&rsquo;s a script that operates on the selected contact and lets you log activity in its note:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-applescript" data-lang="applescript"><span class="line"><span class="cl"><span class="k">set</span> <span class="nv">theDate</span> <span class="k">to</span> <span class="nb">current date</span>
</span></span><span class="line"><span class="cl"><span class="k">set</span> <span class="nv">noteDate</span> <span class="k">to</span> <span class="nb">do shell script</span> <span class="s2">&#34;date &#39;+%Y-%m-%d&#39;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">tell</span> <span class="nb">application</span> <span class="s2">&#34;Contacts&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="k">set</span> <span class="nv">selectedPeople</span> <span class="k">to</span> <span class="nv">selection</span>
</span></span><span class="line"><span class="cl">	<span class="k">repeat</span> <span class="k">with</span> <span class="nv">thePerson</span> <span class="k">in</span> <span class="nv">selectedPeople</span>
</span></span><span class="line"><span class="cl">		<span class="k">set</span> <span class="nv">customDates</span> <span class="k">to</span> <span class="nv">custom</span> <span class="nv">dates</span> <span class="k">of</span> <span class="nv">thePerson</span>
</span></span><span class="line"><span class="cl">		<span class="k">set</span> <span class="nv">lastContactedExists</span> <span class="k">to</span> <span class="no">false</span>
</span></span><span class="line"><span class="cl">		<span class="k">repeat</span> <span class="k">with</span> <span class="nv">aCustomDate</span> <span class="k">in</span> <span class="nv">customDates</span>
</span></span><span class="line"><span class="cl">			<span class="k">if</span> <span class="na">label</span> <span class="k">of</span> <span class="nv">aCustomDate</span> <span class="ow">is</span> <span class="s2">&#34;last contacted&#34;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">				<span class="k">set</span> <span class="nv">value</span> <span class="k">of</span> <span class="nv">aCustomDate</span> <span class="k">to</span> <span class="nv">theDate</span>
</span></span><span class="line"><span class="cl">				<span class="k">set</span> <span class="nv">lastContactedExists</span> <span class="k">to</span> <span class="no">true</span>
</span></span><span class="line"><span class="cl">			<span class="k">end</span> <span class="k">if</span>
</span></span><span class="line"><span class="cl">		<span class="k">end</span> <span class="k">repeat</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="ow">not</span> <span class="nv">lastContactedExists</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">			<span class="k">if</span> <span class="nv">length</span> <span class="k">of</span> <span class="nv">customDates</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">				<span class="k">set</span> <span class="nv">firstCustomDate</span> <span class="k">to</span> <span class="nb">first</span> <span class="nb">item</span> <span class="k">of</span> <span class="nv">customDates</span>
</span></span><span class="line"><span class="cl">				<span class="k">set</span> <span class="nv">newCustomDate</span> <span class="k">to</span> <span class="nb">make</span> <span class="nb">new</span> <span class="nv">custom</span> <span class="nv">date</span> <span class="nb">at</span> <span class="nb">after</span> <span class="nv">firstCustomDate</span>
</span></span><span class="line"><span class="cl">			<span class="k">else</span>
</span></span><span class="line"><span class="cl">				<span class="nb">make</span> <span class="nb">new</span> <span class="nv">custom</span> <span class="nv">date</span> <span class="nb">at</span> <span class="k">end</span> <span class="k">of</span> <span class="nv">custom</span> <span class="nv">dates</span> <span class="k">of</span> <span class="nv">thePerson</span> <span class="k">with</span> <span class="na">properties</span> <span class="p">{</span><span class="na">label</span><span class="p">:</span><span class="s2">&#34;last contacted&#34;</span><span class="p">,</span> <span class="nv">value</span><span class="p">:</span><span class="nv">theDate</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">end</span> <span class="k">if</span>
</span></span><span class="line"><span class="cl">		<span class="k">end</span> <span class="k">if</span>
</span></span><span class="line"><span class="cl">		<span class="k">set</span> <span class="nv">theNote</span> <span class="k">to</span> <span class="nv">note</span> <span class="k">of</span> <span class="nv">thePerson</span> <span class="k">as </span><span class="nc">string</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="nv">theNote</span> <span class="ow">is</span> <span class="s2">&#34;missing value&#34;</span> <span class="k">then</span> <span class="k">set</span> <span class="nv">theNote</span> <span class="k">to</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">		<span class="k">set</span> <span class="nv">prependText</span> <span class="k">to</span> <span class="na">text returned</span> <span class="k">of</span> <span class="p">(</span><span class="nb">display dialog</span> <span class="s2">&#34;Enter text to prepend to the note of &#34;</span> <span class="o">&amp;</span> <span class="na">name</span> <span class="k">of</span> <span class="nv">thePerson</span> <span class="o">&amp;</span> <span class="s2">&#34;:&#34;</span> <span class="nv">default</span> <span class="nv">answer</span> <span class="s2">&#34;&#34;</span> <span class="nb">buttons</span> <span class="p">{</span><span class="s2">&#34;Cancel&#34;</span><span class="p">,</span> <span class="s2">&#34;OK&#34;</span><span class="p">}</span> <span class="nv">default</span> <span class="nb">button</span> <span class="s2">&#34;OK&#34;</span> <span class="nv">cancel</span> <span class="nb">button</span> <span class="s2">&#34;Cancel&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="k">set</span> <span class="nv">noteUpdated</span> <span class="k">to</span> <span class="s2">&#34;[&#34;</span> <span class="o">&amp;</span> <span class="nv">noteDate</span> <span class="o">&amp;</span> <span class="s2">&#34;] &#34;</span> <span class="o">&amp;</span> <span class="nv">prependText</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="nv">theNote</span> <span class="ow">is not</span> <span class="s2">&#34;&#34;</span> <span class="k">then</span> <span class="k">set</span> <span class="nv">noteUpdated</span> <span class="k">to</span> <span class="nv">noteUpdated</span> <span class="o">&amp;</span> <span class="no">return</span> <span class="o">&amp;</span> <span class="nv">theNote</span> <span class="o">&amp;</span> <span class="no">return</span> <span class="o">&amp;</span> <span class="s2">&#34; &#34;</span> <span class="o">&amp;</span> <span class="no">return</span>
</span></span><span class="line"><span class="cl">		<span class="k">set</span> <span class="nv">note</span> <span class="k">of</span> <span class="nv">thePerson</span> <span class="k">to</span> <span class="nv">noteUpdated</span>
</span></span><span class="line"><span class="cl">		<span class="nv">save</span> <span class="nv">thePerson</span>
</span></span><span class="line"><span class="cl">	<span class="k">end</span> <span class="k">repeat</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span> <span class="k">tell</span></span></span></code></pre></div>
<p>So, looking at that, would you <em>want</em> to glue all this together with Applescript?</p>
<p>I don&rsquo;t think so. I don&rsquo;t, anyhow. It just took me a morning to figure that out.</p>
<p>In the process of roughing out automation for creating reminders, for instance, I managed to get Reminders.app to beachball on every run with a simple five-liner. Why? I don&rsquo;t know. Stack Overflow didn&rsquo;t know. But after a good 15 years of using AppleScript for jobs large and small, I know that sometimes you find its weird little corner cases and that&rsquo;s all there is to it. I&rsquo;d rather <a href="https://www.jwz.org/blog/2003/05/no-good-deed-goes-unpunished/">tell Jamie Zawinski that I don&rsquo;t know who the author of XScreensaver is</a> than ask Apple to fix it.</p>
<p>When I ask myself &ldquo;would I want to build something on top of this ecosystem that I mean to use forever?&rdquo; I can&rsquo;t even figure out three scripts I would need to write then get to the end of debugging the second one before I know the answer is &ldquo;no.&rdquo;</p>
<p>I mean, what does <em>forever</em> mean? Because my personal belief is that we have to assess the foreverness of the competing candidates, and probably think about how amenable data kept in the least forever of those formats is to being migrated to a more forever format/system:</p>
<ul>
<li>macOS Contacts</li>
<li>org-mode</li>
<li>vCard</li>
<li>plain text with moderately elaborate markup amenable to some automated processing</li>
</ul>
<p>(I put that list in ascending order of longevity/permanence, feeling very appreciative that org-mode allowed me to reorder it with <code>opt arrow</code>).</p>
<p>I trust macOS Contacts a bit. I don&rsquo;t how much money I would be willing to risk on a series of bets about it working as it does today in 2, 5, or 10 years. While trying to understand my AppleScript options with it I was brought face-to-face with changes to the underlying scripting model several times. In all fairness, those changes played out over decades and it&rsquo;s only because I&rsquo;m at a point in life where I can still think &ldquo;OS X is new&rdquo; that they even seem mentionable. It&rsquo;s also completely possible to get Contacts info out into some other format. There&rsquo;s also just the whole &ldquo;ramming your head against AppleScript&rdquo; aspect of the problem.</p>
<p>Moving up the Pyramid of Forever, I trust org-mode to be around for a very long time, but can also see how the API is still subject to change. Functions come and go so automation can break and make it hard to keep a contacts list maintained. On the other hand, I&rsquo;m not doing much now that couldn&rsquo;t be done by hand until I figured it out, and the things I&rsquo;ve bumped into are pretty small so far: changes in the namespace, functional replacements, etc.</p>
<p>Moving on:</p>
<p>I trust the vCard standard to stay how it is a bit more. It&rsquo;s on &hellip; version 3 or 4? &hellip; of the spec? There&rsquo;s a spec. There are a lot of stakeholders interested in that spec. Even Apple quietly crams a whole vCard property into each contact, even if it has its own version of each property you&rsquo;d find in a vCard anyhow.</p>
<p>So, moving on to the top of the pyramid:</p>
<p>I trust structured plain text to be useful for the rest of my life.</p>
<p>So something built on org-mode seems like the smart play for data longevity? Even if all my automation broke, core org-mode makes it easy to do the things I do: change todo states, add values to the <code>PROPERTIES</code> drawer, add tags, log changes, etc.</p>
<p>The one thing that I&rsquo;ve <em>mostly</em> decided not to worry about is the disconnect between my contacts list and my org-contacts file.</p>
<p>One useful feature of contacts via Fastmail is the dynamic &ldquo;Autosaved&rdquo; group. If I write someone, they go into that group. Periodically moving contacts that surface there into one of my permanent groups then removing them from &ldquo;Autosaved&rdquo; provides a simple, organic workflow for keeping up with new people. There is also a bunch of useful automation present in macOS/iOS for surfacing things about contacts from other apps, so you&rsquo;re constantly being offered the opportunity to pull in new information. This morning, for instance, going through my Contacts list, I noticed that something somewhere in the bowels of macOS or iOS was beginning to notice connections between my contacts and Ivory, the Mastodon client. That&rsquo;s pretty cool.</p>
<p>On the other hand, <em>this</em> is well within AppleScript&rsquo;s wheelhouse:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-applescript" data-lang="applescript"><span class="line"><span class="cl"><span class="k">tell</span> <span class="nb">application</span> <span class="s2">&#34;Contacts&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="k">set</span> <span class="nv">selectedContacts</span> <span class="k">to</span> <span class="nv">selection</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nv">length</span> <span class="k">of</span> <span class="nv">selectedContacts</span> <span class="ow">is not</span> <span class="mi">1</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">		<span class="nb">display alert</span> <span class="s2">&#34;Please select exactly one contact.&#34;</span>
</span></span><span class="line"><span class="cl">		<span class="no">return</span>
</span></span><span class="line"><span class="cl">	<span class="k">end</span> <span class="k">if</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">set</span> <span class="nv">theContact</span> <span class="k">to</span> <span class="nb">first</span> <span class="nb">item</span> <span class="k">of</span> <span class="nv">selectedContacts</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">set</span> <span class="nv">theName</span> <span class="k">to</span> <span class="na">name</span> <span class="k">of</span> <span class="nv">theContact</span> <span class="k">as </span><span class="nc">text</span>
</span></span><span class="line"><span class="cl">	<span class="k">set</span> <span class="nv">theEmails</span> <span class="k">to</span> <span class="nv">value</span> <span class="k">of</span> <span class="nv">emails</span> <span class="k">of</span> <span class="nv">theContact</span> <span class="k">as </span><span class="nc">text</span>
</span></span><span class="line"><span class="cl">	<span class="k">set</span> <span class="nv">thePhones</span> <span class="k">to</span> <span class="nv">value</span> <span class="k">of</span> <span class="nv">phones</span> <span class="k">of</span> <span class="nv">theContact</span> <span class="k">as </span><span class="nc">text</span>
</span></span><span class="line"><span class="cl">	<span class="k">set</span> <span class="nv">theNote</span> <span class="k">to</span> <span class="nv">note</span> <span class="k">of</span> <span class="nv">theContact</span> <span class="k">as </span><span class="nc">text</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c">-- Format the contact data as an org contacts string</span>
</span></span><span class="line"><span class="cl">	<span class="k">set</span> <span class="nv">theContactString</span> <span class="k">to</span> <span class="s2">&#34;** &#34;</span> <span class="o">&amp;</span> <span class="nv">theName</span> <span class="o">&amp;</span> <span class="s2">&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">:PROPERTIES:
</span></span></span><span class="line"><span class="cl"><span class="s2">:EMAIL: &#34;</span> <span class="o">&amp;</span> <span class="nv">theEmails</span> <span class="o">&amp;</span> <span class="s2">&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">:PHONE: &#34;</span> <span class="o">&amp;</span> <span class="nv">thePhones</span> <span class="o">&amp;</span> <span class="s2">&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">:NOTE: &#34;</span> <span class="o">&amp;</span> <span class="nv">theNote</span> <span class="o">&amp;</span> <span class="s2">&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">:NAME: &#34;</span> <span class="o">&amp;</span> <span class="nv">theName</span> <span class="o">&amp;</span> <span class="s2">&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">:END:&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c">-- Copy the contact string to the clipboard</span>
</span></span><span class="line"><span class="cl">	<span class="nb">set the clipboard to</span> <span class="nv">theContactString</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span> <span class="k">tell</span></span></span></code></pre></div>
<p>&ldquo;Look through new contacts, run that script from a keyboard shortcut, paste the new contact into my <code>contacts.org</code> file.&rdquo;</p>
<p>I could go one step further and <em>append</em> the text to my <code>contacts.org</code> file, but I don&rsquo;t like operating on busy files like that.</p>
<p>AppleScript was plainly built to do little things like that. You have to learn its sort of crabbed, verbose way of doing things, but it&rsquo;s not too hard (and Shortcuts is getting pretty good if you can deal with the sudden drop in functionality that can appear out of nowhere when you hit the limits of some Apple engineer&rsquo;s imagination or time).</p>
<p>Anyhow, it all just comes down to aesthetics and preferences, right?</p>
<p>I&rsquo;ve got a draft heading sitting in my blog.org file with a title of &ldquo;Plain text is calming.&rdquo; I&rsquo;m not sure where that little essay is going, but I know where it started: When I&rsquo;m staring at a text editor I feel much better than when I&rsquo;m staring at a web or app UI. I might have some challenges with discoverability, or a lack of forgiveness for little slips of the finger, or whatever. But I still feel better because I&rsquo;ve been a happy citizen of Plaintext Land for over 30 years, and there is a governing mentality there that does not exist in other parts of the technology world. I&rsquo;m not saying the <a href="https://www.puppet.com/docs/puppet/8/http_api/pson.html">occasional wheel doesn&rsquo;t get reinvented,</a> but I am saying that with most plaintext stuff you get to choose your tools, or make them for yourself if there are no good choices. So it&rsquo;s calming because I don&rsquo;t have that feeling of always looking for the exit when I encounter a plaintext system. I know it&rsquo;s there.  That&rsquo;s the preference, anyhow. I made money for a few years being really, really good at turning CMS databases into plaintext and massaging them into other CMSes, so my patience for finding the structure and working with it is high. I don&rsquo;t worry about where the exit is because in my 40-year history with computers, it has never eluded me in the plaintext world.</p>
<p>The aesthetics are another kettle of fish, and plaintext people run a weird gamut from &ldquo;text editors are like samurai swords&rdquo; to &ldquo;mastery of a plaintext interface is a kind of performance art.&rdquo; Right now I&rsquo;m sort of luxuriating in Evil mode, because I finally get the emphasis on ruthless elimination of motion vi engenders. I&rsquo;ve  <a href="/img/Joy04.pdf">made terrible fun of people over this in the distant past</a> and feel a little bad about that, but less than two months into this particular experiment, I don&rsquo;t want to go back. Evil mode is like the end of the first Star Trek movie as far as I&rsquo;m concerned.</p>
<figure><img src="/img/decker_ilia.gif"
    alt="Will Decker and Ilia merging into some sort of computer overmind in Star Trek: TMP">
</figure>

<p>Anyhow, I do want to get back to the whole &ldquo;plaintext is calming&rdquo; idea and do some more writing about it. Today&rsquo;s jaunt into &ldquo;what if I could make what I wanted in the macOS ecosystem?&rdquo; was one of those processes I go through when I&rsquo;ve gone so far with an idea and wonder if I really want to commit &ndash; if I&rsquo;m not making life a little harder on myself than I need to, or if there&rsquo;s not some simpler way to do it (even if still in the DIY mode,) and the answer came back &ldquo;don&rsquo;t think there is.&rdquo; I&rsquo;m at home in what I made.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-04-25</title>
      <link>https://mike.puddingtime.org/posts/2023-04-25-daily-notes/</link>
      <pubDate>Tue, 25 Apr 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-25-daily-notes/</guid>
      <description>Mail restlessness alights on MailMate, editing web forms in Emacs with Atomic Chrome, org-recur for simple and readable recurrence, GUI org-capture with Captee, more on my org PRM.</description>
      <content:encoded><![CDATA[<h2 id="mail-restlessness-alights-on-mailmate">Mail restlessness alights on MailMate</h2>
<p>I was scrolling through <a href="https://www.reddit.com/r/emacs">/r/emacs</a> today and came across someone asking for help configuring GNUS and IMAP. It has been a very long time since I did that, so I had nothing useful to contribute &ndash; that config predated me using version control &ndash; but I did notice a link to
<a href="https://useplaintext.email">https://useplaintext.email</a>, which intrigued me.</p>
<p>The last time I allowed myself to have a strong opinion about email I was writing a &ldquo;how we work&rdquo; for Puppet&rsquo;s engineering department. The boss and I believed that this was our big shot at putting a lot of email evil to rest &ndash; the scourge of top-posting, the blight of replies too widely scoped to too many groups, the simple, everyday <em>harm</em> done by needless reply-alls that add nothing.</p>
<p>It turns out the top-posters won and we just have to live with that.</p>
<p>But there was <a href="https://useplaintext.email">https://useplaintext.email</a> reminding me of a more innocent time, using the word &ldquo;harmful&rdquo; in conjunction with HTML mail, taking one more swing at putting paid to top-posting once and for all.</p>
<p>It also had a list of plaintext email clients that I gave a quick scan, and one jumped out because I&rsquo;d heard of it but never really gave it a spin: <a href="https://freron.com">MailMate</a>. It&rsquo;s a Mac email client, it defaults to plain text but will read and send HTML email (via Markdown formatting on the sending side). It&rsquo;s also super keyboard-centric. <em>And</em> it has a &ldquo;bundles&rdquo; feature that lets you write your own plugins. It comes with a bunch, including one that saves a link to a message in an org-mode file.</p>
<p>I&rsquo;ve been fiddling around with it today and like it a lot. Besides its plaintext-centricity, keyboard-centricity, and extensibility, I love that you can open up a font picker, select a piece of the interface, and define a font for it. I went through and set everything to Fira Code Retina.</p>
<figure><img src="/img/mailmate_screen.jpg"
    alt="MailMate (in Scrambled Mode) with a fixed typeface for its UI"><figcaption>
      <h4>MailMate in Scrambled Mode</h4>
    </figcaption>
</figure>

<p>So, what about mu4e? Or mutt? Still on the docket.</p>
<p>mu4e has been bugging me a little because it has a very strange and possessive set of keymappings that collide with Doom Emacs. It hijacks the space key, so my muscle memory around the spacebar as the leader key is all messed up.</p>
<p>mutt remains mutt. I have a lot of affection for it, but its main advantage over anything at all is its customizable keyboard-centric nature, and MailMate has that, too, with less fussing.</p>
<p>And there is something a little weird about running isync on two machines in the house. I mean, theoretically it is no weirder than running two IMAP clients of any kind on two machines in the house. It&rsquo;s just an IMAP client. But it&rsquo;s a busy one.</p>
<h2 id="atomic-chrome-ghosttext">Atomic Chrome/GhostText</h2>
<p>There have been a few &ldquo;use your favorite editor for text areas in your browser&rdquo; things over the years. <a href="https://github.com/alpha22jp/atomic-chrome">Atomic Chrome</a> seems to work very well with <a href="https://github.com/fregante/GhostText">GhostText</a>, an extension that works with any of Firefox, Safari, or Chrome. You just install the package in Emacs, and invoke the listener with <code>(atomic-chrome-start-server)</code> somewhere in your init. It listens for the browser extension, which can be invoked with <code>CMD SHIFT k</code>, and opens a buffer for editing.</p>
<p>As I said, this kind of thing has been around for years. The Atomic Chrome/GhostText combination just seems to be reliable in a way I haven&rsquo;t come across in the past.</p>
<h2 id="org-recur">org-recur</h2>
<p>Scheduling recurrence in org isn&rsquo;t <em>that</em> bad, but <a href="https://github.com/mrcnski/org-recur">org-recur</a> makes it really simple. It just extends org-mode&rsquo;s syntax and allows you to add recurrence rules in a heading using notation like <code>|+1|</code>, <code>|Wkdy|</code>, or <code>|1,15|</code>, for &ldquo;every day,&rdquo; &ldquo;every weekday,&rdquo; and &ldquo;1st and 15th of every month,&rdquo; respectively.</p>
<h2 id="captee">Captee</h2>
<p>org-capture, like assorted &ldquo;use your favorite editor everywhere&rdquo; plugins, is one of those things I know people have had working for a while. I remember having it set up and working a very long time ago, then I lost that config and just forgot how to do it. <a href="http://yummymelon.com/captee/">Captee</a> is a little macOS app that worked pretty much out of the box once I had an emacsclient app set up.</p>
<p>It sits in your Mac share menu and grabs URLs from browsers and browser-adjacent apps then does &hellip; stuff &hellip; to them. If you want a simple Markdown link, it&rsquo;ll do that. If you want an org-mode link, it&rsquo;ll do that, copying both to the clipboard for you. It&rsquo;ll also work with your org-capture template of choice and send a link + title + selected text to org-mode.</p>
<p>The thing I really like about it is that it works well with my RSS reader, Reeder. I&rsquo;ve just bound it to <code>C</code> in the share actions list and it saves links/titles to my org-mode inbox.</p>
<h2 id="more-on-my-org-prm">More on my org PRM</h2>
<p>I guess the thing I&rsquo;ve been calling a plaintext CRM belongs to the &ldquo;PRM&rdquo; category (for &ldquo;personal,&rdquo; not &ldquo;customers.&rdquo;) So, it&rsquo;s my org PRM now. I&rsquo;ve been getting real use out of it.</p>
<p>Building it has followed a familiar pattern of feeling a gap, thinking surely someone has filled it, realizing that is not true, then going through the same loop of &ldquo;maybe this general purpose tool?&rdquo; and a halting attempt to use it, then a realization that it doesn&rsquo;t matter how many rounded corners and AJAX transition effects the roach motel has &ndash; it&rsquo;s still a roach motel.</p>
<p>It&rsquo;s just a bad category I can only assume is as bad as it is because nobody wants to pay for it at the consumer level, and I think nobody wants to pay for it because social media has ushered in an era where we&rsquo;re all sort of performing the family holiday letter on Facebook every day of the year.  And also our &ldquo;contacts&rdquo; are all over the place. Every attempt to consolidate them and de-dup them is a minor catastrophe, with your sister-in-law manifesting nine times in the same address book and Siri forgetting where &ldquo;home&rdquo; is because something has pulled in your address-free doppelganger.</p>
<p>Anyhow, the <a href="https://mike.puddingtime.org/posts/20230413-making-a-plaintext-personal-crm-with-org-contacts/">thing I built a few weeks ago?</a> I am using it daily:</p>
<ul>
<li>Agenda reports that tell me who I haven&rsquo;t been in touch with, but want to.</li>
<li>Reminders to schedule time with people or follow up on plans.</li>
<li>Easy,fast access to past messages from contacts.</li>
<li>Quick notes about conversations.</li>
<li>Reminders to ping recruiters.</li>
</ul>
<p>There are a lot of contact management apps. There are a few apps that will issue general-purpose &ldquo;AI-driven&rdquo; reminders to contact people. There&rsquo;s nothing that feels as easy to use. I tried one that featured a lot of nice automation, but it was iOS only and there was no way to mass-select and tag contacts. Even with my relatively modest list I would have been an hour pecking in tags. With a contacts.org file, it was very fast and simple. There&rsquo;s not even a smirky &ldquo;only free if your time is worth nothing&rdquo; rejoinder, because most of these products are harder to use and take more time to deliver less, or cost astronomical amounts for what they do.</p>
<p>Being plaintext and org-mode/elisp driven, it&rsquo;s also super easy to extend and modify. If I don&rsquo;t like a decision I made about how something works, it&rsquo;s an easy change. With org-mode capture templates, the input is all uniform and structured, so I don&rsquo;t worry about backing out or moving the content elsewhere. Basically, it&rsquo;s as calming for me as text ever has been.</p>
<p>Anyhow, I use it daily, I like it a lot, and it feels good to use.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Quick mu4e notes</title>
      <link>https://mike.puddingtime.org/posts/2023-04-20-quick-mu4e-notes/</link>
      <pubDate>Thu, 20 Apr 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-20-quick-mu4e-notes/</guid>
      <description>The bear dances! And it dances &amp;hellip; pretty good?</description>
      <content:encoded><![CDATA[<p><a href="https://www.djcbsoftware.nl/code/mu/mu4e.html">mu4e</a> is pretty good!</p>
<p>I went into giving mu a shot giving myself a giant side-eye for doing anything that involved running some MDA on a laptop, which is the minimum to use something like mu.</p>
<p>The intensity of the irritation with myself just deepened when my first pick for delivery &ndash; offlineimap &ndash; didn&rsquo;t pan out and I found myself configuring <a href="https://isync.sourceforge.io/">isync</a> to see if that would do any better. But isync (dba mbsync) works pretty well. It was easy to configure, I figured out how to gpg-encrypt my credentials, and I got it all set up in <a href="https://github.com/lra/mackup">mackup</a> such that I only have to configure/reconfigure in one place.</p>
<p>Most of my aversion to fiddling around with mail comes down to the MDA part, either because of the fragility of the component itself, or the flakiness of running these things on a laptop and how they&rsquo;ll cope with being daemonized in an environment that&rsquo;s not awake all the time. isync itself seems fine after several days, and it seems to be okay running as a <a href="https://github.com/Homebrew/homebrew-services">homebrew service</a> (with one minor caveat).</p>
<p>So that&rsquo;s getting mail down to the machine.</p>
<p><a href="https://github.com/djcb/mu">mu</a> itself &ndash; the indexing/search service for the maildir that isync creates &ndash; is pretty good. I&rsquo;ve got ~231,000 messages indexed in it, and it&rsquo;s super fast. As I&rsquo;ve been working on cleaning up my contacts list it&rsquo;s been great for just <code>mu find &quot;someone&quot;</code> from the command line. In some ways it&rsquo;s almost too helpful given the volume of messages, because you get stuff like multiple reply-to&rsquo;s in headers from Google+ email notifications or whatever, so one name can return 20 or 30 results in an address search.</p>
<p>So that brings us to mu4e.</p>
<p>Most of my aversion to running anything to do with &rsquo;net activity on Emacs comes down to blocking the whole app on a slow operation. I used to use GNUS for both IMAP and Usenet, and remember sometimes just having to get up and walk away during a sync until something finally got around to downloading. It was no way to live and I swore off anything to do with mail on Emacs unless I was willing to do it with an MDA of some kind in place (with all the attendant reasons I did not want to do that applying).</p>
<p>mu4e doesn&rsquo;t even really interact with whatever we could consider a &ldquo;physical&rdquo; mail message, though. I mean, yes &hellip; when you write a message with it, it is creating a tmp of something that is eventually handed off to an MTA, but for reading and processing it is not touching Maildir messages in the filesystem &ndash; it is instead interacting with the mu database as a set of queries. It&rsquo;s super fast. Fast the way Spotlight <em>can</em> be in Apple Mail, or search <em>can</em> be in Gmail, but consistently so.</p>
<p>UI-wise, mu4e is initially puzzling.</p>
<p>It starts from a place of &ldquo;every list of mail is just a database query, not a list of files in a <code>Maildir</code> directory.&rdquo; That&rsquo;s fine. Lots of things in computing exist as vectorized representations of an object in filesystem. The difference between mu4e and some of these other styles of digital information is that not a ton of work has been done to re-translate these vectorized abstractions back into their old metaphor. So the menus, etc. talk in terms of &ldquo;lists of headers&rdquo; and not &ldquo;folders of messages.&rdquo;</p>
<p>Broadly, you can tell mu4e started from mu &ndash;  &ldquo;let&rsquo;s make a mail search engine&rdquo; &ndash;  and then found expression as an Emacs MUA. While other MUAs <em>include</em> the idea of marking and operating but tend to start from a place of direct operation on a message (mutt&rsquo;s an exception), mu4e starts from the assumption you&rsquo;re going to mark and operate. So you don&rsquo;t &ldquo;delete a message,&rdquo; you mark it for deletion (or moving, or whatever) then either execute your marks with the <code>x</code> keystroke, or sign off on executing them when you leave a given header list (i.e. what everyone else calls a folder).</p>
<p>It&rsquo;s &hellip; I hate to even make it sound like this is a thing. If you have room in your life for setting up an MDA, a search engine for mail, and an Emacs MUA, you have whatever it is one needs to interact with a thin layer of abstraction over that whole pile of other abstractions. In some ways, mu4e feels to me like what might have happened if we chucked every innovation in mail interfaces that occurred after <a href="https://en.wikipedia.org/wiki/MH_Message_Handling_System">mh</a> and went straight to &ldquo;nah, dawg, your mail is still there on disk, but it also lives in The Matrix.&rdquo; There&rsquo;s just a little ramp for your muscle memory, is all.</p>
<p>So, what do you get in exchange, I guess?</p>
<p>First, it overcomes the core objection to running an MUA on Emacs at all: Everything except composing a message is a database operation, so everything is pretty fast.</p>
<p>People report being slowed down when trying to send messages with large attachments, and the proposed workaround (an async method you can configure) reportedly flakes out now and then. A dedicated MUA like Apple Mail might just step over that by backgrounding the send operation and letting you go on your way. Some webmail apps will give you the AJAX-y spinner until they&rsquo;re done receiving the attachment, but not otherwise lock you out of using your browser. Conceivably, a big attachment with mu4e will still cost you the use of your text editor for the duration of the attachment. People who refuse to use their text editors for things besides just editing text will find that unacceptable and weird, but also know it&rsquo;s a problem they&rsquo;ll never have.  People who think it&rsquo;s right and proper to use their text editors to catch up on Mastodon, read RSS, send mail, do their calendaring, track their todos, browse the web &hellip; aaaaaaand <em>sometimes</em> edit a text file may be more put off.</p>
<p>By default, at least in Doom, it also hooks its <code>update</code> function into firing off your MDA so it can make sure the database has the latest messages. So when you check your mail with it, it wants to kick off an <code>mbsync</code> run. That doesn&rsquo;t block it. I think it&rsquo;s possible to configure it to just prompt a reindexing of your Maildir instead of a whole MDA run. I need to do a little more in-depth investigation of how well isync is working for me because right now I think mu4e and the Homebrew daemonization fight with each other, but the net effect is that one process gets isync to download my mail instead of the other.</p>
<p><em>Otherwise</em> it is very, very fast, and its keyboard-centric UI is built toward getting at stuff quickly with a bunch of terse keystrokes to navigate to bookmarked mailboxes and canned search queries. Once you get the hang of marking/operating on a list of headers (with equally efficient keystrokes you can also customize) it&rsquo;s a mail processing machine.</p>
<p>No, sorry, excuse me &ndash; it is a mail database processing machine.</p>
<p>I&rsquo;ve previously named a few of these, but besides speed and efficiency, it offers a few other benefits:</p>
<p>First, I love composing mail in org mode markup. I sent myself a few test mails and loved, for instance, that an org mode src block was correctly colorized. org markup is a little more verbose than Markdown in some places. For instance, a blockquote isn&rsquo;t done with a leading <code>&gt;</code> but with a <code>+begin_quote</code> and <code>+end_quote</code> block.</p>
<p>Second, it&rsquo;s easily hooked into <code>org-capture</code>. Here&rsquo;s a capture template for putting a message in your inbox, marked for action within two days:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="o">&#39;</span><span class="p">(</span><span class="s">&#34;M&#34;</span> <span class="s">&#34;process-soon&#34;</span> <span class="nv">entry</span> <span class="p">(</span><span class="nv">file+headline</span> <span class="s">&#34;inbox.org&#34;</span> <span class="s">&#34;Messages&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="s">&#34;* TODO %:fromname: %a %?\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \&#34;+2d\&#34;))&#34;</span><span class="p">)</span></span></span></code></pre></div>
<p>In Doom Emacs, you get at that with <code>SPC X M</code>. When it&rsquo;s time to deal with the message, just tap <code>enter</code> on the heading and mu4e opens the message. Excuse me, no, it retrieves the header from the database.</p>
<p>In terms of drawbacks, setup time and learning curve aside, it has a few downsides:</p>
<p>At least one keymapping doesn&rsquo;t play well with Doom Emacs. In mu4e, the <code>SPC</code> key is mapped to <code>scroll-up-command</code> to serve as a pager, whereas that&rsquo;s the leader key for Doom everywhere else. The workaround is to use <code>OPT SPC</code> to get to Doom&rsquo;s menu, but I&rsquo;m still baking that into my muscle memory.</p>
<p>While orgmail-mode is cool and all, it interacts weirdly with the rest of the package sometimes, and I wish I could toggle its HTML mail features on and off now and then.</p>
<p>Its HTML mail presentation is as woeful as any mail client that starts from plaintext land, and the remedy is the same as it is in mutt: Learn the shortcut for opening HTML mail of any complexity straight into your browser.</p>
<p>Finally, it doesn&rsquo;t interact as well with <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Window-Convenience.html#index-winner_002dmode">winner mode</a> as I&rsquo;d like, leaving frames in a weird state after some operations. I did convince ChatGPT to write a hook for me to get mail composer frames to close instead of leaving the view split:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">after!</span> <span class="nv">mu4e</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-mu4e-close-frame-after-send</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Close the frame after sending a message in mu4e.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nf">eq</span> <span class="nv">major-mode</span> <span class="ss">&#39;mu4e-compose-mode</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">             <span class="p">(</span><span class="nv">not</span> <span class="p">(</span><span class="nv">mu4e~message-autopgp-p</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">delete-frame</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;message-sent-hook</span> <span class="nf">#&#39;</span><span class="nv">my-mu4e-close-frame-after-send</span><span class="p">))</span></span></span></code></pre></div>
<p>org-mail also seems to leave behind spare buffers it uses to put together the plaintext part of its multipart messages.</p>
<p>Net, though, it&rsquo;s so fast and efficient that I can see past most of that. I&rsquo;m sort of curious about connecting mutt to notmuch to see how that works, mostly because I know mutt very, very well and feel a little more fluent when it comes to customizing it. Some of the stuff I&rsquo;ve got set up in mu4e could be done with a little utility scripting in mutt.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Extending the plaintext CRM to mail contacts</title>
      <link>https://mike.puddingtime.org/posts/2023-04-18-extending-the-plaintext-crm-to-mail-contacts/</link>
      <pubDate>Tue, 18 Apr 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-18-extending-the-plaintext-crm-to-mail-contacts/</guid>
      <description>Added a little automation to contacts.org with a function that auto-populates a message buffer in mu4e.</description>
      <content:encoded><![CDATA[<p>I did some menu cleanup and refactor today to get my plaintext CRM into a slightly more mnemonic state. Here are the mappings, which are readable enough:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">map!</span> <span class="nb">:mode</span> <span class="nv">org</span>
</span></span><span class="line"><span class="cl">      <span class="nb">:leader</span>
</span></span><span class="line"><span class="cl">     <span class="p">(</span><span class="nb">:prefix-map</span> <span class="p">(</span><span class="s">&#34;C&#34;</span> <span class="o">.</span> <span class="s">&#34;CRM&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;Schedule Contact&#34;</span> <span class="s">&#34;s&#34;</span> <span class="nf">#&#39;</span><span class="nv">org-schedule-heading</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;Clear TODO states&#34;</span> <span class="s">&#34;z&#34;</span> <span class="nf">#&#39;</span><span class="nv">my/org-remove-todo</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;Update CONTACTED to today&#34;</span> <span class="s">&#34;t&#34;</span> <span class="nf">#&#39;</span><span class="nv">org-set-contacted-today</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;Update CONTACTED to ...&#34;</span> <span class="s">&#34;d&#34;</span> <span class="nf">#&#39;</span><span class="nv">org-set-contacted-date</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;SCHEDULE a date&#34;</span> <span class="s">&#34;S&#34;</span> <span class="nf">#&#39;</span><span class="p">(</span><span class="nb">lambda</span> <span class="p">()</span> <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span> <span class="p">(</span><span class="nv">my/org-set-heading-state-and-time</span> <span class="s">&#34;&#34;</span> <span class="mi">30</span> <span class="ss">&#39;s</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;Mail this contact&#34;</span> <span class="s">&#34;m&#34;</span> <span class="nf">#&#39;</span><span class="nv">my-org-contacts-email</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">     <span class="p">(</span><span class="nb">:prefix-map</span> <span class="p">(</span><span class="s">&#34;C r&#34;</span><span class="o">.</span> <span class="s">&#34;Remember to ...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">       <span class="nb">:desc</span> <span class="s">&#34;... write within 7 days&#34;</span> <span class="s">&#34;w&#34;</span> <span class="nf">#&#39;</span><span class="p">(</span><span class="nb">lambda</span> <span class="p">()</span> <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span> <span class="p">(</span><span class="nv">my/org-set-heading-state-and-time</span> <span class="s">&#34;WRITE&#34;</span> <span class="mi">7</span> <span class="ss">&#39;d</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">       <span class="nb">:desc</span> <span class="s">&#34;... followup in 3 days&#34;</span> <span class="s">&#34;f&#34;</span> <span class="nf">#&#39;</span><span class="p">(</span><span class="nb">lambda</span> <span class="p">()</span> <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span> <span class="p">(</span><span class="nv">my/org-set-heading-state-and-time</span> <span class="s">&#34;FOLLOWUP&#34;</span> <span class="mi">3</span> <span class="ss">&#39;s</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">       <span class="nb">:desc</span> <span class="s">&#34;... ping within 7 days&#34;</span> <span class="s">&#34;p&#34;</span> <span class="nf">#&#39;</span><span class="p">(</span><span class="nb">lambda</span> <span class="p">()</span> <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span> <span class="p">(</span><span class="nv">my/org-set-heading-state-and-time</span> <span class="s">&#34;PING&#34;</span> <span class="mi">3</span> <span class="ss">&#39;d</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">       <span class="nb">:desc</span> <span class="s">&#34;... invite within 3 days&#34;</span> <span class="s">&#34;i&#34;</span> <span class="nf">#&#39;</span><span class="p">(</span><span class="nb">lambda</span> <span class="p">()</span> <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span> <span class="p">(</span><span class="nv">my/org-set-heading-state-and-time</span> <span class="s">&#34;INVITE&#34;</span> <span class="mi">3</span> <span class="ss">&#39;d</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre></div>
<p>It&rsquo;s a bunch of &ldquo;tap the leader key, tap &ldquo;<code>C</code>&rdquo; for &ldquo;CRM,&rdquo; then do some common stuff,&rdquo; like setting deadlines to write someone, or update the <code>:CONTACTED:</code> property, or just set the <code>SCHEDULED:</code> date on a record. This is the <code>my/org-set-heading-state-and-time</code> function:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">my/org-set-heading-state-and-time</span> <span class="p">(</span><span class="nv">state</span> <span class="nv">days</span> <span class="kp">&amp;optional</span> <span class="nv">time-type</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Sets the TODO state and deadline or scheduled date of the current heading.
</span></span></span><span class="line"><span class="cl"><span class="s">   STATE is the new TODO state to set, and DAYS is the number
</span></span></span><span class="line"><span class="cl"><span class="s">   of days from the current date to set the new time. If TIME-TYPE
</span></span></span><span class="line"><span class="cl"><span class="s">   is &#39;d&#39;, sets a deadline; if &#39;s&#39;, sets a scheduled date; otherwise,
</span></span></span><span class="line"><span class="cl"><span class="s">   prompts the user for the time type. Removes any existing schedules
</span></span></span><span class="line"><span class="cl"><span class="s">   or deadlines before setting the new time.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span> <span class="p">(</span><span class="nf">list</span> <span class="s">&#34;WRITE&#34;</span> <span class="mi">7</span> <span class="no">nil</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">org-entry-put</span> <span class="no">nil</span> <span class="s">&#34;TODO&#34;</span> <span class="nv">state</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nv">org-entry-get</span> <span class="no">nil</span> <span class="s">&#34;DEADLINE&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">org-entry-delete</span> <span class="no">nil</span> <span class="s">&#34;DEADLINE&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nv">org-entry-get</span> <span class="no">nil</span> <span class="s">&#34;SCHEDULED&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">org-entry-delete</span> <span class="no">nil</span> <span class="s">&#34;SCHEDULED&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">new-time</span> <span class="p">(</span><span class="nf">format-time-string</span> <span class="s">&#34;&lt;%Y-%m-%d %a&gt;&#34;</span>
</span></span><span class="line"><span class="cl">                                      <span class="p">(</span><span class="nf">time-add</span> <span class="p">(</span><span class="nf">current-time</span><span class="p">)</span> <span class="p">(</span><span class="nv">days-to-time</span> <span class="nv">days</span><span class="p">)))))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">cond</span> <span class="p">((</span><span class="nf">equal</span> <span class="nv">time-type</span> <span class="ss">&#39;d</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nv">org-deadline</span> <span class="no">nil</span> <span class="nv">new-time</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">          <span class="p">((</span><span class="nf">equal</span> <span class="nv">time-type</span> <span class="ss">&#39;s</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nv">org-schedule</span> <span class="no">nil</span> <span class="nv">new-time</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="no">t</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nb">setq</span> <span class="nv">time-type</span> <span class="p">(</span><span class="nf">completing-read</span> <span class="s">&#34;Set time type (d/s): &#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nv">my/org-set-heading-state-and-time</span> <span class="nv">state</span> <span class="nv">days</span> <span class="p">(</span><span class="nb">if</span> <span class="p">(</span><span class="nv">string=</span> <span class="nv">time-type</span> <span class="s">&#34;d&#34;</span><span class="p">)</span> <span class="ss">&#39;d</span> <span class="ss">&#39;s</span><span class="p">))))))</span></span></span></code></pre></div>
<p>It&rsquo;s written with the menu system in mind. It&rsquo;d be too clunky to use interactively &ndash; too many possible states to remember, etc. but as part of a bunch of canned menu options you can get to with one or two taps it saves a bunch of typing and cursor motion for common operations.</p>
<p>Then I thought, &ldquo;it&rsquo;d be handy to just visit a record and have an option to compose a mail,&rdquo; so <code>my-org-contacts-email</code> was born:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-org-contacts-email</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Open am email message to the email address in the EMAIL property of the current org-contacts heading.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nf">eq</span> <span class="nv">major-mode</span> <span class="ss">&#39;org-mode</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">email</span> <span class="p">(</span><span class="nv">org-entry-get</span> <span class="p">(</span><span class="nf">point</span><span class="p">)</span> <span class="s">&#34;EMAIL&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">if</span> <span class="nv">email</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nb">progn</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nb">featurep</span> <span class="ss">&#39;mu4e</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">              <span class="p">(</span><span class="nv">mu4e</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nv">mu4e-compose-new</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nv">message-goto-to</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nf">insert</span> <span class="nv">email</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nv">message-goto-body</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nf">insert</span> <span class="s">&#34;\n\n&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nf">message</span> <span class="s">&#34;No email address found.&#34;</span><span class="p">)))))</span></span></span></code></pre></div>
<p>It has some behavioral issues I need to straighten out, but if mu4e is running and I tap <code>SPC C m</code> while positioned over a contact, it opens and pre-addresses a new message in mu4e.</p>
<p>I think it&rsquo;s beyond the ken of <code>org-caldav</code>, but I suppose a call out to AppleScript could create similar functionality for scheduling things with a contact.</p>
<p>I really like the Doom menu system (and I suppose I&rsquo;d like Spacemacs&rsquo; as well). The last time I was all-in on org mode I had so much trouble with all the Emacs chords that I ended up setting up <a href="https://gitlab.com/phillord/org-drill/">org-drill</a> to periodically train. With Doom&rsquo;s menus, there are decent mnemonics up front, then visual reminders along the way. It still takes time to learn everything, but you get reminders and you can stop to study the menu if you forget. I don&rsquo;t know how many times I have mashed <code>CTRL g</code> when I lost track of my fingers during a complex vanilla Emacs sequence.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Succumbed to mu.</title>
      <link>https://mike.puddingtime.org/posts/2023-04-17-succumbed-to-mu-dot/</link>
      <pubDate>Mon, 17 Apr 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-17-succumbed-to-mu-dot/</guid>
      <description>This had to happen eventually.</description>
      <content:encoded><![CDATA[<p>I had some futzing time before writing time this morning, so I succumbed to what I initially thought was just getting <a href="https://www.offlineimap.org/">OfflineIMAP</a> going so I could get some speed improvements from mutt. Then I noticed lbdb had a <a href="https://github.com/djcb/mu">mu</a> backend, which would mean address lookup for 20 years of email. And that meant my <code>packages.el</code> file had that <code>;;(mu4e +org)</code> just sitting there, waiting to be uncommented.</p>
<p>I have a little self-control, so I made myself wait until I had mutt working before trying out <a href="https://www.djcbsoftware.nl/code/mu/mu4e.html">mu4e</a>.</p>
<p>And at that point, there was a yak capering about in my living room, and it had to be shaved:</p>
<ul>
<li>mu</li>
<li>msmtp</li>
<li>mu4e</li>
<li>&hellip; and isync</li>
</ul>
<p>isync because I found a bug in OfflineIMAP, which was inevitable given the 20-year-old email corpus I&rsquo;ve been lugging around between mail servers. It was killing Homebrew&rsquo;s ability to run offlineimap daemonized, so down that rabbit hole I went to satisfy myself the problem was widespread enough that it was worth considering alternatives, and isync has some good press.</p>
<p>Initial impressions:</p>
<ul>
<li>mu is pretty cool on its own. Very curious to play with my 20 years of email with it.</li>
<li>I haven&rsquo;t really tested mu&rsquo;s performance under mutt with search. But it is nice having very fast address lookup.</li>
<li>msmtp is &hellip; fine? I was using built-in SMTP for mutt, msmtp is there for mu4e&rsquo;s benefit so I just use it for both clients now.</li>
<li>isync seems fast enough and works well once the initial mail store is read into maildir.</li>
</ul>
<p>Tomorrow I&rsquo;ll move the data and databases over to my desktop</p>
<p>Oh &hellip; mu4e.</p>
<p>It is weird, but it&rsquo;s my kind of weird. Very high concept. Super fast. The &ldquo;squee&rdquo; factor is being able to compose mail in org-mode markup, which it turns into multipart mail. If you read the HTML version of your mail, mu4e messages look like rich text. If you read the plaintext version, it applies some plaintext styling:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Heading
</span></span><span class="line"><span class="cl">═══════
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">*Bold* and /italics/ and [a link].
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[a link] &lt;https://mike.puddingtime.org&gt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Subheading
</span></span><span class="line"><span class="cl">──────────</span></span></code></pre></div>
<p>Search is superfast, navigating between folders is keyboard-centric, and because the mail retrieval stuff is happening outside of an Emacs thread, it doesn&rsquo;t block. I think you can set it up to run isync async inside Emacs, but I just noticed someone&rsquo;s config a few minutes ago and it&rsquo;s bedtime.</p>
<p>I am not sure what its future will be. I really like my mutt setup. I wonder if there&rsquo;s a way to get the org-mode mail composition using Emacs as my mutt mail editor. Science needs to be done.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Making a plaintext personal CRM with org-contacts</title>
      <link>https://mike.puddingtime.org/posts/2023-04-13-making-a-plaintext-personal-crm-with-org-contacts/</link>
      <pubDate>Thu, 13 Apr 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-13-making-a-plaintext-personal-crm-with-org-contacts/</guid>
      <description>I don&amp;rsquo;t like the looks of any of the personal CRM software out there, so I&amp;rsquo;m making a plaintext one.</description>
      <content:encoded><![CDATA[<p>This morning Al and I took our coffee walk, but she had to hop on a call, so for the two-mile walk back home I had some time to think about the habit on my list that popped up today: <code>Social Maintenance</code> and I also happen to have, for assorted reasons, a massive amount of poorly directed nervous energy. I am scattered and my thoughts are darting all over the place, and there&rsquo;s enough jittery energy built up  that the thought of cycling through a bunch of &ldquo;what if I try <em>this</em>&rdquo; stuff is sort of comforting.</p>
<p>I started trying to cultivate a social maintenance habit with the thought in mind that I had no idea what I was really thinking, just that during this current period it is important to me to keep up social contact in ways large and small. Pretty soon thereafter I realized I had an organizational problem on my hands: My address books were kind of a mess. Not very well organized, old data, a ton of contacts with old work addresses, etc. I spent a day straightening that out and got to a place of mostly clean.</p>
<p>The next problem that presented itself was that &ldquo;personal CRM&rdquo; is just an  awful software category. Whenever I see a new contact management app, I think &ldquo;oh, this is surely the one that will let you do something with your existing information, or add useful information,&rdquo; but it never seems to be. The more competent looking entries in the market cost a lot. Searching yields a lot of &ldquo;make one in Trello,&rdquo; &ldquo;make one in Notion,&rdquo; etc.</p>
<p>I just stopped thinking about it and decided &ldquo;do it off the top of your head until something comes up for you.&rdquo;</p>
<p>So this morning, Al was on her call, and I had a <code>Social Maintenance</code> habit popping up on my agenda as a thing I was supposed to do today, and I&rsquo;d been reading about <code>org-contacts</code>, <code>org-vcard</code>, and the ways they can integrate with an org-mode agenda to show birthdays or other anniversaries. By a few blocks later I&rsquo;d thought of how I might wedge CRM-like data into that system with org <code>:PROPERTIES:</code> drawers:</p>
<ul>
<li>desired frequency</li>
<li>date last contacted</li>
<li>notes on the last contact</li>
</ul>
<p>This is all stuff you could do in a spreadsheet, and I think a lot of people do it that way. I have an aversion to spreadsheet applications, though.</p>
<p>By the time we were home, I had the beginnings of a plan: Export my macOS address book to a big vcard file, use <code>org-vcard</code> to import it into a contacts file, then start figuring out the mechanics of adding the fields I needed to drive org agenda views.</p>
<h2 id="getting-my-contacts-into-org-contacts">Getting my contacts into org-contacts</h2>
<p>There&rsquo;s an <code>org-vcard</code> package that theoretically handles the process of moving a vcard file into an org file. The maintainer has announced that they&rsquo;re not going to work on it any longer, and it seems to have problems with macOS Contacts output.</p>
<p>I put together a script (well, ChatGPT and I put together a script) that parses a VCF file and dumps the contacts out into the right format. I just cat&rsquo;d its output into the right file. It is probably best described as a menace to your data. I had so recently scrubbed my contacts that I trusted it enough.</p>
<p>An org-contacts record looks like this:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">\* Joe Grudd :social:
</span></span><span class="line"><span class="cl">:PROPERTIES:
</span></span><span class="line"><span class="cl">:EMAIL: joe@grudd.com
</span></span><span class="line"><span class="cl">:WEBSITE: http://joe.grudd.com
</span></span><span class="line"><span class="cl">:CONTACTED: 2023-04-12
</span></span><span class="line"><span class="cl">:END:</span></span></code></pre></div>
<p>There are a few other fields, like birthday and physical address, too.</p>
<p>On its own, it doesn&rsquo;t do a ton. You can add notes to a :NOTES: property if you like, and you can search the entire file with an <code>org-contacts</code> command that lists results instead of just doing a normal text search operation.</p>
<h2 id="tracking-contact-information">Tracking contact information</h2>
<p>There are a few ways I thought of to come at what I wanted to do, which amounted to:</p>
<ul>
<li>
<p>Keeping track of whom I&rsquo;ve had contact with</p>
</li>
<li>
<p>Keeping track of when I last had contact with someone</p>
</li>
<li>
<p>Keeping track of useful details about people</p>
</li>
<li>
<p>Surfacing people I haven&rsquo;t seen in a while</p>
<p>The <code>NOTES</code> property in a vcard record is fine, but org-mode provides a way to add a log to each record in its own drawer, which changes the record to look like this:</p>
</li>
</ul>
<!--listend-->






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-org" data-lang="org"><span class="line"><span class="cl">\* Joe Grudd :social:
</span></span><span class="line"><span class="cl"><span class="c">:PROPERTIES:
</span></span></span><span class="line"><span class="cl"><span class="cs">:EMAIL: joe@grudd.com
</span></span></span><span class="line"><span class="cl"><span class="cs">:WEBSITE: http://joe.grudd.com
</span></span></span><span class="line"><span class="cl"><span class="cs">:CONTACTED: 2023-04-12
</span></span></span><span class="line"><span class="cl"><span class="c">:END:</span>
</span></span><span class="line"><span class="cl"><span class="c">:LOGBOOK:
</span></span></span><span class="line"><span class="cl"><span class="cs">  - Note taken on [2023-04-12 Wed 11:16] \\
</span></span></span><span class="line"><span class="cl"><span class="cs">    Caught up over IM for the first time in a while. He&#39;s moving to California next month.
</span></span></span><span class="line"><span class="cl"><span class="c">  :END:</span></span></span></code></pre></div>
<p>org-mode pretties all this stuff up, so the <code>LOGBOOK</code> and <code>PROPERTIES</code> drawers aren&rsquo;t always visible.</p>
<p>I also added the <code>CONTACTED</code> field to <code>PROPERTIES</code>. It&rsquo;s just an ISO-8601 date meant to reflect the last time I had some kind of contact, even if it&rsquo;s just a ping.</p>
<p>So at this point, I could just use this as is and it&rsquo;d be no worse than a spreadsheet.</p>
<h2 id="automating-updates">Automating updates</h2>
<p>I wanted a way to quickly note a contact &ldquo;touch&rdquo; so I made a few functions for that:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">org-set-contacted-today</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Set the CONTACTED property of the current item to today&#39;s date.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">org-set-property</span> <span class="s">&#34;CONTACTED&#34;</span> <span class="p">(</span><span class="nf">format-time-string</span> <span class="s">&#34;%Y-%m-%d&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">org-set-contacted-date</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Set the CONTACTED property of the current item to a chosen date.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">date</span> <span class="p">(</span><span class="nv">org-read-date</span> <span class="no">nil</span> <span class="no">t</span> <span class="no">nil</span> <span class="s">&#34;Enter the date: &#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">org-set-property</span> <span class="s">&#34;CONTACTED&#34;</span> <span class="p">(</span><span class="nf">format-time-string</span> <span class="s">&#34;%Y-%m-%d&#34;</span> <span class="nv">date</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">map!</span> <span class="nb">:mode</span> <span class="nv">org-mode</span>
</span></span><span class="line"><span class="cl">      <span class="nb">:localleader</span>
</span></span><span class="line"><span class="cl">      <span class="nb">:desc</span> <span class="s">&#34;Set CONTACTED property to today&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="s">&#34;c t&#34;</span> <span class="nf">#&#39;</span><span class="nv">org-set-contacted-today</span>
</span></span><span class="line"><span class="cl">      <span class="s">&#34;c d&#34;</span> <span class="nf">#&#39;</span><span class="nv">org-set-contacted-date</span>
</span></span><span class="line"><span class="cl">      <span class="s">&#34;c z&#34;</span> <span class="nf">#&#39;</span><span class="nv">my/org-remove-todo</span>
</span></span><span class="line"><span class="cl">                <span class="p">)</span></span></span></code></pre></div>
<p>Those two allow me to set the <code>CONTACTED</code> property either to today&rsquo;s date (<code>spc m c t</code>), or by interactively selecting a date (<code>spc m c d</code>). There&rsquo;s a third mapping that lets me z out the TODO status of a contact (<code>spc m c z</code>), which I will get to.</p>
<h2 id="agenda-customization">Agenda customization</h2>
<p>Next up, I wanted some kind of agenda automation &ndash; custom views that&rsquo;d let me see contacts overdue for some kind of ping. I made a few driven by a combination of tags and age of the <code>CONTACTED</code> field.</p>
<p>Here&rsquo;s one of them, driven by a function that finds aged contacts:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;org-agenda-custom-commands</span>
</span></span><span class="line"><span class="cl">             <span class="o">&#39;</span><span class="p">(</span><span class="s">&#34;N&#34;</span> <span class="s">&#34;Professional network last contacted &gt; 90 days ago&#34;</span>
</span></span><span class="line"><span class="cl">               <span class="p">((</span><span class="nv">tags</span> <span class="s">&#34;network&#34;</span>
</span></span><span class="line"><span class="cl">                      <span class="p">((</span><span class="nv">org-agenda-overriding-header</span> <span class="s">&#34;Network contacts, not contacted in the past 90 days&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                       <span class="p">(</span><span class="nv">org-tags-match-list-sublevels</span> <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                       <span class="p">(</span><span class="nv">org-agenda-skip-function</span>
</span></span><span class="line"><span class="cl">                        <span class="p">(</span><span class="nb">lambda</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">                          <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nv">org-contacted-more-than-days-ago</span> <span class="mi">90</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                            <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nv">outline-next-heading</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                                <span class="p">(</span><span class="nf">goto-char</span> <span class="p">(</span><span class="nf">point-max</span><span class="p">))))))))</span>
</span></span><span class="line"><span class="cl">                <span class="p">)))</span></span></span></code></pre></div>
<p>So in Doom, I can tap <code>spc oAN</code> and get a list of contacts tagged with <code>network</code> whom I haven&rsquo;t had any contact with for more than 90 days.</p>
<h2 id="setting-priority-by-touch-date">Setting priority by touch date</h2>
<p>I wanted a way to see which contacts were aging and decided to use plain old priorities for that, so a function looks at the difference between today and <code>CONTACTED</code> and prioritizes more aged contacts higher:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">my/org-update-priorities-based-on-contacted</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">save-excursion</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">goto-char</span> <span class="p">(</span><span class="nf">point-min</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">while</span> <span class="p">(</span><span class="nf">re-search-forward</span> <span class="s">&#34;^\\*+ &#34;</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">contacted-date</span> <span class="p">(</span><span class="nv">org-entry-get</span> <span class="p">(</span><span class="nf">point</span><span class="p">)</span> <span class="s">&#34;CONTACTED&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nv">today</span> <span class="p">(</span><span class="nf">format-time-string</span> <span class="s">&#34;%Y-%m-%d&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nb">when</span> <span class="nv">contacted-date</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">days-ago</span> <span class="p">(</span><span class="nf">-</span> <span class="p">(</span><span class="nv">time-to-days</span> <span class="p">(</span><span class="nf">current-time</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">                             <span class="p">(</span><span class="nv">time-to-days</span> <span class="p">(</span><span class="nv">org-time-string-to-time</span> <span class="nv">contacted-date</span><span class="p">)))))</span> <span class="c1">; calculate days since CONTACTED date</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nv">org-set-property</span> <span class="s">&#34;PRIORITY&#34;</span>
</span></span><span class="line"><span class="cl">                               <span class="p">(</span><span class="nb">cond</span>
</span></span><span class="line"><span class="cl">                                <span class="p">((</span><span class="nf">&lt;</span> <span class="nv">days-ago</span> <span class="mi">45</span><span class="p">)</span> <span class="s">&#34;C&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                                <span class="p">((</span><span class="nf">&lt;</span> <span class="nv">days-ago</span> <span class="mi">90</span><span class="p">)</span> <span class="s">&#34;B&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                                <span class="p">(</span><span class="no">t</span> <span class="s">&#34;A&#34;</span><span class="p">)))))))))</span></span></span></code></pre></div>
<p>It&rsquo;s connected to a save hook, so every contact&rsquo;s priority gets recalculated at save:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;after-save-hook</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nb">lambda</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nf">string-equal</span> <span class="p">(</span><span class="nf">buffer-file-name</span><span class="p">)</span> <span class="s">&#34;~/org/contacts.org&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">              <span class="p">(</span><span class="nv">my/org-update-priorities-based-on-contacted</span> <span class="p">))))</span></span></span></code></pre></div>
<p>That prioritization shows up in the agenda views I set up, with <code>[A]</code> priority contacts getting their own section.</p>
<h2 id="custom-todo-states">Custom TODO states</h2>
<p>Finally, I wanted a way to keep track of where a given contact is, or cue myself on next steps, so I set up custom TODO states just for my <code>contacts.org</code> file:</p>
<p><code>#+TODO: PING(p) PINGED(P!) FOLLOWUP(f) SKED(s) | TIMEOUT(t) OK(o)</code></p>
<p>By putting a <code>!</code> inside the shortcut parens, org-mode will automatically log changes in and out of those states. For now I just have <code>PINGED</code> wired up that way, and <code>TIMEOUT</code> and <code>OK</code>, as <code>DONE</code> equivalents will similarly trigger a log entry.</p>
<p><code>FOLLOWUP</code> and <code>SKED</code> are there as reminders that I need to do something next. <code>TIMEOUT</code> is a way to tell myself I gave it a shot and nothing came of it. <code>OK</code> is just an interim state on the way to no state until the agenda surfaces someone again.</p>
<p>The logging for these state changes looks like this in a given contact entry:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-org" data-lang="org"><span class="line"><span class="cl">\* PINGED Joe Grudd :social:
</span></span><span class="line"><span class="cl"><span class="c">:PROPERTIES:
</span></span></span><span class="line"><span class="cl"><span class="cs">:EMAIL: joe@grudd.com
</span></span></span><span class="line"><span class="cl"><span class="cs">:WEBSITE: http://joe.grudd.com
</span></span></span><span class="line"><span class="cl"><span class="cs">:CONTACTED: 2023-04-12
</span></span></span><span class="line"><span class="cl"><span class="c">:END:</span>
</span></span><span class="line"><span class="cl"><span class="c">:LOGBOOK:
</span></span></span><span class="line"><span class="cl"><span class="cs">- State &#34;PINGED&#34;     from &#34;PING&#34;   [2023-04-11 Tue 20:21]
</span></span></span><span class="line"><span class="cl"><span class="cs">- Note taken on [2023-04-12 Wed 11:16] \\
</span></span></span><span class="line"><span class="cl"><span class="cs">  Caught up over text for the first time in a while. He&#39;s moving to California next month.
</span></span></span><span class="line"><span class="cl"><span class="c">:END:</span></span></span></code></pre></div>
<p>This is also where that last &ldquo;z&rdquo; keybinding comes in:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">my/org-remove-todo</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">org-set-property</span> <span class="s">&#34;TODO&#34;</span> <span class="s">&#34;&#34;</span><span class="p">))</span></span></span></code></pre></div>
<p>With <code>spc m c z</code> I can zero out the TODO state of a given contact without triggering a log entry, keeping a little bit of noise down.</p>
<h2 id="what-else">What else?</h2>
<p>That&rsquo;s the system. I guess the summary is:</p>
<p>&ldquo;I&rsquo;ve used org-contacts to keep my contacts in a plaintext file. By using existing data features and agenda customizations, I get prompts that will help me cultivate my <code>Social Maintenance</code> habit when it&rsquo;s due. With a few custom functions and a save hook, I can use light automation to make the text more dynamic without a lot of day-to-day effort.&rdquo;</p>
<p>And I&rsquo;m a little more clear on what &ldquo;social maintenance&rdquo; can mean, now. I think I&rsquo;d created an ill-defined monster the longer I let it sit there with no shape. As I put this together I got to think about what would be meaningful, and I realized it just makes my day when I get a text from someone asking how it&rsquo;s going, so that&rsquo;s a fine standard to apply.</p>
<p>And yes, it was an interesting ChatGPT exercise. It would have taken me days to suss all this out on my own. I just don&rsquo;t have the elisp. It took much less time just dialoging with the bot, and it let me work much more iteratively if an idea didn&rsquo;t test quite right. I wonder how this would have gone if I&rsquo;d thought of trying it when I was using Obsidian a lot, or if I&rsquo;d been in more of a Rails or Sinatra mood.</p>
<p>I think the whole thing will seem like overkill to some, but I am not good at keeping up with people. I am not going to go all autobiographical to explain it, I&rsquo;m just gonna say that there is what I want to do and there is what I do, and they aren&rsquo;t aligned, and I know enough about myself to know that in the absence of a supporting system my good intentions will not mean anything.</p>
<p>And I&rsquo;ve had a few recent interactions with people I haven&rsquo;t spoken to in a long time. It feels really good to reconnect, even if it&rsquo;s just a few lines of &ldquo;what&rsquo;s up with you?&rdquo; So I&rsquo;ve built a system to help me get more of that.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-04-12</title>
      <link>https://mike.puddingtime.org/posts/2023-04-12-daily-notes/</link>
      <pubDate>Wed, 12 Apr 2023 16:01:09 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-12-daily-notes/</guid>
      <description>More ChatGPT and org, using the org agenda, Yellowjackets again, Doom keybindings</description>
      <content:encoded><![CDATA[<h2 id="chatgpt-and-org-configuration">ChatGPT and org configuration</h2>
<p>I tried out <a href="https://github.com/alphapapa/org-super-agenda">org-superagenda</a> a while back. It improves on the vanilla org agenda by creating customizable sections, which help it scan a little better. I bounced off of it because while I wanted the quality of life improvements it offered, I was struggling a little with the syntax, and was caught up in that brainspace you can get into where you just want the thing to work and it&rsquo;s throwing off your sense of time and perception of the required investment to make it work.</p>
<p>This morning I was looking at my agenda and hating it because it was in a &ldquo;mostly correct except where it is glaringly incorrect&rdquo; state, so I figured it&rsquo;d be a good practical task to throw at ChatGPT:</p>
<p><code>Describe an orgmode super agenda configuration that shows habits, important items, overdue items, and items due in the near future</code></p>
<p>I got a copy-pastable example that met the requirements.</p>
<p><code>Could you add items due today to that list</code></p>
<p>Yep. That worked.</p>
<p><code>could you move the today list to second place and add a list at the bottom of unscheduled todo items</code></p>
<p>That response worked well, too. It does a decent job of explaining what each piece of the solution does.</p>
<h2 id="using-the-org-agenda">Using the org agenda</h2>
<p>Figuring out the org agenda has been key to how I use the tool.</p>
<p>With a good agenda setup I can feel pretty on top of things. When it&rsquo;s broken I know there are things out there in my file collection that I&rsquo;m not going to see. As I&rsquo;ve leaned into org capture, that&rsquo;s become even more true, because capture buffers keep you out of the file you&rsquo;re adding something to: You don&rsquo;t see the other things in there because you don&rsquo;t go past them to get to where you&rsquo;re adding new content.</p>
<p>Besides surfacing stuff, the agenda is also the nerve center. You can do basic scheduling and status changes from it, and maybe even more importantly for a sense of organizational calm, you can refile from it. So rather than visiting each file to find stuff and move it around, you can see it all from the agenda overview and refile it from there.</p>
<p>With a restored agenda, I made the connection between my literate Emacs config and all the other stuff flying around in my org mode ecosystem: Links I gathered about configuration tweaks or things I&rsquo;d like to try can more easily go into a literate config file, so I made an &ldquo;Ideas&rdquo; heading at the bottom of the file and started refiling my the Emacs-related things in my agenda&rsquo;s inbox into my <code>config.org</code> file.</p>
<p>People love hooking into org, too, so even things that started life without org mode in mind can pick up org affinities. The pinboard mode I adopted, for instance, doesn&rsquo;t natively use org&rsquo;s link storing function when copying a link, but someone wrote a function to do that.  Now I can retrieve a link and add it to a post without taking my hands off the keyboard or switching contexts.</p>
<h3 id="which-reminds-me-dot-dot-dot">Which reminds  me &hellip;</h3>
<p>I discovered <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Window-Convenience.html">winner-mode</a> today.</p>
<p>It&rsquo;s annoying when an Emacs mode splits the window into frames, then leaves two frames behind when I quit it. <code>winner-mode</code> &ldquo;records the changes in the window configuration (i.e., how the frames are partitioned into windows), so that you can undo them.&rdquo; It&rsquo;s useful to me because I want to use <code>pinboard-mode</code> as a link retrieval tool for blogging. Once I&rsquo;ve grabbed the link, I just want to tap <code>q</code> and get back to my blog buffer, not find myself with a split window. <code>winner-mode</code> closes the pinboard buffer, then removes the frame, and I&rsquo;m back where I left off, able to add my link and keep typing.</p>
<h2 id="custom-doom-keybindings">Custom Doom keybindings</h2>
<p>I&rsquo;ve been digging Doom&rsquo;s modal interface, and waiting around for a reason to extend it. Yesterday&rsquo;s addition of <code>pinboard.el</code> finally gave me an excuse, since Doom was killing its keybindings out of the box.</p>
<p>The <code>p</code> prefix in Doom&rsquo;s menu system is already occupied by <code>projectile</code>, so I used <code>P</code>:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">map!</span> <span class="nb">:leader</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">:prefix-map</span> <span class="p">(</span><span class="s">&#34;P&#34;</span> <span class="o">.</span> <span class="s">&#34;Pinboard&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;open Pinboard&#34;</span> <span class="s">&#34;p&#34;</span> <span class="nf">#&#39;</span><span class="nv">pinboard</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;open current link&#34;</span> <span class="s">&#34;o&#34;</span> <span class="nf">#&#39;</span><span class="nv">pinboard-open</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;copy org link&#34;</span> <span class="s">&#34;l&#34;</span> <span class="nf">#&#39;</span><span class="nv">org-store-link</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;edit link&#34;</span> <span class="s">&#34;e&#34;</span> <span class="nf">#&#39;</span><span class="nv">pinboard-edit</span>
</span></span><span class="line"><span class="cl">        <span class="nb">:desc</span> <span class="s">&#34;copy URL&#34;</span> <span class="s">&#34;c&#34;</span> <span class="nf">#&#39;</span><span class="nv">pinboard-kill-url</span>
</span></span><span class="line"><span class="cl">        <span class="p">)))</span></span></span></code></pre></div>
<p>So <code>spc Pp</code> will open the pinboard buffer (or switch to it), <code>spc Po</code> will open a given link, <code>spc Pl</code> will store an org link (for retrieval via <code>spc mll</code>), etc. etc.</p>
<p>One thing I&rsquo;m struggling with here is a vagary of Doom as an environment. The logical place for all of that is in the <code>bindings.el</code> file, but the bindings don&rsquo;t &ldquo;take&rdquo; when I put them there.  They do when I put them in <code>config.el</code>. The docs weren&rsquo;t super helpful in debugging that, and the things that look syntactically intuitive didn&rsquo;t seem to solve the problem.</p>
<p>It&rsquo;s no big deal, and I&rsquo;d rather just have all of that stuff travel together with the mode it addresses, anyhow, but it&rsquo;s a thing I Do Not Understand About the Environment except at a very vague &ldquo;well, there&rsquo;s a lot of lazy loading going on to keep things fast&rdquo; level, and it&rsquo;s going to bother me.</p>
<p>I should just add an <code>INSOMNIA</code> state to my TODO lists and save it for the next &ldquo;welp, it&rsquo;s 3 a.m. and I might as well screw around with this problem&rdquo; session.</p>
<h2 id="yellowjackets-again">Yellowjackets again</h2>
<p>Well, we finished the first season last night.</p>
<ul>
<li><strong>Standalone season</strong> score: 8</li>
<li><strong>Prospects for the future</strong> score: 5</li>
</ul>
<p>Basically, my &ldquo;endless puzzlebox&rdquo; antennae are quivering.</p>
<p>The season all on its own was gripping and kept our interest. I felt invested in the characters and whatever they were dealing with. I love the way it walks right up to the <em><a href="https://www.imdb.com/title/tt6998518/">Mandy</a></em> line a few times. It has a dark sense of humor but it&rsquo;s not mean.</p>
<p>The 2 missing points for the standalone season score are because it had some minor pacing/bog-down stuff in the middle, and because some stuff going on just felt like gratuitous puzzlebox misdirection. It felt at times like it was written too self-consciously aware of recap culture and a certain kind of mock-obsessive over-read/over-think that comes along with that.</p>
<p>The &ldquo;prospects for the future&rdquo; score is a function of how I felt as the credits rolled on the season ender, and it honestly wasn&rsquo;t great. The episode didn&rsquo;t feel energetic, it suggested an appetite for &ldquo;surprise reversal&rdquo; that will exceed my patience over the long haul, and it reminded a bit too much of the first couple of seasons of HBO&rsquo;s <em><a href="https://www.imdb.com/title/tt8068860/">Servant</a></em>, which I abandoned with no remorse at the end of the second season.</p>
<p>I feel a little bad about my reaction, because maybe I&rsquo;m suggesting that television productions should simply abandon the only tools they have to get more seasons. In some ways, they <em>have</em> to pander to recap culture. They <em>have</em> to pander to fannish over-analysis. They <em>have</em> to end each season with a hook and a sense of incompleteness. They <em>have</em> to live within a fickle system run by people addicted to the analytics streaming affords, who will happily kill a property and move on to the next with no sense of investment.</p>
<p>But, you know, don&rsquo;t point out a problem without pointing out a solution:</p>
<p><em>For All Mankind</em> (Al prefers to think of it as <em>Space is Trying to Murder You Again This Week</em>) does a nice job with this conundrum: Each season has an arc and a sense of conclusion. There&rsquo;s payoff. Then it does an end-credits thing where it flash-forwards to the next season&rsquo;s era and offers you a look. It doesn&rsquo;t appeal to your thwarted expectations of closure, it appeals to your curiosity.</p>
<p>And to make note of a counterpoint, <em>Succession</em> isn&rsquo;t above leaving things on a hanging note of tension, but I&rsquo;ve stuck with it. It&rsquo;s not terrible to leave things unresolved, or end a season with a directional cue in the form of an unfinished arc. Maybe the thing I&rsquo;m reacting to with the puzzlebox stuff is the garish palette those shows paint with, swinging for the meme fences.</p>
<p>Anyhow, we have a few episodes of <em>Yellowjackets</em> season 2 cued up. The prospect of watching them, having skimmed a few episode descriptions in Plex, is not sparking a &ldquo;full-body yes.&rdquo; There&rsquo;s just so much other stuff out there that I&rsquo;m okay with the thought of letting it have its run then deciding whether it&rsquo;s worth it to watch through the whole thing.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Writing elisp, Puppet code, and Ruby with ChatGPT.</title>
      <link>https://mike.puddingtime.org/posts/2023-04-10-elisp-puppet-ruby-chatgpt/</link>
      <pubDate>Mon, 10 Apr 2023 09:36:26 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-10-elisp-puppet-ruby-chatgpt/</guid>
      <description>I finally took the time to play with ChatGPT to configure Emacs and write some Ruby.</description>
      <content:encoded><![CDATA[<p>I finally got curious enough, and had rendered a particular Google account unimportant enough, to give ChatGPT a try. I&rsquo;ll leave out the obvious goofs &ndash; asking it to deliver the Gettysburg Address in the style of Jeff Lebowski &ndash; and write up a few slightly more complex requests. Trying to get Eliza to say swears in eighth grade got boring fast, so nothing I asked it to do was borne out of a spirit of malice toward it. Just curiosity.</p>
<p>Overall, it was a land of contrasts. It did some things really well, or got to &ldquo;really well&rdquo; with a few followup requests. But on the other end of the spectrum it simply invented non-existent functionality then documented how to configure it.</p>
<p>I don&rsquo;t have any particularly original takeaways. Put me in the broad camp of &ldquo;human venality is going to be the real problem here,&rdquo; in ways it already is where other kinds of automation are concerned. We live in a society where people not only, like, read a newspaper in their Tesla, but literally crawl into the back seat and take naps.</p>
<p>The trivial tasks I fed it were limited, so the errors it made were obvious.  I wasn&rsquo;t trying to prove or disprove its &hellip; quality?  If you&rsquo;ve ever gotten into an argument with a word processor&rsquo;s grammar checker you&rsquo;ll sort of understand what you&rsquo;re up against in this case, too, with the improvement over that scenario being that instead of staring at the alleged bad grammar and ultimately learning you&rsquo;re either a &ldquo;leave the blue squiggles&rdquo; person or a &ldquo;can&rsquo;t tolerate any blue squiggles&rdquo; person, you can tell it you didn&rsquo;t care for the answer and it often takes the hint and fixes the problem.</p>
<p>But you have to know that you don&rsquo;t like the answer. So when it wrote a Puppet module for me and did so with insecure code, I noticed that and told it to do better and it did. Nothing got into production. When it gave me unreadable output for a train schedule, its first correction was at least obviously and intuitively wrong. Nothing got into production.</p>
<p>When I think about more complex code I&rsquo;ve written the human dimension of the problem stands out more. I once modeled website revenue for a Rails app, which involved a lot of sorting out when data was sampled vs. when it wasn&rsquo;t, recursive reasoning around costs, etc. and remember the many ways I could lose my train of thought and introduce stuff that looked right even to my experienced eye as a domain expert who knew the problem space as a practitioner <em>and</em> who was describing that expertise in code. No misunderstood requirements, no senior dev fighting with the product owner because reality is stupid, no UX designer arguing that beauty is truth. Just me, passionately invested in the problem, and still introducing errors I couldn&rsquo;t spot on review &hellip; that I could only spot with tedious testing.</p>
<p>Anyhow. Nothing new.</p>
<p>Some of the things I tried:</p>
<h3 id="create-an-org-capture-template-for-daily-health-logging">Create an org capture template for daily health logging</h3>
<p>It did the request perfectly, but slightly idiosyncratically for a log format (it stuck the date in the :DRAWER: instead of as an inactive date label in the head). Subsequent conversational-style prompts (&ldquo;okay, but could you include weight and hours slept?&rdquo;) caused it to add prompts for those to the template, then &ldquo;could you make that information that appends to an org table instead&rdquo; generated a capture template appropriate to appending to a table.</p>
<p>A similar request to create an org-capture template for Hugo blogging was mostly correct, but had a few glitches and the verbose instructions left out a key variable. It was debuggable in a few minutes.</p>
<p>I&rsquo;d score it pretty highly, and using it for that task is just straightforward &ldquo;get to the point of the tool, not the labor involved in the tool&rdquo; utility. Mostly I appreciated that it matched all the parens correctly.</p>
<h3 id="tell-me-how-to-configure-offlineimap-for-use-with-mutt-on-a-mac">Tell me how to configure OfflineIMAP for use with mutt on a Mac</h3>
<p>Did I say yesterday I don&rsquo;t believe in that? I did. But it was on my mind.</p>
<p>It did this pretty well, delivering instructions tailored to the specific &ldquo;mutt + offlineimap&rdquo; use case that were as good as any tutorial, missing only the things that are idiosyncratic to Fastmail, which I forgot to mention to it. I should have thought to tell it I was getting the errors I got to see how it handled that. Instead I just searched for them on DuckDuckGo and got unstuck.</p>
<p>Interestingly, and this happened one other time, I lost the original request to a glitch in the web app. When I restated it only slightly differently &hellip; not in a way that you&rsquo;d think would materially affect the output &hellip; it came up with something slightly different that didn&rsquo;t leave out a key detail the original output did.</p>
<p>I&rsquo;d score it highly again, minus maybe its willingness to make message deletion live by default without warning. Other examples and tutorials I found mention that.</p>
<p>I followed up by asking it to show me how to capture that configuration with Puppet and hiera, and it produced a serviceable OfflineIMAP module. It would have had me storing my credentials in the plain in the Hiera YAML. I responded that I preferred not to do that so it provided me with an example that used eyaml.</p>
<h3 id="tell-me-how-to-use-mutt-with-a-bayesian-filter">Tell me how to use mutt with a Bayesian filter</h3>
<p>It went completely off the rails, inventing filtering functionality for mutt and offering configuration examples that looked &ndash; mutt-like? &ndash; but inventing a configuration variable that doesn&rsquo;t exist, near as I can tell, to invoke a configuration file mutt wouldn&rsquo;t look for to support the non-existent functionality.</p>
<p>Maybe the interesting thing that came out of the interaction was the way it cooked up a mutt-like filtering setup could work in a way that seemed idiomatically correct for mutt. It just did the technical equivalent of adding a sixth finger to the left hand by assuming a generic bayesian filter of <em>some kind</em> and taking the plumbing to connect it for granted.</p>
<h3 id="how-would-i-go-about-adding-a-second-rss-feed-with-a-different-template-for-a-hugo-site">How would I go about adding a second RSS feed with a different template for a hugo site?</h3>
<p>Another miss, with very reasonable-looking instructions that simply didn&rsquo;t work as proposed. I am not sure how close it actually got. That&rsquo;s a problem I spent some time trying to solve yesterday and it seemed close but missed some connections between content and template.</p>
<p>It gave its configuration examples in TOML, and responded correctly to a conversational &ldquo;could I have those examples in YAML&rdquo; prompt.</p>
<h3 id="tell-me-how-to-write-a-sinatra-app-to-download-an-rss-feed-filter-it-for-keywords-and-save-another-version-of-the-feed">Tell me how to write a Sinatra app to download an rss feed, filter it for keywords and save another version of the feed</h3>
<p>Prompted by a Mastodon conversation yesterday about RSS readers that could be used to filter sponsored content posts.</p>
<p>Up front, it&rsquo;s sort of a weird request on my part: I was just lazily typing in part of an idea, including Sinatra as a dependency but not explaining why (my idea would involve creating a sort of RSS proxy with dynamic filtering during each client request). I just wanted to see what it would do without putting a lot of thought into it, or sticking around to narrow things down. So I got a ruby script wrapped in a Sinatra route, honoring the request whether it made a ton of sense or not.</p>
<p>I&rsquo;ve had it do a couple of Ruby scripts, and it remembered to include `require` lines for gems. It didn&rsquo;t do that in this case. I added them and it ran. I had to tweak a few things to get it to run without error, and the filtering didn&rsquo;t work.</p>
<p>I might goof around with this one a bit more to see where it&rsquo;s going wrong.</p>
<p>This lined up with things I&rsquo;ve read from others over the past few months: It produced a scaffold of mostly working code. If I decide to mess around with it more, I&rsquo;ll have been saved digging around for examples of the basic syntax for the assorted parts of the workflow that I know from experience are correct.</p>
<h3 id="what-s-a-good-strategy-for-switching-between-regular-and-ortholinear-keyboards">&ldquo;What&rsquo;s a good strategy for switching between regular and ortholinear keyboards?&rdquo;</h3>
<p>Useless. It provided very reasonable instructions for how to learn how to use an ortholinear keyboard, but didn&rsquo;t address the actual request.</p>
<h3 id="tell-me-how-to-write-a-ruby-script-to-download-train-times-for-a-given-stop-in-portland-oregon">&ldquo;Tell me how to write a ruby script to download train times for a given stop in Portland oregon&rdquo;</h3>
<p>It produced working code that showed me the next arrival times for the next train at my neighborhood stop. It provided the correct link to sign up with TriMet to get an API key.</p>
<p>&ldquo;A-&rdquo; because it didn&rsquo;t translate epoch time to human time in the output. When I asked it to do that, it tried to comply and used the obvious syntax to convert the integer it got back from the API, but got confused by the millisecond format.</p>
<p>I tried the code and replied with:</p>
<p>&ldquo;That time format is still incorrect. I think the timestamps include miliseconds.&rdquo;</p>
<p>It replied with:</p>
<p>&ldquo;You&rsquo;re correct, I apologize for the oversight. It appears that the TriMet API returns timestamps with milliseconds.&rdquo;</p>
<p>Then it produced working code that did a simple operation on the timestamp and passed it along to <code>Time</code> and <code>strftime</code> with correctly formatted output.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-04-08</title>
      <link>https://mike.puddingtime.org/posts/2023-04-08-daily-notes-for-2023-04-08/</link>
      <pubDate>Sat, 08 Apr 2023 10:26:49 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-08-daily-notes-for-2023-04-08/</guid>
      <description>As always, a plaintext revival means a mutt revival.</description>
      <content:encoded><![CDATA[<h3 id="these-things-come-in-waves">These things come in waves</h3>
<p>In the past, when I&rsquo;ve gone through a plaintext or Emacs kick of some kind, I&rsquo;ve blown past what I&rsquo;ve come to think of as a common sense limit: Eventually I&rsquo;m looking at Wanderlust, GNUS, or mu4e and thinking about the whole email in Emacs thing. Inevitably, then, you&rsquo;re looking at some sort of way to sync your IMAP account down to your local machine, and a whole layer goes in to make that work.</p>
<p>I walked up to the line this time around, asked myself what problem I&rsquo;m trying to solve, and remembered that part of what is making Doom Emacs work for me right now is how much I&rsquo;ve been keeping things limited to stuff that has to do with writing and stuff that has to do with personal organization. Those are things that don&rsquo;t stress Emacs&rsquo; single-threaded nature the way I do them, and that don&rsquo;t take me into the murky space between Emacs and the OS.</p>
<p>The problem I am trying to solve whenever I go on these kicks, is the pain of getting parts of the macOS experience into a more keyboard-centric place. Mail always sticks out because I don&rsquo;t like doing Mac Mail from the keyboard. There&rsquo;s <a href="https://smallcubed.com/">Mail Act-On</a>, but at $45 a renewal it&rsquo;s just more than I can see paying, and it doesn&rsquo;t really do much for visualization &ndash; it just makes it easy to move things into folders.</p>
<p>So my mind always goes to <a href="http://www.mutt.org">mutt</a>. It&rsquo;s not perfect &ndash; search is a challenge without something external augmenting it &ndash; but I&rsquo;m not sure it matters in the end: I use Fastmail for IMAP, and I don&rsquo;t mind punting to its web interface if I need to go dig for something.</p>
<p>I thought about mutt this time because my long-standing config has always sort of <em>felt</em> similar to the way Spacemacs and Doom put a modal UI over Emacs.  My mutt macros &ndash; here&rsquo;s a sample &ndash; use <code>.</code> as a leader and are written mnemonically:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">macro index .sn &#34;l ^a^k~N\n&#34; # Show unread/new only
</span></span><span class="line"><span class="cl">macro index .sa &#34;l ^a^kall\n&#34; # show all
</span></span><span class="line"><span class="cl">macro index .C &#34;&lt;esc&gt;V&#34; # toggle threads
</span></span><span class="line"><span class="cl">macro index .si &#34;l (~n5-100|~N)\n&#34; # show interesting 
</span></span><span class="line"><span class="cl">macro index .rs &#34;&lt;enter-command&gt;source ~/.mutt/scores&lt;enter&gt;&#34; # reprocess scores
</span></span><span class="line"><span class="cl">macro index .sf &#34;l ~F\n&#34; # show flagged
</span></span><span class="line"><span class="cl">macro index .hl &#34;l ^a^k!~l\n&#34; # hide lists
</span></span><span class="line"><span class="cl">macro index .to &#34;T ~d&gt;7d\n&#34; # &#34;tag old&#34; -- messages older than 7 days
</span></span><span class="line"><span class="cl">macro index .ab    &#34;&lt;pipe-entry&gt;/opt/homebrew/bin/lbdb-fetchaddr\n&#34;                # Store address details in lbdb.</span></span></code></pre></div>
<p>The value of mutt is less as my everything email client &ndash; I still keep up with mail from my phone or tablet &ndash; and more because over the years I&rsquo;ve tuned it to visualize and process mail from the keyboard. I still read mail with my phone or tablet every day, but don&rsquo;t like to do anything more than flag messages when I&rsquo;m out.</p>
<h3 id="html-mail-and-mutt">HTML mail and mutt</h3>
<p>mutt is sometimes hard to stick with because we lost the plaintext email battle. I know one designer who formats his email with monotype faces in what I&rsquo;d describe as a sort of problematic aesthetic revolt, but otherwise &hellip; we lost and we&rsquo;ll never be able to unsee Calibri.</p>
<p>Sticking <code>elinks</code>, <code>lynx</code> or <code>w3m</code> in your <code>~/.mailcap</code> to show HTML was best practice for a long while, provided you didn&rsquo;t mind also using <code>urlview</code> to display the links in a message once you&rsquo;d read it. I was involved in email marketing during the era when that approach worked, partially because to do HTML mail &ldquo;right&rdquo; back then meant you had someone doing it painstakingly by hand, then reviewing across a multitude of clients and platforms &ndash; you were heavily incentivized to keep it simple.  I bear the scars from a spat with a division of Siemens that was still using an old Lotus Notes and Win2000 in its marketing department. They were the customer, and the mail didn&rsquo;t look good to them, so it didn&rsquo;t look good. That was all, and we were forced to buy the next tier of service from our mail provider so we could add Lotus Notes on Win 2000 to our testing.</p>
<p>Anyhow, &ldquo;<code>elinks</code> in your mailcap and call it a day&rdquo; doesn&rsquo;t work anymore: image text, dozens of links, complex positional markup, etc. etc. etc. and it makes a lot of HTML mail a hash in a plaintext browser. There are a few ways to solve this on a Mac: One is punting to an actual browser, and the other is using the Mac Quicklook service:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">text/html;  open -a firefox %s; nametemplate=%s.html text/html; open -a firefox %s; nametemplate=%s.html; copiousoutput
</span></span><span class="line"><span class="cl">text/html; qlmanage -p %s; nametemplate=%s.html</span></span></code></pre></div>
<p>The former does about what you&rsquo;d expect from looking at it: It uses Firefox (or whatever browser you&rsquo;d care to invoke) to open the HTML part of the message, at which point you can click links, etc.</p>
<p>The latter is a little more obscure, but basically recreates what happens when you select a file and tap the spacebar to preview it on a Mac, popping up a modal window with the contents. This often works well for other kinds of attachments. With HTML mail it is enough to let you read the mail but not really interact with it (e.g. follow a link). The <code>[DEBUG]</code> label at the front of the modal&rsquo;s title suggests that nobody at Apple really took the &ldquo;plain text zealots using this to browse HTML email&rdquo; use case into account when they wrote <code>qlmanage</code>, and the man page makes clear it&rsquo;s just a debugging tool. It&rsquo;ll do if you never intend to interact with a mail.</p>
<p>I&rsquo;m sticking to the Firefox approach. It&rsquo;s super fast if Firefox is already running (it always is), and you can follow links.</p>
<h3 id="these-things-leave-in-waves-too">These things leave in waves, too</h3>
<p>At some point mutt is going to do something to annoy me. I don&rsquo;t know what it&rsquo;s going to be this time. For now, I&rsquo;m just enjoying the periodic dustoff of my config and pleasures of zipping through my inbox. If I had to guess, it&rsquo;ll have something to do with getting email messages into org-mode or calendaring, somehow. There are a few shell-based CalDav clients out there, but they&rsquo;re very sync-and-cache oriented and I just don&rsquo;t like adding services. Had mutt never added IMAP caching and built-in SMTP support, I would have a harder time justifying it.</p>
<p>But I feel more protective of my Emacs and org-mode experience than anything. This run with Doom has yielded the most stable Emacs experience I&rsquo;ve had since switching to Macs mooostly full-time ca. 2004. No mystery segfaults. No hard-locking the UI because I have IMAP, RSS, IRC, and Twitter clients running in my text editor.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-04-03</title>
      <link>https://mike.puddingtime.org/posts/2023-04-03-daily-notes-for-2023-04-03/</link>
      <pubDate>Mon, 03 Apr 2023 11:00:40 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-03-daily-notes-for-2023-04-03/</guid>
      <description>Vimari, my Emacs origin story, a 24-year-old free sample chapter, and my Jurassic Park moment with a pizza box. John Wick 4, Diego Sanchez has lessons.</description>
      <content:encoded><![CDATA[<h3 id="vimari-and-my-emacs-origin-story">Vimari and my Emacs origin story</h3>
<p>Some time in 1991 I got a job at Indiana University. It wasn&rsquo;t much of a job, but for someone who&rsquo;d quit his job at a newspaper and had just spent a year flipping burgers at a place called &ldquo;G.D. Ritzy&rsquo;s,&rdquo; it was okay.</p>
<p>Everybody at IU could get an account on a VAX cluster running VMS. You could log in on one of the many VT100&rsquo;s scattered around campus, or telnet in via one of the Macs (SE&rsquo;s mostly in the public clusters) or PCs (a bunch of Zenith 286&rsquo;s.) If you had a modem at home you could get in that way, too. The machines in the cluster were all named things like &ldquo;Rose,&rdquo; &ldquo;Jade,&rdquo; &ldquo;Aqua,&rdquo; and other shades, so people called them &ldquo;the color computers.&rdquo; By early &rsquo;90s shared computing standards they were simple enough to use: You got a menu at login that offered the basics (email, directory services, interactive chat, etc.), and there was a small collection of utilities people wrote that you could install to do stuff like look up which user was logged into which terminal in a given lab (which broke whenever a terminal got moved, because the utility location database was put together by hand.)</p>
<p>The VAX clusters were hideously overloaded and logins were queued. At lunch I&rsquo;d walk from my work building over to a nearby academic building that had a study carrel with a VT100 taking up all the desk area, start a login, open my lunch and finish most of my sandwich before my password would be accepted. Once in it was faster but still pokey, so I&rsquo;d spend the hour doing email or bickering on Forum, the local discussion board.</p>
<p>I complained about how slow things were to a friend who was doing her PhD in biology, and she told me the resident nerd in her lab had helped everybody get &ldquo;metal&rdquo; accounts, which were much faster. I&rsquo;d seen them in use but assumed they were reserved for some class of university person I was not. &ldquo;No,&rdquo; she told me, &ldquo;just go to the computing services helpdesk in the union, and don&rsquo;t say &lsquo;metal,&rsquo; say &lsquo;unix.&rsquo; You have to say you want a &lsquo;unix&rsquo; account.&rdquo;</p>
<p>Okay. Got it. So on my next stop by the union I went down there and told the help desk person &ldquo;please give me a &lsquo;unix&rsquo; account.&rdquo;</p>
<p>He collected some information and jotted my username and password on a tri-folded pamphlet that said something like &ldquo;UNIX At Indiana University.&rdquo; The pamphlet served mainly to say &ldquo;you&rsquo;re about to use something that will remind you of MS-DOS just enough to confuse you but not enough to help you.&rdquo; It also explained how to write an alias to make some things be more like MS-DOS, and it said if you wanted to write a file, you should use a program called <code>vi</code>.</p>
<p>I logged into my new account on a node called &lsquo;silver,&rsquo; and right away noticed that the login was instantaneous, and that it dumped me into a bare prompt. No helpful menu. No nothing. I spent a lot of time in that pamphlet, learning that <code>elm</code> was for email, and that I had a choice of <code>rn</code> or <code>tin</code> for this thing called Usenet that absolutely kicked Forum&rsquo;s ass, and that there were these things called <code>man</code> pages that were both often delightful and occasionally infuriating.</p>
<p>I was mostly interested in using my account for writing, though, since I could keep my work on a central machine and get at it from anywhere on campus or from home, where I had a Lear-Siegler ADM3A+ and a 300-baud modem. <code>vi</code> posed a small problem there, however, as it didn&rsquo;t seem to have word-wrap. I mean, I am sure it probably did, but <code>man vi</code> wasn&rsquo;t telling me how that might work.</p>
<p>So I made my way down to the UCS help desk in the student union again and said to the person at the counter, &ldquo;I am trying to write with my unix account, and there&rsquo;s no word wrap in <code>vi</code>.&rdquo;</p>
<p>&ldquo;Oh, huh. I don&rsquo;t know. I just use WordPerfect. Um &hellip; the guy who knows unix is here.&rdquo;</p>
<p>So he shouted over his shoulder, &ldquo;hey, how do you turn on word wrap in vi? It&rsquo;s for a unix account.&rdquo;</p>
<p>&ldquo;Oh, it doesn&rsquo;t have it. Tell him to use Emacs.&rdquo;</p>
<p>&ldquo;Okay. Yeah. Um, you should use Emacs. It sounds like it has word wrap.&rdquo;</p>
<p>Then he slid me a salmon-colored tri-fold pamphlet that said &ldquo;Emacs at Indiana University.&rdquo;</p>
<p>Okay.</p>
<p>The pamphlet said nothing about word-wrap, but I had a USENET account, so I asked whichever Emacs group I found first, and someone started me down the path. That&rsquo;s it. 32 years later &ldquo;I am an Emacs user&rdquo; because in 1991 I couldn&rsquo;t figure out word-wrap in vi.</p>
<p>&ldquo;Unix&rdquo; (I later learned I was actually using Ultrix) took over how I thought about computers. When I put the ADM3A+ aside so I could use an IBM XT I&rsquo;d bought at university auction for $35, I reversed my journey of aliasing all the Unix shell commands to their DOS equivalents and installed something called 4DOS, which provided an improved shell for MS-DOS machines and allowed me to make Unix-like aliases. Dumpster-diving outside one of the academic buildings I found a complete set of disks and manuals for <a href="https://en.wikipedia.org/wiki/Sprint_(word_processor)">Borland Sprint</a>, which was a word processor for DOS that included keystroke emulation layers for WordStar (whatevs), WordPerfect (hot), and Emacs (!).</p>
<p>That also primed me for my first &ldquo;tech job,&rdquo; sorting out a Sun pizza box that served as a printing queue for a pair of Xerox DocuTech&rsquo;s in my office. When the thing went down, my boss grabbed me because &ldquo;you know computers&rdquo; and I was allowed to actually sit at the terminal, wherein I had my _<em>Jurassic Park</em> moment a year before <em>Jurassic Park</em>.</p>
<p><img src="/img/jurassic-park-unix.jpg" alt="Screen capture of Lex in Jurassic Park saying &lsquo;it&rsquo;s a unix system, I know this.&rsquo;"></p>
<p>It <em>was</em> a Unix sytem, and I <em>did</em> know it. Mostly. Enough that the Xerox support tech and I were able to communicate over a very long support session, determine that my boss kept turning the box off at night, which was keeping <code>cron</code> from running, and killing the print queue when <code>/tmp</code> filled up. From that point forward, some of my job was my old job and some of it was just doing computer stuff that needed to be done.</p>
<p>Being pointed to Emacs also started my education about Free Software (&ldquo;open source&rdquo; was years away). I&rsquo;d never really thought about software as a thing you&rsquo;d think about ethically. I thought shareware was cool but usually bad compared to the stuff you got at WaldenSoft, and that the best software had to be fished out of a dumpster outside the communications department building after some professor had moved on. Emacs was happy to educate me about all that, though.</p>
<p>When Linux turned up I was completely primed for it. I didn&rsquo;t have the hardware or skill to install it, and wouldn&rsquo;t until 1995, but wow was I ready for a real Unix on hardware I could afford.</p>
<p>Anyhow, the whole &ldquo;vi vs. Emacs&rdquo; thing was always the source of some wry amusement to me. When I wrote a book about Linux that had <a href="/img/Joy04.pdf">a whole chapter on the flame wars of the late 20th century Linux community</a> the matter figured prominently. When we released a sample chapter on LinuxToday people felt this was divisive and unworthy of the open source community ethos:</p>
<blockquote>
<p>Vi fans are proud of their hard-earned knowledge and mastery. You can find Web pages with buttons that read, “Crafted with the vi editor.” There are vi coffee cups with the commands you might need to know printed on the sides. Vi people take a ruthless pleasure in telling newbies to use vi. They know what the newbie’s getting into, and they aren’t about to warn them. If the newbie works in an adjoining cubicle, vi users sit quietly and listen to the newbie’s terminal beep over and over and over while the first lesson of vi is pounded into their skulls: You can’t “just start typing” with vi. People who want to do that are morally defective.</p>
</blockquote>
<p>But personally I just sort of kept quiet about the whole thing outside of admitting that I was an Emacs person and sometimes mentioning that was mostly owing to an historical accident. I mean, when Puppet started doing stuff with Clojure in 2013,  and suddenly Emacs-by-way-of-Spacemacs started turning up on more screens, I did feel a small surge of vindication, but also could not puzzle out the whole <a href="https://github.com/emacs-evil/evil">Evil</a> thing.</p>
<p>But here I am, typing this on Emacs using Doom Emacs and keeping the Evil layer turned on because I got a little bored and wondered what life could have been like if someone had told me vi had word-wrap in 1991.  Interestingly, because I have applied myself to learning and practicing vs. backing into the bare minimum over the years, I think I might be at least as proficient from the past several weeks of practice. I&rsquo;ve got a janky, hybrid style right now, because Doom is set up to let a lot of Emacs keybindings still work, and also lets me use more traditional Mac keybindings for basic text operations. Maybe it&rsquo;s less of a conversion to the <code>vi</code> keybindings and more an appreciation of Doom&rsquo;s modal interface. But I do continue to find myself on the control key less, and I appreciate that.</p>
<p>Oh, right: It has taken enough that I added <a href="https://github.com/televator-apps/vimari">Vimari</a> to Safari. It gives you a bunch of vim keybindings. The one I actually like the most is <code>f</code> to label all the links on the screen and jump to one.</p>
<h3 id="spacemacs">Spacemacs</h3>
<p>Speaking of Spacemacs, I did give it another look over the weekend just because Doom doesn&rsquo;t use <code>~/.emacs.d</code> and Spacemacs doesn&rsquo;t look in <code>~/.config</code>, so swapping configs is a cheap thrill. I completely get the charm, and could see myself using it if I&rsquo;d have tried it before Doom, but I did find some config conventions a little less to my liking &ndash; they sort of tangle things up in a way that feels more error prone &ndash;  and I found the out-of-the-box configs in Doom more to my liking.</p>
<h3 id="john-wick-chapter-4">John Wick Chapter 4</h3>
<p>Al and I went to see the new <em>John Wick</em> movie over the weekend. It&rsquo;s long and I would argue it is too much of its particular good thing. Running close to three hours, there&rsquo;s a whole section I think they could have removed, losing little.  At the same time, Donnie Yen is so great as Caine. Watching his more old-school cinematic martial arts style contrasted with John Wick&rsquo;s sometimes awkward, brutally utilitarian &ldquo;not going for a submission, just holding your head still so I can shoot it&rdquo; fight choreography was cool, and it made me glad I&rsquo;ve got <em>Blind Fury</em>, <em>The 36th Chamber of Shaolin</em>, and <em>The Five Venoms</em> lined up on Plex.</p>
<p>I guess it feels a little churlish to complain about 3-hour run times. I remember when even up-market Hollywood stuff was frequently coming in at under 2 hours, and it felt penny-pinching and sad.</p>
<p>Anyhow, tomorrow is a big day. Al helped me rehearse yesterday, and I&rsquo;m sitting here in that state you get into when you&rsquo;ve prepared right up to the point of over-preparation and you need to stop so your brain can consolidate it all and you can just go in and play your game, knowing that you&rsquo;re going to tell the best possible story about who you are, then leave it to the people on the other side of the table to decide if they want that.</p>
<p>To quote the great Diego Sanchez:</p>
<p><img src="/img/diego.gif" alt="GIF of Diego Sanchez chanting &lsquo;yes&rsquo; as he walks in for a fight"></p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-03-29</title>
      <link>https://mike.puddingtime.org/posts/2023-03-29-daily-notes-for-2023-03-29/</link>
      <pubDate>Wed, 29 Mar 2023 11:42:01 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-03-29-daily-notes-for-2023-03-29/</guid>
      <description>Trying org-journal, Good Sudoku, blog content migration tools.</description>
      <content:encoded><![CDATA[<p><em>Breaking</em>: I just discovered Doom&rsquo;s <code>rotate text</code> module in the process of thinking &ldquo;why can I not just flip this post&rsquo;s draft metadata from <code>true</code> to <code>false</code> with a keystroke? Did I see something about that in <code>init.el</code>?&rdquo; I <em>did</em> see something about that in <code>init.el</code>, so I uncommented the line, did a <code>doom sync</code>, and it&rsquo;s there: just put a word under the point and <code>] r</code> to go through the candidates.</p>
<p>Anyhow &hellip; as I was about to post:</p>
<p>I am in one of those liminal places people find themselves in from time to time.  I suppose the best thing you can say about them is that it&rsquo;s better when you know you&rsquo;re there than when you don&rsquo;t, because you at least have a fighting chance of arresting the worst of your bad habits.</p>
<h2 id="good-sudoku-is-real-sudoku-i-guess">Good Sudoku is real Sudoku, I guess</h2>
<p>For instance, sometimes it&rsquo;s good to stop moving around so much and just wait the thing out. Sudoku has always been good at that for me, but so much of my conception of Sudoku involved mandatory tedium. Like, I didn&rsquo;t even fully embrace the &ldquo;logic&rdquo; parts of the game because some of what made it soothing was the dull repetition of pre-filling all the gimmes, and you don&rsquo;t need hard puzzles to waste a bunch of time on that while you fight with a virtual copy of your office nemesis.</p>
<p><a href="https://www.playgoodsudoku.com">Good Sudoku</a> for iOS/iPadOS is several years old, now. I saw it come out, downloaded it, and honestly thought there was some sort of catch to it. It has a few provisions for automating or at least bringing focus to the early stages of a puzzle, and I found that with those affordances I can reliably complete puzzles at the &ldquo;advanced&rdquo; level without getting out of my comfort zone in terms of logical patterns. I can finish some &ldquo;Expert&rdquo; ones without a hint, and maybe half of them with just a single hint. It was so jarring to me that I even went looking for evidence that there might be people who hate it for spoiling a tedious and frustrating but essential element of the game. Like, maybe there are people out there who <em>like</em> that you have to do all the paperwork. If there are, I didn&rsquo;t see them in the first few pages of a DuckDuckGo query asking if Good Sudoku can even be considered real Sudoku.</p>
<p>So the revelation, I guess, is that Sudoku remains fun with those affordances in place. You still have to, like, use logic and stuff &hellip; you just have to learn more advanced things more quickly because the quality of life enhancements get you there faster. But there&rsquo;s still plenty of challenge left. For the first time, though, Sudoku is a question of &ldquo;how good do I care to become?&rdquo; instead of &ldquo;how much tedium can I take?&rdquo;</p>
<p>Maybe more importantly than being &ldquo;fun,&rdquo; Sudoku remains absorbing. When my brain spins up too far, and I find myself stuck in those things I do when I&rsquo;m in a liminal space, it&rsquo;s a way to background the things that feel like distractions, soak up some excess cognitive capacity, and process the thing that is eating me at a level I can deal with while I give over some spare cycles to spotting a new pattern I&rsquo;m still trying to internalize.</p>
<h2 id="org-journal">org-journal</h2>
<p>I&rsquo;ve had a daily journal practice going for a little while now, partially cribbed from a pre-made paper daily journal I tried out a few years ago. In its most recent form, the day starts with three prompts:</p>
<ul>
<li>What&rsquo;s today&rsquo;s biggest challenge?</li>
<li>What are you happiest about?</li>
<li>What are you most nervous about?</li>
</ul>
<p>&hellip; and it ends with three prompts:</p>
<ul>
<li>What happened today?</li>
<li>What went well today?</li>
<li>What could you improve?</li>
</ul>
<p>I include my morning and evening entries in my habit trackers so I can get a reminder, and I set up a template in DayOne to pre-fill the entry for the day.</p>
<p>I&rsquo;ve been pretty good about sticking to it, but I noticed recently that it was not working on a few levels:</p>
<p>First, it has become perfunctory &ndash; a task to accomplish. When I tap back through past entries I didn&rsquo;t have much of a sense of &ldquo;me&rdquo; in there because the entries were brief and suggestive of me just being very much in my own head and not doing much written thinking or processing.</p>
<p>Second, the questions have some issues. In particular, I noticed &ldquo;what are you most nervous about&rdquo; was putting me in a mindset where I had to cast about to think about something to be nervous about. That&rsquo;s &hellip; that&rsquo;s something to do when maybe you don&rsquo;t have an amygdala. It took me some time to get around to understanding how much that question was infusing my thinking with the idea that I was &ldquo;anxious.&rdquo; Glad I did.</p>
<p>So I did the thing I do when something I do isn&rsquo;t working for me and I made it a set of documents. It was a good excuse to try out org roam as a Zettelkasten replacement for Obsidian. The three nodes I made were:</p>
<ul>
<li>Journaling: tools</li>
<li>Journaling: practices</li>
<li>Journaling: experiments</li>
</ul>
<p>All of them link back to a &ldquo;Purpose: Writing&rdquo; node.</p>
<p>Then I put down some time on the schedule to write some notes about each, asking what I want to get out of the practice, what tools I have under consideration for continuing it (e.g. Obsidian, <a href="https://dayoneapp.com">DayOne</a>, assorted Emacs stuff), and which experiments I mean to run for how long to see what works.</p>
<p>I&rsquo;ve just started a  &ldquo;use <a href="https://github.com/bastibe/org-journal">org-journal</a>&rdquo; experiment.  I use the vanilla config from Doom, and I added a morning and evening entry template using <a href="https://github.com/joaotavora/yasnippet">yasnippet</a> to keep the investment in automation light for now. The one minor disappointment I&rsquo;m experiencing is how <code>org-crypt</code> works, which is entry-by-entry, and manually. Maybe there&rsquo;s a different way to protect the content anyhow, but <code>org-crypt</code> seems to be the Doom-blessed approach, and I was hoping for something a bit more transparent. I&rsquo;m also guessing there&rsquo;s a way to make it more transparent at the cost of eating someone else&rsquo;s elisp off the sidewalk.</p>
<p>Playing with tools is just sort of the fun part of it. It was immensely useful, once again, to sit down and write about why I even cared and wanted to do this, and when I sat down this morning to write my first entry of the day the renewed sense of purpose did as much as anything to make the entry more rich. I can imagine &ldquo;me in ten years&rdquo; getting something out of that entry, which is a vast improvement over the bulk of the past quarter&rsquo;s worth of entries.</p>
<h3 id="migrating-content-from-microblog">Migrating content from micro.blog</h3>
<p>I downloaded the smaller set of archives from micro.blog this week and started seeing what it would take to move the content into place and start chipping away at a few generations of thinking about image hosting and markup. It&rsquo;s all Hugo files, so that&rsquo;s good, and the assorted idiosyncracies are all distinct enough from each other that there&rsquo;s not a lot of &ldquo;this regexp is going to wipe out something completely unrelated.&rdquo;</p>
<p>A few useful tools in this process:</p>
<ul>
<li><a href="https://www.publicspace.net/ABetterFinderRename/index.html">A Better Finder Rename</a> is wonderful for traversing a directory and &hellip; renaming things. Being able to rename files three levels deep in a hierarchy based on their parent folders is pretty handy. I had a license years ago. It was worth the reup.</li>
<li><a href="https://www.devontechnologies.com/apps/freeware">EasyFind</a> is great for fast searches of files in a way that works better for me than how Spotlight operates, then makes them available for bulk operation. In this case, it helped in quickly segregating files by certain metadata and moving them off into subdirectories. Great value for no cost.</li>
<li><a href="https://www.barebones.com/products/bbedit/">BBEdit</a> is such a champ at bulk file processing. Having a visual regexp tool to pre-flight operations across a collection of files is great. Saving those operations is great. It&rsquo;s fast, stable, and doesn&rsquo;t blink when you toss thousands of text files at it.</li>
</ul>
<p>I wanted to go at some of the migration challenges with scripting, but there seems to be <a href="https://pypi.org/project/python-frontmatter/">a single Python lib</a> that groks YAML frontmatter in Markdown, and that&rsquo;s not one of my good languages, so I&rsquo;d be hand-rolling something that I&rsquo;d rather not. The three tools I listed above are all pretty capable and have the advantage of offering some sort of pre-flight feedback, sometimes with syntax highlighting, etc. I&rsquo;ll take those shortcuts.</p>
<p>And wow is this all so much better than the stuff I used to make money dealing with: Legacy blogging systems with a database backend and a bizarre blend of &ldquo;yes, there&rsquo;s the body of the article right there in the <code>body</code> field, but where on earth is the title? I can see it on the front end but it does not exist in this db dump.&rdquo; (A: The title was in a separate table from the content table &ndash; which was specific to the site &ndash; and that titles table covered every site under management by that CMS, <em>and</em> no they wouldn&rsquo;t export that for my client when they left the service. I got super creative with the Bing API to reunite all the articles with their titles for that gig.)</p>
<p>Anyhow, that&rsquo;s plenty for today and I need to get a run in. Ben&rsquo;s home this week and we&rsquo;re taking him out tonight. It is still sometimes strange to have become a person who lives in a home that a 19-year-old man comes home to now and then, and it was also strange to realize two hours into a conversation with him yesterday that he is just this person it is great to have a conversation with. But it&rsquo;s strange in the most wonderful way.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-03-24</title>
      <link>https://mike.puddingtime.org/posts/2023-03-24-daily-notes-for-2023-03-24/</link>
      <pubDate>Fri, 24 Mar 2023 10:04:10 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-03-24-daily-notes-for-2023-03-24/</guid>
      <description>More on learning with Vim Adventures, TickTick is out, time to pack it in on micro.blog.</description>
      <content:encoded><![CDATA[<h3 id="re-ticktick">re: TickTick</h3>
<p>It has been supplanted by org-mode.</p>
<p>Final verdict: It&rsquo;s pretty good. If I had to put all my to-do lists in a proprietary, closed-format tool, it would probably be the one, or at least in the running with Things. I just appear to be due for an org-mode kick, and TickTick happened to be standing around when it happened.</p>
<p>In terms of getting out of org-mode what I was getting out of  TickTick beyond a simple todo list, it came down to mobile, habits, and pomodoros.</p>
<p>[beorg][] handles Reminders integration. Doom Emacs lets you pull in <code>org-habits</code> out of the box, so I just did that and set up a habits file. They&rsquo;re pulled into my agenda, which shows streaks information for them.</p>
<p>I also added <code>org-pomodoro</code>, which works about like you&rsquo;d expect: Pick an item from the agenda, trigger the timer, and it adds a time entry to that item in its home file for each Pomodoro completed:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">** omg.lol Docs
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">*** Git workflow
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">**** DONE Beginner section
</span></span><span class="line"><span class="cl">DEADLINE: &lt;2023-03-24 Fri&gt;
</span></span><span class="line"><span class="cl">:LOGBOOK:
</span></span><span class="line"><span class="cl">CLOCK: [2023-03-24 Fri 14:19]--[2023-03-24 Fri 14:44] =&gt;  0:25
</span></span><span class="line"><span class="cl">CLOCK: [2023-03-24 Fri 13:49]--[2023-03-24 Fri 14:14] =&gt;  0:25
</span></span><span class="line"><span class="cl">CLOCK: [2023-03-24 Fri 11:25]--[2023-03-24 Fri 11:50] =&gt;  0:25
</span></span><span class="line"><span class="cl">CLOCK: [2023-03-24 Fri 10:14]--[2023-03-24 Fri 10:39] =&gt;  0:25
</span></span><span class="line"><span class="cl">CLOCK: [2023-03-24 Fri 09:38]--[2023-03-24 Fri 10:03] =&gt;  0:25
</span></span><span class="line"><span class="cl">:END:</span></span></code></pre></div>
<p><a href="https://writequit.org/denver-emacs/presentations/2017-04-11-time-clocking-with-org.html">I found this presentation helpful for figuring out how to add reporting with the time data you can gather</a>.</p>
<h4 id="always-coming-home">Always coming home</h4>
<p>At some point we have to acknowledge to ourselves that maybe the chaos is the actual pattern, or that the things we think are chaotic are not after all, even if we can&rsquo;t quite feel the rhythm.</p>
<p>When it comes to tools &ndash; especially productivity ones &ndash; I am fickle. I&rsquo;ve been through four or five major &ldquo;all in on org&rdquo; moments in my life, and then I&rsquo;ve fallen out of them.</p>
<p>org-mode can be tough to stick with: Emacs can be crabby, the ecosystem feels fragile sometimes, and you occasionally go through these periods where everyone&rsquo;s carrying on about some new Emacs build or hotness and you chase after it ten minutes before a day full of meetings where the segfaults start in the middle of a note.</p>
<p>No amount of fluency with the tool or joy in the format can get you around the days where the tool just doesn&rsquo;t feel steady.</p>
<p>On the other hand, one missing piece from previous Big Org periods has been a habit I picked up during the pandemic of being more circumspect about the tools I pick up and what I want to do with them. I write about what I hope to get out of something. I think about what I want to use it for. Sometimes I learn about a new feature or approach and decide to roll it in, but I&rsquo;ve gotten a lot better at knowing why I use the things I do, and what I want out of them. I&rsquo;m also more suspicious of changing them up much.</p>
<p>In assorted parts of my technical life, that new habit has been a real boon, because &ldquo;tech&rdquo; in the broadest sense is something I like to play with, and I used to constantly break the rule &ldquo;Don&rsquo;t try anything new on race day,&rdquo; with all the ensuing chaos that comes with it. Like, years ago past Mike got really disgusted at work and swore he was done with his job and applied for a bunch of jobs, and decided that was the right time to change email providers because he heard that the one he was switching to had some cool features. Yes, some mails went missing.</p>
<p>Where my Emacs life is concerned, it just comes down to &ldquo;one thing at a time, only one thing a day, if at all.&rdquo;</p>
<p>I self-interpret that to mean &ldquo;you can turn on one module and snarf up one quick tweak or imported config to go with it.&rdquo; Adding <code>org-super-agenda</code>? Great &ndash; turn it on and add one config change. Doing pomodoros? Okay, don&rsquo;t change your org agendas to show the timing, just make sure you can record the times consistently, and that it isn&rsquo;t making things feel wobbly. I usually just do a pomodoro of fiddling at the beginning of the day, which is about enough time to find something, turn it on, and see if it passes the initial use test before it&rsquo;s time to do other stuff.</p>
<p>I&rsquo;ve been harping a lot elsewhere on how stable Doom Emacs feels compared to my own <code>init.el</code> ecosystem, but I suspect part of it is just that I&rsquo;ve been very careful about what I add and how much I add at a time. I think Emacs is in a unique tier of sensitivity to a lot of thrashy change, but just about anything built on a lot of user-generated content (e.g. modules, add-ons, plugins) can be made to misbehave and become hard to troubleshoot.</p>
<p>Another thing that has changed about me over the past few years has been a growing awareness that I can get into a headspace where I prize automation and less overall motion to the point of paralysis. It took seeing other people falling into that pit &ndash; believing that they came into work that day to automate something and not to achieve an outcome &ndash; to get me to see it in myself and snap out of it a little.</p>
<h3 id="vim-adventures">Vim Adventures</h3>
<p>I mentioned yesterday that I&rsquo;ve been enjoying Vim Adventures:</p>
<iframe src="https://social.lol/@mph/110075234226930854/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe><script src="https://social.lol/embed.js" async="async"></script>
<p>&ldquo;Enjoying&rdquo; is sort of relative. It wants you to learn stuff that is a slog, and it has a few puzzle challenges that can be challenging since they not only demand you use the keys you&rsquo;ve been learning to accomplish the task, they sometimes require you to do a little lateral thinking. You can&rsquo;t get away with just memorizing a keystroke for a given lesson, use the keystroke a few times, then get on with it. You end up using the keystroke repeatedly trying to solve a puzzle in under <em>n</em> keystrokes, sometimes not realizing there&rsquo;s another lesson buried in there about cursor motion behavior or what have you.</p>
<p>In the end, though, the puzzles are well constructed. New stuff comes in at a steady pace, and each new set of challenges provide a mix of what you&rsquo;ve already learned with the new stuff, so you have to constantly adapt. I tried another, less gamified vim tutorial to see if it would work better for me and it was disorienting after a few hours with Vim Adventures: I couldn&rsquo;t see how any of it could possibly stick in any meaningful timeframe.</p>
<p>I&rsquo;m typing this in the space between writing pomodoros this morning. This is the first day I&rsquo;ve had all week to be deep in a writing/revision cycle using what I&rsquo;ve been learning. It&rsquo;s been interesting to realize how much stuff Vim Adventures has taught me to &ldquo;just do&rdquo; with minimal delay, but I can still sense the occasional spike in cognitive load when a few decades of muscle memory collide with newly learned things that are still up there in the thinking layers.</p>
<p>It&rsquo;s also interesting, as someone whose first deep Unix experience dates back to an Ultrix box and VT100 in 1991, how much these assorted UI ecosystems have come to acknowledge each other. Doom understands the basic Mac text keybindings, so when I&rsquo;ve exhausted my vi keybinding knowledge and just need to do a damn thing to a block of text, cmd-x and cmd-v are right there.</p>
<p>I have asked myself a few times &ldquo;why are you doing this at all,&rdquo; and as near as I can figure it comes down to:</p>
<ul>
<li>Finding I prefer hand positioning that involves fewer control key chords.</li>
<li>Enjoying the learning experience. It&rsquo;s stimulating.</li>
<li>A recent encounter with the mythical &ldquo;vi only&rdquo; system in the form of my EdgeRouter X. Dinking around with files in that thing was a pain, just as the vi bigots have always warned. Completely doable with my limited repertoire of vi skills, but clumsy.</li>
</ul>
<p>I suppose I should also sing Doom Emacs&rsquo; praises once more: It does a lot to make Emacs feel more stable by taking care of housekeeping and providing some reasonable defaults. It&rsquo;s a good learning platform because there are fewer random things going on out of the box. I don&rsquo;t know if I&rsquo;d be able to tolerate the learning curve with my own <code>init.el</code> in place.</p>
<h3 id="probably-time-to-wind-down-on-microblog">Probably time to wind down on micro.blog</h3>
<p>A few months ago I took this site and moved it from Jekyll to Hugo. Jekyll was fine and all, but the more I dug into Hugo&rsquo;s features the more it seemed like an interesting direction to go. I also wanted to move the site from <em>looking</em> personal marketing heavy to just being a blog that also has stuff in it about work/business sometimes.</p>
<p>That was a liberating move: I was able to get myself into a pretty easy writing/publishing workflow that was perhaps a little more computer-bound than what I could get away with on micro.blog, but not so bad.</p>
<p>I kept sticking to my micro.blog presence partially because it has robust cross-posting features I hadn&rsquo;t bothered to suss out using something like IFTTT or Zapier. At the same time, I have a little too much web producer left in me to be comfortable with two domains that are roughly doing the same thing. I once automated a consolidation, content migration, and re-canonicalization of four dozen websites. People sneer about SEO and all the evils of the SEO industry, but there are search engines in the world and there are reasons to care about what they make of your web presence.</p>
<p>If all I wanted to do was have a blog in the most traditional &ldquo;reverse-chronological-ordered posts&rdquo; sense of the word, I&rsquo;d probably stick with micro.blog. Its Hugo foundations allow just enough flexibility to do the basics, and your content can be exported with relatively few idiosyncracies &ndash; no worse than any other Hugo theme. You can write shortcodes and customize a lot of the way the site works.</p>
<p>It&rsquo;s kind of a frustrating platform for iterative development, though. There&rsquo;s enough variance between a basic Hugo theme and what micro.blog needs that you have to do some trial-and-error. Using vanilla Hugo on a laptop, iterative learning is lightning fast and the feedback loops border on instantaneous, especially with <code>hugo server --navigateToChanged</code>. With micro.blog, there&rsquo;s a build time delay to figure out if your thing worked or not, or to get feedback on how it is failing.</p>
<p>I have also found I prefer the free-wheeling nature of Mastodon a little more appealing than the social layer of micro.blog. I&rsquo;ve written about that <a href="https://mike.puddingtime.org/posts/2023-03-13-the-pleasures-of-a-small-mastodon-instance/#comparing-to-microblog">elsewhere</a>, so we&rsquo;ll leave it alone here.</p>
<p>Anyhow, it&rsquo;s time to go through the past couple of years of micro.blogging and work out how to manage that migration. One idea I want to explore is the creation of a &ldquo;microblog&rdquo; content type that would allow me to just move all that stuff into its own silo largely untouched, with some design work to cope with the titleless posts over the years, and with some logic in my Atom feed to allow for ongoing microposts that stay out of Atom but still get syndicated over Mastodon.  Similarly, that could be a quick path to getting all my old dot unplanned content moved over under its own &ldquo;vintage&rdquo; content type.</p>
<p>At some point I am not going to have the kind of time on my hands that I have now, so my thinking is beginning to shift to &ldquo;what&rsquo;s expedient&rdquo; vs. &ldquo;what could enhance your career as a Hugo consultant with yourself as your only client.&rdquo;</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-03-22</title>
      <link>https://mike.puddingtime.org/posts/2023-03-22-daily-notes-for-2023-03-22/</link>
      <pubDate>Wed, 22 Mar 2023 10:42:33 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-03-22-daily-notes-for-2023-03-22/</guid>
      <description>Succumbing to org-roam, the pleasures of a straight razor competently wielded, Decline of Western Civilization.</description>
      <content:encoded><![CDATA[<h3 id="succumbing-to-org-roam">Succumbing to org-roam</h3>
<p>Well, it took less than 12 hours to go from &ldquo;I&rsquo;m not going to even touch that&rdquo; to &ldquo;huh, I wonder if it&rsquo;s cool?&rdquo;</p>
<p>Yes, <a href="https://www.orgroam.com">org-roam</a> is cool. It&rsquo;s a Zettelkasten implementation built atop org-mode. To make it work in Doom Emacs you just add it to the org-mode line in Doom&rsquo;s <code>init.el</code>:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">(org +roam2) </span></span></code></pre></div>
<p>&hellip; and then run <code>doom sync</code>.</p>
<p>You should add a <code>roam</code> subdir to your standard org files location or it will complain when you try to use it.</p>
<p>You can instantiate a new node with <code>spc n r i</code> (&rsquo;n&rsquo;otes, &lsquo;r&rsquo;oam, &lsquo;i&rsquo;nsert)</p>
<p>That gets you a roam buffer and you can start typing. As with most transient Emacs buffers, <code>C-c</code> will save and exit.</p>
<p>If you want to link to a separate note, you can start typing its name in the body of the current note and get an autocomplete list.</p>
<p>If you link to a note from another note, Roam takes care of adding a backlink at the bottom of the target note.</p>
<p>As with all things Emacs, there are org-roam configs you can go find on the street and stick in your mouth. As with all things Emacs, I didn&rsquo;t describe it that way because I thought that would make such an approach attractive to you. I want you to be repulsed by that approach because it is unclean. One of the advantages of Doom Emacs (or Spacemacs, or Prelude) is that if they include a package, they probably include some basic configuration, so you can kick the tires then start layering on capabilities.</p>
<p>Anyhow, in its basic Doom Emacs config, org-roam is unremarkable. If you want a zettel and don&rsquo;t want Emacs, go get Obsidian or one of its competitors. I&rsquo;m going to stick with it for a while. As I mentioned <a href="/posts/2023-03-21-daily-notes-for-2023-03-21/">yesterday</a>, I like org-mode&rsquo;s intertwingling of tasks/actions/todos and prose, so it suits me.</p>
<h3 id="the-pleasures-of-a-straight-razor-competently-wielded">The pleasures of a straight razor competently wielded</h3>
<p>A brief history of me and professional grooming:</p>
<ul>
<li>My grandmother paid for my first stylist haircut when I was in 7th grade. I had no idea how to maintain it.</li>
<li>I spent a few years just telling barbers to take it all off.</li>
<li>The army taught me the pleasures of walking in, paying your $5, and getting a high-and-tight. Once I&rsquo;d been in a few years, I&rsquo;d modify the request to say &ldquo;leave a little up top.&rdquo;</li>
<li>Over the past 20 years I developed an appreciation for Great Clips because they store your preferences and last cut in the computer under your phone number.</li>
</ul>
<p>Then last year I walked into a barber shop near the office because things were dire and I had a few minutes. The barber handled the basic cut, then offered to do some detail work with a straight razor since he had time. That part was amazing, and it made my day.</p>
<p>I started going back, partially because it was a great first experience and partly because the barber was utterly disinterested in small talk. Just enough to establish we spoke a common tongue, then nothing except the occasional request for a decision.  We did enter into an extended dialog about my beard made up of very sharp exchanges in the ensuing months. He was in favor of taking more of it off, and I would say &ldquo;no, I&rsquo;m not there yet, please just do what you can with it.&rdquo; He&rsquo;d mutter and then cluck when he got to the part where it began to curl at the bottom. &ldquo;I can&rsquo;t do anything with this &hellip; you&rsquo;re sure you&rsquo;re okay?&rdquo;</p>
<p>Then last week I had a video conference and was wearing a shirt with a collar and a jacket and I realized I couldn&rsquo;t see my collar under my beard. I couldn&rsquo;t really see my mouth, either.</p>
<p>I recently read about a study that suggested people with beards will ultimately be perceived as more trustworthy and accessible <em>once they are given an opportunity to smile</em>. Until that point, the unbearded have all the social advantages. So I decided it might be best to make my mouth observable. COVID and masking did reveal me to be a proficient eyebrow flasher, but I don&rsquo;t think you can completely rely on that.</p>
<p>So I booked time with my barber and left out the haircut (I&rsquo;m good for a few more weeks) but did add the razor true-up.</p>
<p>When I sat down he resignedly asked &ldquo;the usual, just fix the scruff?&rdquo; and I said &ldquo;no, I&rsquo;d like to get some of that length and volume out of there.&rdquo; He started to nod vigorously, and we entered into an extended negotiation measured in finger widths (&ldquo;okay, but top of finger or bottom?&rdquo;) and ultimately settled on something that would both reveal my mouth and also let you see my neck and/or collar.</p>
<p>Then it was just closing my eyes and enjoying the hot towel, thick lather, and precision work of a sharp straight razor, including temples and neck.</p>
<p>Restorative.</p>
<p>I go all the way across town &ndash; the barber moved from near the office to even further west &ndash; but it&rsquo;s worth the train ride once a month to have a good barber.</p>
<h3 id="movie-decline-of-western-civilization">Movie: Decline of Western Civilization</h3>
<p>I rewatched Penelope Spheeris&rsquo; <em>Decline of Western Civilization</em> for the umpteenth time. X is one of my top 5 favorite bands of all time, so I love everything with them in it, even if John Doe&rsquo;s trolling over &ldquo;Johnny Hit and Run Pauline&rdquo; makes me cringer harde with every viewing.  The people around the periphery are great, too, including Club 88&rsquo;s owner, who is determined to greet the whole freak show playing out in his venue with a certain patient equanimity I hope I can equal as the world moves on around me. And I&rsquo;m grimly fascinated with Fear, and Lee Ving in particular, and his theatrical hate.</p>
<p>Punk was the first real subgenre I embraced. I was up at 2 in the morning in 10th grade, working on a paper for my journalism class, when the college radio station I&rsquo;d been listening to jazz on hours earlier suddenly crackled back to life from its post-midnight-signoff hiss because someone had snuck into the studio and announced the first (and possibly last) installment of &ldquo;Goshen College&rsquo;s Guts Radio.&rdquo;</p>
<p>Then they peeled my skull back with Fear, Black Flag, Dead Kennedys, and stuff I never heard again.</p>
<p>I mentioned it to the stoner who sat in front of me in American History and he came back the next day with the Dead Boys&rsquo; <em>Young, Loud and Snotty</em> on one side of a cassette tape, and a hastily assembled tour of more vintage punk on the other.</p>
<p>Anyhow, <em>Decline</em>: X are the odd ones out there. A punk act, yes, but with the seeds of their eventual trajectory present if you look for them. The case has been made that they were a case of tragic mistiming and I think it might be true: There they were at the height of their <em>energy</em> in 1980, but the <em>sensibility</em> they anticipated was years away from the eventual saturation it achieved with vintage scavengers and billy boys. My affection for X is undying: They were my bridge from a sullen, resentful anger toward all the normal people to a belief that maybe <em>I</em> was one of the decent people, too.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-03-21</title>
      <link>https://mike.puddingtime.org/posts/2023-03-21-daily-notes-for-2023-03-21/</link>
      <pubDate>Tue, 21 Mar 2023 11:03:54 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-03-21-daily-notes-for-2023-03-21/</guid>
      <description>Back to org-mode, a decent C25K Apple Watch app, custom Hugo RSS.</description>
      <content:encoded><![CDATA[<h3 id="back-to-org-mode">Back to org-mode</h3>
<p>Reasonable default configurations have been a pleasure of [Doom Emacs][]. Even org-mode, which I had somewhat dialed in on my own, works well enough, and maybe better, under Doom. When I took my <code>org-conf.el</code> apart I realized how many geological layers of features that sounded interesting but never made their way into regular use were sitting there, gumming things up and slowing things down.</p>
<p>I posted last night about a nicely wired up Projectile/org-mode pairing:</p>
<iframe src="https://social.lol/@mph/110059541236136990/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe><script src="https://social.lol/embed.js" async="async"></script>
<p>Whenever I get bit by the org-mode bug, the first thing I notice and remember loving is the intertwining of text and tasks. Sitting down and making lists in an app has never felt completely comfortable to me, and the notes capabilities of a lot of task apps leave me cold. They look and feel like afterthoughts, and the text is dead and inert inside them. Once the task is done, the text is effectively gone unless you take time to pull it out and put it somewhere.</p>
<p>When your todos and text are happening on equal footing with each other, your &ldquo;todo list&rdquo; stops being a todo list and starts being a sort of log or journal. Structure your notes correctly within todos, and org-mode makes it easy to copy them into another file or hierarchy, or you can just leave them in place and keep moving.</p>
<p>Preparing for a meeting this week, I loved sketching in the things I needed to cover as headings that happened to be todos, then launching straight into notes underneath those headings, roughing in initial thoughts or leaving myself prompts without clicking into a cramped little box.</p>
<p>I loved org-mode when I worked in a status report work culture because my weekly report was also my todo list. I wrote an exporter that kept out the stuff nobody else cared about, but showed the most recent log entry in each item. As priorities shifted, my status report was always up to date. As I wrote each week&rsquo;s update, I could see the previous week&rsquo;s just below it in the item drawer. Items that were delegated, on hold, or dropped, reflected reality at the moment of export. Attempts to do similar with other tools never came close, no matter how robust their scripting libraries.</p>
<p>So, having an Emacs distro that feels very solid underfoot and presents a clean, useful, uncluttered org configuration is a real joy.</p>
<p>I am also enjoying <a href="https://beorgapp.com">Beorg</a>, an iOS/iPadOS app that works well with org-mode, syncing via iCloud, Dropbox, WebDAV, or Box. It tilts toward the todo/agenda-oriented parts of the org-mode experience, but you can edit your prose notes with it in a pinch. It can also integrate with iOS Reminders and Calendar apps, so your agenda view can reflect your org stuff and your phone stuff if you have to live in a split ecosystem for things like shopping lists. It&rsquo;s not a completely seamless experience, but it is smooth and works well.</p>
<p>And the whole experience reminds me that, speaking only for myself, as much as I think it&rsquo;s possible to get work done on an iPad, I can&rsquo;t get it done as well as I can on a laptop or desktop machine.</p>
<h3 id="c25k-phone-app">C25K phone app</h3>
<p>&ldquo;Try to get more exercise&rdquo; has found its way onto the medical agenda, so I am trying to get more exercise.  My routine over the past couple of years has involved 3 or 4 miles of walking most weekdays, and upwards of 6 or 8 on weekends. That has served me pretty well, but after a few experiments and some measuring, it&rsquo;s pretty clear that 30 minutes of running every other day is helping even more.</p>
<p><a href="http://www.c25k.com">Couch to 5k</a> has been my go-to &ldquo;get back into running&rdquo; program over the years. It&rsquo;s a slow ramp &ndash; slower than I&rsquo;d like some days. When I compare how well I&rsquo;ve kept up a running habit (and kept feeling healthy) ramping myself up vs. sticking to C25K, it&rsquo;s clear I do better letting myself be held back a little.</p>
<p>When I first did C25K I did it using a Timex Ironman and watching the stopwatch. That wasn&rsquo;t great because it kept me from just going to my running place. In early smartphone days I was happy to use an app, but wow was iOS terrible for that kind of thing back then: Music never coming back after a voice prompt, bad UI ideas, etc.</p>
<p>I&rsquo;d always hoped Apple Watch would address it, but for a few years it was even worse, and I went through a series of hacks and workarounds, but was resigned to just keeping my phone on me for runs.</p>
<p>This time around it seems Apple Watch is finally mature enough to support a standalone C25K app in the form of <a href="https://apps.apple.com/us/app/watchto5k-couch-to-5k-watch/id1517914828">WatchTo5K</a>. It&rsquo;s part of a crowded field, and there may be others that work just fine, but WatchTo5K had decent reviews and has gotten me through three weeks so far with no complaints. It just works, it&rsquo;s simple, and it talks to Apple Health so I can correlate runs with a few other biometrics.</p>
<p>The only other wrinkle isn&rsquo;t a big deal: I run in a park across the street from my house, so the watch is constantly picking up then dropping my Wi-Fi network. Even though my running playlist is downloaded to the watch, it causes the music to stutter every time I run back out of range. Putting the watch in airplane mode addresses that.</p>
<p>It&rsquo;s pretty nice to just put on my watch and Beats Fit Pros, start my playlist, start the app, and start running, with nothing else to think about or fiddle with for the next 30 minutes.</p>
<h3 id="custom-hugo-rss">Custom Hugo RSS</h3>
<p>I made a small tweak to my site&rsquo;s RSS feed, adding a shortcode to list the tags for each post and adding it to each entry&rsquo;s description. It&rsquo;s a small adaptation to reflect the ways I use my feed to cross-post to Mastodon and Twitter. Mastodon is especially on my mind, given that tags are what drives discovery. For my daily posts it&rsquo;ll be a little redundant and I guess I could build some logic in to handle that, but not today.</p>
<p>Here&rsquo;s the shortcode (<code>rss_tags.html</code>):</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">{{- $tags := .Language.Params.Taxonomies.tag | default &#34;tags&#34; }}
</span></span><span class="line"><span class="cl">{{- range ($.GetTerms $tags) }}
</span></span><span class="line"><span class="cl">  #{{ .LinkTitle }}
</span></span><span class="line"><span class="cl">{- end }}</span></span></code></pre></div>
<p>&hellip; and <a href="https://codingnconcepts.com/hugo/custom-rss-feed-hugo/#customize-rss-feed">here&rsquo;s the tutorial I used</a> to figure out how to customize the feed. It just involved changing the description element:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;description&gt;{{ .Summary | html }} &lt;br /&gt;
</span></span><span class="line"><span class="cl">  {{ partial &#34;rss_tags.html&#34; . }}
</span></span><span class="line"><span class="cl">&lt;/description&gt;</span></span></code></pre></div>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2023-03-20</title>
      <link>https://mike.puddingtime.org/posts/2023-03-20-daily-notes-for-2023-03-20/</link>
      <pubDate>Mon, 20 Mar 2023 09:33:02 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-03-20-daily-notes-for-2023-03-20/</guid>
      <description>Doom Emacs, Mackup for config backups, Rocky IV, Jedi: Fallen Order.</description>
      <content:encoded><![CDATA[<p>Well, we got busy and it was hard to keep up daily posts last week. So back at it this week.</p>
<h3 id="doom-emacs">Doom Emacs</h3>
<p>I made it a point to give myself a bunch of fussing around time yesterday, and decided to spend it on installing <a href="https://github.com/doomemacs/doomemacs">Doom Emacs</a>. In its own words:</p>
<blockquote>
<p>Doom is a configuration framework for GNU Emacs tailored for Emacs bankruptcy veterans who want less framework in their frameworks, a modicum of stability (and reproducibility) from their package manager, and the performance of a hand rolled config (or better). It can be a foundation for your own config or a resource for Emacs enthusiasts to learn more about our favorite operating system.</p>
</blockquote>
<p>There&rsquo;s a small omission: It also starts from the assumption you want to use <a href="https://github.com/emacs-evil/evil">Evil mode</a>.</p>
<p>So, the highlights?</p>
<ul>
<li>You get a splash screen with the option to restart your last session, open your org agenda, go to your config files.</li>
<li>You get a modal interface with handy menus you can open up by tapping the space bar.</li>
<li>You get a more terse config up front by uncommenting functionality in an init file and letting Doom handle a lot of presets.</li>
<li>You have to take a few more steps when you make a change because you have to run an external command to compile your config.</li>
<li>You get a little more verbosity in parts of your config because you have to frame any custom changes as post-instantiation variables for a given module.</li>
</ul>
<p>My subjective take thus far:</p>
<ul>
<li>Initially hated it because of course I did: I&rsquo;ve got Stockholm syndrome around my multi-file Emacs config, and Doom even cuts you off from using Emacs&rsquo; native Customize.</li>
<li>Went to bed thinking &ldquo;if this feels god awful tomorrow morning, when it is time to get things done, I am going to get rid of it ASAP.&rdquo;</li>
<li>Woke up feeling curious and a little eager to try it out.</li>
<li>Currently in the painful &ldquo;develop muscle memory&rdquo; phase for some basic operations, still stumbling with modal editing, but not having a pinkie poised over the control key is nice.</li>
<li>I kind of like the whole <code>doom sync</code> workflow when I make a change. A lot of weird Emacs things-that-go-wrong seem to come down to package weirdness and compile errors, and Doom does a lot to clean that stuff up.</li>
<li>A little more empathy for the ortholinear and Planck people when the space-bar is what initiates actions and there&rsquo;s less emphasis on the control key.</li>
<li>I like the preset configs for features I wouldn&rsquo;t have bothered with otherwise. I&rsquo;ve come to appreciate minimaps, and wouldn&rsquo;t have bothered with one if it weren&rsquo;t something I could simply turn on and expect to work without a lot of fiddling.</li>
<li>The theme I settled on (&ldquo;Nord&rdquo;) is coherent and well thought out, and it covers all the UI I&rsquo;ve encountered so far. One challenge with Emacs themes is the challenge with any theme, I guess, which is that you can&rsquo;t always know what&rsquo;s out there with its own notions about a good palette. As a result, you sometimes get disappearing UI elements as the foreground of something coincidentally matches the theme&rsquo;s background, etc.</li>
</ul>
<p>You don&rsquo;t have to do the whole Evil thing, either: It can be toggled off and you still get a lot of Doom affordances, but with more complex keystrokes to invoke them. I&rsquo;m keeping it on because I have time to mess with it, and because my foundational Unix user myth re: my editor religion is a matter of freak happenstance I&rsquo;ve never really reconciled myself to.</p>
<p>No verdict yet, really, besides &ldquo;gonna keep using it because it has some very sane defaults that make Emacs feel more cohesive than my hacked-together &ldquo;<code>init.el</code> of Theseus&rdquo; that started its life on an Amiga 500 in 1996.</p>
<h3 id="mackup">Mackup</h3>
<p><a href="https://github.com/lra/mackup">Mackup</a> is just this backup config thing. On a Mac you install it from Homebrew, run it, and it backs up configs for over 550 applications: Everything from Adium to zsh, with ssh, Emacs, tmux, Sublime, git, rubocop and hundreds more in between.</p>
<p>Basic features:</p>
<ul>
<li>A variety of cloud stores: Dropbox, iCloud, Google Drive, and your own filesystem.</li>
<li>Exclude lists, for the things you don&rsquo;t want backed up/syncing across machines.</li>
<li>An Include list, to narrow what it touches to explicit apps.</li>
<li>Custom files, so you can tell it to, e.g. backup your <code>~/bin</code> or something with an odd location for its config.</li>
</ul>
<p>It has a dry-run switch so you can review what it would do, and a &ldquo;no, this is awful, put it all back&rdquo; argument.</p>
<p>There are some bugs. It did something weird to my iTerm config after I forced it to, reasoning that the only reason I use iTerm is because some YouTuber told me to and so didn&rsquo;t care if I learned a Mackup limitation the hard way. It also believes that the Doom Emacs config is somewhere it is not, so I wrote a custom config for that in two minutes:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[application]
</span></span><span class="line"><span class="cl">name = My Doom Emacs
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[configuration_files]
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[xdg_configuration_files]
</span></span><span class="line"><span class="cl">doom</span></span></code></pre></div>
<p>Verdict so far: It&rsquo;s fine and I&rsquo;m going to keep using it. I recently started putting more config stuff in Git and was beginning to think about how to make something similar. Glad I don&rsquo;t have to.</p>
<h3 id="rocky-iv">Rocky IV</h3>
<p>We finished up our run of the OG Rocky movies I was willing to watch with <em>Rocky IV</em> last night. The one with the Russian. Al was in her phone after the first montage/music video (of four? I lost count). I knew it was going to be awful, but I haven&rsquo;t seen it since my dad took me and Cousin Scotty to see it in the theater in 1985 and a mild spirit of completionism had descended on me.</p>
<p>It was sort of interesting to see the music video editing sensibility in the direction. Like, you could spot music video tropes in the angles and cuts. It served to make Drago, the Russian, weirdly sympathetic because some of it is bewildering, or at least seems designed to provoke feelings of bewilderment and maybe a little nausea. I think the tempo of editing is generally faster these days, but perhaps less jumpy and discontiguous.</p>
<p>Anyhow, I found myself wondering when they were going to show Drago being injected with steroids with a brief closeup of a dripping needle, then wondered how, almost 40 years later, I remembered that passing detail, then learned it was because they show the needle four or five times in case you were looking away and didn&rsquo;t get that the Russian was cheating.</p>
<p>Also, wow, this weird conflation of Soviet and Nazi ideologies where the Russians start bragging that Drago is of superior genetic stock.</p>
<p>And the lyrics in one of the music video tracks about how it feels like &ldquo;freedom is on the ropes.&rdquo;</p>
<h3 id="finished-jedi-fallen-order">Finished Jedi: Fallen Order</h3>
<p>I wrapped up <em>Star Wars Jedi: Fallen Order</em> over the weekend.
:
I get the impression it is very much A Kind of Game with a lot of the conventions people not only tolerate but even look forward in that kind of thing.</p>
<p>I found some of it frustrating until I dug into the configuration menu and found I could turn on some accessibility features that made a few recurring tasks (e.g. grabbing while jumping) less fiddly, and that allowed me to spend more time exploring and letting the story unfold than repeatedly falling to my death or tumbling to the bottom of some puzzle.</p>
<p>I learned to live with Jedi Wall Running, but never warmed up to all the moments where you have to slide down a slick mud or ice path and time jumps/grabs/wall-runs/bounces. That all felt less like Jedi Bad-Assery and more like someone decided to reskin a snowboarding game.</p>
<p>I was also a little over all the planet-hopping. You have to revisit things several times. I get that part of the way you make the power fantasy aspects of these games feel more acute is by presenting an impossible obstacle then letting the character skill up and overcome it. But that <em>could</em> take the form of presenting an impossible <em>kind</em> of obstacle and letting the player skill up and overcome one <em>just like it</em> somewhere else?</p>
<p>As a <em>Star Wars</em> property, I really enjoyed it. It&rsquo;s a lightweight story, but the whole time period between the fall of the Republic and SW:ANH has good story-telling potential, and I liked what they did with it in this game.</p>
<p>The upcoming sequel won&rsquo;t be on PS4, so &hellip; so much for all my gloating about being a trailing-edge casual who doesn&rsquo;t need the latest.</p>
<p>Anyhow, I think my next game is going to be <em>Ghost of Tsushima</em>. I went into <em>Fallen Order</em> thinking it&rsquo;d be a good way to get a little more grounded in modern Big Games, and <em>Ghost</em> is what I had in mind specifically.</p>
<p>Okay. We&rsquo;re at time. This was more of a tool for procrastination today than it should have been. I want to put in two hours on some overdue work.</p>
]]></content:encoded>
    </item>
    <item>
      <title>org-mode In Your Pocket Is a GNU-Shaped Devil</title>
      <link>https://mike.puddingtime.org/posts/2010-02-03-orgmode-in-your/</link>
      <pubDate>Wed, 03 Feb 2010 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2010-02-03-orgmode-in-your/</guid>
      <description>&lt;p&gt;If the iPhone has helped me accomplish one thing, it has probably been
to make it easier for me to stay away from Emacs.&lt;/p&gt;
&lt;p&gt;It works like this:&lt;/p&gt;
&lt;p&gt;It is not controversial to assert that Emacs is an environment all its
own. You can find libraries and packages that allow Emacs to acknowledge
and talk to outside environments, so it&amp;rsquo;s not a &lt;em&gt;closed&lt;/em&gt; environment,
but it&amp;rsquo;s different enough that there&amp;rsquo;s some fiddling involved to get it
chatting with the outside world.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>If the iPhone has helped me accomplish one thing, it has probably been
to make it easier for me to stay away from Emacs.</p>
<p>It works like this:</p>
<p>It is not controversial to assert that Emacs is an environment all its
own. You can find libraries and packages that allow Emacs to acknowledge
and talk to outside environments, so it&rsquo;s not a <em>closed</em> environment,
but it&rsquo;s different enough that there&rsquo;s some fiddling involved to get it
chatting with the outside world.</p>
<p>The iPhone could also be considered an environment all its own, but it&rsquo;s
an environment built with an eye on a broader context. iPhones have a
pretty easy time doing things like talking to iCal or Outlook with a few
button clicks, for instance. Now, unlike Emacs, there&rsquo;s a point with the
iPhone where no amount of grunting or straining will matter, and if you
want it to talk to something else nobody else has bothered to make it
talk to, there&rsquo;s an SDK you can download.</p>
<p>All that said, when Emacs and iPhone can both respond to a particular requirement with &ldquo;there&rsquo;s an [app | elisp package] for that,&rdquo; the iPhone variation will usually involve a quick download and three or four fields in a configuration screen, tops.</p>
<p>When I got an iPhone, I was a pretty heavy Emacs <a href="http://orgmode.org/">org mode</a> user. The
smartphone I had prior to the iPhone was a BlackBerry, and the
BlackBerry never really talked to my Mac on any useful level: lost
contacts, extra contacts, a new contact for every phone number I had
listed for what had once been a single contact, crummy calendar syncing,
forget about bookmarks syncing, etc. etc. etc. Because the BlackBerry
sucked for me as a Mac user, and because iCal was anemic when it came to
todos, org mode was able to fend off everything.</p>
<p>I won&rsquo;t go into a lot of detail about org mode except to say that it&rsquo;s
neat. You just open a &ldquo;.org&rdquo; file in Emacs and start typing using a
pretty simple notation. For instance &hellip;</p>
<pre><code>* PracNet

** TODO Look at reviews: can we get user information to the front page? (ASP)

   DEADLINE:

** TODO Look at inside pages: make a toolkit for callouts that can fit into the CSS

   DEADLINE:
</code></pre>
<p>When that text appears in an Emacs buffer in org mode, it&rsquo;s nicely color
coded. A few keystrokes make it easy to cycle between &ldquo;TODO&rdquo; and &ldquo;DONE&rdquo;
or some other status.</p>
<p>As with all things Emacs, it&rsquo;s very customizable.</p>
<p>Then the iPhone came along and promised me that if I would accept a few
small tradeoffs, it would sync up with a lot more of my stuff:
bookmarks, addresses, e-mail, etc. etc. etc. I&rsquo;d have all that stuff in
my pocket, and when I returned home my Mac would automagically commune
with it to learn what had changed in my absence.</p>
<p>org mode fell by the wayside, and the little ecosystem I&rsquo;d created
within Emacs crumbled because it was no longer a place to live &hellip; just
a place to visit when I needed to push text around.</p>
<p>So <a href="http://mobileorg.ncogni.to/">MobileOrg</a> strikes me as fascinating and horrifying at the same
time. All it does is this:</p>
<p>You save your Emacs org mode files on a WebDAV server, load MobileOrg
onto your iPhone, and you&rsquo;ll have org mode on your iPhone and it&rsquo;ll all
sync up, just like Remember the Milk or ToodleDo or any of the other
todo services that have &ldquo;an app for that.&rdquo;</p>
<p>&ldquo;If you are a MobileMe user, you already have access to a WebDAV server:
iDisk,&rdquo; says the MobileOrg site in a manner I cannot help but read as
<em>insinuating.</em></p>
<p>&ldquo;Sucker &hellip; walked away from Emacs and even took the extra step of
slurping the MobileMe kool-aid thinking it&rsquo;d harden your resolve against
ever returning. Well &hellip; fine &hellip; <em>keep</em> your precious iDisk &hellip; it will
become the tool of your re-liberation.&rdquo;</p>
<p>Less than two years ago, when I was venturing forth from org mode and
getting to know the iPhone as a way to keep all my Stuff in sync,
MobileOrg would have had me at hello. Now it just gives me the shaking
fits.</p>
<p>With Emacs, you don&rsquo;t just go &ldquo;la la la &hellip; I&rsquo;m gonna add org mode back
and call it a day!&rdquo; You think to yourself, &ldquo;I love org mode. I wish
there was an easy way to turn an e-mail message into a todo &hellip;&rdquo; and the
next thing you know you&rsquo;re dealing with how to configure <a href="http://gnus.org/">GNUS</a>.</p>
<p>Then you think &ldquo;All my calendar stuff is in Google calendar &hellip; how can
I get it into my org mode agenda?&rdquo; and that means you&rsquo;re off reading
<a href="http://bc.tech.coop/blog/070306.html">this guy&rsquo;s page</a> and just getting angrier and angrier.</p>
<p>Then you go in the kitchen and make a drink, and while you&rsquo;re making it
and calming down you think to yourself, if I&rsquo;m doing all this stuff in
Emacs anyhow, what would it hurt to <a href="http://www.instantmessagingplanet.com/public/article.php/3742411">follow Twitter in Emacs</a>?</p>
<p>Now you&rsquo;re not drinking because you&rsquo;re angry &hellip; you&rsquo;re drinking because
you wonder what happened to you and it makes you sad. But you&rsquo;re drunk,
so it seems like a perfectly good idea to <a href="http://mwolson.org/projects/EmacsMuse.html">build an entire Web site
using nothing but Emacs because then you can get a LaTeX version of it
for if the asteroids hit and their radiation destroys all HTML</a>. And
having decided to do that, part of you thinks about how glad you are you
have org mode, so you can organize the lengthy process of making sure
you never have to leave Emacs again.</p>
<p>It&rsquo;s knowing what&rsquo;s in store for me as I sit here with MobileOrg on my
iPhone and the necessary WebDAV share all set up that makes me read this
and just want to spit nails:</p>
<blockquote>
<p>At its core, Org-mode is a simple outliner for note-taking and list
management. You can learn the basics for using it in five minutes. This
may be all you need, and Org-mode will not impose more complex features
on you.</p>
</blockquote>
<p>That&rsquo;s right &hellip; because org-mode is just a collection of lisp running
in an editor. It <em>cannot</em> impose more complex features on you. The
genius of org-mode is that you will eventually impose more complex
features on yourself.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
