<!DOCTYPE html>
<html lang="en">
  <head>
	<meta name="generator" content="Hugo 0.152.2">
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge"><title>David Edmondson </title>

  <link rel="icon" type="image/png" href="/favicon.ico" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="" />
  <link rel="stylesheet" type="text/css" media="screen" href="/css/main.css" />

  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Bitter:ital,wght@0,100..900;1,100..900&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap" rel="stylesheet">

</head>

  <body>
    <div class="content">
      <header>
  <nav>
    <a href="/now">David Edmondson</a>
  </nav>
</header>


      <main class="list">

        
        

        
        <section class="list-item">
          <h1 class="title"><a href="/posts/2025-11-13-don-t-forget-to-trim/">Don&#39;t forget to TRIM</a></h1>
<time>November 13, 2025</time>
<div class="description">
  <p>Last year I built a new home fileserver, mostly because I wanted to switch to an all flash pool of storage. Spinning rust is great for cost effectiveness, but it is (relatively) noisy and noticeably slower. The system is not particularly exciting:</p>
<ul>
<li>Fractal Design Node 304 case (left over from a previous project),</li>
<li><a href="https://www.gigabyte.com/Motherboard/B550I-AORUS-PRO-AX">Gigabyte B550I Aorus motherboard</a>,</li>
<li>AMD Ryzen 7 5700G,</li>
<li>64GB RAM,</li>
<li>512GB Samsung 970 Evo NVME drive as a boot device,</li>
<li>4 x 4TB Crucial BX500 SSD drives for data,</li>
<li>Intel X550 network card (2 x 10Gb ethernet).</li>
</ul>
<p>Initially the machine was installed with Debian Stable, the four drives set up as a ZFS RAIDZ pool. It worked well, for about 8 months.</p>
<p>After that, things started to slow down. Any significant write IO to the ZFS pool would cause IO stalls, timeouts and generally slowness. I spent quite a bit of time ignoring the problem, then made sporadic efforts to figure it out. None of this produced any useful results, even when I moved the four drives into another machine (also running Debian).</p>
<p>Finally it occurred to me that I hadn&rsquo;t turned on <code>autotrim</code> for the pool! Getting ZFS to trim the pool manually (using <code>zpool trim</code>) took several hours, but the performance improved immediately afterwards. After that I turned on <code>autotrim</code> (using <code>zpool set</code>) and the IO slowdowns have stayed away for around six months. So if you are seeing IO timeouts and stalls when ZFS flushes transactions, check whether enabling TRIM will speed things along for you.</p>

</div>

        </section>
        
        <section class="list-item">
          <h1 class="title"><a href="/posts/2025-08-01-miniflux-tweaks/">Miniflux Tweaks</a></h1>
<time>August 1, 2025</time>
<div class="description">
  <p>Having used <a href="https://miniflux.app/">Miniflux</a> as my feed reader for a few years, I recently made a few tweaks to make it more pleasant.</p>
