<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="https://relvokcor.xyz/~moondog8" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Workbench</title>
    <link>https://relvokcor.xyz/~moondog8</link>
    <atom:link href="https://relvokcor.xyz/feed.xml" rel="self" type="application/rss+xml" />
    <description>Projects and such</description>
    <language>en</language>
    <item>
      <title>Exporting Org Mode to Markdown with Yaml Frontmatter</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2026-05-21-org-markdown-frontmatter/</link>
      <description>&lt;h2&gt;Exporting Org Mode to Markdown with Yaml Frontmatter&lt;/h2&gt;
&lt;p&gt;Most static site generators use &lt;a href=&quot;https://daringfireball.net/projects/markdown/&quot;&gt;Markdown&lt;/a&gt; as their input format.&lt;/p&gt;
&lt;p&gt;Org mode&#39;s built-in Markdown exporter works quite well, and &lt;a href=&quot;https://github.com/larstvei/ox-gfm&quot;&gt;ox-gfm&lt;/a&gt; gives you the extra bells and whistles supported by &lt;a href=&quot;https://github.github.com/gfm/&quot;&gt;GitHub flavored Markdown&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are two problems:&lt;/p&gt;
&lt;h3&gt;Problems&lt;/h3&gt;
&lt;h4&gt;Static site generators rely on YAML frontmatter for document metadata&lt;/h4&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;---
title: Hello World
description: A brief description of this content
date: 2026-05-21
tags: foo, bar, bat
---
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Various org-to-markdown exporters have lousy support for frontmatter&lt;/h4&gt;
&lt;p&gt;(There is &lt;a href=&quot;https://ox-hugo.scripter.co/&quot;&gt;ox-hugo&lt;/a&gt;, but it uses various structural conventions that quickly get frustrating if you&#39;re not using &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt;.)&lt;/p&gt;
&lt;h3&gt;A &lt;s&gt;Lazy Solution&lt;/s&gt; Hack&lt;/h3&gt;
&lt;p&gt;An elisp function to provide better frontmatter support is on my one-of-these-days lists, but in the meantime, if you can live it and if you don&#39;t mind using &lt;code&gt;ox-gfm&lt;/code&gt;, you can just define your frontmatter as an &lt;code&gt;export&lt;/code&gt; block at the top of the org files you want to export to markdown:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-org&quot;&gt;#+BEGIN_EXPORT markdown
---
title: Inline YAML Frontmatter
description: It&#39;s ugly but it works
---
#+END_EXPORT

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ante erat, sollicitudin ac elit in, accumsan sollicitudin nunc. Mauris consequat tincidunt facilisis. Maecenas ut mi diam. In vehicula ipsum sed purus semper, ut porta nisi bibendum. Pellentesque in est tristique, hendrerit enim non, sodales mauris. Fusce ut nulla placerat nisi elementum tempor. Donec imperdiet mollis odio, dictum posuere nulla bibendum congue. Sed sapien justo, molestie id convallis a, dapibus sit amet mauris. Sed malesuada faucibus erat eget dignissim. Mauris lacinia nunc eu gravida blandit. Nullam viverra diam vel tincidunt aliquam. Proin at accumsan turpis, iaculis malesuada odio. Pellentesque id faucibus augue.

Fusce et libero sed est porttitor dignissim. Quisque rhoncus lacus ac laoreet interdum. In tortor libero, ultricies vitae accumsan nec, mattis vel orci. Quisque facilisis tincidunt mi, at mattis ipsum cursus eu. Donec faucibus a ante ac volutpat. Etiam dui eros, pulvinar congue accumsan ac, ultrices et eros. Aliquam non vehicula tortor, ut laoreet nisi. Nulla facilisi. Phasellus vel bibendum mi. Donec a urna nisi. Pellentesque tempus nunc et tellus convallis eleifend.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;code&gt;ox-gfm&lt;/code&gt; is necessary because the native &lt;code&gt;ox-md&lt;/code&gt; exporter helpfully converts occurrences of &lt;code&gt;---&lt;/code&gt; into emdashes.)&lt;/p&gt;
</description>
      <pubDate>Wed, 20 May 2026 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2026-05-21-org-markdown-frontmatter/</guid>
    </item>
    <item>
      <title>Formatting a Cheap Generic MicroSD Card For the Digitech Trio+</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/trio-plus-microsd-format/</link>
      <description>&lt;h2&gt;Formatting a Cheap Generic MicroSD Card For the Digitech Trio+&lt;/h2&gt;
&lt;p&gt;I purchased a couple of cheap no-name MicroSD cards for use with my &lt;a href=&quot;https://digitech.com/dp/trio-plus/&quot;&gt;Trio+&lt;/a&gt; pedal. According to the &lt;a href=&quot;https://digitech.com/wp-content/uploads/2022/09/DigiTech_TrioPlus_Manual.pdf&quot;&gt;manual&lt;/a&gt;, the Trio+ should automatically handle formatting a new card when powered on, but I was getting the flashing red &lt;em&gt;Part&lt;/em&gt; LEDs that indicate a problem with the media.&lt;/p&gt;
&lt;h3&gt;Checking the format of a known good card&lt;/h3&gt;
&lt;p&gt;I mounted&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://relvokcor.xyz/~moondog8/stuff/trio-plus-microsd-format/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; the Trio+ card I was already using in MacOS and ran &lt;code&gt;diskutil list&lt;/code&gt;, which revealed:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;/dev/disk4 (internal, physical):
 #:                       TYPE NAME                    SIZE       IDENTIFIER
 0:     FDisk_partition_scheme                        *7.9 GB     disk4
 1:                 DOS_FAT_32 TRIOPLUS                7.9 GB     disk4s1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Checking the format of the new card&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;diskutil list&lt;/code&gt; showed a couple of differences:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;/dev/disk4 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *7.8 GB     disk4
   1:             Windows_FAT_32 NO NAME                 7.8 GB     disk4s1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From what I understand, &lt;code&gt;diskutil&lt;/code&gt; on MacOS supports a single &lt;code&gt;FAT32&lt;/code&gt; filesystem type, and &lt;code&gt;DOS_FAT_32&lt;/code&gt; and &lt;code&gt;Windows_FAT_32&lt;/code&gt; are both aliases for it. (I have no idea why &lt;code&gt;diskutil&lt;/code&gt; read the two different cards differently.)&lt;/p&gt;
&lt;h3&gt;Reformatting the new card&lt;/h3&gt;
&lt;p&gt;Making &lt;strong&gt;EXTRA SURE&lt;/strong&gt; that I was using the new empty card and not my old one with a bunch of song data on it, I ran:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;diskutil erasevolume FAT32 &amp;quot;TRIOPLUS&amp;quot; disk4s1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;after which &lt;code&gt;diskutil list&lt;/code&gt; displayed:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;/dev/disk4 (internal, physical):
 #:                       TYPE NAME                    SIZE       IDENTIFIER
 0:     FDisk_partition_scheme                        *7.8 GB     disk4
 1:                 DOS_FAT_32 TRIOPLUS                7.8 GB     disk4s1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When I put the freshly formatted card into the Trio+ and powered it on, the card mounted as expected: the &#39;Part&#39; lights came on in an a sequential amber pattern for a few moments and then the pedal finished booting as normal.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Make sure your full-size SD card adapter works; the cheap no-name card came with one, but when I tried using it MacOS didn&#39;t see it at all. I switched to a Sandisk adapter I had lying around and that worked. &lt;a href=&quot;https://relvokcor.xyz/~moondog8/stuff/trio-plus-microsd-format/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <pubDate>Wed, 13 May 2026 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/trio-plus-microsd-format/</guid>
    </item>
    <item>
      <title>Directionally Aware Collision Detection in Pico-8</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2026-01-04-pico-8-collisions/</link>
      <description>&lt;h2&gt;Directionally Aware Collision Detection in Pico-8&lt;/h2&gt;
&lt;div class=&quot;ABSTRACT&quot;&gt;
&lt;p&gt;Notes on detecting which side of the hit box a sprite has hit for the Pico-8 fantasy console&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I&#39;ve been tinkering with &lt;a href=&quot;https://www.lexaloffle.com/pico-8.php&quot;&gt;Pico-8&lt;/a&gt; lately and I find myself wanting to be able to detect collisions between a sprite and a map tile, and change the sprite direction accordingly (basically the same &amp;quot;bouncing ball&amp;quot; behavior you see in a lot of intro lessons, where a ball is moving on a diagonal and reverses X direction if it hits the side of the screen, or Y direction if it hits the top or bottom.&lt;/p&gt;
&lt;h3&gt;Basic Collision Detection&lt;/h3&gt;
&lt;p&gt;There are some good Pico-8 collision detection how-tos out there:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://nerdyteachers.com/PICO-8/Collision/98&quot;&gt;PICO-8 Collision Function&lt;/a&gt; (&lt;em&gt;very&lt;/em&gt; small function that test whether the map tile at &lt;code&gt;x, y&lt;/code&gt; has a given flag)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lexaloffle.com/bbs/?tid=3116&quot;&gt;Simple Collision Function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gamedev.docrobs.co.uk/first-steps-in-pico-8-easy-collisions-with-map-tiles&quot;&gt;First Steps in PICO-8: Easy Collisions with Map Tiles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;...but these only return a boolean indicating a collision state; there&#39;s no way to determine which side the collision has happened on.&lt;/p&gt;
&lt;h3&gt;Determining Directionality&lt;/h3&gt;
&lt;p&gt;Their function uses &lt;a href=&quot;https://en.wikipedia.org/wiki/Slope&quot;&gt;slopes&lt;/a&gt; to compare the angle of the sprite to the nearest corner of the hitbox, where the nearest corner is determined by which geometric quadrant the sprite is moving towards.&lt;/p&gt;
&lt;p&gt;TeamworkCast implements a function that determines whether an object is colliding vertically or horizontally as part of their Breakout clone series on YouTube, in video #7&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://relvokcor.xyz/~moondog8/stuff/2026-01-04-pico-8-collisions/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;There are some subtleties involved in actually integrating this function as well, and those are covered in video #8.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://relvokcor.xyz/~moondog8/stuff/2026-01-04-pico-8-collisions/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Video: &lt;a href=&quot;https://www.youtube.com/watch?v=AGblHq-ZamI,&quot;&gt;https://www.youtube.com/watch?v=AGblHq-ZamI,&lt;/a&gt; Code: &lt;a href=&quot;https://pastebin.com/dCRQsXTJ&quot;&gt;https://pastebin.com/dCRQsXTJ&lt;/a&gt; &lt;a href=&quot;https://relvokcor.xyz/~moondog8/stuff/2026-01-04-pico-8-collisions/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Video: &lt;a href=&quot;https://www.youtube.com/watch?v=fBi6vPcFmJ4&quot;&gt;https://www.youtube.com/watch?v=fBi6vPcFmJ4&lt;/a&gt; &lt;a href=&quot;https://relvokcor.xyz/~moondog8/stuff/2026-01-04-pico-8-collisions/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <pubDate>Sat, 03 Jan 2026 19:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2026-01-04-pico-8-collisions/</guid>
    </item>
    <item>
      <title>Note to Self: Networking Edition</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-12-19-note-to-self-networking-edition/</link>
      <description>&lt;h2&gt;Note to Self: Networking Edition&lt;/h2&gt;
