<?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/denote/</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>Sun, 20 Apr 2025 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://mike.puddingtime.org/tags/denote/index.xml" rel="self" type="application/rss+xml" />
    <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>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 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-07-11</title>
      <link>https://mike.puddingtime.org/posts/2023-07-11-daily-notes/</link>
      <pubDate>Tue, 11 Jul 2023 06:01:33 -0700</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-07-11-daily-notes/</guid>
      <description>Garmin GPS stuff, trying Wikiloc, calming down about notes, settling in at work.</description>
      <content:encoded><![CDATA[<h2 id="garmin-and-gps-stuff">Garmin and GPS stuff</h2>
<p>We took a weekend trip down to the Alsea Falls area, west of Corvallis. We camped in the federal campground there, and spent Saturday hiking up Marys Peak.</p>
<p>This is the second season we&rsquo;ve had our Garmin <a href="https://www.garmin.com/en-US/p/592606">inReach Mini</a>, a small GPS device that offers basic tracking plus emergency satellite communications (SOS and texting) and live weather. We got it after a small scare on our trip to the Redwoods last spring.</p>
<p>I&rsquo;m a hardware GPS holdout. I&rsquo;ve used a number of iPhone apps including Gaia GPS and AllTrails, but my issues with using an iPhone in the backcountry amount to the unpredictability of the devices: I&rsquo;d like better guarantees about the stability of the data I keep on them, I don&rsquo;t trust their power management over the course of a day on the trail, and I live in a biome that makes fussing with a touch screen in the field a nightmare six months out of the year.</p>
<p>Before we got the Mini we already had a <a href="https://www.garmin.com/en-US/p/669284">Garmin GPSMAP 64sx</a>. Even when I&rsquo;ve been experimenting with iPhone apps on the trail I&rsquo;ve preferred to download my routes to the 64sx, even if I&rsquo;m leaving it off and buried in my pack. It&rsquo;s a good insurance policy that paid off a few years ago when we were hiking through burned out areas in Central Oregon and lost the trail thanks to massive deadfalls: the extra topo layers I had loaded into it made it easy to look up the trail on the spot and figure out where to rejoin it.</p>
<p>I&rsquo;d like to shed the 64sx and I&rsquo;ve eyed the inReach-enabled handhelds Garmin&rsquo;s got on the market. They offer rechargeable or AA batteries, do all the handheld GPS stuff, and include the same emergency comms options. The Mini is so small, though, that it&rsquo;s not a huge burden to have two hardware devices. The Mini has a &lsquo;biner I clip to whatever pack strap is handy up near my shoulders and mostly stays out of the way. I just make sure to plug it into the car to recharge it whenever we set out on a trip. So I don&rsquo;t think a whole new device is necessary and I&rsquo;ll just live with the extra hardware.</p>
<p>This weekend convinced me I could probably loosen up a little on using an iPhone on hikes, though. Marys Peak isn&rsquo;t that remote, and there&rsquo;s even 5G cell coverage at the top, so the stakes were lower and made it easier to experiment.</p>
<p>People dis the company for limiting the connectivity of its devices to preserve a focus on hardware, but Garmin&rsquo;s Explore app does a decent job of turning your smartphone into an expensive dongle that offers better ergonomics if you&rsquo;re mostly sticking to easier dayhiking situations. Once paired, the Bluetooth sync between phone and GPS device is solid and fast, and Explore includes topo maps and the ability to add tracks and waypoints to your Garmin account. So you can download a GPX file before heading out, import it into Explore, and it will both sync to your Garmin account and &mdash; once paired up &mdash; your dedicated GPS devices. Any tracks you record on your hardware sync to Explore, where it&rsquo;s much easier to use the phone UI to rename, relabel, and organize once you&rsquo;re off the trail. It also offers a map on a larger, big screen you can consult in a pinch. It&rsquo;d still suck in the rain, but it&rsquo;s there for quick use.</p>
<p>This weekend I addressed a few of my hangups about how little I trust iPhones to behave when my back is turned by making a pair of shortcuts that alternately power down all the radios and put the phone in low power mode or bring the radios back up, and saved them to my homescreen. When we got to a point on the trail where we weren&rsquo;t sure what it would mean to take one route or the other, Explore&rsquo;s topo map made it easy to do a quick consult and make a decision. Having a bigger, brighter, faster screen to explore with was better than the slower, smaller, harder to read 64sx. Then the phone got put away and off we went.  For the kind of hiking we usually do, that seems like a workable use case. So I expect the 64sx will be spending more time at the bottom of a pack.</p>
<p>I did spend some time imagining an iPhone Ultra during the more boring part of the trail, though.</p>
<h2 id="wikiloc">Wikiloc</h2>
<p>Another iPhone GPS challenge involves downloading GPX files. Some apps make it pretty hard to do from mobile even if they do offer the option via a desktop interface, and you&rsquo;re sort of swimming upstream when you do anything on iOS that involves a data file.  I found Wikiloc, which has a reasonable $9.99/year subscription and a 14-day trial, so I&rsquo;m going to give it a try on our trips over the next few weeks. The subscription includes a simple interface to save GPX files to your phone&rsquo;s storage, send them to your Apple Watch, or share them to Garmin devices. I learned I can just use the share sheet to send them to the Explore app, where they sync to my Garmin account.  That&rsquo;s a big improvement over AllTrails&rsquo; mobile app.</p>
<p>Wikiloc is crowdsourced, so you&rsquo;re better off using it when you have time to vet the trails at home, or the connectivity to do so in camp. The ones I&rsquo;ve looked up so far seem fine based on past experience, you just have to choose between several for a few locations, and people don&rsquo;t always clean up the ten minutes they spent walking around the trailhead, visiting the toilet, and walking back and forth from car to picnic table from their GPX files.</p>
<p>We have a few guidebooks to Oregon trails we use to get ideas for hikes, then compare and contrast with the online tracks. It can make for some amusing triangulation: The books are a little dated and fusty, preferring trail names that don&rsquo;t always line up with the names the forest or park services use on the signage. The crowdsourced online trail resources sometimes feel like they were annotated by someone who thinks &ldquo;walk a mile or two and turn left where someone left a Snickers wrapper in the weeds&rdquo; counts as expert guidance.</p>
<p>Anyhow, we&rsquo;re headed to the Diamond Lake area in a few weeks and there are some trails to try it out on. I don&rsquo;t know if we&rsquo;ll make another run at Mt. Bailey this year, though.</p>
<h2 id="anchoring-on-the-denote-way">Anchoring on The Denote Way</h2>
<p>I&rsquo;m a month into &ldquo;Obsidian but with Denote file naming and frontmatter conventions&rdquo; and it&rsquo;s surprisingly calming.</p>
<p>I&rsquo;ve settled on 12 plugins, several of which are discretionary or just around to be used for the API they provide to another plugin, and I&rsquo;ve discarded the things in my setup that were sort of nice but unreliable for syncing. It&rsquo;s smooth, syncing is reliable, and 30+ days into a new job I&rsquo;m finding search works well.</p>
<p>I felt a little itchiness about the setup a few days ago, and the thing that kept me from doing anything about it was the sense that settling on the Denote formatting conventions for file names and frontmatter means the option&rsquo;s there to move between Obsidian and Emacs whenever, so why bother now? They&rsquo;re just Markdown notes. I will probably not revisit north of 75 percent of them ever for anything more than digging out a fact here or there. I can type them into anything. If I ever get to a point where org-mode&rsquo;s better syntax is called for, I&rsquo;ll just slip over to Emacs and carry on. Both formats work in Denote.</p>
<p>Def <a href="https://bear.app">curious about Bear 2</a> tho. It keeps the content in some sort of db though, right?</p>
<h2 id="belonging">Belonging</h2>
<p>I had a chat with a senior executive in my foodchain today. I found myself saying, &ldquo;there&rsquo;s some stuff that&rsquo;s a little messed up I have to deal with, but I belong here and I&rsquo;m the kind of person you need handling this stuff.&rdquo;</p>
<p>Little moments like that have been happening here and there, when I feel a little frustrated that something is just sorta dumb and dysfunctional or broken, then I pause for a moment and think &ldquo;Good. I&rsquo;m the right person to fix this. It&rsquo;s why I&rsquo;m here.&rdquo;</p>
<p>I love my Puppet friends dearly, wouldn&rsquo;t trade the experience for the world, and had the good fortune to go out with a great person to report to who did a lot to help me get back a sense of what I could do, but on balance the last few years of that place did me no favors, and I let a lot of self doubt seep in. It feels good to begin recovering a little more sense of what I&rsquo;m supposed to be about. I&rsquo;m so glad I got to take a break before I jumped back in.</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-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-23</title>
      <link>https://mike.puddingtime.org/posts/2023-05-23-daily-notes/</link>
      <pubDate>Tue, 23 May 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-05-23-daily-notes/</guid>
      <description>Doom&amp;rsquo;s UI-building affordances. A little more on Denote. Fences are weird.</description>
      <content:encoded><![CDATA[<h2 id="the-ui-construction-set">The UI construction set</h2>
<p>Years and years ago, before it was what it is today, which is horrible, Electronic Arts did some interesting marketing things that would lead you to believe that it was less a software company than some sort of rural artist colony that happened to make software but otherwise spent its time in rustic pursuits. They had a &ldquo;Construction Set&rdquo; product line that let you make your own stuff: music, racing games, pinball games, and adventure games.</p>
<p>I had the <a href="https://en.wikipedia.org/wiki/Adventure_Construction_Set">Adventure Game</a> and Racing Destruction Construction Sets and they were really fun. The Adventure Game set gave you all you needed to make a world with regions, rooms, things, and creatures. Things could do magical stuff, and creatures had a very simple set of behavioral rules.</p>
<p>That was my first experience with a software tool that let me make things inside a computer.</p>
<p>Jump forward a few years, and Borland came out with <a href="https://en.wikipedia.org/wiki/Sprint_(word_processor)">Sprint</a>, an extensible word processor with a modifiable UI that let you pick from several basic keybinding profiles (WordStar and Emacs, at least) and then add your own customizations if you wanted.</p>
<p>I was reminded of Sprint this morning as I sat down to extend Doom&rsquo;s menus for use with Denote, <a href="/posts/2023-05-22-more-plaintext-primitivism-with-denote/">which I wrote about yesterday</a>. It&rsquo;s just very clean and easy to 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="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;n&#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 class="p">)))</span></span></span></code></pre></div>
<p>It took me a few minutes to find my way back to how to deal with a keybinding collision in Doom&rsquo;s mappings &ndash; it has Deft bound to <code>d</code> under the <code>notes</code> (org) section. I don&rsquo;t use Deft and didn&rsquo;t want to skirt around the binding with <code>D</code> for <code>denote</code> so I had to nil <code>d</code> out before I could use it.</p>
<p>Otherwise &ndash; five minutes of work to build out a submenu for Denote with a mix of things I&rsquo;ll use all the time (making new notes, doing a ripgrep search of my Denote directory, showing backlinks) plus a few things that are useful in the short term, such as renaming a file on the disk after changing its metadata (since Denote uses file naming as metadata) or removing provisional keywords I used to move a bunch of notes in and operate on them in steps.</p>
<p>It&rsquo;s simple, mnemonic, but also offers visual prompts to help with learning. After a while you&rsquo;re not even going to look at the menu because the simple three-key sequences sink in after enough repetition.</p>
<p>It has made learning how to do new things much, much easier than it used to be. I&rsquo;ve just taken to opening a scratch buffer, copying over an existing menu config and clearing it out, then I start trying to do things with a new tool, figuring out over the course of a few hours what things I&rsquo;d like to be able to get to with a few keystrokes instead of remembering the function name or native keybindings. As I figure one of those things out, I add it to the menu, evaluate, and keep going. That is so much better than all the chord memorization I used to do.</p>
<h2 id="a-little-more-on-denote">A little more on Denote</h2>
<p>I also spent some time this morning figuring out how to do things &ldquo;the Denote Way,&rdquo; which means leveraging existing tools in Emacs instead of learning a bunch of functions that significantly duplicate functionality you already have.</p>
<p>&ldquo;Part of the reason Denote does not reinvent existing functionality is to encourage you to learn more about Emacs,&rdquo; says Denote&rsquo;s creator, Prot. Like, just bookmark your Denote directory and use the built-in find-file command in (<code>SPC .</code> to narrow by tags in <code>dired</code> in Doom), because tags are embedded in filenames, and lead with <code>_</code>. If you need fulltext search, ripgrep is there for you, and you&rsquo;ve probably already used it somewhere else.</p>
<p>I appreciate the approach. I think it will lead to learning how to do more by using fewer things across different use cases, instead of learning shallow functionality across a plethora of hyper-specialized tools.</p>
<p>I also learned that Denote leverages org dynamic blocks, so you can create dynamic backlinks blocks with live links:</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;_management&#34;
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">#+END:</span></span></span></code></pre></div>
<p><code>C-c C-c</code> in the block and it dynamically updates all the items tagged with <code>management</code>. All that stuff is just atomized interview prep notes from my job search, which I broke down and stuck in org-roam and spent a little time converting to Denote&rsquo;s format to try things out.</p>
<p><video width="100%" controls><source src="/img/denote_org_dblock.mp4" type="video/mp4">
Your browser does not support the video tag.</video></p>
<h2 id="fully-equipped">Fully equipped</h2>
<p>I took my Townie down to Foster Rd. for lunch today, then stopped off at one of the local bike shops in the Mt. Scott neighborhood. At some point early in my ownership I stuck hybrid pedals on it. Years ago Shimano came out with <a href="https://bike.shimano.com/en-US/technologies/component/details/shimano-clickr.html">the Click&rsquo;r pedal</a>, which offered some of the stability and torque advantages of a clipless pedal with a little more ease of use. The hybrid pedals were supposed to make it easier to just hop on and ride with street shoes on if you didn&rsquo;t want to change, or to snap in with cleats if you wanted to do a longer ride (or ride in the rain).</p>
<p>In practice, I don&rsquo;t think it was a great idea. I very seldom wanted to wear the cleats, and don&rsquo;t use the Townie for more than a few miles at a time. The right side of the pedals never seemed to be facing up. And they were small under normal street shoes.</p>
<p>So I just got some decent pedals with good traction today, and also added a cup holder, which seemed to tickle the counter guy.</p>
<p>&ldquo;It&rsquo;s complete now,&rdquo; he said.</p>
<p>I&rsquo;ve got a six mile ride for lunch on Thursday &hellip; that&rsquo;s a little farther than I usually consider, but new pedals and a cup holder seem to demand a celebratory cruise.</p>
<h2 id="fences">Fences</h2>
<p>I need to do some reading on fences. The one around our property is in bad shape. The way our house is built and situated, the east and west sides don&rsquo;t need one for privacy at all. The north side sort of demands it during the summer months &ndash; our neighbors on that side are as avid about their back yard time as we are.</p>
<p>But also, fences are sort of weird to me. Whoever built our house took the initiative to put one in. Our neighbors to the east sort of built off of it to fence in the south side of their lot. Our neighbors to the west don&rsquo;t care because their garage is our west property line.  My thought is just &ldquo;there is a total of one east window in this house, and it is a high window that doesn&rsquo;t line up with the neighbors&rsquo; west window, and there are no west windows at all, so why even have fences on those sides?&rdquo;</p>
<p>I&rsquo;m wondering if there&rsquo;s a way to handle the north side &hellip; the longest part of our lot that shares a boundary with a neighbor &hellip; without a <em>fence</em> fence. Or if the answer is something relatively high back there, but not as high (and hence more durable?) on the other two sides.</p>
<p>But mostly I just don&rsquo;t understand anything about fences at all.</p>
<p>When I look at them, sometimes they seem to be for privacy &ndash; they&rsquo;re high and block people on the street seeing in &ndash; and other times they seem to be <em>kind of</em> for security? Like, you&rsquo;d have to make an effort to vault a waist-high one made out of chain link,  or they wall off access to the back yard, or they (more rarely) seal in the driveway (though good lord do I get annoyed with all the old chain link driveway gates that just sort of loll around blocking the sidewalk).  Sometimes they just seem to be there to demark the property line, which would suggest something less elaborate would do, and serve mainly as lawn mower guidance.</p>
<p>They weren&rsquo;t a common feature in the small town where I lived in Indiana. They weren&rsquo;t common in the Virginia neighborhood I lived in, or else they were low, chain link things.  They were unheard of out in the Pennsylvania coal and dairy country I lived in except for one place that was half house, half mechanic&rsquo;s garage there in the hamlet.  I remember low, chain link fences around every yard in Houston, TX as a child. The only childhood home I can remember having tall fences was when my family lived in a townhouse in suburban Pittsburgh, and everyone had a tiny patch of back patio. They&rsquo;re very common in this neighborhood, more tall than not for newer construction, more likely to be low chain link things for all the smaller postwar houses.</p>
<p>Anyhow, I need to learn more about them. There&rsquo;s the part of me trying to engage with the whole topic by observation &ndash; a mode I get into that Al tolerates, but barely &ndash;  and the part of me that has a vague inkling that fences around yards might be one of those things that are <em>common</em> but also <em>not thought through in detail</em>, which means there are lots of opportunities to step on norms people didn&rsquo;t even know they had.</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>
  </channel>
</rss>