<p>One of the nice features is that you can add CSS to the delivered pages in the application. Scan for <em>Custom CSS</em> in the <em>Settings</em> page.</p>
<p>Here is what I have so far:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">.</span><span class="nc">entry-content</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">font-family</span><span class="p">:</span> <span class="n">Palatino</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="p">#</span><span class="nn">page-header-title</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">font-family</span><span class="p">:</span> <span class="n">Palatino</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="nt">a</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">text-decoration-line</span><span class="p">:</span> <span class="kc">none</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nv">--body-color</span><span class="p">:</span> <span class="mh">#747473</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nv">--body-background</span><span class="p">:</span> <span class="mh">#f7f6f4</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nv">--body-background-opaque</span><span class="p">:</span> <span class="mh">#f7f6f4</span><span class="n">ff</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nv">--link-color</span><span class="p">:</span> <span class="mh">#e06151</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nv">--link-visited-color</span><span class="p">:</span> <span class="mh">#c04131</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="p">@</span><span class="k">media</span> <span class="o">(</span><span class="nt">prefers-color-scheme</span><span class="o">:</span> <span class="nt">dark</span><span class="o">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nv">--body-color</span><span class="p">:</span> <span class="mh">#bebfc2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="nv">--body-background</span><span class="p">:</span> <span class="mh">#252935</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="nv">--body-background-opaque</span><span class="p">:</span> <span class="mh">#252935</span><span class="n">ff</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="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">media</span> <span class="nt">screen</span> <span class="nt">and</span> <span class="o">(</span><span class="nt">max-width</span><span class="o">:</span> <span class="nt">480px</span><span class="o">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">body</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">margin-left</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">margin-right</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</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="p">.</span><span class="nc">pagination-entry-bottom</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">body</span><span class="o">-</span><span class="n">background</span><span class="o">-</span><span class="n">opaque</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">position</span><span class="p">:</span> <span class="kc">fixed</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">bottom</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">padding-left</span><span class="p">:</span> <span class="mi">10</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">padding-right</span><span class="p">:</span> <span class="mi">10</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">width</span><span class="p">:</span> <span class="mi">95</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">margin-bottom</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">padding-bottom</span><span class="p">:</span> <span class="mi">40</span><span class="kt">px</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="p">.</span><span class="nc">entry-content</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">padding-bottom</span><span class="p">:</span> <span class="mi">40</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>There are two sets of changes:</p>
<ul>
<li>The first simply modifies the font used for the content and the colours (both light and dark schemes). I find Palatino easier on the eyes when reading longer content, and the off-white background less jarring.</li>
<li>The second change is aimed at improving usability on mobile devices, as quite a bit of my use of Miniflux is as a PWA on my phone. For this the margins are tweaked to be slightly wider, but more importantly the <em>Previous</em> and <em>Next</em> links at the bottom of the page are fixed in place at the bottom of the screen, over the content. This means that there is no need to scroll to the top or bottom of the page to select them - it&rsquo;s almost like having a toolbar in a traditional app.</li>
</ul>
<p>Here is the end result:
<figure class="center"><img src="/images/2025-08-01-102603-miniflux.jpg"
    alt="Miniflux with tweaks">
</figure>
</p>

</div>

        </section>
        
        <section class="list-item">
          <h1 class="title"><a href="/posts/2025-02-18-khal-to-org--multiday-events/">Khal to Org - multiday events</a></h1>
<time>February 18, 2025</time>
<div class="description">
  <p><a href="/posts/2024-01-25-evolution-and-org-mode">Previously</a> I mentioned using Evolution→khal→org-mode to enable me to see my upcoming calendar events in my org-mode agenda. Recently I noticed that multiday events are not handled well - khal is instructed to output the <em>start</em> time for each event, which is always the first day.</p>