&lt;div class=&quot;ABSTRACT&quot;&gt;
  &lt;div&gt;&lt;/div&gt;
&lt;p&gt;Networking things I am perpetually having to look up how to do&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;Get a List of Every IP on a LAN&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://relvokcor.xyz/~moondog8/stuff/2025-12-19-note-to-self-networking-edition/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;p&gt;(Where &lt;code&gt;192.168.1.255&lt;/code&gt; is the current machine&#39;s broadcast address)&lt;/p&gt;
&lt;h4&gt;Using &lt;code&gt;ping&lt;/code&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arp -a
ping -c 1 192.168.1.255
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Using &lt;code&gt;nmap&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;(provides more details)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;nmap -sn 192.168.1.0/24
&lt;/code&gt;&lt;/pre&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://blog.paessler.com/how-to-see-all-ip-addresses-on-network-a-guide-for-it-professionals&quot;&gt;How to see all IP addresses on network: A guide for IT professionals&lt;/a&gt; &lt;a href=&quot;https://relvokcor.xyz/~moondog8/stuff/2025-12-19-note-to-self-networking-edition/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <pubDate>Thu, 18 Dec 2025 19:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-12-19-note-to-self-networking-edition/</guid>
    </item>
    <item>
      <title>Note to Self: Lilypond Edition</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-12-04-note-to-self-lilypond-edition/</link>
      <description>&lt;h2&gt;Note to Self: Lilypond Edition&lt;/h2&gt;