<p>Here is an updated script which should be used instead.</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">#!/usr/bin/env zsh
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="nv">diary</span><span class="o">=</span><span class="si">${</span><span class="nv">HOME</span><span class="si">}</span>/.emacs.d/diary.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">start</span><span class="o">=</span><span class="k">$(</span>date --date<span class="o">=</span><span class="s1">&#39;-30days&#39;</span> <span class="s1">&#39;+%Y-%m-%d&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">end</span><span class="o">=</span><span class="k">$(</span>date --date<span class="o">=</span><span class="s1">&#39;+30days&#39;</span> <span class="s1">&#39;+%Y-%m-%d&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">(</span><span class="nb">echo</span> <span class="s2">&#34;#+title: Calendar&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> khal list <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>      --day-format <span class="s2">&#34;DATE={date}&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>      --format <span class="s2">&#34;TITLE={title}{repeat-symbol}{alarm-symbol}
</span></span></span><span class="line"><span class="cl"><span class="s2">TIME={start-end-time-style}
</span></span></span><span class="line"><span class="cl"><span class="s2">{description}
</span></span></span><span class="line"><span class="cl"><span class="s2">END&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>      <span class="si">${</span><span class="nv">start</span><span class="si">}</span> <span class="si">${</span><span class="nv">end</span><span class="si">}</span> <span class="p">|</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>     <span class="k">while</span> <span class="nb">read</span> i<span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">         <span class="k">if</span> <span class="o">[[</span> <span class="si">${</span><span class="nv">i</span><span class="si">}</span> <span class="o">==</span> <span class="nv">DATE</span><span class="o">=</span>* <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">             <span class="nv">DATE</span><span class="o">=</span><span class="si">${</span><span class="nv">i</span><span class="p">##DATE=</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">         <span class="k">elif</span> <span class="o">[[</span> <span class="si">${</span><span class="nv">i</span><span class="si">}</span> <span class="o">==</span> <span class="nv">TITLE</span><span class="o">=</span>* <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">             <span class="nv">TITLE</span><span class="o">=</span><span class="si">${</span><span class="nv">i</span><span class="p">##TITLE=</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">         <span class="k">elif</span> <span class="o">[[</span> <span class="si">${</span><span class="nv">i</span><span class="si">}</span> <span class="o">==</span> <span class="nv">TIME</span><span class="o">=</span>* <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">             <span class="nv">TIME</span><span class="o">=</span><span class="si">${</span><span class="nv">i</span><span class="p">##TIME=</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">         <span class="k">elif</span> <span class="o">[[</span> <span class="si">${</span><span class="nv">i</span><span class="si">}</span> <span class="o">==</span> END <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">             <span class="nb">echo</span> <span class="s2">&#34;* </span><span class="si">${</span><span class="nv">TITLE</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="nb">echo</span> <span class="s2">&#34;&lt;</span><span class="si">${</span><span class="nv">DATE</span><span class="si">}</span><span class="s2"> </span><span class="si">${</span><span class="nv">TIME</span><span class="si">}</span><span class="s2">&gt;&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="nb">echo</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">DESCRIPTION</span><span class="k">:-</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">             <span class="nv">TITLE</span><span class="o">=</span><span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="nv">TIME</span><span class="o">=</span><span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&#34;&#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="k">if</span> <span class="o">[[</span> <span class="si">${</span><span class="nv">DESCRIPTION</span><span class="si">}</span> <span class="o">==</span> <span class="s2">&#34;&#34;</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">                 <span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$i</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="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">DESCRIPTION</span><span class="si">}</span><span class="s2">\n</span><span class="nv">$i</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="k">fi</span>
</span></span><span class="line"><span class="cl">         <span class="k">fi</span>
</span></span><span class="line"><span class="cl">     <span class="k">done</span><span class="o">)</span> &gt; <span class="si">${</span><span class="nv">diary</span><span class="si">}</span></span></span></code></pre></div>

</div>

        </section>
        
        <section class="list-item">
          <h1 class="title"><a href="/posts/2024-03-12-mail-app-random-signatures/">Mail.app random signatures</a></h1>
<time>March 12, 2024</time>
<div class="description">
  <p>When using an emacs based mail client for many years, I collected
various song lyrics that I particularly enjoyed and automatically
added them to my signature on outgoing email. As a result of various
life changes I&rsquo;m consuming a lot less email, and have largely switched
to Mail.app, which can cope fine with the reduced volume.</p>
<p>I missed my signatures, though, and it doesn&rsquo;t seem to be possible to
write a Mail.app plugin to get them back with the officially supported
APIs from Apple (there are some solutions that monkey patch their way
in, but they seem unreliable and regularly break).</p>
<p>Mail.app <em>does</em> support adding random signatures from a list, but
maintaining that list by hand is painful. Instead, here is a small
elisp script that will initialise the available signatures via
Applescript.</p>
<p>It uses the same
<a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/play/cookie1.el">cookie</a>
file format as the source, which was easiest for me, but you could
easily switch to something else.</p>
<p>No warranty, please let me know if you have trouble or enjoy it 😃</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">require</span> <span class="ss">&#39;cookie1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">;;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defvar</span> <span class="nv">maildotapp-signatures</span> <span class="p">(</span><span class="nv">expand-file-name</span> <span class="s">&#34;~/u/lib/fortune&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;A file containing quips to use as part of a signature, in a format
</span></span></span><span class="line"><span class="cl"><span class="s">understood by the `cookie-snarf&#39; function.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">;;</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">maildotapp-signature--delete-existing</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">ns-do-applescript</span> <span class="s">&#34;
</span></span></span><span class="line"><span class="cl"><span class="s">tell application \&#34;Mail\&#34;
</span></span></span><span class="line"><span class="cl"><span class="s">     set sigCount to (count of signatures)
</span></span></span><span class="line"><span class="cl"><span class="s">     repeat sigCount times
</span></span></span><span class="line"><span class="cl"><span class="s">          delete signature 1
</span></span></span><span class="line"><span class="cl"><span class="s">     end repeat
</span></span></span><span class="line"><span class="cl"><span class="s">end tell
</span></span></span><span class="line"><span class="cl"><span class="s">&#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">maildotapp-signature--add-sig</span> <span class="p">(</span><span class="nv">name</span> <span class="nv">content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">ns-do-applescript</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;
</span></span></span><span class="line"><span class="cl"><span class="s">tell application \&#34;Mail\&#34;
</span></span></span><span class="line"><span class="cl"><span class="s">     make new signature at beginning of signatures with properties {name:\&#34;%s\&#34;, content:\&#34;%s\&#34;}
</span></span></span><span class="line"><span class="cl"><span class="s">end tell
</span></span></span><span class="line"><span class="cl"><span class="s">&#34;</span>
</span></span><span class="line"><span class="cl">			     <span class="nv">name</span>
</span></span><span class="line"><span class="cl">			     <span class="nv">content</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">maildotapp-signature--prepare</span> <span class="p">(</span><span class="nv">quip</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Based on a QUIP, prepare a complete signature.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">concat</span> <span class="s">&#34;dme.\n-- \n&#34;</span> <span class="nv">quip</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">maildotapp-signature--quote</span> <span class="p">(</span><span class="nc">string</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Ensure that STRING is safely quoted.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; XXX dme: This is something, but it is enough?</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">replace-regexp-in-string</span> <span class="s">&#34;\&#34;&#34;</span> <span class="s">&#34;\\\\\&#34;&#34;</span> <span class="nc">string</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">;;</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">maildotapp-signature-go!</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Replace all of the signatures in Mail.app with those from
</span></span></span><span class="line"><span class="cl"><span class="s">`maildotapp-signatures&#39;.
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">After running this function, go to Mail.app and set the &#39;Choose
</span></span></span><span class="line"><span class="cl"><span class="s">Signature:&#39; option of relevant accounts to &#39;At Random&#39;.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">maildotapp-signature--delete-existing</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">signatures</span> <span class="p">(</span><span class="nv">cookie-snarf</span> <span class="nv">maildotapp-signatures</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">mapcar</span> <span class="p">(</span><span class="nb">lambda</span> <span class="p">(</span><span class="nv">content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	      <span class="p">(</span><span class="nv">maildotapp-signature--add-sig</span> <span class="p">(</span><span class="nv">maildotapp-signature--quote</span> <span class="p">(</span><span class="nv">substring</span> <span class="nv">content</span> <span class="mi">0</span> <span class="p">(</span><span class="nf">min</span> <span class="mi">30</span> <span class="p">(</span><span class="nf">length</span> <span class="nv">content</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">					     <span class="p">(</span><span class="nv">maildotapp-signature--prepare</span> <span class="p">(</span><span class="nv">maildotapp-signature--quote</span> <span class="nv">content</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">	    <span class="nv">signatures</span><span class="p">)))</span></span></span></code></pre></div>

</div>

        </section>
        
        <section class="list-item">
          <h1 class="title"><a href="/posts/2024-02-02-small-http-post-server/">A small HTTP POST server</a></h1>
<time>February 2, 2024</time>
<div class="description">
  <p>A couple of weeks ago Neil mentioned on Mastodon being interested in a privacy focused GPS logger for use in a car, which was odd, as I was thinking about the exact same thing a few days before. <a href="https://toot.me.uk/@revk">RevK</a> jumped in to provide something, which Neil <a href="https://neilzone.co.uk/2024/01/revks-privacy-friendly-gps-logger/">wrote about</a> a short while later. I was lucky enough to be able to buy one of the first versions (<a href="https://www.aa.net.uk/etc/circuit-boards/gps/">everyone can get one now</a>), but was a bit stuck for time to play with it initially, which I&rsquo;ve been able to remedy over the last couple of days.</p>
<p>It&rsquo;s a fabulous device, with lots of lovely touches - loads of LEDs used to show which GPS satellites are in use, upload progress, OTA upgrade progress, etc. Really great stuff.</p>
<p>One of the nice features of the firmware is that it will upload traces to an HTTP server of your choice with a <a href="https://en.wikipedia.org/wiki/POST_(HTTP)">POST</a> request. While most HTTP servers support this, it can be a bit of a faff getting things all plumbed together when you just want to test something. To that end, here is a small HTTP POST server in Python that can be used for testing:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="ch">#!/usr/bin/env python3</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">http.server</span> <span class="kn">import</span> <span class="n">BaseHTTPRequestHandler</span><span class="p">,</span> <span class="n">HTTPServer</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">handler</span><span class="p">(</span><span class="n">BaseHTTPRequestHandler</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">do_POST</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">content_length</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s1">&#39;Content-Length&#39;</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">        <span class="n">body</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rfile</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">content_length</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">send_response</span><span class="p">(</span><span class="mi">200</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">end_headers</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">file</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">[</span><span class="mi">2</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">file</span><span class="p">,</span> <span class="s1">&#39;wb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">out</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">out</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">body</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Wrote </span><span class="si">{</span><span class="n">content_length</span><span class="si">}</span><span class="s2"> bytes to </span><span class="si">{</span><span class="n">file</span><span class="si">}</span><span class="s2">.&#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">with</span> <span class="n">HTTPServer</span><span class="p">((</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="mi">8000</span><span class="p">),</span> <span class="n">handler</span><span class="p">)</span> <span class="k">as</span> <span class="n">server</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span></span></span></code></pre></div>
<p>This listens on port 8000 on the local machine without SSL. Configure your logger to point at it, and it should upload the relevant files (GPX in my case), which are then stored in the current directory:</p>
<pre tabindex="0"><code>172.16.100.162 - - [02/Feb/2024 10:24:38] &#34;POST /?logger1-2024-02-01T21-46-06Z.gpx HTTP/1.1&#34; 200 -
Wrote 131661 bytes to logger1-2024-02-01T21-46-06Z.gpx.
172.16.100.162 - - [02/Feb/2024 10:24:52] &#34;POST /?logger1-2024-02-01T22-00-01Z.gpx HTTP/1.1&#34; 200 -
Wrote 30774 bytes to logger1-2024-02-01T22-00-01Z.gpx.
</code></pre><p>This is not likely to be something that you&rsquo;d use long term, but it&rsquo;s convenient for testing.</p>
<p>Next up is to have the server provide access to the uploaded GPX traces using <a href="https://leafletjs.com/">Leaflet maps</a> for visualisation, but that&rsquo;s for next week.</p>

</div>

        </section>
        
        <section class="list-item">
          <h1 class="title"><a href="/posts/2024-01-25-evolution-and-org-mode/">Evolution calendars in Org Mode&#39;s agenda</a></h1>
<time>January 25, 2024</time>
<div class="description">
  <p>On a Linux GNOME desktop it&rsquo;s convenient to use Evolution as a calendar sync tool (for <a href="https://www.fastmail.com">Fastmail</a> in my case). Once a configuration has been created, you can stash away the <code>&lt;mumble&gt;.source</code> files, drop them in place on another machine and (subject to re-entering your password), everything just works.</p>
<p>Such calendars are also available through GNOME Calendar, which is a little easier on the eye for casual glances.</p>
<p>Spending a lot of time in emacs, and enjoying org-mode more all of the time, I&rsquo;d really like all of my calendar events shown in the org agenda. Achieving that consists of two parts:</p>
<ol>
<li>getting the events out of the Evolution calendar into a more pliable format,</li>
<li>adding the events to an org file so that they are shown in the agenda.</li>
</ol>
<p>To simplify the implementation, I use <a href="https://github.com/pimutils/khal">khal</a> as a parser for vCalendar files. It&rsquo;s definitely the case that you could use <code>vdirsyncer</code> and avoid Evolution, but given that the GUI is sometimes convenient, this way requires configuring only a single sync tool.</p>
<p>Getting events out of Evolution is achieved by grovelling in the sqlite database that Evolution uses as a cache:</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">#!/usr/bin/env zsh
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> -e
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">calendir</span><span class="o">=</span><span class="si">${</span><span class="nv">HOME</span><span class="si">}</span>/v/calendar
</span></span><span class="line"><span class="cl"><span class="nv">dblist</span><span class="o">=(</span>
</span></span><span class="line"><span class="cl">    9ccf564d3aac1c2a02a29be8d44720ec7ea0d5a3
</span></span><span class="line"><span class="cl">    62870b2ad9e6a1e04b800fea354ae44e6b20f754
</span></span><span class="line"><span class="cl">    ca1c1bad361ca6e59b57d86f9e06c3fd5ffd4ccc
</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">convert_one_calendar <span class="o">()</span>
</span></span><span class="line"><span class="cl"><span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Evolution sqlite db:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">local</span> <span class="nv">db</span><span class="o">=</span><span class="nv">$1</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Khal directory to populate:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">local</span> <span class="nv">dst</span><span class="o">=</span><span class="nv">$2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="o">[[</span> -d <span class="si">${</span><span class="nv">dst</span><span class="si">}</span> <span class="o">]]</span> <span class="o">||</span> mkdir -p <span class="si">${</span><span class="nv">dst</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nb">cd</span> <span class="si">${</span><span class="nv">dst</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    sqlite3 <span class="si">${</span><span class="nv">db</span><span class="si">}</span> <span class="s2">&#34;select ECacheOBJ from ECacheObjects&#34;</span> <span class="p">|</span><span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	csplit <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	    --quiet <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	    --elide-empty-files <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	    --suffix-format <span class="s2">&#34;%03d.ics&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	    - <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	    <span class="s1">&#39;/BEGIN:VEVENT/&#39;</span> <span class="s1">&#39;{*}&#39;</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"># Convert each of the Evolution cache databases to a Khal compatible</span>
</span></span><span class="line"><span class="cl"><span class="c1"># directory of .ics files:</span>
</span></span><span class="line"><span class="cl"><span class="c1">#</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> db in <span class="si">${</span><span class="nv">dblist</span><span class="si">}</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    rm -r <span class="si">${</span><span class="nv">calendir</span><span class="si">}</span>/<span class="si">${</span><span class="nv">db</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    convert_one_calendar <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	<span class="si">${</span><span class="nv">HOME</span><span class="si">}</span>/.cache/evolution/calendar/<span class="si">${</span><span class="nv">db</span><span class="si">}</span>/cache.db <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	<span class="si">${</span><span class="nv">calendir</span><span class="si">}</span>/<span class="si">${</span><span class="nv">db</span><span class="si">}</span>
</span></span><span class="line"><span class="cl"><span class="k">done</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Write a khal config to match:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">config_dir</span><span class="o">=</span><span class="si">${</span><span class="nv">HOME</span><span class="si">}</span>/.config/khal
</span></span><span class="line"><span class="cl"><span class="nv">config_file</span><span class="o">=</span><span class="si">${</span><span class="nv">config_dir</span><span class="si">}</span>/config
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[[</span> -d <span class="si">${</span><span class="nv">config_dir</span><span class="si">}</span> <span class="o">]]</span> <span class="o">||</span> mkdir <span class="si">${</span><span class="nv">config_dir</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">cat &gt; <span class="si">${</span><span class="nv">config_file</span><span class="si">}</span> <span class="s">&lt;&lt;EOF
</span></span></span><span class="line"><span class="cl"><span class="s">[calendars]
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> db in <span class="si">${</span><span class="nv">dblist</span><span class="si">}</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    cat &gt;&gt; <span class="si">${</span><span class="nv">config_file</span><span class="si">}</span> <span class="s">&lt;&lt;EOF
</span></span></span><span class="line"><span class="cl"><span class="s">[[${db}]]
</span></span></span><span class="line"><span class="cl"><span class="s">path = ${calendir}/${db}
</span></span></span><span class="line"><span class="cl"><span class="s">type = calendar
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl"><span class="k">done</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">cat &gt;&gt; <span class="si">${</span><span class="nv">config_file</span><span class="si">}</span> <span class="s">&lt;&lt;EOF
</span></span></span><span class="line"><span class="cl"><span class="s">[locale]
</span></span></span><span class="line"><span class="cl"><span class="s">timeformat = %H:%M
</span></span></span><span class="line"><span class="cl"><span class="s">dateformat = %Y-%m-%d
</span></span></span><span class="line"><span class="cl"><span class="s">longdateformat = %Y-%m-%d
</span></span></span><span class="line"><span class="cl"><span class="s">datetimeformat = %Y-%m-%d %H:%M
</span></span></span><span class="line"><span class="cl"><span class="s">longdatetimeformat = %Y-%m-%d %H:%M
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span></span></span></code></pre></div>
<p>In the script, update the <code>dblist</code> variable to include the list of Evolution calendars that you want to convert - you can see their names in <code>~/.cache/evolution/calendar</code>. The outputs of the script end up in <code>~/v/calendar</code>, or update the <code>calendir</code> variable to suit your preferences.</p>
<blockquote>
<p>Note that the script will <strong>overwrite</strong> your current khal configuration file.</p>
</blockquote>
<p>Now we have a pile of <code>.ics</code> files and a khal configuration configured to parse them. Using that in the org agenda requires another conversion:</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">#!/usr/bin/env zsh
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="nv">diary</span><span class="o">=</span><span class="si">${</span><span class="nv">HOME</span><span class="si">}</span>/.emacs.d/diary.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">start</span><span class="o">=</span><span class="k">$(</span>date --date<span class="o">=</span><span class="s1">&#39;-30days&#39;</span> <span class="s1">&#39;+%Y-%m-%d&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">end</span><span class="o">=</span><span class="k">$(</span>date --date<span class="o">=</span><span class="s1">&#39;+30days&#39;</span> <span class="s1">&#39;+%Y-%m-%d&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">khal list <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>     --day-format <span class="s2">&#34;&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>     --format <span class="s2">&#34;* {title}{repeat-symbol}{alarm-symbol}
</span></span></span><span class="line"><span class="cl"><span class="s2">&lt;{start-date} {start-end-time-style}&gt;
</span></span></span><span class="line"><span class="cl"><span class="s2">{description}&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>     <span class="si">${</span><span class="nv">start</span><span class="si">}</span> <span class="si">${</span><span class="nv">end</span><span class="si">}</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>     &gt; <span class="si">${</span><span class="nv">diary</span><span class="si">}</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>     2&gt; /dev/null</span></span></code></pre></div>
<p>This one is less thorough - it only includes events for the previous 30 and next 30 days. You could tweak this, of course, but I find it sufficient for awareness in the org agenda.</p>
<p>The script generates <code>~/.emacs.d/diary.org</code>, which you should ensure to include in <code>org-agenda-files</code> so that the events contained therein are displayed.</p>
<p>That&rsquo;s it! I run the pair of scripts in sequence every hour, but you can decide what to do about that.</p>
<blockquote>
<p>Originally I was generating an emacs diary file, and that works out okay. It means that <code>org-timeblock</code> is unaware of the entries, though, which can sometimes be an inconvenience.</p>
</blockquote>

</div>

        </section>
        
        <section class="list-item">
          <h1 class="title"><a href="/posts/2024-01-20-new-tablet/">Looking for a new non-iPad tablet</a></h1>
<time>January 20, 2024</time>
<div class="description">
  <p>Dear Lazyweb,</p>
<p>I&rsquo;m looking for recommendations for a non-iPad tablet, which I imagine means Android. The requirements are not very specific - at least
200dpi, around 10&quot;, under £300 (would like under £200). Ideally I would be able to run upstream Android, but I realise that this is unlikely
to be possible without buying a Google Pixel tablet.</p>
<p>The Amazon Fire HD tablets would probably be fine in most respects, except that I don&rsquo;t believe that it&rsquo;s possible to get rid of the Amazon
advertising skin any more (I grabbed a refurb Fire HD 10 to try, and the approach using adb to delete packages now fails), and I find it
quite annoying.</p>
<p>Something like the HONOR Pad X9 or Lenovo Tab P11 look better, but I don&rsquo;t see any non-fluff reviews.</p>
<p>Use is ePub (non-Amazon) reading, web browsing, a little light Home Assistant, occasionally video when travelling. No games.</p>
<p>Any suggestions?</p>

</div>

        </section>
        
        <section class="list-item">
          <h1 class="title"><a href="/posts/2023-02-01-160224/">Gatwick North Terminal</a></h1>
<time>February 1, 2023</time>
<div class="description">
  <img src="/images/gatwick.png" alt="" width="100%">

</div>

        </section>
        
        <section class="list-item">
          <h1 class="title"><a href="/posts/2023-01-12-152645/">Four Tet @TheLotRadio 2022-12-01</a></h1>
<time>January 12, 2023</time>
<div class="description">
  <p><a href="https://www.youtube.com/watch?v=kjuPalIWNaM&amp;t=1620s">Four Tet @TheLotRadio 2022-12-01</a></p>
<p>Enjoyed this a lot.</p>

</div>

        </section>
        
        <section class="list-item">
          <h1 class="title"><a href="/posts/2023-01-12-tubeless-is-great/">Tubeless is great</a></h1>
<time>January 12, 2023</time>
<div class="description">
  <img src="/images/IMG_1568.jpeg" alt="Tubeless is great" width="100%">
Tubeless is great

</div>

        </section>
        

        
    <ul class="pagination pagination-default">
      <li class="page-item disabled">
        <a aria-disabled="true" aria-label="First" class="page-link" role="button" tabindex="-1"><span aria-hidden="true">&laquo;&laquo;</span></a>
      </li>
      <li class="page-item disabled">
        <a aria-disabled="true" aria-label="Previous" class="page-link" role="button" tabindex="-1"><span aria-hidden="true">&laquo;</span></a>
      </li>
      <li class="page-item active">
        <a aria-current="page" aria-label="Page 1" class="page-link" role="button">1</a>
      </li>
      <li class="page-item">
        <a href="/page/2/" aria-label="Page 2" class="page-link" role="button">2</a>
      </li>
      <li class="page-item">
        <a href="/page/3/" aria-label="Page 3" class="page-link" role="button">3</a>
      </li>
      <li class="page-item">
        <a href="/page/4/" aria-label="Page 4" class="page-link" role="button">4</a>
      </li>
      <li class="page-item">
        <a href="/page/5/" aria-label="Page 5" class="page-link" role="button">5</a>
      </li>
      <li class="page-item">
        <a href="/page/2/" aria-label="Next" class="page-link" role="button"><span aria-hidden="true">&raquo;</span></a>
      </li>
      <li class="page-item">
        <a href="/page/83/" aria-label="Last" class="page-link" role="button"><span aria-hidden="true">&raquo;&raquo;</span></a>
      </li>
    </ul>
      </main>

      <footer>
  <nav>
    Made with <a href="https://gohugo.io">Hugo</a> by <a href="/now">dme</a> on November 13, 2025.
  </nav>
</footer>

    </div>
  </body>
</html>