&lt;h3&gt;Vertically Align and Horizontally Space Markup Above the Staff&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-lilypond&quot;&gt;% This controls the vertical padding between the staff and text.
% (Higher number = more space.)
&#92;override TextScript.staff-padding = #5
% This controls the horizontal space between text items.
% (Useful to force a little extra space between text items
% so they&#39;re all on one line)
&#92;override TextScript.extra-spacing-width = #&#39;(-0.5 . +0.5)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Presumably this should work for markup below the staff too)&lt;/p&gt;
</description>
      <pubDate>Wed, 03 Dec 2025 19:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-12-04-note-to-self-lilypond-edition/</guid>
    </item>
    <item>
      <title>Note to Self: ImageMagick Edition</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-12-03-note-to-self-imagemagick-edition/</link>
      <description>&lt;h1&gt;Note to Self: ImageMagick Edition&lt;/h1&gt;
&lt;p&gt;(Or, things I am perpetually looking up how to do with ImageMagick)&lt;/p&gt;
&lt;p&gt;Notes refer to the ImageMagick 7 &lt;code&gt;magick&lt;/code&gt; command-line tool unless otherwise noted.&lt;/p&gt;
&lt;h3&gt;Generate a Limited Palette From a Source Image&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;magick &amp;lt;input.png&amp;gt; -colors 64 -unique-colors -scale 1000% &amp;lt;palette.png&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Scale is not necessary if you&#39;re just using the palette file for quantization, but it&#39;s nice to be able to actually see the colors.&lt;/p&gt;
&lt;p&gt;(via &lt;a href=&quot;https://unix.stackexchange.com/questions/407449/create-palette-image-with-multiple-rows-using-imagemagick&quot;&gt;Stackexchange&lt;/a&gt;)&lt;/p&gt;
&lt;h3&gt;Apply a Limited Color Palette to an Image&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;magick &amp;lt;input.png&amp;gt; -remap &amp;lt;palette.png&amp;gt; &amp;lt;output.png&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want the resulting image to include a smaller number of colors while still restricting those colors to the palette:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;magick &amp;lt;input.png&amp;gt; -remap &amp;lt;palette.png&amp;gt; -colors &amp;lt;n&amp;gt; &amp;lt;output.png&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;!-- Generated by Stubble v0.3.2 --&gt;
</description>
      <pubDate>Tue, 02 Dec 2025 19:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-12-03-note-to-self-imagemagick-edition/</guid>
    </item>
    <item>
      <title>Harmonize: an app for exploring scales and chords</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-10-30-harmonize-intro/</link>
      <description>&lt;h1&gt;Harmonize: an app for exploring scales and chords&lt;/h1&gt;
&lt;p&gt;This is an app that lets you select a note and scale, and shows you all of the diatonic chords for that scale.&lt;/p&gt;
&lt;img src=&quot;https://relvokcor.xyz/assets/img/hF67nGxjQ--300.png&quot; width=&quot;300&quot; height=&quot;449&quot; alt=&quot;Screenshot of a web app showing the D Dorian scale and diatonic chords&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;
&lt;p&gt;It also allows you to highlight notes, which can be useful for exploring their distribution among those chords.&lt;/p&gt;
&lt;p&gt;The app is at &lt;a href=&quot;https://relvokcor.xyz/~moondog8/apps/harmonize/index.html&quot;&gt;/~moondog8/apps/harmonize/&lt;/a&gt; for now.&lt;/p&gt;
&lt;p&gt;Source code is at &lt;a href=&quot;https://codeberg.org/MysteryDevices/harmonize&quot;&gt;https://codeberg.org/MysteryDevices/harmonize&lt;/a&gt;.&lt;/p&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Wed, 29 Oct 2025 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-10-30-harmonize-intro/</guid>
    </item>
    <item>
      <title>Note to Self: Docker Edition</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-10-21-docker-nts/</link>
      <description>&lt;h1&gt;Note to Self: Docker Edition&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Searching and removing Docker images by Repository Name:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;docker images &amp;quot;repositoryname/*&amp;quot; --format &amp;quot;:&amp;quot; | xargs docker image rm
&lt;/code&gt;&lt;/pre&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Mon, 20 Oct 2025 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-10-21-docker-nts/</guid>
    </item>
    <item>
      <title>Running `yt-dlp` with Cookies</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-10-16-yt-dlp-cookies/</link>
      <description>&lt;h1&gt;Running &lt;code&gt;yt-dlp&lt;/code&gt; with Cookies&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;yt-dlp --cookies-from-browser firefox:default-release --user-agent &amp;quot;Mozilla/5.0&amp;quot; &amp;lt;url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Wed, 15 Oct 2025 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-10-16-yt-dlp-cookies/</guid>
    </item>
    <item>
      <title>Looptober 2025</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-10-09-looptober-2025/</link>
      <description>&lt;h1&gt;Looptober 2025&lt;/h1&gt;
&lt;p&gt;Somehow it&#39;s already October, which means it&#39;s time for the informal personal challenge to make a daily-ish loop or short snippet of music for no other reason than that it&#39;s good to make music and force yourself not to overthink it.&lt;/p&gt;
&lt;p&gt;I&#39;m collecting tracks with Faircamp as I go &lt;a href=&quot;https://relvokcor.xyz/music/looptober-2025&quot;&gt;here&lt;/a&gt;, or you can listen with the embedded player below:&lt;/p&gt;
&lt;iframe loading=&quot;lazy&quot; src=&quot;https://relvokcor.xyz/~moondog8/music/looptober-2025/embed/all/&quot; style=&quot;border: none; height: 49.6px; min-width: 480px;&quot; title=&quot;Audio player widget for &amp;quot;Looptober 2025&amp;quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Wed, 08 Oct 2025 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-10-09-looptober-2025/</guid>
    </item>
    <item>
      <title>Found an Old Friend</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-08-30-ipod-3rd-generation/</link>
      <description>&lt;h1&gt;Found an Old Friend&lt;/h1&gt;
&lt;img src=&quot;https://relvokcor.xyz/assets/img/dpPu0xtQkD-300.png&quot; width=&quot;300&quot; height=&quot;300&quot; alt=&quot;A white 3rd-generation clickwheel iPod MP3 player&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;
&lt;p&gt;In 2004 I bought this 30 gigabyte iPod from a colleague, and I used it extensively for the next 2-3 years.&lt;/p&gt;
&lt;p&gt;I think I stopped using it due to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Its battery capacity being shot (and no way to power it in the car because it only charges via FireWire port)&lt;/li&gt;
&lt;li&gt;Dwindling hardware support for FireWire connectors (at least on devices I owned)&lt;/li&gt;
&lt;li&gt;Starting a telecommuting gig that meant far less time spent in the car&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;m reasonably sure I still have the original wall wart, and if I can lay my hands on it I&#39;m going to see if it will power up.&lt;/p&gt;
</description>
      <pubDate>Fri, 29 Aug 2025 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-08-30-ipod-3rd-generation/</guid>
    </item>
    <item>
      <title>A Bash Alias For Viewing READMEs From the Command Line</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-07-23-readme-command/</link>
      <description>&lt;h1&gt;A Bash Alias For Viewing READMEs From the Command Line&lt;/h1&gt;
&lt;p&gt;It occurred to me that it would be nice to be able to display the contents of a README file in the terminal without knowing the file format or whether it&#39;s upper/lower case, and some yak-shaving ensued.&lt;/p&gt;
&lt;p&gt;This is a &lt;code&gt;bash&lt;/code&gt; alias that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Makes a temp directory&lt;/li&gt;
&lt;li&gt;Looks for any file in the current directory whose name begins with &lt;code&gt;readme&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Uses &lt;code&gt;pandoc&lt;/code&gt; to convert the first README found into a &lt;a href=&quot;https://man7.org/linux/man-pages/man1/man.1.html&quot;&gt;section 1 man page&lt;/a&gt; in the temp directory&lt;/li&gt;
&lt;li&gt;Uses &lt;code&gt;sed&lt;/code&gt; to add a &lt;code&gt;.TH&lt;/code&gt; topic line at the top of the man page, as pandoc does not seem to do this on its own&lt;/li&gt;
&lt;li&gt;Displays the man page using the linux-specific &lt;code&gt;-l&lt;/code&gt; option (This alias will not work on MacOS, which I assume means it also won&#39;t work on FreeBSD)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;man&lt;/li&gt;
&lt;li&gt;pandoc&lt;/li&gt;
&lt;li&gt;mktemp&lt;/li&gt;
&lt;li&gt;sed&lt;/li&gt;
&lt;li&gt;xargs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The Alias&lt;/h2&gt;
&lt;p&gt;Add the following at the end of your &lt;code&gt;~/.bash_aliases&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;alias readme=&amp;quot;RMDIR=`mktemp -d -p ${TMPDIR-/tmp} readme-XXXXXX`; find . -iname &#39;readme.*&#39; -maxdepth 1 | head -n 1 | xargs  -I {} pandoc {} -o $RMDIR/readme.1;sed -i &#39;1s/^/.TH README 1&#92;n/&#39; $RMDIR/readme.1; man -l $RMDIR/readme.1&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then either close and reopen your terminal, or type &lt;code&gt;source ~/.bash_aliases&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now you should be able to &lt;code&gt;cd&lt;/code&gt; to a directory containing a README (or &lt;code&gt;Readme.md&lt;/code&gt;, or &lt;code&gt;ReadMe.rst&lt;/code&gt;, etc) file and type:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;readme
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to quickly view it.&lt;/p&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Tue, 22 Jul 2025 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-07-23-readme-command/</guid>
    </item>
    <item>
      <title>Chord Navigator, Part 1</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-06-06-chord-navigator-01/</link>
      <description>&lt;h1&gt;Chord Navigator, Part 1&lt;/h1&gt;
&lt;p&gt;One of the first apps I purchased on my first smart phone and still use almost daily is &lt;a href=&quot;https://apps.apple.com/us/app/guitartoolkit-tuner-metronome-chords-scales/id284962368&quot;&gt;Guitar Toolkit&lt;/a&gt;, which is an invaluable tool for finding scales and chords for pretty much any stringed instrument in any tuning you could want.&lt;/p&gt;
&lt;p&gt;One very helpful feature I didn&#39;t notice until a couple of years ago is the ability to look up a scale or mode (D Dorian, for example) and then get a list of all diatonic[^1] chords in the scale.&lt;/p&gt;
&lt;p&gt;However... when practicing or fooling around with songwriting or composition I find apps to be quite distracting in a way that dedicated hardware is not, and that got me thinking about making a practice/songwriting/learning device for browsing scales and the chords that sound good with them.&lt;/p&gt;
&lt;img src=&quot;https://relvokcor.xyz/assets/img/YupVjHNUk7-300.png&quot; width=&quot;300&quot; height=&quot;225&quot; alt=&quot;An Adafruit Metro, 20x4 LCD character display, and a couple of potentiometers breadboarded together. The display shows the text &#39;D Dorian.&#39;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;
&lt;hr /&gt;
&lt;p&gt;[^1] Chords containing only notes in a given scale&lt;/p&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Thu, 05 Jun 2025 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-06-06-chord-navigator-01/</guid>
    </item>
    <item>
      <title>Tangling Org Mode Properties Into Source Code Blocks</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-05-15-tangling-org-mode-props/</link>
      <description>&lt;h1&gt;Tangling Org Mode Properties Into Source Code Blocks&lt;/h1&gt;
&lt;p&gt;A problem I&#39;ve been trying to solve on and off for a number of years is: I&#39;d like to be able to consistently generate multiple artifacts (PDF, web graphics, MIDI) from a single &lt;a href=&quot;https://lilypond.org/&quot;&gt;Lilypond&lt;/a&gt; arrangement &lt;em&gt;and&lt;/em&gt; collect multiple arrangements into a single document (using &lt;a href=&quot;https://lilypond.org/doc/v2.24/Documentation/usage/lilypond_002dbook&quot;&gt;lilypond-book&lt;/a&gt;, for example.)&lt;/p&gt;
&lt;p&gt;Lilypond supports this up to a point. You can assign chunks of notation to variables and then define multiple &lt;code&gt;&#92;score&lt;/code&gt; blocks that re-use them, but I always find myself having to refresh my memory for things like unfolding repeats for MIDI output or transposing an entire score. Things get verbose and repetitive, and not unlike old-school static HTML web sites where tweaking the appearance of something means editing every single page because they all have quirks and inconsistencies.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://orgmode.org/&quot;&gt;Org mode&lt;/a&gt;, a Swiss-army knife authoring environment/document format that can do all kinds of things. One of its most interesting features is the ability to evaluate/interpolate/export blocks of source code within an Org mode document. Using &lt;a href=&quot;https://orgmode.org/manual/Noweb-Reference-Syntax.html&quot;&gt;noweb reference syntax&lt;/a&gt; you can insert blocks of code into other blocks of code... in my case I am hoping I can come up with an Org mode template/workflow that will let me focus on just the actual content of arrangements, and use &lt;a href=&quot;https://orgmode.org/manual/Extracting-Source-Code.html&quot;&gt;org-babel-tangle&lt;/a&gt; to generate lilypond files for different targets (PDF/svg/transposition/MIDI/lytex).&lt;/p&gt;
&lt;p&gt;The first problem I needed to solve was being able to reuse properties across source code blocks, and I got it working:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-org&quot;&gt;# -*- mode: org; org-confirm-babel-evaluate: nil; -*-
# -*- mode: org; org-use-property-inheritance: t; -*-
:PROPERTIES:
:TITLE: The Quick Brown Fox
:COMPOSER: Arthur &#92;&amp;quot;Two-Sheds&amp;quot;&#92; Jackson
:COPYRIGHT: 1969
:END:

* Lilypond

#+begin_src lilypond :tangle quick-brown-fox.ly :noweb yes :padline no
  version &amp;quot;2.24&amp;quot;

  &#92;header {
   title = &amp;quot;&amp;lt;&amp;lt;get(&amp;quot;TITLE&amp;quot;)&amp;gt;&amp;gt;&amp;quot;
   composer = &amp;quot;&amp;lt;&amp;lt;get(&amp;quot;COMPOSER&amp;quot;)&amp;gt;&amp;gt;&amp;quot;
   copyright = &amp;quot;&amp;lt;&amp;lt;get(&amp;quot;COPYRIGHT&amp;quot;)&amp;gt;&amp;gt;&amp;quot;
  }

  &#92;score relative c&#39; {
    c d e f
  }
  &#92;layout()
#+end_src

* Markdown

#+begin_src markdown :tangle quick-brown-fox.md :noweb yes :padline no
  # &amp;lt;&amp;lt;get(&amp;quot;TITLE&amp;quot;)&amp;gt;&amp;gt;

  ## By &amp;lt;&amp;lt;get(&amp;quot;COMPOSER&amp;quot;)&amp;gt;&amp;gt;, &amp;lt;&amp;lt;get(&amp;quot;COPYRIGHT&amp;quot;)&amp;gt;&amp;gt;

  Lorem ipsum dolor sit amet
#+end_src


# Helper function that can be used to insert org-mode properties into source blocks:
#+NAME: get
#+begin_src elisp :var prop=&amp;quot;title&amp;quot; :results value :exports none
   (prin1 (org-entry-get (point) prop &#39;selective))
#+end_src 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running &lt;code&gt;org-babel-tangle&lt;/code&gt; on this file generates two new files:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;quick-brown-fox.ly&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-lilypond&quot;&gt;version &amp;quot;2.24&amp;quot;

&#92;header {
 title = &amp;quot;The Quick Brown Fox&amp;quot;
 composer = &amp;quot;Arthur &#92;&amp;quot;Two-Sheds&amp;quot;&#92; Jackson&amp;quot;
 copyright = &amp;quot;1969&amp;quot;
}

&#92;score relative c&#39; {
  c d e f
}
&#92;layout()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;p&gt;&lt;code&gt;quick-brown-fox.md&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;# The Quick Brown Fox

## By Arthur &#92;&amp;quot;Two-Sheds&amp;quot;&#92; Jackson, 1969

Lorem ipsum dolor sit amet
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a minimal and not super-useful example but it has promise.&lt;/p&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Wed, 14 May 2025 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-05-15-tangling-org-mode-props/</guid>
    </item>
    <item>
      <title>Ciglet: Figlet Comment Blocks</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2025-02-21-ciglet/</link>
      <description>&lt;h1&gt;Ciglet: Figlet Comment Blocks&lt;/h1&gt;
&lt;p&gt;I often use &lt;a href=&quot;http://www.figlet.org/&quot;&gt;FIGlet&lt;/a&gt; in code comments; if a file I&#39;m working on is particulary large and hairy, big comments can provide useful visual landmarks as you scroll around.&lt;/p&gt;
&lt;p&gt;I also like to leave myself a big old temporary&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;//  _____ ___  ____   ___  
// |_   _/ _ &#92;|  _ &#92; / _ &#92; 
//   | || | | | | | | | | |
//   | || |_| | |_| | |_| |
//   |_| &#92;___/|____/ &#92;___/ 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;at the end of the day with some notes about where I left off.&lt;/p&gt;
&lt;p&gt;You can easily pipe figlet&#39;s output to the pasteboard on MacOS like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;% figlet TODO | pbcopy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...but got tired enough of typing &lt;code&gt;| pbcopy&lt;/code&gt;, pasting, and then having to select the newly pasted text and comment it out that I hacked together a Bash script that wraps the &lt;code&gt;figlet&lt;/code&gt; command and:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Accepts an additional initial &lt;code&gt;-a&lt;/code&gt; argument (&lt;strong&gt;a&lt;/strong&gt; for &lt;strong&gt;add&lt;/strong&gt;) for the comment character you want to use (Defaults to &lt;code&gt;//&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Passes any additional arguments directly to figlet&lt;/li&gt;
&lt;li&gt;Pipes the output of &lt;code&gt;figlet&lt;/code&gt; into &lt;code&gt;sed&lt;/code&gt; to add the comment prefix to each line&lt;/li&gt;
&lt;li&gt;Pipes the output of &lt;em&gt;that&lt;/em&gt; onto the pasteboard so you can just paste it into your editor. (It also prints it to STDOUT.)&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;#!/bin/bash

#    _______       __     __ 
#   / ____(_)___ _/ /__  / /_
#  / /   / / __ `/ / _ &#92;/ __/
# / /___/ / /_/ / /  __/ /_  
# &#92;____/_/&#92;__, /_/&#92;___/&#92;__/  
#        /____/              
#
# Figlet Code Comments (MacOS)

# Default prefix
prefix=&amp;quot;//&amp;quot;

# Check for -a option first
if [[ &amp;quot;$1&amp;quot; == &amp;quot;-a&amp;quot; &amp;amp;&amp;amp; -n &amp;quot;$2&amp;quot; ]]; then
    prefix=&amp;quot;$2&amp;quot;
    shift 2
fi

# Escape the prefix for sed
escaped_prefix=$(echo &amp;quot;$prefix&amp;quot; | sed &#39;s/[&#92;/&amp;amp;]/&#92;&#92;&amp;amp;/g&#39;)

# Run figlet with all remaining arguments, add prefix, and send to both stdout and pbcopy
figlet &amp;quot;$@&amp;quot; | sed &amp;quot;s/^/$escaped_prefix /&amp;quot; | tee &amp;gt;(pbcopy) 
echo &amp;quot;&amp;quot;
echo &amp;quot;(Copied to clipboard)&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you save it to an executable file called &lt;code&gt;ciglet&lt;/code&gt; somewhere in your PATH, you can run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ciglet -a &#39;#&#39; -f slant &#39;Hello, World!&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and you should see&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#     __  __     ____           _       __           __    ____
#    / / / /__  / / /___       | |     / /___  _____/ /___/ / /
#   / /_/ / _ &#92;/ / / __ &#92;      | | /| / / __ &#92;/ ___/ / __  / / 
#  / __  /  __/ / / /_/ /      | |/ |/ / /_/ / /  / / /_/ /_/  
# /_/ /_/&#92;___/_/_/&#92;____( )     |__/|__/&#92;____/_/  /_/&#92;__,_(_)   
#                      |/                                      

(Copied to clipboard)
&lt;/code&gt;&lt;/pre&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Thu, 20 Feb 2025 19:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2025-02-21-ciglet/</guid>
    </item>
    <item>
      <title>How to get a node.js `Dirent` object directly from a path</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2024-11-08-how-to-get-a-object-directly-from-a-path/</link>
      <description>&lt;h1&gt;How to get a node.js &lt;code&gt;Dirent&lt;/code&gt; object directly from a path&lt;/h1&gt;
&lt;p&gt;I found myself needing a &lt;code&gt;Dirent&lt;/code&gt; object for a known path, and as far as I can tell there&#39;s no way
to instantiate one; although you can do:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;const myDirEnt = new Dirent();
myDirent.name = &#39;/path/to/a/file.txt&#39;;
myDirent.path = myDirent.parentPath = &#39;/path/to/a/&#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;isFile()&lt;/code&gt;, &lt;code&gt;isDirectory()&lt;/code&gt;, etc. methods all return false.&lt;/p&gt;
&lt;p&gt;So, I wrote a function returns a functional &lt;code&gt;Dirent&lt;/code&gt; object:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import fs from &amp;quot;fs/promises&amp;quot;;

/**
 * Utility function to get a `Dirent` object for a given path without using `fs.readdir`
 */
const getDirent = async (filePath: PathLike): Promise&amp;lt;Dirent&amp;gt; =&amp;gt; {
  const stat = await fs.lstat(filePath);
  const pathInfo = path.parse(filePath as string);
  return {
    name: pathInfo.base,
    path: pathInfo.dir,
    parentPath: pathInfo.dir,
    isDirectory: () =&amp;gt; stat.isDirectory(),
    isFile: () =&amp;gt; stat.isFile(),
    isSymbolicLink: () =&amp;gt; stat.isSymbolicLink(),
    isBlockDevice: () =&amp;gt; stat.isBlockDevice(),
    isCharacterDevice: () =&amp;gt; stat.isCharacterDevice(),
    isFIFO: () =&amp;gt; stat.isFIFO(),
    isSocket: () =&amp;gt; stat.isSocket(),
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Thu, 07 Nov 2024 19:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2024-11-08-how-to-get-a-object-directly-from-a-path/</guid>
    </item>
    <item>
      <title>Stupid Strudel Tricks</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2024-10-25-stupid-strudel-tricks/</link>
      <description>&lt;h1&gt;Stupid Strudel Tricks&lt;/h1&gt;
&lt;p&gt;I found myself wanting to import a helper function into the &lt;a href=&quot;https://strudel.cc/&quot;&gt;Strudel REPL&lt;/a&gt; for reasons, and I know the thing to do would be to set up my own local custom REPL where I can load whatever I want, but I am lazy and I was also curious whether shenanigans like this would even work.&lt;/p&gt;
&lt;p&gt;The answer is yes. I bundled my library into a script that uses an &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/IIFE&quot;&gt;IIFE&lt;/a&gt; to assign all of its exports to a global variable, and a common pattern for loading JS code from a remote URL boils down to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fetch the script as a &lt;code&gt;Blob&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Make an &lt;code&gt;ObjectURL&lt;/code&gt; from the blob&lt;/li&gt;
&lt;li&gt;Create a new &lt;code&gt;script&lt;/code&gt; element with the &lt;code&gt;ObjectURL&lt;/code&gt; as its &lt;code&gt;src&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add the new &lt;code&gt;script&lt;/code&gt; element to the DOM&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And it works! But I&#39;d get an error the first time I evaluated the code, despite &lt;code&gt;awaiting&lt;/code&gt; async code... the issue wound up being that I was trying to invoke my imported code before the newly-injected &lt;code&gt;script&lt;/code&gt; element had finished loading.&lt;/p&gt;
&lt;p&gt;A typical pattern for this is to add a listener to the &lt;code&gt;load&lt;/code&gt; event on the &lt;code&gt;script&lt;/code&gt; element, and use the callback to invoke your code, but that doesn&#39;t seem to play nicely with the Strudel REPL. So, I just resorted to an plain old &lt;code&gt;while&lt;/code&gt; loop to wait for the function to be defined (with a timeout to prevent an infinite loop if it doesn&#39;t load for some reason)&lt;/p&gt;
&lt;p&gt;Altogether, this is what I wound up with:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const res = await fetch(&#39;https://sound.intercrap.com/strudel/interleave-recursive.bundle.js&#39;);
const ilBlob = await res.blob();
const objURL = (window.URL ? URL : webkitURL).createObjectURL(ilBlob);
const sc = document.createElement(&#39;script&#39;);
sc.setAttribute(&#39;src&#39;, objURL);
sc.setAttribute(&#39;type&#39;, &#39;text/javascript&#39;);
sc.setAttribute(&#39;id&#39;, &#39;interleave-recursive&#39;);
document.head.appendChild(sc)
let start = new Date();
while (typeof interleaveRecursive === &#39;undefined&#39;) {
  if (new Date() - start &amp;gt; 5000) throw new Error(&#39;Couldn&#92;&#39;t load interleaveRecursive&#39;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All of this feels klugey and ill-advised, but I had a bee in my bonnet to see if I could use &lt;a href=&quot;https://foxdot.org/&quot;&gt;FoxDot&lt;/a&gt; style interleaved patterns of pitch and duration in Strudel.&lt;/p&gt;
&lt;p&gt;The answer to that is yes, sort of, but it goes against the grain in terms of how cycles work. But it raises some pretty interesting possibilities: https://strudel.cc/?zbR09cmu96Wr)&lt;/p&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Thu, 24 Oct 2024 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2024-10-25-stupid-strudel-tricks/</guid>
    </item>
    <item>
      <title>Strudel Live Code Cheat Sheet</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2024-10-24-strudel-live-code-cheat-sheet/</link>
      <description>&lt;h1&gt;Strudel Live Code Cheat Sheet&lt;/h1&gt;
&lt;p&gt;Notes-to-self for &lt;a href=&quot;https://strudel.cc/&quot;&gt;strudel.cc&lt;/a&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Globally set cycles per second&lt;/td&gt;
&lt;td&gt;&lt;code&gt;setCps(n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Default: 1 cycle per second&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Globally set cycles per minute&lt;/td&gt;
&lt;td&gt;&lt;code&gt;setCpm(n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Default: 60 cycles per minute&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Wed, 23 Oct 2024 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2024-10-24-strudel-live-code-cheat-sheet/</guid>
    </item>
    <item>
      <title>A Mellotron sample library for Strudel</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2024-10-16-strudel-mellotron/</link>
      <description>&lt;h1&gt;A Mellotron sample library for Strudel&lt;/h1&gt;
&lt;p&gt;It&#39;s Looptober again and I got off to a pretty good start using &lt;a href=&quot;https://strudel.cc/&quot;&gt;Strudel&lt;/a&gt; for most of my loops, both out of convenience and as a learning exercise.&lt;/p&gt;
&lt;p&gt;It wasn&#39;t long before I got interested in Strudel&#39;s ability to import samples from anywhere on the web&lt;sup&gt;&lt;a href=&quot;https://relvokcor.xyz/~moondog8/stuff/2024-10-16-strudel-mellotron/#1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, and it seemed like a no-brainer to make a library using the &lt;a href=&quot;https://www.leisureland.us/mellotron.htm&quot;&gt;leisureland Mellotron samples&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It works! You can use load it in your Strudel pieces by adding this to the top of your REPL:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;samples(&#39;https://sound.intercrap.com/strudel/mellotron/strudel.json&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will make a bunch of Mellotron instruments available to the &lt;code&gt;sound()&lt;/code&gt; function:&lt;/p&gt;
&lt;style&gt;.mel dt {font-family:monospace;font-weight:bold;}&lt;/style&gt;
&lt;dl class=&quot;mel&quot;&gt;
&lt;dt&gt;8Choir&lt;/dt&gt;&lt;dd&gt;
8 Choir
&lt;/dd&gt;
&lt;dt&gt;Bassoon&lt;/dt&gt;&lt;dd&gt;
Bassoon
&lt;/dd&gt;
&lt;dt&gt;Cello&lt;/dt&gt;&lt;dd&gt;
Cello
&lt;/dd&gt;
&lt;dt&gt;CombinedChoir&lt;/dt&gt;&lt;dd&gt;
Combined Choir
&lt;/dd&gt;
&lt;dt&gt;GC3Brass&lt;/dt&gt;&lt;dd&gt;
GC3 Brass
&lt;/dd&gt;
&lt;dt&gt;ItalianAccordion&lt;/dt&gt;&lt;dd&gt;
Italian Accordion
&lt;/dd&gt;
&lt;dt&gt;M300A&lt;/dt&gt;&lt;dd&gt;
Two Violins
&lt;/dd&gt;
&lt;dt&gt;M300B&lt;/dt&gt;&lt;dd&gt;
Solo Violin
&lt;/dd&gt;
&lt;dt&gt;MixedBrassB&lt;/dt&gt;&lt;dd&gt;
Mixed Brass B
&lt;/dd&gt;
&lt;dt&gt;MkIIChurchOrgan&lt;/dt&gt;&lt;dd&gt;
Lowrey Organ
&lt;/dd&gt;
&lt;dt&gt;MkIICombinedBrass&lt;/dt&gt;&lt;dd&gt;
MkII Combined Brass
&lt;/dd&gt;
&lt;dt&gt;MkIIFlute&lt;/dt&gt;&lt;dd&gt;
MkII Flute
&lt;/dd&gt;
&lt;dt&gt;MkIIViolins&lt;/dt&gt;&lt;dd&gt;
MkII Violins
&lt;/dd&gt;
&lt;dt&gt;Orchestra&lt;/dt&gt;&lt;dd&gt;
Orchestra
&lt;/dd&gt;
&lt;dt&gt;StJohnsOrgan&lt;/dt&gt;&lt;dd&gt;
St John’s Wood Church Organ
&lt;/dd&gt;
&lt;dt&gt;StringSection&lt;/dt&gt;&lt;dd&gt;
String Section
&lt;/dd&gt;
&lt;dt&gt;TenorAltoSax&lt;/dt&gt;&lt;dd&gt;
Tenor &amp;amp; Alto Sax
&lt;/dd&gt;
&lt;dt&gt;TenorSax&lt;/dt&gt;&lt;dd&gt;
Tenor Sax
&lt;/dd&gt;
&lt;dt&gt;Trombone&lt;/dt&gt;&lt;dd&gt;
Trombone
&lt;/dd&gt;
&lt;dt&gt;TromboneTrumpet&lt;/dt&gt;&lt;dd&gt;
Trombone &amp;amp; Trumpet
&lt;/dd&gt;
&lt;dt&gt;Trumpet&lt;/dt&gt;&lt;dd&gt;
Trumpet
&lt;/dd&gt;
&lt;dt&gt;Vibes&lt;/dt&gt;&lt;dd&gt;
Vibes
&lt;/dd&gt;
&lt;dt&gt;Woodwind2&lt;/dt&gt;&lt;dd&gt;
Woodwind 2
&lt;/dd&gt;
&lt;dl&gt;
&lt;h2&gt;Hear it in Action&lt;/h2&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://post.lurk.org/@froos&quot;&gt;froos&lt;/a&gt; for this one!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://strudel.cc/?AwZC_0IlpDnY&quot;&gt;Mellotron Test 2 by froos&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a name=&quot;1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt; When hosting your own Strudel sample library, your web server will need to be configured to allow CORS for the strudel.json and audio sample files. &lt;a href=&quot;https://enable-cors.org/server.html&quot;&gt;This site&lt;/a&gt; is pretty helpful.&lt;/a&gt;&lt;/p&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
&lt;/dl&gt;&lt;/dl&gt;</description>
      <pubDate>Tue, 15 Oct 2024 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2024-10-16-strudel-mellotron/</guid>
    </item>
    <item>
      <title>Harmonize Scales with the Python Musthe library</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2024-07-30-musthe-harmonize/</link>
      <description>&lt;h1&gt;Harmonize Scales with the Python Musthe library&lt;/h1&gt;
&lt;p&gt;I&#39;m pleased to say that a new feature I wrote for the Python
&lt;a href=&quot;https://github.com/gciruelos/musthe&quot;&gt;musthe&lt;/a&gt; music theory library has accepted
and merged into the code base.&lt;/p&gt;
&lt;p&gt;If you&#39;re not familiar with Musthe, it&#39;s a general-purpose library for exploring
scales and chords; the project README gives a good overview of the kinds of
things you can do with it.&lt;/p&gt;
&lt;p&gt;I added two new methods to the
&lt;a href=&quot;https://github.com/gciruelos/musthe/blob/master/musthe/musthe.py#L444&quot;&gt;Scale&lt;/a&gt;
class: &lt;code&gt;harmonize()&lt;/code&gt; and &lt;code&gt;harmonize_dict()&lt;/code&gt;. Given any scale, these methods will
return all of the diatonic chords (That is, chords containing notes from that
scale,) plus dominant 7th chords.&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;As of July 2024, you&#39;ll need to install musthe directly from the git repository to use the latest features, as there has not been a new PyPi release since 2018:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pip install musthe@git+https://github.com/gciruelos/musthe
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;For example, to get a dictionary of chords for
the E Dorian scale:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from musthe import Note, Scale
from pprint import pprint

scale = Scale(Note(&#39;E&#39;), &#39;dorian&#39;)
pprint(scale.harmonize(), indent=2, compact=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will give you:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[ [ Chord(Note(&#39;E4&#39;), &#39;min&#39;), Chord(Note(&#39;E4&#39;), &#39;min7&#39;),
    Chord(Note(&#39;E4&#39;), &#39;sus2&#39;), Chord(Note(&#39;E4&#39;), &#39;sus4&#39;),
    Chord(Note(&#39;E4&#39;), &#39;open5&#39;), Chord(Note(&#39;E4&#39;), &#39;min9&#39;)],
  [ Chord(Note(&#39;F#4&#39;), &#39;min&#39;), Chord(Note(&#39;F#4&#39;), &#39;min7&#39;),
    Chord(Note(&#39;F#4&#39;), &#39;sus4&#39;), Chord(Note(&#39;F#4&#39;), &#39;open5&#39;)],
  [ Chord(Note(&#39;G4&#39;), &#39;maj&#39;), Chord(Note(&#39;G4&#39;), &#39;dom7&#39;),
    Chord(Note(&#39;G4&#39;), &#39;maj7&#39;), Chord(Note(&#39;G4&#39;), &#39;sus2&#39;),
    Chord(Note(&#39;G4&#39;), &#39;open5&#39;), Chord(Note(&#39;G4&#39;), &#39;dom9&#39;),
    Chord(Note(&#39;G4&#39;), &#39;maj9&#39;)],
  [ Chord(Note(&#39;A4&#39;), &#39;maj&#39;), Chord(Note(&#39;A4&#39;), &#39;dom7&#39;),
    Chord(Note(&#39;A4&#39;), &#39;sus2&#39;), Chord(Note(&#39;A4&#39;), &#39;sus4&#39;),
    Chord(Note(&#39;A4&#39;), &#39;open5&#39;), Chord(Note(&#39;A4&#39;), &#39;dom9&#39;)],
  [ Chord(Note(&#39;B4&#39;), &#39;min&#39;), Chord(Note(&#39;B4&#39;), &#39;min7&#39;),
    Chord(Note(&#39;B4&#39;), &#39;sus2&#39;), Chord(Note(&#39;B4&#39;), &#39;sus4&#39;),
    Chord(Note(&#39;B4&#39;), &#39;open5&#39;), Chord(Note(&#39;B4&#39;), &#39;min9&#39;)],
  [Chord(Note(&#39;C#4&#39;), &#39;dim&#39;), Chord(Note(&#39;C#4&#39;), &#39;m7dim5&#39;)],
  [ Chord(Note(&#39;D4&#39;), &#39;maj&#39;), Chord(Note(&#39;D4&#39;), &#39;dom7&#39;),
    Chord(Note(&#39;D4&#39;), &#39;maj7&#39;), Chord(Note(&#39;D4&#39;), &#39;sus2&#39;),
    Chord(Note(&#39;D4&#39;), &#39;sus4&#39;), Chord(Note(&#39;D4&#39;), &#39;open5&#39;),
    Chord(Note(&#39;D4&#39;), &#39;dom9&#39;), Chord(Note(&#39;D4&#39;), &#39;maj9&#39;)]]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, for a human-friendlier output you can use &lt;code&gt;harmonize_dict()&lt;/code&gt; and format the
chords as strings:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;for note, chords in scale.harmonize_dict().items():
  print(note)
  for c in chords:
    print(f&amp;quot;&#92;t{c}&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which gives you:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;E
        Emin
        Emin7
        Esus2
        Esus4
        Eopen5
        Emin9
F#
        F#min
        F#min7
        F#sus4
        F#open5
G
        Gmaj
        Gdom7
        Gmaj7
        Gsus2
        Gopen5
        Gdom9
        Gmaj9
A
        Amaj
        Adom7
        Asus2
        Asus4
        Aopen5
        Adom9
B
        Bmin
        Bmin7
        Bsus2
        Bsus4
        Bopen5
        Bmin9
C#
        C#dim
        C#m7dim5
D
        Dmaj
        Ddom7
        Dmaj7
        Dsus2
        Dsus4
        Dopen5
        Ddom9
        Dmaj9
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you prefer to omit dominant 7th chords, you can use
&lt;code&gt;harmonize(include_dom7=False)&lt;/code&gt; and &lt;code&gt;harmonize_dict(include_dom7=False)&lt;/code&gt;.&lt;/p&gt;
</description>
      <pubDate>Mon, 29 Jul 2024 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2024-07-30-musthe-harmonize/</guid>
    </item>
    <item>
      <title>A hacked-together Python command-line Audio Player</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2024-07-10-python-player/</link>
      <description>&lt;h1&gt;A hacked-together Python command-line Audio Player&lt;/h1&gt;
&lt;p&gt;The other day it occurred to me to see if there were any good terminal-based audio players since the last time I looked.&lt;/p&gt;
&lt;p&gt;There weren&#39;t, at least not in the goldilocks zone that I have in mind, which is a little more than &lt;code&gt;mplayer&lt;/code&gt; and a lot less than &lt;code&gt;cmus&lt;/code&gt;. All I want is a terminal command that takes some audio filenames and plays them with a nice TUI and basic start/pause/stop/skip controls.&lt;/p&gt;
&lt;p&gt;While poking around today I found the Python &lt;a href=&quot;https://pypi.org/project/audioplayer/&quot;&gt;audioplayer&lt;/a&gt; library, and it didn&#39;t take much to get a script working that will:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Load audio files from a directory&lt;/li&gt;
&lt;li&gt;Play them in order, using &lt;a href=&quot;https://tqdm.github.io/&quot;&gt;tqdm&lt;/a&gt; to show a progress bar as they go.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from audioplayer import AudioPlayer
import os
from time import time
from tqdm import tqdm
ALBUM = &#39;./Optiganally Yours/O.Y. In Hi-Fi&#39;
for f in sorted(os.listdir(ALBUM)):
    if f[-4:] == &#39;flac&#39;:
        p = AudioPlayer(f&amp;quot;{ALBUM}/{f}&amp;quot;)
        # (There might be a way to make the player load the file without
		#  the play/pause step, but I haven&#39;t dug too deeply)
        p.play()
        p.pause()
        dur = round(p._player.duration())
        started_at = time()
        tick = started_at
        p.play()
        pbar.update(1)
        is_playing = True
        with tqdm(total=dur, desc=f.rjust(25, &#39; &#39;)) as pbar:
            while round(p._player.currentTime()) &amp;lt;= dur and is_playing:
                now = time()
                if now - tick &amp;gt;= 1:
                    pbar.update(1)
                    tick = now
                if tick - started_at &amp;gt;= dur:
                    is_playing = False
        p.stop()
        p.close()
        pbar.close()
&lt;/code&gt;&lt;/pre&gt;
&lt;img src=&quot;https://relvokcor.xyz/assets/img/iub74mLdbK-300.png&quot; width=&quot;300&quot; height=&quot;174&quot; alt=&quot;An album playing in a Python REPL&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;
&lt;p&gt;I also discovered &lt;a href=&quot;https://pypi.org/project/blessed/&quot;&gt;blessed&lt;/a&gt;, which could be used to build an actual interface.&lt;/p&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;You&#39;ll need &lt;a href=&quot;https://gstreamer.freedesktop.org/&quot;&gt;gstreamer&lt;/a&gt; installed on your system, and the following Python packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;audioplayer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tqdm&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I ran this right from a REPL, but it ought to work as a script.&lt;/p&gt;
&lt;!-- Generated by Stubble v0.4.0-dev --&gt;
</description>
      <pubDate>Tue, 09 Jul 2024 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2024-07-10-python-player/</guid>
    </item>
    <item>
      <title>A Chord Progression Generating Bot for the Fediverse</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2024-03-28-a-chord-progression-generating-bot-for-the-fediverse/</link>
      <description>&lt;h1&gt;A Chord Progression Generating Bot for the Fediverse&lt;/h1&gt;
&lt;img src=&quot;https://relvokcor.xyz/assets/img/btN7dAjCdr-300.png&quot; width=&quot;300&quot; height=&quot;173&quot; alt=&quot;A programmatically generated image of a randomly generated chord progression&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;
&lt;p&gt;My short term obsession for the last couple of weeks has been &lt;a href=&quot;https://banjo.town/@progressions&quot;&gt;@progressions&lt;/a&gt;, a Python-based bot that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generates a random chord progression in a random key&lt;/li&gt;
&lt;li&gt;Generates &lt;a href=&quot;https://lilypond.org/&quot;&gt;LilyPond&lt;/a&gt; markup to display the chords in standard musical notation (along with their names and roman numerals)&lt;/li&gt;
&lt;li&gt;Engraves the LilyPond to a PNG file&lt;/li&gt;
&lt;li&gt;Applies a random color scheme to it to keep things interesting&lt;/li&gt;
&lt;li&gt;Toots it to a &lt;a href=&quot;https://joinmastodon.org/&quot;&gt;Mastodon&lt;/a&gt; instance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have a couple of additional features in mind, and eventually I want to apply things learned to an Arduino device that would function as a songwriting and/or practice tool.&lt;/p&gt;
</description>
      <pubDate>Wed, 27 Mar 2024 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2024-03-28-a-chord-progression-generating-bot-for-the-fediverse/</guid>
    </item>
    <item>
      <title>Personal Advent of Code 2023</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/aoc-2023/</link>
      <description>&lt;h1&gt;Personal Advent of Code 2023&lt;/h1&gt;
  &lt;!-- # - &quot;Advent of Code&quot;
  # - &quot;Personal Advent of Code&quot;
  # - &quot;Rust&quot;
  # - &quot;MOS 6502&quot;
  # - &quot;Commodore 64&quot;
  # - &quot;Retrocomputing&quot;
  # - &quot;Monthly Challenges&quot; --&gt;
&lt;p&gt;I like &lt;a href=&quot;https://adventofcode.com/&quot;&gt;Advent of Code&lt;/a&gt; in &lt;em&gt;concept&lt;/em&gt;, but I&#39;ve never managed to stick with it more than a couple of days; I don&#39;t do well with the &amp;quot;frustrating arbitrary logic puzzles I will never need to deal with IRL unless it&#39;s in the context of a crappy tech job interview&amp;quot; aspect of it.&lt;/p&gt;
&lt;p&gt;But I still have plenty to learn with &lt;a href=&quot;https://rustlang.org/&quot;&gt;Rust&lt;/a&gt; and my new related short-term obsession, &lt;a href=&quot;https://llvm-mos.org/wiki/Rust&quot;&gt;Rust for the MOS 6502 microprocessor&lt;/a&gt;. Giving myself discrete little challenges to chip away at will probably serve me well.&lt;/p&gt;
&lt;p&gt;I don&#39;t think I&#39;m going to make an entire list ahead of time, though, because that&#39;s not how short-term attention span obsession works for me.&lt;/p&gt;
&lt;p&gt;My December 1 challenge will be:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Create a Rust/MOS6502 template repository that includes a README with environment setup steps&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;!-- Generated by Stubble v0.3.2 --&gt;</description>
      <pubDate>Sat, 25 Nov 2023 19:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/aoc-2023/</guid>
    </item>
    <item>
      <title>Using the Eleventy RSS Plugin with &amp;#x60;pathPrefix&amp;#x60;</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2023-11-21-using-the-eleventy-rss-plugin-with-pathprefix/</link>
      <description>&lt;h1&gt;Using the Eleventy RSS Plugin with `pathPrefix`&lt;/h1&gt;
&lt;p&gt;This site (at the time of this post, anyway) is hosted on a &lt;a href=&quot;https://tildeverse.org/&quot;&gt;tilde&lt;/a&gt; and as such every resource on it has a URI beginning with &lt;code&gt;/~moondog8&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;pathPrefix&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Eleventy provides a config option called &lt;a href=&quot;https://www.11ty.dev/docs/config/#deploy-to-a-subdirectory-with-a-path-prefix&quot;&gt;&lt;code&gt;pathPrefix&lt;/code&gt;&lt;/a&gt; for this scenario.&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;absoluteUrl&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.11ty.dev/docs/plugins/rss/&quot;&gt;Eleventy RSS Plugin&lt;/a&gt; provides a filter called &lt;code&gt;absoluteUrl&lt;/code&gt; that you can use to prepend your site&#39;s domain name to any page links that appear in your RSS feed.&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;absoluteUrl&lt;/code&gt; with &lt;code&gt;pathPrefix&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;When trying to get an RSS feed for this site working, I used one of the &lt;a href=&quot;https://www.11ty.dev/docs/plugins/rss/#sample-feed-templates&quot;&gt;sample feed templates&lt;/a&gt; and all of the permalinks were broken; &lt;code&gt;absoluteUrl&lt;/code&gt; has no awareness of &lt;code&gt;pathPrefix&lt;/code&gt;, and it took me a minute to figure out how to get them working.&lt;/p&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;p&gt;In a nutshell: Anywhere in your RSS template that you see a link being passed to the &lt;code&gt;absoluteUrl&lt;/code&gt; filter, ie:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-njk&quot;&gt;{{ permalink | absoluteUrl(metadata.url) }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-njk&quot;&gt;{%- set absolutePostUrl = post.url | absoluteUrl(metadata.url) %}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Send it through the &lt;code&gt;url&lt;/code&gt; filter&lt;sup&gt;*&lt;/sup&gt; first:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-njk&quot;&gt;{%- set absolutePostUrl = post.url | url | absoluteUrl(metadata.url) %}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;sup&gt;*&lt;/sup&gt;I haven&#39;t tried this with the newer &lt;a href=&quot;https://www.11ty.dev/docs/plugins/html-base/&quot;&gt;HTMLBase&lt;/a&gt; element, but if I read the documentation correctly, you should be able to use:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-njk&quot;&gt;{%- set absolutePostUrl = post.url | htmlBaseUrl | absoluteUrl(metadata.url) %}
&lt;/code&gt;&lt;/pre&gt;
&lt;!-- Generated by Stubble v0.3.2 --&gt;
</description>
      <pubDate>Mon, 20 Nov 2023 19:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2023-11-21-using-the-eleventy-rss-plugin-with-pathprefix/</guid>
    </item>
    <item>
      <title>Stubble!</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/2023-11-14-stubble/</link>
      <description>&lt;h1&gt;Stubble!&lt;/h1&gt;
&lt;p&gt;I started fooling around with Eleventy around the same time I started fooling around with Rust, and although typing out a few lines of front matter is not a ton of work in the scheme of things, I did find myself thinking it would be nice to have a tool that would take a title and stub out a new Markdown file for me... so I wrote one in Rust (with help from &lt;a href=&quot;https://robloranger.ca/index.html&quot;&gt;Rob&lt;/a&gt;!)&lt;/p&gt;
&lt;p&gt;It&#39;s called &lt;strong&gt;Stubble&lt;/strong&gt; and it&#39;s already grown a fair bit beyond the above description, but I&#39;ve been trying to build it in a &amp;quot;works minimally, also provides power user features&amp;quot; frame of mind.&lt;/p&gt;
&lt;p&gt;If you run stubble with a single argument:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;stubble &amp;quot;My New Post&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It generates a file called &lt;code&gt;YYYY-MM-DD-my-new-post.md&lt;/code&gt; in the current directory (where &lt;code&gt;YYYY-MM-DD&lt;/code&gt; is the current date).&lt;/p&gt;
&lt;p&gt;The file looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;---
title: &amp;quot;My New Post&amp;quot;
date: 2023-11-14
author: &amp;quot;Andy Chase&amp;quot;
uuid: 88d71e51-391d-405e-9ead-50ae6a4ee5b7
---
# My New Post

&amp;lt;!-- Generated by Stubble v0.3.2 --&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s pretty handy!&lt;/p&gt;
&lt;p&gt;You can also add a description, and tags, override various options, and (soon) choose multiple built-in formats (Currently the only other one that&#39;s been implemented is a &lt;code&gt;.org&lt;/code&gt; stub, but the plumbing is there for as many text-based file types as a person could need.)&lt;/p&gt;
&lt;p&gt;Here&#39;s the help overview as of version 0.3.2, released earlier today:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;Stubble is a command-line tool for quickly generating markdown files for use by static site generators. Given a title, it will generate a date-stamped markdown file with pre-populated YAML front-matter.

Usage: stubble [OPTIONS] &amp;lt;TITLE&amp;gt; [DEST]

Arguments:
  &amp;lt;TITLE&amp;gt;  Title of the post
  [DEST]   Output destination [default: .]

Options:
  -s, --slug &amp;lt;SLUG&amp;gt;                Optional slug to be used for the permalink
  -t, --tag [&amp;lt;TAG&amp;gt;...]             Tag(s) to apply to the post. Separate multiple tags with spaces
  -D, --date &amp;lt;DATE&amp;gt;                Override the post date: YYYY-MM-DD
  -d, --description &amp;lt;DESCRIPTION&amp;gt;  Post description
  -a, --author [&amp;lt;AUTHOR&amp;gt;]          The name of the author
  -f, --format [&amp;lt;FORMAT&amp;gt;]          The output format that should be used to render the stub. [default: md]
  -o, --output &amp;lt;OUTPUT&amp;gt;            Override the default filename
  -e, --editor [&amp;lt;EDITOR&amp;gt;]          Open in &amp;lt;EDITOR&amp;gt;
  -y, --yes                        Automatically answer &#39;Y&#39; to all prompts (including existing file warnings)
  -h, --help                       Print help (see more with &#39;--help&#39;)
  -V, --version                    Print version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There&#39;s no real roadmap yet; so far it&#39;s mostly been an exercise in getting familiar with Rust.&lt;/p&gt;
&lt;p&gt;The only other major feature I have in mind is the ability to bring your own templates (Stubble uses &lt;a href=&quot;https://github.com/sunng87/handlebars-rust&quot;&gt;handlebars-rust&lt;/a&gt; under the hood) and add your own key/value pairs.&lt;/p&gt;
&lt;p&gt;I&#39;m also hoping this project holds my interest long enough to build an actual info/documenation web site for it, and finally learn about getting software into various package management registries.&lt;/p&gt;
&lt;p&gt;In the meantime, though, you can install Stubble with cargo if you already have a Rust environment on your machine:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cargo install stubble
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also visit its &lt;a href=&quot;https://crates.io/crates/stubble&quot;&gt;Crates.io&lt;/a&gt; page, or look at the &lt;a href=&quot;https://codeberg.org/mysteryhouse/stubble&quot;&gt;source code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;!-- Generated by Stubble v0.3.2 --&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;!-- Generated by Stubble v0.3.2 --&gt;
</description>
      <pubDate>Mon, 13 Nov 2023 19:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/2023-11-14-stubble/</guid>
    </item>
    <item>
      <title>Hexadecimal colors and the Rust `palette` Crate</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/hex-colors-and-the-rust-palette-crate/</link>
      <description>&lt;h1&gt;Hexadecimal colors and the Rust &lt;code&gt;palette&lt;/code&gt; Crate&lt;/h1&gt;
&lt;p&gt;My ongoing &lt;a href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt; tinkering found me wanting to fool around with color manipulation; I&#39;d like to write a color exploration/palette generator web API and front end.&lt;/p&gt;
&lt;p&gt;This led me to the &lt;a href=&quot;https://crates.io/crates/palette&quot;&gt;palette&lt;/a&gt; crate, which I&#39;m pretty sure does everything I need and then some, but because I&#39;m still in &amp;quot;only know enough to be dangerous&amp;quot; mode with Rust, it took me a while to figure out how to instantiate an &lt;code&gt;Rgb&lt;/code&gt; struct directly from a web-style &lt;code&gt;#abcdef&lt;/code&gt; hexadecimal color string.&lt;/p&gt;
&lt;p&gt;TL;DR, you can use the &lt;code&gt;FromStr&lt;/code&gt; trait:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;use std::str::FromStr;
use palette::{rgb, Srgb};

let my_rgb: rgb::Rgb&amp;lt;Srgb, u8&amp;gt; = rgb::Rgb::from_str(&amp;quot;336699&amp;quot;).unwrap()

println!(&amp;quot;{:?}&amp;quot;, my_rgb);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Rgb { red: 51, green: 102, blue: 153, standard: PhantomData&amp;lt;palette::rgb::rgb::Rgb&amp;gt; }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;rgb::Rgb::from_str()&lt;/code&gt; supports strings with a leading octothorpe (&lt;code&gt;&amp;quot;#336699&amp;quot;&lt;/code&gt;), and it will also take a &lt;code&gt;&amp;amp;String&lt;/code&gt; instead of a literal.&lt;/p&gt;
&lt;!-- Generated by Stubble v0.1.1 --&gt;
</description>
      <pubDate>Sat, 04 Nov 2023 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/hex-colors-and-the-rust-palette-crate/</guid>
    </item>
    <item>
      <title>Archaeology</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/archaeology/</link>
      <description>&lt;h2&gt;Archaeology&lt;/h2&gt;
&lt;p&gt;Now that I seem to be &lt;a href=&quot;https://maggieappleton.com/garden-history&quot;&gt;gardening&lt;/a&gt; again I&#39;ve decided to start working on pulling in content from various regularly-ish updated web presences I&#39;ve had going back to ~2000. A lot of it is actually still out there on an &lt;em&gt;ancient&lt;/em&gt; web site that I&#39;ve been meaning to mothball forever.&lt;/p&gt;
&lt;p&gt;A couple of years ago I went to the trouble of dumping it into JSON, but that was as far as I got.&lt;/p&gt;
&lt;p&gt;Somewhere or other I &lt;em&gt;also&lt;/em&gt; have the archive of everything I uploaded to Flickr from 2004 until... 2016ish?&lt;/p&gt;
&lt;p&gt;It will be nice if I can massage it all into regular old markdown files with related media all in one place... after almost 30 years on the web, markdown feels like the best long-game format for staying on top of all of my old crap. SSGs come and go, but pretty much all of them operate on the principle of &amp;quot;chew on markdown and turn it into something else,&amp;quot; and I like that better than logging into some web admin and hoping it still works.&lt;/p&gt;
&lt;p&gt;This is my third attempt at reviving some kind of personal web site in the last year, and each time I have avoided the word &amp;quot;blog&amp;quot; as much as I can, because I&#39;ve never liked it. At the time the words &amp;quot;blog,&amp;quot; &amp;quot;blogger,&amp;quot; and &amp;quot;blogging&amp;quot; started to became A Thing circa 2000, I remember it seeming like tech journalists were &lt;em&gt;really&lt;/em&gt; trying to make it happen.&lt;/p&gt;
&lt;p&gt;People regularly posting dated entries to personal websites was not a new thing, but the combination of 1) the web and home computers having been around long enough to no longer be nerds-only and 2) the emergence of free online services that made it easy to post date-based journaled entries was something new, and I guess &amp;quot;blog&amp;quot; was the term that was quirky and annoying enough to stick.&lt;/p&gt;
&lt;p&gt;This was also around the time that people began to get truly obsessed with SEO, and the narrative shifted from &amp;quot;I don&#39;t know, just put some funny/cool stuff up on my web hosting account&amp;quot; to &amp;quot;but if you don&#39;t update your blog regularly and have a specific focus and pepper your entries with just the right amount of keywords and tags, it will negatively affect your search engine ranking and that&#39;s the worst thing that could possibly happen!&amp;quot;&lt;/p&gt;
&lt;p&gt;As a relatively green web dev who was trying to get into the game, I bought into that mindset and lost the thread for a long time. Web sites went from an amazing global way to share knowledge and content to increasingly indistinguishable brochures, all twisted by whatever the prevailing SEO wisdom of the month was.&lt;/p&gt;
&lt;p&gt;I also went through several cycles of &amp;quot;but if I&#39;m a professional web developer then I should have a slick and polished and carefully curated web site!&amp;quot; but my actual web graphic design skills peaked around the time of the dot com crash and the days when being able to competently construct your own resume/portfolio site were enough to get you an interview, if not a job, are far in the past, so... those never amounted to anything either.&lt;/p&gt;
&lt;p&gt;So, fie on blogs. This is just a web site.&lt;/p&gt;
&lt;!-- Generated by Stubble v0.1.1 --&gt;
</description>
      <pubDate>Fri, 03 Nov 2023 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/archaeology/</guid>
    </item>
    <item>
      <title>Note to Self: OS Keyboard Shortcuts Edition</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/os-shortcuts/</link>
      <description>&lt;h1&gt;Note to Self: OS Keyboard Shortcuts Edition&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:left&quot;&gt;Environment&lt;/th&gt;
&lt;th style=&quot;text-align:left&quot;&gt;Task&lt;/th&gt;
&lt;th style=&quot;text-align:left&quot;&gt;Keyboard Shortcut&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;strong&gt;MacOS&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Emoji picker&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;code&gt;Ctrl + Cmd + Space&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Show hidden files in Finder&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;code&gt;Cmd + Shift + .&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;!-- Generated by Stubble v0.1.1 --&gt;
</description>
      <pubDate>Thu, 02 Nov 2023 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/os-shortcuts/</guid>
    </item>
    <item>
      <title>Note to Self: Emacs Edition</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/emacs/</link>
      <description>&lt;h1&gt;Note to Self: Emacs Edition&lt;/h1&gt;
&lt;p&gt;Keybindings and such that I really ought to remember by now&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:left&quot;&gt;Mode&lt;/th&gt;
&lt;th style=&quot;text-align:left&quot;&gt;Task&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th style=&quot;text-align:left&quot;&gt;Note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;strong&gt;General&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Make text larger&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C-x C-=&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Make text smaller&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C-x C--&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Comment out the current line or region&lt;/td&gt;
&lt;td&gt;&lt;code&gt;comment-dwim&lt;/code&gt; (&lt;code&gt;M-;&lt;/code&gt;)&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Get help for a function&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C-h f &amp;lt;function name&amp;gt; RET&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;See the current value of a variable&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C-h v &amp;lt;variable name&amp;gt; RET&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Show all active keybindings for current buffer&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C-h b&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Close =dired= buffers behind you as you navigate&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(setq dired-kill-when-opening-new-dired-buffer t)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Run a shell command and put its output into the current buffer&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C-u M-!&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Pass the current region to a shell command and replace it with the output&lt;/td&gt;
&lt;td&gt;&lt;code&gt;M-|&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;strong&gt;Working with Buffers&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Save all buffers&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C-x s !&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;strong&gt;Moving Around&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Go to start or end of buffer&lt;/td&gt;
&lt;td&gt;&lt;code&gt;M-&amp;lt;&lt;/code&gt; (start), &lt;code&gt;M-&amp;gt;&lt;/code&gt; (end)&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;strong&gt;Org mode&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Open an agenda view restricted to the current buffer, subtree or region&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C-a &amp;lt;&lt;/code&gt;                                                  (Then select an agenda)&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Detangle source code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;org-babel-detangle&lt;/code&gt; (&lt;strong&gt;Important:&lt;/strong&gt; must be run from the tangled source code buffer, not the original org file)&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;strong&gt;Dired&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Delete marked files&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dired-do-delete&lt;/code&gt; (&lt;code&gt;D&lt;/code&gt;)&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;strong&gt;Markdown&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Insert a table&lt;/td&gt;
&lt;td&gt;&lt;code&gt;markdown-insert-table&lt;/code&gt; (&lt;code&gt;C-c C-s t&lt;/code&gt;)&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Insert a table column&lt;/td&gt;
&lt;td&gt;&lt;code&gt;markdown-table-insert-column&lt;/code&gt; (&lt;code&gt;C-c S-&amp;lt;right&amp;gt;&lt;/code&gt;)&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Row is inserted to the &lt;em&gt;left&lt;/em&gt; of point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Insert a table row&lt;/td&gt;
&lt;td&gt;&lt;code&gt;markdown-table-insert-row&lt;/code&gt; (&lt;code&gt;C-c S-&amp;lt;down&amp;gt;&lt;/code&gt;)&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Row is inserted &lt;em&gt;above&lt;/em&gt; point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;strong&gt;TRAMP&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Edit a file with &lt;code&gt;sudo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C-x C-f /sudo::/etc/my/protected-file.conf&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Open a file over SSH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C-x C-f /ssh:user@example.com:/path/to/remote/file.txt&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;strong&gt;Dates&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Formatting dates+times&lt;/td&gt;
&lt;td&gt;&lt;code&gt;format-time-string&lt;/code&gt; &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Time-Parsing.html#index-format_002dtime_002dstring&quot;&gt;(formatting reference)&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;strong&gt;Customization&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Set a variable in =.dir-locals.el=&lt;/td&gt;
&lt;td&gt;&lt;code&gt;M-x add-dir-local-variable&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;| &lt;strong&gt;Misc.&lt;/strong&gt;                |                                                                         |                                                                                  |                                        |
|                          | Tail a file                                                             | &lt;code&gt;auto-revert-tail-mode&lt;/code&gt;                                                          |                                        |&lt;/p&gt;
</description>
      <pubDate>Thu, 02 Nov 2023 08:11:06 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/emacs/</guid>
    </item>
    <item>
      <title>Note to Self: When Thunar Hangs on an SFTP gvfs Session and Won&#39;t Restart</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/thunar-sftp/</link>
      <description>&lt;h1&gt;Note to Self: When Thunar Hangs on an SFTP gvfs Session and Won&#39;t Restart&lt;/h1&gt;
&lt;h2&gt;Environment&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://manjaro.org/&quot;&gt;Manjaro Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.xfce.org/&quot;&gt;xfce desktop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I had a Thunar file manager window connected to a remote server using an &lt;code&gt;ssh://user@hostname/path/to/remote/subdir&lt;/code&gt; URL (which uses &lt;a href=&quot;https://en.wikipedia.org/wiki/GVfs&quot;&gt;gvfs&lt;/a&gt; under the hood)&lt;/li&gt;
&lt;li&gt;The window froze and I eventually got a &amp;quot;taking a long time to respond / do you want to terminate?&amp;quot; sort of message&lt;/li&gt;
&lt;li&gt;Terminating from that dialog did close all of my Thunar windows, but Thunar would not relaunch after that.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;A bit of searching led me to a more or less identical issue description &lt;a href=&quot;https://forum.xfce.org/viewtopic.php?id=11936&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;TL;DR&lt;/h3&gt;
&lt;p&gt;There were some stray &lt;code&gt;gvfsd-sftp&lt;/code&gt; processes still running. I killed them with:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;pkill -f gvfsd-sftp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After that, Thunar opened right back up.&lt;/p&gt;
</description>
      <pubDate>Tue, 31 Oct 2023 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/thunar-sftp/</guid>
    </item>
    <item>
      <title>Site Goals</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/goals/</link>
      <description>&lt;h1&gt;Goals for this Site&lt;/h1&gt;
&lt;p&gt;Before I was dragged kicking and screaming into modern JavaScript-based web design, I would often try out whatever web app I was building in &lt;a href=&quot;https://lynx.invisible-island.net/&quot;&gt;Lynx&lt;/a&gt;, the text-based web browser that&#39;s been around since 1992.&lt;/p&gt;
&lt;p&gt;If a web site/web app works in Lynx --by which I mean: makes sense structurally and still provides the functionality intended-- it&#39;s doing something right.&lt;/p&gt;
&lt;p&gt;Modern frameworks like Vue and React are clever and interesting and even sometimes fun to use, but every once in a while I have an out of body of experience where I really &lt;em&gt;look&lt;/em&gt; at the massively complex Rube Goldberg machinery that JavaScript developers have built to shadow the DOM, render custom markup in the browser (and, now, even more absurdly, on the server), bundle code from thousands of JavaScript packages, and ultimately just spit it back out as HTML, and I want to turn off my computer, stand up, and move to a cave.&lt;/p&gt;
&lt;p&gt;So, maintaining this site as an old-school, click-a-link-and-refresh-the-browser site is goal number 1.&lt;/p&gt;
&lt;h2&gt;Accessibility&lt;/h2&gt;
&lt;p&gt;I need to do better than &amp;quot;make sure to put alt-text on images,&amp;quot; it&#39;s embarrassing how little experience I have in this area for as long as I&#39;ve been at this.&lt;/p&gt;
&lt;h2&gt;Etc.&lt;/h2&gt;
&lt;p&gt;I&#39;ve been using Emacs for 20+ years but it wasn&#39;t until earlier this year that I made an attempt at actually using it IDE style (vs jumping in to hack on a file or two.) It&#39;s slow going, but that&#39;s OK.&lt;/p&gt;
</description>
      <pubDate>Mon, 30 Oct 2023 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/goals/</guid>
    </item>
    <item>
      <title>Concerning Habits</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/concerning-habits/</link>
      <description>&lt;h1&gt;Concerning Habits&lt;/h1&gt;
&lt;p&gt;It&#39;s been about one year since I started a bullet journal in an effort to keep on top of all-the-things.&lt;/p&gt;
&lt;p&gt;I did fairly well for a couple of months, then hit a point where I found myself migrating the same unfinished tasks too many weeks in a row and spiraled into futility mode for a while.&lt;/p&gt;
&lt;p&gt;When I came out of it, I re-discovered &lt;a href=&quot;https://orgmode.org/&quot;&gt;Org Mode&lt;/a&gt; for the umpteenth time, and &lt;em&gt;this&lt;/em&gt; time I also discovered habit mode, which is absolutely brilliant for all of the trivial &amp;quot;change the HEPA filter on the vacuum cleaner in &lt;em&gt;n&lt;/em&gt; months&amp;quot; crap that has a tendency to slip days, weeks, months, even years past due. Org Mode doesn&#39;t provide any magic to make the &amp;quot;hey this non-trivial thing that you need to do still hasn&#39;t been done&amp;quot; problem go away, but it &lt;em&gt;does&lt;/em&gt; let you punt them into the future for a while.&lt;/p&gt;
&lt;p&gt;It&#39;s mildly upsetting to realize I&#39;ve already been at this a year. On the one hand I don&#39;t feel anywhere near being on top of all-the-things... on the other, little things definitely pile up less than they used to, so I&#39;ll call that a win.&lt;/p&gt;
</description>
      <pubDate>Sun, 29 Oct 2023 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/concerning-habits/</guid>
    </item>
    <item>
      <title>That one time I worked on Star Trek: Deep Space Nine</title>
      <link>https://relvokcor.xyz/~moondog8/stuff/star-trek-deep-space-nine/</link>
      <description>&lt;h1&gt;That one time I worked on Star Trek: Deep Space Nine&lt;/h1&gt;
&lt;p&gt;In late 1996/early 1997 I found myself working at a practical special effects shop in North Hollywood, California, doing mostly menial tasks on various props and costumes for this and that, but also learning the trade and demonstrating enough of a knack for it that I was put on some builds.  By far the most noteworthy one I worked on was this target robot suit for Star Trek: Deep Space Nine Season 5, episode 18, &lt;em&gt;Business as Usual&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I worked under the supervision of the designer and from what I remember, fabricated most of the base armor pieces and did a fair amount of detail work as well, with the designer putting on final touches.&lt;/p&gt;
&lt;p&gt;I missed the episode when it originally aired and &lt;em&gt;finally&lt;/em&gt; saw it all these years later, now that I&#39;m finally watching the series from start to end. Like so many effects projects that you spend weeks of your life working on, it is visible for about one second in the final episode:&lt;/p&gt;
&lt;img src=&quot;https://relvokcor.xyz/assets/img/d7TsA6eW-X-300.png&quot; width=&quot;300&quot; height=&quot;211&quot; alt=&quot;Still frame from Star Trek: Deep Space Nine Season 5, episode 18, featuring a gold/bronze colored target droid marching towards the camera.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;</description>
      <pubDate>Tue, 17 Sep 2019 20:00:00 +0000</pubDate>
      <dc:creator>Andy Chase</dc:creator>
      <guid>https://relvokcor.xyz/~moondog8/stuff/star-trek-deep-space-nine/</guid>
    </item>
  </channel>
</rss>