<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Protesilaos: Coding blog</title>
    <description>Coding blog</description>
    <link>https://protesilaos.com/codelog</link>
    <atom:link href="https://protesilaos.com/codelog.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 25 Jun 2026 11:12:42 +0000</pubDate>
    
    
    <item>
      <title>Emacs: modus-themes version 5.3.0</title>
      <description>Information about the latest version of my highly accessible themes for GNU Emacs.</description>
      <pubDate>Sun, 21 Jun 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-06-21-emacs-modus-themes-5-3-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-06-21-emacs-modus-themes-5-3-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just published the latest stable release of <a href="https://protesilaos.com/emacs/modus-themes">the Modus
themes</a>. The change log
entry is reproduced further below. For any questions, you are welcome
to <a href="https://protesilaos.com/contact/">contact me</a>. I will now work to
apply these same changes to emacs.git, so please wait a little longer
for the updates to trickle down to you.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">modus-themes</code> (also built into Emacs 28+)</li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/modus-themes-changelog">https://protesilaos.com/emacs/modus-themes-changelog</a></li>
  <li>Colour palette: <a href="https://protesilaos.com/emacs/modus-themes-colors">https://protesilaos.com/emacs/modus-themes-colors</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/modus-themes-pictures">https://protesilaos.com/emacs/modus-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/modus-themes">https://github.com/protesilaos/modus-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/modus-themes">https://gitlab.com/protesilaos/modus-themes</a></li>
    </ul>
  </li>
  <li>Backronym: My Old Display Unexpectedly Sharpened … themes.</li>
</ul>

<hr />

<h2>5.3.0 on 2026-06-21</h2>

<p>The Modus themes are in a stable state. To my mind, they provide the
best “default theme” experience across the 40+ original themes I have
carefully designed.</p>

<p>Modus is also a platform for making themes for Emacs. There are plenty
of derivatives already. I am linking to them through the project’s
README.md and am always happy to mention more packages—just let me
know.</p>

<p>This version does not include many user-facing changes. Most of my
work focused on making internal refinements.</p>

<h3>Load the themes through the <code class="language-plaintext highlighter-rouge">early-init.el</code></h3>

<p>The Modus themes can now be loaded through the <code class="language-plaintext highlighter-rouge">early-init.el</code> file.
The idea is to avoid the flash of light that occurs under certain
conditions during startup.</p>

<p>This feature is the result of several changes to helper functions,
especially those contributing to the <code class="language-plaintext highlighter-rouge">modus-themes-generate-palette</code>
function that Modus derivatives may be relying on.</p>

<p>Thanks to Steven Allen for an intermediate refinement in pull request
194 and to Mike Olson for another relevant tweak in pull request 199:</p>

<ul>
  <li><a href="https://github.com/protesilaos/modus-themes/pull/194">https://github.com/protesilaos/modus-themes/pull/194</a></li>
  <li><a href="https://github.com/protesilaos/modus-themes/pull/199">https://github.com/protesilaos/modus-themes/pull/199</a></li>
</ul>

<p>Steven’s contribution no longer exists in the code base due to other
changes I made, but was still useful at the time.</p>

<p>Both changes are small, meaning that their authors do not need to
assign copyright to the Free Software Foundation.</p>

<p>Also thanks to Jacod “Jake” Gordon for reminding me to apply one of
the new functions to the <code class="language-plaintext highlighter-rouge">org-habit</code> faces. This was done in issue
197: <a href="https://github.com/protesilaos/modus-themes/issues/197">https://github.com/protesilaos/modus-themes/issues/197</a>.</p>

<h3>The underline for widget fields has the correct colour</h3>

<p>Relevant faces use the palette entry for <code class="language-plaintext highlighter-rouge">border</code> (invoke the command
<code class="language-plaintext highlighter-rouge">modus-themes-preview-colors</code> or <code class="language-plaintext highlighter-rouge">modus-themes-preview-colors-current</code>
to view the entries in a theme’s palette).</p>

<p>A popular package that makes use of <code class="language-plaintext highlighter-rouge">widget.el</code> widgets is <code class="language-plaintext highlighter-rouge">notmuch</code>.</p>

<p>Thanks to ukiran03 for the contribution, which was done in pull
request 193: <a href="https://github.com/protesilaos/modus-themes/pull/193">https://github.com/protesilaos/modus-themes/pull/193</a>.
The change is small, meaning that ukiran03 does not need to assign
copyright to the Free Software Foundation.</p>

<h3>A palette can now have a <code class="language-plaintext highlighter-rouge">bg-popup</code> entry</h3>

<p>This gives users and derivative themes the option to pick a suitable
value for popup interfaces, such as those of the <code class="language-plaintext highlighter-rouge">company</code> and <code class="language-plaintext highlighter-rouge">corfu</code>
packages.</p>

<p>Thanks to aikrahguzar for making this suggestion in issue 70 of my
<code class="language-plaintext highlighter-rouge">ef-themes</code> repository (the <code class="language-plaintext highlighter-rouge">ef-themes</code> are built on top of the
<code class="language-plaintext highlighter-rouge">modus-themes</code> since Modus version <code class="language-plaintext highlighter-rouge">5.0.0</code>, Ef version <code class="language-plaintext highlighter-rouge">2.0.0</code>):
<a href="https://github.com/protesilaos/ef-themes/issues/70">https://github.com/protesilaos/ef-themes/issues/70</a>.</p>

<h3>Support for faces or packages</h3>

<ul>
  <li><code class="language-plaintext highlighter-rouge">lin</code> by Protesilaos.</li>
  <li><code class="language-plaintext highlighter-rouge">pulsar</code> by Protesilaos.</li>
  <li><code class="language-plaintext highlighter-rouge">institution-calendar</code> by Protesilaos.</li>
  <li><code class="language-plaintext highlighter-rouge">markdown-ts-mode</code> by Rahul Martim Juliato and Stéphane Marks.</li>
  <li><code class="language-plaintext highlighter-rouge">trust-manager</code> by Eshel Yaron.</li>
  <li><code class="language-plaintext highlighter-rouge">typst-ts-mode</code> by Ziqi Yang. Thanks to Pranshu Sharma for
suggesting its inclusion in issue 208: <a href="https://github.com/protesilaos/modus-themes/issues/208">https://github.com/protesilaos/modus-themes/issues/208</a>.</li>
  <li>new <code class="language-plaintext highlighter-rouge">elfeed</code> faces since the maintenance of the project was assumed
by Daniel Mendler, Karthik Chikmagalur, and Ihor Radchenko. To this
end, thanks to Steven Allen for pull request 217 that added the
<code class="language-plaintext highlighter-rouge">elfeed-show-*</code> faces: <a href="https://github.com/protesilaos/modus-themes/pull/217">https://github.com/protesilaos/modus-themes/pull/217</a></li>
</ul>

<h3>Internal refinements to the <code class="language-plaintext highlighter-rouge">modus-themes-with-colors</code> macro</h3>

<p>It now correctly handles the order of default palette colours and
user-defined palette overrides. Thanks to JD Smith for the
contribution in pull request 191: <a href="https://github.com/protesilaos/modus-themes/pull/191">https://github.com/protesilaos/modus-themes/pull/191</a>.</p>

<p>The change is small, meaning that JD does not need to assign copyright
to the Free Software Foundation.</p>

<h3>The <code class="language-plaintext highlighter-rouge">multiple-cursors</code> are fine even when a bar is used</h3>

<p>When the <code class="language-plaintext highlighter-rouge">cursor-type</code> is configured to be a <code class="language-plaintext highlighter-rouge">bar</code>, the fake cursors
produced by the <code class="language-plaintext highlighter-rouge">multiple-cursors</code> package will still look right.
Thanks to Elias Gabriel Perez for the change to the
<code class="language-plaintext highlighter-rouge">mc/cursor-bar-face</code> in pull request 213: <a href="https://github.com/protesilaos/modus-themes/pull/213">https://github.com/protesilaos/modus-themes/pull/213</a>.</p>

<h3>The <code class="language-plaintext highlighter-rouge">blink-matching-paren-offscreen</code> is the same as <code class="language-plaintext highlighter-rouge">show-paren-match</code></h3>

<p>This is for thematic consistency. Thanks to Troy Brown for suggesting
this change in issue 209: <a href="https://github.com/protesilaos/modus-themes/issues/209">https://github.com/protesilaos/modus-themes/issues/209</a>.</p>

<h3>Get <code class="language-plaintext highlighter-rouge">vc-annotate</code> look right</h3>

<p>The built-in <code class="language-plaintext highlighter-rouge">vc-annotate</code> command relies on a user option to read
color values. We cannot handle this nicely at the theme level. Users
need to write their own configuration like this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-modus-vc-annotate</span> <span class="p">(</span><span class="k">&amp;rest</span> <span class="nv">_</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">modus-themes-with-colors</span>
    <span class="p">(</span><span class="k">setq</span> <span class="nv">vc-annotate-background-mode</span> <span class="no">nil</span><span class="p">)</span>
    <span class="p">(</span><span class="k">setq</span> <span class="nv">vc-annotate-very-old-color</span> <span class="nv">fg-dim</span><span class="p">)</span>
    <span class="p">(</span><span class="k">setq</span> <span class="nv">vc-annotate-color-map</span>
          <span class="o">`</span><span class="p">((</span> <span class="mi">20.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">red</span><span class="p">)</span>
            <span class="p">(</span> <span class="mi">40.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">red-cooler</span><span class="p">)</span>
            <span class="p">(</span> <span class="mi">60.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">red-warmer</span><span class="p">)</span>
            <span class="p">(</span> <span class="mi">80.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">yellow-warmer</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">100.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">yellow</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">120.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">yellow-cooler</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">140.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">green-warmer</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">160.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">green</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">180.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">green-cooler</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">200.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">cyan-cooler</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">220.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">cyan-warmer</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">240.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">cyan</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">260.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">blue-warmer</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">280.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">blue</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">300.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">blue-cooler</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">320.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">blue-intense</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">340.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">magenta-cooler</span><span class="p">)</span>
            <span class="p">(</span><span class="mi">360.</span> <span class="o">.</span> <span class="o">,</span><span class="nv">fg-dim</span><span class="p">)))))</span>

<span class="p">(</span><span class="nv">with-eval-after-load</span> <span class="ss">'vc-annotate</span>
  <span class="p">(</span><span class="nv">my-modus-vc-annotate</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'enable-theme-functions</span> <span class="nf">#'</span><span class="nv">my-modus-vc-annotate</span><span class="p">))</span>
</code></pre></div></div>

<p>[ The above code is relevant as of this writing. Though remember that
  I do not keep older publications up-to-date. The only source of
  truth is the manual of the Modus themes. ]</p>

<h3>Two old user options are no longer needed</h3>

<p>The user options <code class="language-plaintext highlighter-rouge">modus-themes-completions</code> and <code class="language-plaintext highlighter-rouge">modus-themes-prompts</code>
are obsolete. They used to be relevant before the introduction of
palette overrides.</p>

<h3>Rewrote large parts of the manual</h3>

<p>I did it for clarity, but also to remove notes that were specific to
older versions of Emacs.</p>

<h3>Many new ERT tests for the project</h3>

<p>I have written many tests. They do not cover every single function,
though the plan is to do that eventually. These tests are important to
ensure that Modus is a solid platform for making derivative themes.</p>

<p>Much of this was done live: <a href="https://protesilaos.com/codelog/2026-04-10-emacs-spontaneous-live-modus-themes/">https://protesilaos.com/codelog/2026-04-10-emacs-spontaneous-live-modus-themes/</a>.</p>

<p>Thanks to Benjamin Kästner for a couple of tweaks to a relevant macro
in the tests’ file. This was done in pull request 212, with further
changes by me: <a href="https://github.com/protesilaos/modus-themes/pull/212">https://github.com/protesilaos/modus-themes/pull/212</a>.</p>

<h3>Links to projects related to Modus</h3>

<p>In the README.md I now mention projects that are related to the Modus
themes, such as derivative Emacs themes, but also ports for other
editors.</p>

<p>There is also a link to my <code class="language-plaintext highlighter-rouge">modus-themes-exporter</code> package, which I
developed during a live stream:</p>

<ul>
  <li><a href="https://github.com/protesilaos/modus-themes-exporter">https://github.com/protesilaos/modus-themes-exporter</a></li>
  <li><a href="https://protesilaos.com/codelog/2026-04-13-emacs-live-develop-modus-themes-exporter-package/">https://protesilaos.com/codelog/2026-04-13-emacs-live-develop-modus-themes-exporter-package/</a></li>
</ul>

<h3>Git commits</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git shortlog 5.2.0..5.3.0 --summary --numbered
    123	Protesilaos
     2	Benjamin Kästner
     2	Steven Allen
     1	Elias Gabriel Perez
     1	JD Smith
     1	Mike Olson
     1	ukiran03
</code></pre></div></div>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: ef-themes version 2.2.0</title>
      <description>Information about the latest version of my colourful-yet-legible themes for GNU Emacs.</description>
      <pubDate>Sun, 21 Jun 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-06-21-emacs-ef-themes-2-2-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-06-21-emacs-ef-themes-2-2-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <code class="language-plaintext highlighter-rouge">ef-themes</code> are a collection of light and dark themes for GNU
Emacs that provide colourful (“pretty”) yet legible options for users
who want something with a bit more flair than the <code class="language-plaintext highlighter-rouge">modus-themes</code> (also
designed by me).</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">ef-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/ef-themes">https://protesilaos.com/emacs/ef-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/ef-themes-changelog">https://protesilaos.com/emacs/ef-themes-changelog</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/ef-themes">https://github.com/protesilaos/ef-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/ef-themes">https://gitlab.com/protesilaos/ef-themes</a></li>
    </ul>
  </li>
  <li>Backronym: Eclectic Fashion in Themes Hides Exaggerated Markings,
Embellishments, and Sparkles.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 2.2.0 on 2026-06-21</h2>

<p>This version contains two new themes and several stylistic refinements
to existing items in the collection.</p>

<h3>Enjoy <code class="language-plaintext highlighter-rouge">ef-arcadia</code> and <code class="language-plaintext highlighter-rouge">ef-atlantis</code> themes</h3>

<p><code class="language-plaintext highlighter-rouge">ef-arcadia</code> is a light theme with a green, humid feel. <code class="language-plaintext highlighter-rouge">ef-atlantis</code>
is a dark theme with aquatic colours.</p>

<h3>Improved style for <code class="language-plaintext highlighter-rouge">company</code> and <code class="language-plaintext highlighter-rouge">corfu</code> popups</h3>

<p>I have revised the colour that each theme applies to the popup
background. It should now be more consistent with all other elements
on display.</p>

<p>Thanks to aikrahguzar for suggesting a review in issue 70:
<a href="https://github.com/protesilaos/ef-themes/issues/70">https://github.com/protesilaos/ef-themes/issues/70</a>.</p>

<h3>The current line highlight for completions is easier to spot</h3>

<p>This is the background of the selected candidate in the minibuffer
while using the <code class="language-plaintext highlighter-rouge">vertico</code> package (among other similar interfaces).
The colours I am now using are more consistent with their context and
also work better as part of a popup completion interface, as noted
above.</p>

<h3>Palette refinements for several themes</h3>

<p>I have made subtle changes to a few colour values. These are fine
details. The overarching goal is to be consistent throughout.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: testing common colour values with the doric-themes</title>
      <description>Code I use to get a preview of common colours that I need to configure for my Doric themes.</description>
      <pubDate>Wed, 17 Jun 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-06-17-emacs-testing-doric-themes-common-colour-values/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-06-17-emacs-testing-doric-themes-common-colour-values/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <code class="language-plaintext highlighter-rouge">doric-themes</code> are the minimalist counterpart of my <code class="language-plaintext highlighter-rouge">modus-themes</code>
and <code class="language-plaintext highlighter-rouge">ef-themes</code>. They define few colours and exercise restraint in how
they customise faces. This means that there rarely is a context that
has red, green, yellow, blue, magenta, and cyan. Those are reserved
for cases where colour-coding is needed. Whereas with my other themes
colour is used with the dual intent of establish rhythm and order in
addition to any colour-coding.</p>

<p>Because of this, it is difficult for me to test the relevant values.
Each Doric theme defines entries in its palette like <code class="language-plaintext highlighter-rouge">fg-red</code> and
<code class="language-plaintext highlighter-rouge">bg-blue</code>. So I decided to write a small snippet that shows text which
uses those colours in context.</p>

<p>The idea is to create faces that get the appropriate <code class="language-plaintext highlighter-rouge">:foreground</code> and
<code class="language-plaintext highlighter-rouge">:background</code> attributes with their proper values. Then write text in
a buffer that displays each face.</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">defconst</span> <span class="nv">test-doric-accents</span>
  <span class="o">'</span><span class="p">(</span> <span class="nv">fg-red</span> <span class="nv">fg-green</span> <span class="nv">fg-yellow</span> <span class="nv">fg-blue</span> <span class="nv">fg-magenta</span> <span class="nv">fg-cyan</span>
     <span class="nv">bg-red</span> <span class="nv">bg-green</span> <span class="nv">bg-yellow</span> <span class="nv">bg-blue</span> <span class="nv">bg-magenta</span> <span class="nv">bg-cyan</span><span class="p">))</span>

<span class="p">(</span><span class="nb">dolist</span> <span class="p">(</span><span class="nv">accent</span> <span class="nv">test-doric-accents</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">custom-declare-face</span>
   <span class="p">(</span><span class="nb">intern</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"test-doric-%s"</span> <span class="nv">accent</span><span class="p">))</span>
   <span class="no">nil</span>
   <span class="s">"Test."</span>
   <span class="ss">:group</span> <span class="ss">'doric-themes</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">test-doric-set-accent-faces</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">doric-themes-with-colors</span>
    <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">predicate</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nc">symbol</span><span class="p">)</span> <span class="p">(</span><span class="nv">string-prefix-p</span> <span class="s">"bg"</span> <span class="p">(</span><span class="nb">symbol-name</span> <span class="nc">symbol</span><span class="p">))))</span>
           <span class="p">(</span><span class="nv">foregrounds</span> <span class="p">(</span><span class="nv">seq-remove</span> <span class="nv">predicate</span> <span class="nv">test-doric-accents</span><span class="p">))</span>
           <span class="p">(</span><span class="nv">backgrounds</span> <span class="p">(</span><span class="nv">seq-filter</span> <span class="nv">predicate</span> <span class="nv">test-doric-accents</span><span class="p">))</span>
           <span class="p">(</span><span class="nv">foreground-faces</span> <span class="p">(</span><span class="nb">mapcar</span>
                              <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">accent</span><span class="p">)</span>
                                <span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="p">(</span><span class="nb">intern</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"test-doric-%s"</span> <span class="nv">accent</span><span class="p">))</span>
                                  <span class="p">((</span><span class="no">t</span> <span class="ss">:foreground</span> <span class="o">,</span><span class="p">(</span><span class="nb">symbol-value</span> <span class="nv">accent</span><span class="p">)))))</span>
                              <span class="nv">foregrounds</span><span class="p">))</span>
           <span class="p">(</span><span class="nv">background-faces</span> <span class="p">(</span><span class="nb">mapcar</span>
                              <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">accent</span><span class="p">)</span>
                                <span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="p">(</span><span class="nb">intern</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"test-doric-%s"</span> <span class="nv">accent</span><span class="p">))</span>
                                  <span class="p">((</span><span class="no">t</span> <span class="ss">:background</span> <span class="o">,</span><span class="p">(</span><span class="nb">symbol-value</span> <span class="nv">accent</span><span class="p">)</span> <span class="ss">:foreground</span> <span class="o">,</span><span class="nv">fg-main</span><span class="p">))))</span>
                              <span class="nv">backgrounds</span><span class="p">)))</span>
      <span class="p">(</span><span class="nb">apply</span> <span class="nf">#'</span><span class="nv">custom-set-faces</span> <span class="p">(</span><span class="nb">append</span> <span class="nv">foreground-faces</span> <span class="nv">background-faces</span><span class="p">)))))</span>

<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'doric-themes-after-load-theme-hook</span> <span class="nf">#'</span><span class="nv">test-doric-set-accent-faces</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">test-doric-show-accents</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">buffer</span> <span class="p">(</span><span class="nv">get-buffer-create</span> <span class="s">"*test-doric-themes-accents*"</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">with-current-buffer</span> <span class="nv">buffer</span>
      <span class="p">(</span><span class="nv">erase-buffer</span><span class="p">)</span>
      <span class="p">(</span><span class="nb">dolist</span> <span class="p">(</span><span class="nv">accent</span> <span class="nv">test-doric-accents</span><span class="p">)</span>
        <span class="c1">;; Pangram from my `show-font' package...</span>
        <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">text</span> <span class="s">"Protesilaos may find zesty owls and quiet jays vexing the black cat"</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">styled</span> <span class="p">(</span><span class="nv">propertize</span> <span class="nv">text</span> <span class="ss">'face</span> <span class="p">(</span><span class="nb">intern</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"test-doric-%s"</span> <span class="nv">accent</span><span class="p">)))))</span>
          <span class="p">(</span><span class="nv">insert</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"%s\n"</span> <span class="nv">styled</span><span class="p">)))))</span>
    <span class="p">(</span><span class="nv">display-buffer</span> <span class="nv">buffer</span><span class="p">)))</span>
</code></pre></div></div>

<p>Reload the theme for changes to take effect.</p>

<p>And, yes, I had the motivation to write this because I am developing
new themes.</p>

<h2>Doric themes sources</h2>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: flat Dired listing for REGEXP, optionally up to DAYS since last modification</title>
      <description>Two custom Dired commands I use to have flat listings of files inside of Emacs.</description>
      <pubDate>Sat, 13 Jun 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-06-13-emacs-flat-dired-for-regexp-since-days/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-06-13-emacs-flat-dired-for-regexp-since-days/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>When we call <code class="language-plaintext highlighter-rouge">dired</code> from Lisp, we can pass it a list of files instead
of a directory. This gives us a fully fledged Dired buffer for those
files. My most common use-case is to produce flat listing, so that I
do not have to go searching in exactly which directory some file is
(e.g. in the Downloads folder there is some zip archive that I
downloaded with a bunch of files in a complex structure).</p>

<h2>A flat Dired listing</h2>

<p>For a while now I have been using my own command to create a Dired
buffer from the current directory (which can always be updated on
demand with <code class="language-plaintext highlighter-rouge">M-x cd</code>). It is <code class="language-plaintext highlighter-rouge">prot-dired-search-flat-list</code>. Here is
the code:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defvar</span> <span class="nv">prot-dired-regexp-history</span> <span class="no">nil</span>
  <span class="s">"Minibuffer history of `prot-dired-regexp-prompt'."</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired-regexp-prompt</span> <span class="p">()</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">default</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">prot-dired-regexp-history</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">read-regexp</span>
     <span class="p">(</span><span class="nv">format-prompt</span> <span class="s">"Files matching REGEXP"</span> <span class="nv">default</span><span class="p">)</span>
     <span class="nv">default</span> <span class="ss">'prot-dired-regexp-history</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired--get-files</span> <span class="p">(</span><span class="nv">regexp</span><span class="p">)</span>
  <span class="s">"Return files matching REGEXP, recursively from `default-directory'."</span>
  <span class="p">(</span><span class="nv">directory-files-recursively</span> <span class="nv">default-directory</span> <span class="nv">regexp</span> <span class="no">nil</span><span class="p">))</span>

<span class="c1">;;;###autoload</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired-search-flat-list</span> <span class="p">(</span><span class="nv">regexp</span><span class="p">)</span>
  <span class="s">"Return a Dired buffer for files matching REGEXP.
Perform the search recursively from the current directory."</span>
  <span class="p">(</span><span class="nv">interactive</span> <span class="p">(</span><span class="nb">list</span> <span class="p">(</span><span class="nv">prot-dired-regexp-prompt</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">if-let*</span> <span class="p">((</span><span class="nv">files</span> <span class="p">(</span><span class="nv">prot-dired--get-files</span> <span class="nv">regexp</span><span class="p">))</span>
            <span class="p">(</span><span class="nv">relative-paths</span> <span class="p">(</span><span class="nb">mapcar</span> <span class="nf">#'</span><span class="nv">file-relative-name</span> <span class="nv">files</span><span class="p">)))</span>
      <span class="p">(</span><span class="nv">dired</span> <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"prot-flat-dired for `%s'"</span> <span class="nv">regexp</span><span class="p">)</span> <span class="nv">relative-paths</span><span class="p">))</span>
    <span class="p">(</span><span class="nb">error</span> <span class="s">"No files matching `%s'"</span> <span class="nv">regexp</span><span class="p">)))</span>
</code></pre></div></div>

<p>I could modify <code class="language-plaintext highlighter-rouge">prot-dired-search-flat-list</code> to also prompt for a
directory, though I optimise for the common workflow of operating from
where I am (and I generally do not like overloading the <code class="language-plaintext highlighter-rouge">C-u</code> with
special cases that I will never remember—a new command with a name I
can search for is better).</p>

<h2>Flat listing limited to last modified since DAYS</h2>

<p>Yesterday I had the need to browse a massive directory, but only
wanted to get a couple of files out of it. I realised that I had to
filter my last modified, so I extended my above use-case with the new
command <code class="language-plaintext highlighter-rouge">prot-dired-search-flat-list-since-days</code>. Here is what I came
up with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defvar</span> <span class="nv">prot-dired-days-prompt-history</span> <span class="no">nil</span>
  <span class="s">"Minibuffer history for `prot-dired-days-prompt'."</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired-days-prompt</span> <span class="p">()</span>
  <span class="s">"Prompt for days and return them as a number."</span>
  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nb">first</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">prot-dired-days-prompt-history</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">default</span> <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">stringp</span> <span class="nb">first</span><span class="p">)</span>
                    <span class="p">(</span><span class="nv">string-to-number</span> <span class="nb">first</span><span class="p">))))</span>
    <span class="p">(</span><span class="nv">read-number</span> <span class="s">"Number of days: "</span> <span class="nv">default</span> <span class="ss">'prot-dired-days-prompt-history</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired--get-last-modified</span> <span class="p">(</span><span class="nv">files</span> <span class="nv">days</span><span class="p">)</span>
  <span class="s">"Return list of FILES last modified since DAYS."</span>
  <span class="p">(</span><span class="nv">seq-filter</span>
   <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">file</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">and-let*</span> <span class="p">((</span><span class="nv">attributes</span> <span class="p">(</span><span class="nv">file-attributes</span> <span class="nv">file</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">last-modified</span> <span class="p">(</span><span class="nb">nth</span> <span class="mi">5</span> <span class="nv">attributes</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">last-modified-seconds</span> <span class="p">(</span><span class="nv">time-to-seconds</span> <span class="nv">last-modified</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">current-time</span> <span class="p">(</span><span class="nv">current-time</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">current-time-seconds</span> <span class="p">(</span><span class="nv">time-to-seconds</span> <span class="nv">current-time</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">delta-seconds</span> <span class="p">(</span><span class="nb">*</span> <span class="nv">days</span> <span class="mi">24</span> <span class="mi">60</span> <span class="mi">60</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">oldest-seconds</span> <span class="p">(</span><span class="nb">-</span> <span class="nv">current-time-seconds</span> <span class="nv">delta-seconds</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">_</span> <span class="p">(</span><span class="nb">&gt;=</span> <span class="nv">last-modified-seconds</span> <span class="nv">oldest-seconds</span><span class="p">)))))</span>
   <span class="nv">files</span><span class="p">))</span>

<span class="c1">;;;###autoload</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired-search-flat-list-since-days</span> <span class="p">(</span><span class="nv">regexp</span> <span class="nv">days</span><span class="p">)</span>
  <span class="s">"Return Dired buffer with files matching REGEXP up to DAYS since last modification.
Perform the search recursively from the current directory."</span>
  <span class="p">(</span><span class="nv">interactive</span>
   <span class="p">(</span><span class="nb">list</span>
    <span class="p">(</span><span class="nv">prot-dired-regexp-prompt</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">prot-dired-days-prompt</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">if-let*</span> <span class="p">((</span><span class="nv">files</span> <span class="p">(</span><span class="nv">prot-dired--get-files</span> <span class="nv">regexp</span><span class="p">)))</span>
      <span class="p">(</span><span class="nv">if-let*</span> <span class="p">((</span><span class="nv">files-filtered</span> <span class="p">(</span><span class="nv">prot-dired--get-last-modified</span> <span class="nv">files</span> <span class="nv">days</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">relative-paths</span> <span class="p">(</span><span class="nb">mapcar</span> <span class="nf">#'</span><span class="nv">file-relative-name</span> <span class="nv">files-filtered</span><span class="p">)))</span>
          <span class="p">(</span><span class="nv">dired</span> <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"prot-flat-dired since %d days for `%s'"</span> <span class="nv">days</span> <span class="nv">regexp</span><span class="p">)</span> <span class="nv">relative-paths</span><span class="p">))</span>
        <span class="p">(</span><span class="nb">error</span> <span class="s">"No files last modified within the last %d days"</span> <span class="nv">days</span><span class="p">))</span>
    <span class="p">(</span><span class="nb">error</span> <span class="s">"No files matching `%s'"</span> <span class="nv">regexp</span><span class="p">)))</span>
</code></pre></div></div>

<p>Note that I always design my minibuffer prompts to have their own
history, because then I only get relevant entries when I press <code class="language-plaintext highlighter-rouge">M-p</code>
(<code class="language-plaintext highlighter-rouge">previous-history-element</code>) and <code class="language-plaintext highlighter-rouge">M-n</code> (<code class="language-plaintext highlighter-rouge">next-history-element</code>) at the
prompt (and the built-in <code class="language-plaintext highlighter-rouge">savehist-mode</code> takes care to persist those).</p>

<p>Everything is part of my Emacs configuration: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a>.
I will not be updating this article, so make sure to check for any
further refinements there.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs live with Sacha Chua about ‘Underappreciated Built-ins’ on Thursday 11 June 17:30 Europe/Athens</title>
      <description>We will talk about the Emacs blog carnival topic for June, which is about underappreciated features that are built into Emacs.</description>
      <pubDate>Tue, 09 Jun 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-06-09-emacs-live-sacha-chua-built-ins/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-06-09-emacs-live-sacha-chua-built-ins/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=yuJYEua0ZwA">https://www.youtube.com/watch?v=yuJYEua0ZwA</a></p>
         
         <p>I will join Sacha’s live stream this Thursday to talk about
underappreciated features that are built into Emacs. There are a lot
of nice things that are available out-of-the-box (plus many packages
that build on top of them). I am looking forward to it!</p>

<p>The video will be recorded for future reference.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs live with Sacha Chua about ‘May I recommend’ on Thursday 28 May 17:30 Europe/Athens</title>
      <description>We will talk about the Emacs blog carnival topic for May, which is 'May I recommend'.</description>
      <pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-05-27-emacs-live-sacha-chua-may-i-recommend/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-05-27-emacs-live-sacha-chua-may-i-recommend/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=xl-ifABU45A">https://www.youtube.com/watch?v=xl-ifABU45A</a></p>
         
         <p>Tomorrow, the 28th of May 2026 at 17:30 Europe/Athens time, I will
join Sacha Chua’s live stream.</p>

<p>We will talk about the Emacs blog carnival topic for this month, which
is “May I recommend”. The video will be recorded for future reference.</p>

<p>I already have some ideas and am looking forward to our chat!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: ef-arcadia and ef-atlantis are part of the ef-themes</title>
      <description>I added a new light and dark theme to my 'ef-themes' package for Emacs.</description>
      <pubDate>Thu, 21 May 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-05-21-emacs-ef-arcadia-ef-atlantis-themes/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-05-21-emacs-ef-arcadia-ef-atlantis-themes/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I have added two new themes to the current development target of my
<code class="language-plaintext highlighter-rouge">ef-themes</code> package. Screenshots are available below. Remember that
the themes are highly customisable: you can change practically
everything about them.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">ef-arcadia</code> is a light theme with a verdant, humid aesthetic.</li>
  <li><code class="language-plaintext highlighter-rouge">ef-atlantis</code> is a dark theme with an aquatic feel.</li>
</ul>

<p>Both deliver the familiar colourfulness and good legibility of the
<code class="language-plaintext highlighter-rouge">ef-themes</code>.</p>

<p>Always <strong>click to enlarge the image</strong> for best results.</p>

<h3>ef-arcadia</h3>

<p><a href="https://protesilaos.com/assets/images/ef/ef-arcadia.png"><img alt="ef-arcadia theme sample" src="https://protesilaos.com/assets/images/ef/ef-arcadia.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-arcadia-git.png"><img alt="ef-arcadia theme git sample" src="https://protesilaos.com/assets/images/ef/ef-arcadia-git.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-arcadia-mail.png"><img alt="ef-arcadia theme mail sample" src="https://protesilaos.com/assets/images/ef/ef-arcadia-mail.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-arcadia-org.png"><img alt="ef-arcadia theme org sample" src="https://protesilaos.com/assets/images/ef/ef-arcadia-org.png" /></a></p>

<h3>ef-atlantis</h3>

<p><a href="https://protesilaos.com/assets/images/ef/ef-atlantis.png"><img alt="ef-atlantis theme sample" src="https://protesilaos.com/assets/images/ef/ef-atlantis.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-atlantis-git.png"><img alt="ef-atlantis theme git sample" src="https://protesilaos.com/assets/images/ef/ef-atlantis-git.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-atlantis-mail.png"><img alt="ef-atlantis theme mail sample" src="https://protesilaos.com/assets/images/ef/ef-atlantis-mail.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-atlantis-org.png"><img alt="ef-atlantis theme org sample" src="https://protesilaos.com/assets/images/ef/ef-atlantis-org.png" /></a></p>

<h2>Coming in version 2.2.0 (next stable release)</h2>

<p>The character of each theme is well defined. I may still make some
refinements.</p>

<p>Remember that since version <code class="language-plaintext highlighter-rouge">2.0.0</code>, the <code class="language-plaintext highlighter-rouge">ef-themes</code> are built on top
of my <code class="language-plaintext highlighter-rouge">modus-themes</code>. This means that they are highly customisable,
support a wide range of packages and face groups, and are extensively
tested down to the finest details.</p>

<p>Enjoy!</p>

<hr />

<p>The <code class="language-plaintext highlighter-rouge">ef-themes</code> are a collection of light and dark themes for GNU
Emacs that provide colourful (“pretty”) yet legible options for users
who want something with a bit more flair than the <code class="language-plaintext highlighter-rouge">modus-themes</code> (also
designed by me).</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">ef-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/ef-themes">https://protesilaos.com/emacs/ef-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/ef-themes-changelog">https://protesilaos.com/emacs/ef-themes-changelog</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/ef-themes">https://github.com/protesilaos/ef-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/ef-themes">https://gitlab.com/protesilaos/ef-themes</a></li>
    </ul>
  </li>
  <li>Backronym: Eclectic Fashion in Themes Hides Exaggerated Markings,
Embellishments, and Sparkles.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: Denote version 4.2.0</title>
      <description>Information about the latest version of my Denote package for GNU Emacs.</description>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-05-20-emacs-denote-4-2-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-05-20-emacs-denote-4-2-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Denote aims to be a simple-to-use, focused-in-scope, and effective
note-taking and file-naming tool for Emacs.</p>

<p>Denote is based on the idea that files should follow a predictable and
descriptive file-naming scheme.  The file name must offer a clear
indication of what the contents are about, without reference to any
other metadata.  Denote basically streamlines the creation of such
files or file names while providing facilities to link between them
(where those files are editable).</p>

<p>Denote’s file-naming scheme is not limited to “notes”.  It can be used
for all types of file, including those that are not editable in Emacs,
such as videos.  Naming files in a constistent way makes their
filtering and retrieval considerably easier.  Denote provides relevant
facilities to rename files, regardless of file type.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote">https://protesilaos.com/emacs/denote</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/denote-changelog">https://protesilaos.com/emacs/denote-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/denote">https://github.com/protesilaos/denote</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/denote">https://gitlab.com/protesilaos/denote</a></li>
    </ul>
  </li>
  <li>Video demo: <a href="https://protesilaos.com/codelog/2022-06-18-denote-demo/">https://protesilaos.com/codelog/2022-06-18-denote-demo/</a></li>
  <li>Backronyms: Denote Everything Neatly; Omit The Excesses.  Don’t Ever
Note Only The Epiphenomenal.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 4.2.0 on 2026-05-20</h2>

<p>This version brings several improvements to the core <code class="language-plaintext highlighter-rouge">denote</code> package
as well as all the Denote extensions I maintain. The core package is
stable, its feature set is rich, and the wider ecosystem of extensions
is growing.</p>

<p>Most of the changes documented herein are of interest to experienced
users who may be looking for ways to refine their workflow. I
recommend that new users start with the basics, as I explained them in
the original video demonstration of Denote or as they are documented
in the manual’s section for newcomers:</p>

<ul>
  <li><strong>Webpage:</strong> <a href="https://protesilaos.com/emacs/denote#h:c54bedb4-5377-4dbd-853c-5870ace6eb33">https://protesilaos.com/emacs/denote#h:c54bedb4-5377-4dbd-853c-5870ace6eb33</a>.</li>
  <li><strong>Info manual:</strong> With the latest <code class="language-plaintext highlighter-rouge">denote</code> package installed, evaluate <code class="language-plaintext highlighter-rouge">(info "(denote) Getting started with Denote")</code>.</li>
</ul>

<p>Remember that the release notes are true only at the time of
publication. The single source of truth is the official manual.</p>

<h3>Core Denote</h3>

<h4>Overview of the new features</h4>

<ul>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">denote-dired-focus</code> will filter the results of an
existing <code class="language-plaintext highlighter-rouge">denote-dired</code> buffer. Use this to narrow down the results.</p>
  </li>
  <li>
    <p>In Org files, the <code class="language-plaintext highlighter-rouge">denote:</code> link type can now be previewed using the
built-in <code class="language-plaintext highlighter-rouge">org-link-preview</code> command, starting with Org version
<code class="language-plaintext highlighter-rouge">9.8.0</code>.</p>
  </li>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">denote-link-or-create-with-command</code> extends the
existing convenience functions of the “do or create note” kind.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-file-prompt</code> uses completion metadata to sort by most
recently accessed, group by directory or file extension, and cover
packages that display cosmetic icons alongside completion
candidates.</p>
  </li>
  <li>
    <p>Denote now enforces a controlled vocabulary for keywords when
<code class="language-plaintext highlighter-rouge">denote-infer-keywords</code> is set to <code class="language-plaintext highlighter-rouge">nil</code>, such that only the
<code class="language-plaintext highlighter-rouge">denote-known-keywords</code> are provided as an option at the relevant
prompts.</p>
  </li>
  <li>
    <p>The mechanism for integrating Denote with <code class="language-plaintext highlighter-rouge">org-capture</code> now supports
prompting for an signature via <code class="language-plaintext highlighter-rouge">denote-org-capture-with-prompts</code>
(the signature is an optional, free-form component of the Denote
file-naming scheme).</p>
  </li>
  <li>
    <p>Several packages that extend Denote are documented in the manual. If
you have a package for Denote, let me know and I will write a
section about it.</p>
  </li>
</ul>

<h4>Focus a <code class="language-plaintext highlighter-rouge">denote-dired</code> buffer with <code class="language-plaintext highlighter-rouge">denote-dired-focus</code></h4>

<p>The command <code class="language-plaintext highlighter-rouge">denote-dired</code> produces a Dired listing of file names that
match the given regular expressions. Users can benefit from the Denote
file-naming scheme to, for example, include all files that have the
keyword <code class="language-plaintext highlighter-rouge">_emacs</code>. In the resulting Dired buffer, the new command
<code class="language-plaintext highlighter-rouge">denote-dired-focus</code> can then be invoked to further narrow down the
results, such as to only show files that have <code class="language-plaintext highlighter-rouge">2026</code> in their file
(with default settings, the date is part of the Denote identifier).</p>

<p>I implemented this feature in response to issue 693 by 82Kang:
<a href="https://github.com/protesilaos/denote/issues/693">https://github.com/protesilaos/denote/issues/693</a>.</p>

<h4>Improvements to the file prompt</h4>

<p>Various Denote commands prompt for a file name: for instance,
<code class="language-plaintext highlighter-rouge">denote-link</code> asks which file to link to. This file prompt is now
augmented with completion metadata that transform how files look and
how the information is organised.</p>

<p>Before, the prompt presented full file names like:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>20220610T043241--initial-thoughts-on-the-zettelkasten-method__notetaking.org
20220610T062201--define-custom-org-hyperlink-type__denote_emacs_package.md
20220610T162327--on-hierarchy-and-taxis__notetaking_philosophy.txt
</code></pre></div></div>

<p>Those same file names are now transformed to look like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2022-06-10  initial-thoughts-on-the-zettelkasten-method  notetaking
2022-06-10  define-custom-org-hyperlink-type  denote_emacs_package
2022-06-10  on-hierarchy-and-taxis  notetaking_philosophy
</code></pre></div></div>

<p>The files will be grouped by file extension or directory (if they are
in a subdirectory of the <code class="language-plaintext highlighter-rouge">denote-directory</code>). Furthermore, they will
be sorted by most recently accessed.</p>

<p>The underlying file names are still available except that their
presentation is modified. This means that input at the minibuffer
prompt will still match everything they contain.</p>

<p>This completion metadata extends to the packages <code class="language-plaintext highlighter-rouge">all-the-icons</code> and
<code class="language-plaintext highlighter-rouge">nerd-icons</code>, which are now instructed to add the correct file icons
to the completion candidates: an Org file will have the unicorn icon
beside it, for example.</p>

<p>Users who do not like the new style can revert to the plain
presentation by setting <code class="language-plaintext highlighter-rouge">denote-file-prompt-extra-metadata</code> to <code class="language-plaintext highlighter-rouge">nil</code>.</p>

<p>Advanced users who wish to set up the <code class="language-plaintext highlighter-rouge">completion-category-overrides</code>
may target the <code class="language-plaintext highlighter-rouge">denote-file</code> completion category or, anyhow, modify
the <code class="language-plaintext highlighter-rouge">denote-file-prompt-extra-metadata</code>.</p>

<h4>Link to a file or create a new note using a specific command</h4>

<p>Denote provides many “convenience wrapper” commands that do something
quickly which can also be achieved with minimal configuration. For
example, the <code class="language-plaintext highlighter-rouge">denote</code> command may be modified to also prompt for a
file type and so the <code class="language-plaintext highlighter-rouge">denote-type</code> command is like <code class="language-plaintext highlighter-rouge">denote</code> with the
addition of the file type prompt. Users can look at the source code of
<code class="language-plaintext highlighter-rouge">denote-type</code> to write their own small variations (the manual provides
several examples as well).</p>

<p>The <code class="language-plaintext highlighter-rouge">denote-open-or-create-with-command</code> may then use those to
implement its specified behaviour of “open an existing file or create
it using a convenience wrapper command”.</p>

<p>Same principle for the new <code class="language-plaintext highlighter-rouge">denote-link-or-create-with-command</code>: it
makes possible the workflow of “link to an existing file or create a
new note with the given command”.</p>

<p>Convenience wrappers are listed in the value of the user option
<code class="language-plaintext highlighter-rouge">denote-commands-for-new-notes</code>.</p>

<p>Thanks to Matthew Batson for building on top of existing functionality
to contribute <code class="language-plaintext highlighter-rouge">denote-link-or-create-with-command</code> in pull request
674: <a href="https://github.com/protesilaos/denote/pull/674">https://github.com/protesilaos/denote/pull/674</a>. Matthew has
assigned copyright to the Free Software Foundation.</p>

<h4>Preview <code class="language-plaintext highlighter-rouge">denote:</code> links in Org files</h4>

<p>Starting with Org version <code class="language-plaintext highlighter-rouge">9.8.0</code> custom link types such as <code class="language-plaintext highlighter-rouge">denote:</code>
can implement their own preview mechanism. In practice, this means
that <code class="language-plaintext highlighter-rouge">denote:</code> links pointing to image files will now work as expected
with <code class="language-plaintext highlighter-rouge">org-link-preview</code> (remember that the Denote file-naming scheme
can be applied to any file and is in no way specific to
note-taking—I use it for documents and videos, for example).</p>

<p>Thanks to Samuel W. Flint for the original contribution in pull request 683:
<a href="https://github.com/protesilaos/denote/pull/683">https://github.com/protesilaos/denote/pull/683</a>, with further changes
by me. The original contribution is small, meaning that Samuel does
not need to assign copyright to the Free Software Foundation.</p>

<h4>Signature support in Org capture</h4>

<p>The <code class="language-plaintext highlighter-rouge">denote-org-capture-with-prompts</code> function now supports the
signature file name component as an additional parameter. This
function is meant to be used in tandem with the <code class="language-plaintext highlighter-rouge">org-capture</code>
mechanism, as shown in the manual.</p>

<p>Thanks to Tobias Lidman-Strauss for the contribution in merge request
2 on the GitLab mirror: <a href="https://gitlab.com/protesilaos/denote/-/merge_requests/2">https://gitlab.com/protesilaos/denote/-/merge_requests/2</a>.
The change is small, meaning that Tobias does not need to assign
copyright to the Free Software Foundation.</p>

<h4>The <code class="language-plaintext highlighter-rouge">denote-fontify-links-mode</code> is only relevant for <code class="language-plaintext highlighter-rouge">.txt</code> files</h4>

<p>The <code class="language-plaintext highlighter-rouge">denote:</code> links are automatically highlighted as links in Org and
Markdown bufers. Users who prefer to write notes in plain <code class="language-plaintext highlighter-rouge">.txt</code> files
must enable the <code class="language-plaintext highlighter-rouge">denote-fontify-links-mode</code> to get the same effect.</p>

<p>I have revised <code class="language-plaintext highlighter-rouge">denote-fontify-links-mode</code> to only work with <code class="language-plaintext highlighter-rouge">.txt</code> as
its other users were not necessary. In the process, I have deprecated
the <code class="language-plaintext highlighter-rouge">denote-fontify-links-mode-maybe</code> function: just use the <code class="language-plaintext highlighter-rouge">denote-fonftify-links-mode</code>.</p>

<p>The keys <code class="language-plaintext highlighter-rouge">RET</code> and <code class="language-plaintext highlighter-rouge">C-c C-o</code> open the link (same keys used by Org and
Markdown modes).</p>

<h4>Growing ecosystem of Denote packages</h4>

<p>In the Denote manual I mention packages that build on top of Denote.
There is one section for each package. The manual now includes the
following:</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">denote-agenda</code> (by Samuel W. Flint):</strong> Use Denote notes as Org agenda files.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">denote-journal-capture</code> (by Samuel W. Flint):</strong> Enhanced journaling workflows.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">denote-lint</code> (Peter Smith):</strong> Checks for inconsistencies in Denote file names and front matter.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">denote-project-notes</code> (by Samuel W. Flint):</strong> Integrate Denote with Emacs’ built-in project support.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">denote-regexp</code> (by Samuel W. Flint):</strong> Search and link notes using regular expressions.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">denote-review</code> (by Matto Fransen):</strong> A package for reviewing notes over time.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">denote-sections</code> (by Samuel W. Flint):</strong> Manage sections within Denote notes.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">denote-wordcloud</code> (by Alexander Kuzmin):</strong> Generate word clouds from Denote notes.</li>
</ul>

<h4>Miscellaneous</h4>

<ul>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">denote-dired</code> (alias <code class="language-plaintext highlighter-rouge">denote-sort-dired</code>) is refactored
to work as intended in all cases. Thanks to kilesduli for the
contribution in pull request 666: <a href="https://github.com/protesilaos/denote/pull/666">https://github.com/protesilaos/denote/pull/666</a>.
Further changes by me, including the option to maintain many
separate <code class="language-plaintext highlighter-rouge">denote-dired</code> buffers, which I did in response to issue
693 by 82Kang: <a href="https://github.com/protesilaos/denote/issues/693">https://github.com/protesilaos/denote/issues/693</a>.</p>
  </li>
  <li>
    <p>I have revised the <code class="language-plaintext highlighter-rouge">denote-grep</code> mechanism and all of its ancillary
functions and variables are revised in the interest of consistency
and maintainability. Thanks to gnuhack for contributing a macro that
was meant to streamline some commands. This was done in pull request
697: <a href="https://github.com/protesilaos/denote/pull/697">https://github.com/protesilaos/denote/pull/697</a>. I eventually
changed lots of things so that the macro was not relevant anymore,
though mine was a change with a wider scope.</p>
  </li>
  <li>
    <p>The Org link storage mechanism (<code class="language-plaintext highlighter-rouge">denote-link-ol-store</code>) now works
correctly within <code class="language-plaintext highlighter-rouge">org-capture</code> buffers, allowing for more flexible
linking workflows.</p>
  </li>
  <li>
    <p>Following non-Denote Markdown links no longer result in an error
under certain circumstances. Thanks to bplubell for the contribution
in pull request 685: <a href="https://github.com/protesilaos/denote/pull/685">https://github.com/protesilaos/denote/pull/685</a>.
The change is small, meaning that its author does not need to assign
copyright to the Free Software Foundation.</p>
  </li>
  <li>
    <p>Retrieving front matter is now more reliable, even when the buffer
is unsaved. Thanks to kilesduli for the contribution in pull request
672: <a href="https://github.com/protesilaos/denote/pull/672">https://github.com/protesilaos/denote/pull/672</a>. Also thanks
to Jean-Philippe Gagné Guay for reviewing the change and for
reporting a problem with an earlier version of the code in issue
670: <a href="https://github.com/protesilaos/denote/issues/670">https://github.com/protesilaos/denote/issues/670</a>. Further
changes by me.</p>
  </li>
  <li>
    <p>The various Denote rename commands that affect the front matter in
files no longer change existing spacing. I did this to address the
comment posted by Morten Kjeldgaard in issue 703: <a href="https://github.com/protesilaos/denote/issues/703">https://github.com/protesilaos/denote/issues/703</a>.</p>
  </li>
  <li>
    <p>Updated the documentation to explain how to automatically encrypt
new notes when using a custom file type.</p>
  </li>
  <li>
    <p>Refined the internal helper functions for directory management and
identifier validation.</p>
  </li>
  <li>
    <p>Thanks to nescias for fixing three typos in the manual. This was
sent to me as a patch, which I installed as commit <code class="language-plaintext highlighter-rouge">c772378</code>.</p>
  </li>
</ul>

<h4>Changes to the extensions of Denote I maintain</h4>

<p>This is about packages I maintain. Some of them were originally part
of the denote.git repository, but I moved them out into their own
packages to make everything easier to reason about.</p>

<h5><code class="language-plaintext highlighter-rouge">consult-denote</code> version 0.5.0</h5>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">consult-denote</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/consult-denote">https://protesilaos.com/emacs/consult-denote</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/consult-denote-changelog">https://protesilaos.com/emacs/consult-denote-changelog</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/consult-denote">https://github.com/protesilaos/consult-denote</a></li>
  <li>
    <p>Backronym: Consult-Orchestrated Navigation and Selection of
Unambiguous Targets…denote.</p>
  </li>
  <li>
    <p>References to the long-obsolete “denote-silo-extras-” prefix are
replaced by “denote-silo-”. Thanks to IT Ascalium for the
contribution in pull request 20: <a href="https://github.com/protesilaos/consult-denote/pull/20">https://github.com/protesilaos/consult-denote/pull/20</a>.
The change is small, so its author does not need to assign copyright
to the Free Software Foundation.</p>
  </li>
  <li>The <code class="language-plaintext highlighter-rouge">consult-denote-file-prompt</code> correctly handles relative file
paths when <code class="language-plaintext highlighter-rouge">denote-directory</code> is set to a list of directories. This
is what the underlying <code class="language-plaintext highlighter-rouge">denote-file-prompt</code> does (which I mentioned
above about its metadata). Thanks to Kai von Fintel for the
contribution in pull request 24: <a href="https://github.com/protesilaos/consult-denote/pull/24">https://github.com/protesilaos/consult-denote/pull/24</a>.
The change does not require copyright assignment.</li>
</ul>

<h5><code class="language-plaintext highlighter-rouge">denote-merge</code> version 0.1.0</h5>

<ul>
  <li>Git repository: <a href="https://github.com/protesilaos/denote-merge">https://github.com/protesilaos/denote-merge</a></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote-merge">https://protesilaos.com/emacs/denote-merge</a></li>
  <li>Backronym: Denote… Merging Eventually Reformats the Given Entries.</li>
</ul>

<p>This is an optional extension to the <code class="language-plaintext highlighter-rouge">denote</code> package. It provides
commands and relevant user options to streamline the work of merging
contents from one Denote file to another. This is for users who
periodically review their notes to add, remove, or otherwise
consolidate their accumulated knowledge.</p>

<h5><code class="language-plaintext highlighter-rouge">denote-journal</code> version 0.3.0</h5>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote-journal</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote-journal">https://protesilaos.com/emacs/denote-journal</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/denote-journal">https://github.com/protesilaos/denote-journal</a></li>
  <li>
    <p>Backronym: Denote… Journaling Obviously Utilises Reasonableness
Notwithstanding Affectionate Longing.</p>
  </li>
  <li>
    <p>The user option <code class="language-plaintext highlighter-rouge">denote-journal-keyword</code> now supports a <code class="language-plaintext highlighter-rouge">nil</code> value,
allowing users to create journal entries without a specific keyword.
Thanks to nescias for sending me the patch via email, which I
installed as commit <code class="language-plaintext highlighter-rouge">d4cc501</code> in denote-journal.git. The change does
not require copyright assignment.</p>
  </li>
  <li>Fixed an issue about how the function <code class="language-plaintext highlighter-rouge">denote-directory-files</code> was
used. Thanks to Donald Brady for reporting the bug in issue 656 on
the main Denote repository and to kamchy for confirming the problem:
<a href="https://github.com/protesilaos/denote/issues/656">https://github.com/protesilaos/denote/issues/656</a>. The approach was
utlimately revised in denote.git courtesy of a change by
Jean-Philippe Gagné Guay in pull request 661:
<a href="https://github.com/protesilaos/denote/pull/661">https://github.com/protesilaos/denote/pull/661</a>.</li>
</ul>

<h5><code class="language-plaintext highlighter-rouge">denote-markdown</code> version 0.3.0</h5>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote-markdown</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote-markdown">https://protesilaos.com/emacs/denote-markdown</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/denote-markdown">https://github.com/protesilaos/denote-markdown</a></li>
  <li>
    <p>Backronyms: Denote… Markdown’s Ambitious Reimplimentations
Knowingly Dilute Obvious Widespread Norms; Denote… Markup
Agnosticism Requires Knowhow to Do Only What’s Necessary.</p>
  </li>
  <li>The package defines a <code class="language-plaintext highlighter-rouge">markdown-obsidian</code> file type which can be
used by relevant note-creating commands, such as <code class="language-plaintext highlighter-rouge">denote</code> or the
convenience wrapper <code class="language-plaintext highlighter-rouge">denote-type</code>. This file type is updated to be
more robust, in accordance with some changes in core Denote (I am
not even documenting those, as they are not intended for users).</li>
</ul>

<h5><code class="language-plaintext highlighter-rouge">denote-org</code> version 0.3.0</h5>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote-org</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote-org">https://protesilaos.com/emacs/denote-org</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/denote-org">https://github.com/protesilaos/denote-org</a></li>
  <li>
    <p>Backronym: Denote… Ordinarily Restricts Gyrations.</p>
  </li>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">denote-org-link-to-heading</code> now supports linking to the
current file when called with a prefix argument. This way, a file
can have links between its headings. Thanks to Tonus for pointing
out that it was impossible to create a link inside the current file.
This was done in issue 17: <a href="https://github.com/protesilaos/denote-org/issues/17">https://github.com/protesilaos/denote-org/issues/17</a>.</p>
  </li>
  <li>
    <p>A helper function for retrieving the backlinks of a heading is
updated to return full file paths. Thanks to Vedang Manerikar for
the contribution in pull request 20: <a href="https://github.com/protesilaos/denote-org/pull/20">https://github.com/protesilaos/denote-org/pull/20</a>.
Vedang has assigned copyright to the Free Software Foundation.</p>
  </li>
  <li>Another helper function is updated to conform with changes to core
Denote with regard to how the <code class="language-plaintext highlighter-rouge">denote-link-description-format</code> is
handled. Thanks to Jung Han for reporting the bug in issue 21:
<a href="https://github.com/protesilaos/denote-org/issues/21">https://github.com/protesilaos/denote-org/issues/21</a>.</li>
</ul>

<h5><code class="language-plaintext highlighter-rouge">denote-silo</code> version 0.3.0</h5>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote-silo</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote-silo">https://protesilaos.com/emacs/denote-silo</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/denote-silo">https://github.com/protesilaos/denote-silo</a></li>
  <li>Backronym: Denote… Silos Insulate Localised Objects.</li>
</ul>

<p>The minibuffer prompt for silo directories uses the corrent completion
category (consistent with what I mentioned above about completion
metadata). Thanks to Wilf-bog for reporting an error with the
completion prompt in issue 1: <a href="https://github.com/protesilaos/denote-silo/issues/1">https://github.com/protesilaos/denote-silo/issues/1</a>.</p>

<h5><code class="language-plaintext highlighter-rouge">denote-sequence</code> version 0.3.0</h5>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote-sequence</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote-sequence">https://protesilaos.com/emacs/denote-sequence</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/denote-sequence">https://github.com/protesilaos/denote-sequence</a></li>
  <li>Backronym: Denote… Sequences Efficiently Queue Unsorted Entries
Notwithstanding Curation Efforts.</li>
</ul>

<p>This package deserved its own release notes, as I did a lot of work on
it. But as this file is already long, I will focus on the essentials:</p>

<ul>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-sequence-scheme</code> used to support a <code class="language-plaintext highlighter-rouge">numeric</code> and
<code class="language-plaintext highlighter-rouge">alphanumeric</code> option. There now is a third one called
<code class="language-plaintext highlighter-rouge">alphanumeric-delimited</code>. It combines features from the other two
and may be better suited for especially long/intricate sequences.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-sequence-reparent</code> command now works recursively to
produce the desired consequences to all descendants of a given
sequence note. Thanks to Peter Prevos for the contribution in pull
request 13, which further changes by me:
<a href="https://github.com/protesilaos/denote-sequence/pull/13">https://github.com/protesilaos/denote-sequence/pull/13</a>.</p>
  </li>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">denote-sequence-view-hierarchy</code> produces a bespoke
buffer with all the sequence notes that form a hierarchy. The buffer
displays file titles, the concomitant sequence, and file keywords.
Each level of depth is expressed by a number of spaces, controlled
by the user option <code class="language-plaintext highlighter-rouge">denote-sequence-hierarchy-indentation</code>. In the
hierarchy buffer, there are commands that move to the next/previous
item, or forward/backward at the same level of depth. <code class="language-plaintext highlighter-rouge">RET</code> opens
the file at point, <code class="language-plaintext highlighter-rouge">TAB</code> folds/unfolds the tree. The user option
<code class="language-plaintext highlighter-rouge">denote-sequence-hierarchy-move-and-open</code> controls whether motion
commands should automatically open the file, which by default
happens in the other window (users who modify the variable
<code class="language-plaintext highlighter-rouge">denote-open-link-function</code> will get the specified behaviour in this
context as well). The <code class="language-plaintext highlighter-rouge">denote-sequence-view-hierarchy</code> can be called
with one or two prefix arguments to limit to a given sequence prefix
and/or level of depth (something that <code class="language-plaintext highlighter-rouge">denote-sequence-dired</code> also
supports). In short, this is a way to visualise your sequence notes
in a buffer that has a different presentation than Dired.</p>
  </li>
  <li>
    <p>Thanks to alan-w-255 for renaming and refining a prompt that is also
used in the hierarchy feature. This was done in pull request 15:
<a href="https://github.com/protesilaos/denote-sequence/pull/15">https://github.com/protesilaos/denote-sequence/pull/15</a>. The change
is small, meaning that its author does not need to assign copyright
to the Free Software Foundation. Further refinements by me.</p>
  </li>
  <li>
    <p>Thanks to Nicolas Semrau for binding <code class="language-plaintext highlighter-rouge">q</code> to <code class="language-plaintext highlighter-rouge">quit-window</code> in the
<code class="language-plaintext highlighter-rouge">denote-sequence-hierarchy-mode-map</code>. This was done in pull request
20: <a href="https://github.com/protesilaos/denote-sequence/pull/20">https://github.com/protesilaos/denote-sequence/pull/20</a>. The
change is small, meaning that Nicolas does not need to assign
copyright to the Free Software Foundation.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-sequence-file-prompt-extra-metadata</code> is the functional
equivalent of the aforementioned <code class="language-plaintext highlighter-rouge">denote-file-prompt-extra-metadata</code>.</p>
  </li>
  <li>
    <p>Thanks to liyingzhi for pointing out an inaccurate comment in the
docstring of <code class="language-plaintext highlighter-rouge">denote-sequence-scheme</code>. This was done in issue 18:
<a href="https://github.com/protesilaos/denote-sequence/issues/18">https://github.com/protesilaos/denote-sequence/issues/18</a>.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-sequence-dired</code> is updated to align with the modalities
of <code class="language-plaintext highlighter-rouge">denote-dired</code>, as noted above. Thanks to juh for reminding me
about the need for changes in issue 14: <a href="https://github.com/protesilaos/denote-sequence/issues/14">https://github.com/protesilaos/denote-sequence/issues/14</a>.</p>
  </li>
  <li>
    <p>Thanks to Stefan Monnier for pointing out a stylistic mistake in an
older version of <code class="language-plaintext highlighter-rouge">denote-sequence-dired</code>. This was done on the
emacs-devel mailing list: <a href="https://lists.gnu.org/archive/html/emacs-devel/2025-11/msg01119.html">https://lists.gnu.org/archive/html/emacs-devel/2025-11/msg01119.html</a>.
Also thanks to Stefan for telling me about some other compiler
warnings: <a href="https://lists.gnu.org/archive/html/emacs-devel/2025-11/msg01119.html">https://lists.gnu.org/archive/html/emacs-devel/2025-11/msg01119.html</a>.</p>
  </li>
</ul>

<h4>Git commits</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/Git/Projects/denote $ git shortlog 4.1.0..4.2.0 --summary --numbered
   184	Protesilaos
     4	duli
     3	Jean-Philippe Gagné Guay
     3	Matthew Batson
     2	alvmts
     2	gnuhack
     1	Alvin Hsu
     1	Matto Fransen
     1	Samuel W. Flint
     1	Tobias Lidman-Strauss
     1	bplubell
     1	gvalson
     1	nescias
</code></pre></div></div>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs coaching with Amin Bandali about ffs, display-buffer-alist, Org, and more</title>
      <description>I had a meeting with Amin Bandali in which we talked about his ffs.el package, display-buffer-alist, and a couple of Org-related topics.</description>
      <pubDate>Fri, 15 May 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-05-15-emacs-amin-bandali-ffs-display-buffer-org-capture/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-05-15-emacs-amin-bandali-ffs-display-buffer-org-capture/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Yesterday I met with Amin Bandali to talk about Emacs. Amin asked me
if he could record the session, which I agreed to. The video is
available on Amin’s website: <a href="https://kelar.org/~bandali/gnu/emacs/ffs-emacs-ext-prot.html">https://kelar.org/~bandali/gnu/emacs/ffs-emacs-ext-prot.html</a>.</p>

<p>We started with a review of the latest changes to the <code class="language-plaintext highlighter-rouge">ffs</code> package
that Amin has been developing. We had looked into it before and wanted
to check on its current state.</p>

<p>Amin then asked me about the <code class="language-plaintext highlighter-rouge">display-buffer-alist</code>, which I had
mentioned before. To me, this is the single most important variable
for making Emacs feel more like your own. The reason is that it allows
you to control the placement of buffers to match your expectations. I
demonstrated some of the main ideas.</p>

<p>Another nice little feature is the built-in <code class="language-plaintext highlighter-rouge">isearch</code>. I explained how
it is especially helpful while recording keyboard macros. Though it is
nice to use in general. One tweak for it is to display a counter with
its matches. Another is to change how it treats spaces, so that it can
match any character in-between. This is not as flexible as, say,
<code class="language-plaintext highlighter-rouge">consult-line</code> (from the <code class="language-plaintext highlighter-rouge">consult</code> package) when combined with
<code class="language-plaintext highlighter-rouge">vertico</code> and <code class="language-plaintext highlighter-rouge">orderless</code>. Though it still has its uses.</p>

<p>[ I have lots of little extras for <code class="language-plaintext highlighter-rouge">isearch</code>, but those should be
  good for most users. ]</p>

<p>Amin told me about rediscovering the value of Org in the context of
statically generating his website. He showed me the custom Org HTML
export backend he has been working on. Org has so many nice features
which can be used independent of each other. In this light, we also
discussed the <code class="language-plaintext highlighter-rouge">diary</code> compared to the Org agenda.</p>

<p>Find all of Amin’s publications on his website: <a href="https://kelar.org/~bandali/">https://kelar.org/~bandali/</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs coaching with Amin Bandali</title>
      <description>I met with Amin Bandali to talk about Emacs, specifically Amin's upcoming ffs.el package.</description>
      <pubDate>Fri, 08 May 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-05-08-emacs-coaching-amin-bandali/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-05-08-emacs-coaching-amin-bandali/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I met with Amin Bandali to talk about Emacs, specifically Amin’s
upcoming <code class="language-plaintext highlighter-rouge">ffs</code> package. Amin informed me about changes to <code class="language-plaintext highlighter-rouge">ffs</code> in
light of a discussion we had during a previous session.</p>

<p>Amin asked me to record the meeting and then publish it, which I
happily agreed to. You can watch it on Amin’s website:
<a href="https://kelar.org/~bandali/gnu/emacs/ffs-code-review-prot.html">https://kelar.org/~bandali/gnu/emacs/ffs-code-review-prot.html</a>.</p>

<p>[ NOTE: I normally do not share anything about my meetings with
  people. Not who they are nor what we talk about. ]</p>

<p>Thanks to Amin for making this happen! I am looking forward to new
developments.</p>

<p>By the way, I learnt about the function <code class="language-plaintext highlighter-rouge">x-export-frames</code> from a
mention in Amin’s <code class="language-plaintext highlighter-rouge">ffs</code> package, which led me to write
<code class="language-plaintext highlighter-rouge">buffer-to-pdf</code>: <a href="https://github.com/protesilaos/buffer-to-pdf">https://github.com/protesilaos/buffer-to-pdf</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs live with Sacha Chua and Philip Kaludercic on 2026-05-14 17:30 Europe/Athens</title>
      <description>We will talk about Emacs 31 and other developments for Emacs 32. We will also discuss the newcomer experience.</description>
      <pubDate>Mon, 04 May 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-05-04-emacs-live-sacha-chua-philip-kaludercic/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-05-04-emacs-live-sacha-chua-philip-kaludercic/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=UqfZZRl_eNw">https://www.youtube.com/watch?v=UqfZZRl_eNw</a></p>
         
         <p>On the 14th of May we will meet with Sacha and Philip to talk about
the upcoming Emacs 31 and other developments heading into Emacs 32.
Philip is a contributor to core Emacs and the main driver behind the
new <code class="language-plaintext highlighter-rouge">newcomers-presets</code> theme, among others. We will cover themes
related to the newcomer experience.</p>

<p>I am looking forward to it!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Re: Emacs and keyboard ergonomics</title>
      <description>I comment on keyboard ergonomics and Emacs key bindings.</description>
      <pubDate>Mon, 04 May 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-05-04-emacs-keyboard-ergonomics/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-05-04-emacs-keyboard-ergonomics/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This is an excerpt from an exchange that I am reproducing with
permission from my correspondent. I am not sharing their contact
details.</p>

<hr />

<blockquote>
  <p>As I understand, you’re using the regular keybindings in emacs. I’m
trying to transition away from the vim way of editing text and was
wondering if you’re using a more ergonomic approach for your text
editing needs. I remember you were using some ergo split keyboards
for that?</p>
</blockquote>

<p>Indeed, I have a split mechanical keyboard (a gift from a person who
identifies as “Andreas”). It is the Iris revision 8 by Keebio. I also
have a regular full-sized keyboard (a gift from Arialdo Martini),
which is the Keychron K5.</p>

<p>[ Keyboard-related articles of mine: <a href="https://protesilaos.com/keeb/">https://protesilaos.com/keeb/</a>. ]</p>

<p>The split keyboard is nice, though it is not a magical solution. Even
with a regular form factor keyboard, I can work with the standard
Emacs keys without any problem. What helps me the most is to configure
one-shot modifiers. This means that I can tap (press once, then
release) a modifier key, then tap a regular key to register it as a
modifier+key event. For example, <code class="language-plaintext highlighter-rouge">C-x</code> is this: tap <code class="language-plaintext highlighter-rouge">Ctrl</code>, then tap
<code class="language-plaintext highlighter-rouge">x</code>. <code class="language-plaintext highlighter-rouge">Shift</code> tapping is especially nice for prose, by the way, and
eases the pressure on the otherwise weak pinky. The time window for
registering a one-shot modifier is configurable.</p>

<p>The other useful tweak for a regular keyboard is to rearrange the
layout of the modifiers. I prefer this order:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Super Alt Ctrl Space Ctrl Alt Super
</code></pre></div></div>

<p>[ If there is a <code class="language-plaintext highlighter-rouge">Menu</code> key, move it to the right corner and consider
  assigning it to the Compose key if you are on Linux. ]</p>

<p>Now <code class="language-plaintext highlighter-rouge">Ctrl</code> is under the thumb, which is especially nice for Emacs.
<code class="language-plaintext highlighter-rouge">Alt</code> and <code class="language-plaintext highlighter-rouge">Super</code> can be swapped, if you use <code class="language-plaintext highlighter-rouge">Super</code> more heavily
(e.g. with a tiling window manager). But the important part is to keep
<code class="language-plaintext highlighter-rouge">Ctrl</code> close to the <code class="language-plaintext highlighter-rouge">Space</code> key.</p>

<p>Whatever you do though, remember to use both sets of modifiers. For
example, <code class="language-plaintext highlighter-rouge">C-x</code> involves the right hand for <code class="language-plaintext highlighter-rouge">Ctrl</code> and the left hand
for <code class="language-plaintext highlighter-rouge">x</code>. <code class="language-plaintext highlighter-rouge">C-p</code> needs the left hand for <code class="language-plaintext highlighter-rouge">Ctrl</code> and the right hand for
<code class="language-plaintext highlighter-rouge">p</code>. This way you distribute the burden so no one side is overworked
(and, of course, you take regular breaks from typing altogether).</p>

<p>Lots of Emacs users will rebind <code class="language-plaintext highlighter-rouge">Caps Lock</code> to <code class="language-plaintext highlighter-rouge">Ctrl</code>. While this is
fine in its own right, it tends to embed bad habits, such as with
using only the left hand to register the very common <code class="language-plaintext highlighter-rouge">C-a</code>, <code class="language-plaintext highlighter-rouge">C-e</code>,
<code class="language-plaintext highlighter-rouge">C-d</code>, <code class="language-plaintext highlighter-rouge">C-f</code>, <code class="language-plaintext highlighter-rouge">C-s</code>, <code class="language-plaintext highlighter-rouge">C-r</code>, <code class="language-plaintext highlighter-rouge">C-w</code>, <code class="language-plaintext highlighter-rouge">C-g</code>, <code class="language-plaintext highlighter-rouge">C-z</code>, <code class="language-plaintext highlighter-rouge">C-x</code>, <code class="language-plaintext highlighter-rouge">C-c</code>, <code class="language-plaintext highlighter-rouge">C-v</code>.
Exclusive left-handed use involves awkward twisting of the muscles
which will probably hurt you over time. Plus, the left pinky is forced
to press and hold a key while being stretched—looks bad. Again,
distribute the load.</p>

<p>The final part that makes everything easier is to configure a “layer”
key. When you press and hold this key, other keys register a different
input than normal. For example, <code class="language-plaintext highlighter-rouge">Caps Lock</code> can be the layer key,
which then makes <code class="language-plaintext highlighter-rouge">h</code>, <code class="language-plaintext highlighter-rouge">j</code>, <code class="language-plaintext highlighter-rouge">k</code>, <code class="language-plaintext highlighter-rouge">l</code> act as arrow keys. Same idea for
mapping <code class="language-plaintext highlighter-rouge">Home</code>, <code class="language-plaintext highlighter-rouge">PgDn</code>, <code class="language-plaintext highlighter-rouge">PgUp</code>, <code class="language-plaintext highlighter-rouge">End</code> someplace that makes sense (mine
are on <code class="language-plaintext highlighter-rouge">y</code>, <code class="language-plaintext highlighter-rouge">u</code>, <code class="language-plaintext highlighter-rouge">i</code>, <code class="language-plaintext highlighter-rouge">o</code>). I prefer to have <code class="language-plaintext highlighter-rouge">Space</code> as that layer
key: it only is a layer when I press and hold it, otherwise it
performs the ordinary function of the <code class="language-plaintext highlighter-rouge">Space</code> key.</p>

<p>It is okay to press and hold <code class="language-plaintext highlighter-rouge">Space</code> because you do it with your
relatively strong thumbs. Better have it this way than pressing and
holding with the pinkies.</p>

<p>All this can be achieved with software such as <code class="language-plaintext highlighter-rouge">kanata</code>. A custom
keyboard with QMK firmware can get the same configuration embedded
directly in the keyboard (so it works without any special program
running on the computer). Kanata will be the cheaper solution and is
probably better overall if you consider that it can apply to a
laptop’s keyboard.</p>

<p>A mistake in all this is to think that an expensive keyboard is
inherently more ergonomic. If you keep curling, overextending, or
anyhow stressing your muscles the injuries will occur regardless. A
new keyboard can help if you use it as an opportunity to retrain your
muscle memory.</p>

<p>Custom keyboards have potential advantages in terms of comfort because
you can change the switches and keycaps that they use. For example,
you can pick a lighter or heavier switch to match your typing
technique. Then you can combine it with a shallower or steeper keycap
profile to get the most out of that setup. There is no right or wrong
here. It is a matter of optimising on top of the strong fundamentals
that I outlined above.</p>

<p>As for <code class="language-plaintext highlighter-rouge">evil-mode</code> in Emacs, I think it is a good solution overall.
You do, however, need to install the <code class="language-plaintext highlighter-rouge">evil-collection</code> package and
probably also configure lots of other key bindings to get exactly what
you want. There are other packages that give you modal editing, though
I have only ever used <code class="language-plaintext highlighter-rouge">evil-mode</code> in earnest: it is fine.</p>

<p>That granted, I find that I do not like modal editing in general. It
is especially inconvenient for me when I write at length (which I do a
lot) because I tend to produce a wall of text in one go. Having a
modal interface gives me no advantage in this common scenario. I also
doubt it ever gave me the edge while programming. The bottleneck is
how quickly and clearly I can think, not how fast I can edit lines of
text (though, yes, Vim’s paradigm is powerful).</p>

<p>Consider then the overall comfort of your setup. Both in terms of the
ergonomics of hardware but also how much effort it takes to maintain
your Emacs configuration. The standard approach to key bindings gives
you something that “just works” with practically every package you
install. It may feel awkward in the beginning if you are coming from
the Vim keys, but will be the most robust solution long-term from the
perspective of maintainability.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: save any buffer as PDF (my new buffer-to-pdf package)</title>
      <description>Video demonstration of my new Emacs package called buffer-to-pdf.</description>
      <pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-05-02-emacs-buffer-to-pdf-new-package/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-05-02-emacs-buffer-to-pdf-new-package/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=JG4R-d0N-is">https://www.youtube.com/watch?v=JG4R-d0N-is</a></p>
         
         <p>In this short video I demonstrate my new package for Emacs. It is
called buffer-to-pdf. The idea is to save your current buffer to a
PDF, while preserving how it looks. This means that your font size,
theme, and other visual effects are preserved and written to the PDF.
buffer-to-pdf is not meant to be a replacement for elaborate export
methods: consider it a quick yet effective way to get a “screen
capture” of your Emacs that you can then share as a document. I
believe this will be especially useful for academics or people who
need to distribute presentation notes on a regular basis. The package
is available here: <a href="https://github.com/protesilaos/buffer-to-pdf">https://github.com/protesilaos/buffer-to-pdf</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: decent defaults I shared with Sacha Chua</title>
      <description>Some basic settings for Emacs that I consider useful for most users.</description>
      <pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-04-30-emacs-decent-default-sacha-chua/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-04-30-emacs-decent-default-sacha-chua/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>These are the basic settings for Emacs that I shared with Sacha Chua
during our livestreamed meeting on 2026-04-30: <a href="https://www.youtube.com/watch?v=z7pcLdwuyxE">https://www.youtube.com/watch?v=z7pcLdwuyxE</a>.</p>

<p><strong>UPDATE 2026-05-01 08:24 +0300:</strong> Added a missing <code class="language-plaintext highlighter-rouge">:config</code> to the
<code class="language-plaintext highlighter-rouge">bookmark</code> block.</p>

<p><strong>UPDATE 2026-05-02 22:33 +0300:</strong> Replaced duplicate <code class="language-plaintext highlighter-rouge">variable-pitch</code>
with the intended <code class="language-plaintext highlighter-rouge">fixed-pitch</code>.</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;;; Sensible defaults that are not too intrusive and focus on common use-cases.  By Protesilaos on 2026-04-30.</span>

<span class="c1">;; These are not all of my favourite options.  I am not even including</span>
<span class="c1">;; any of my packages.  They are just some basics that I consider</span>
<span class="c1">;; useful, given what I have learnt from my exchange with other people</span>
<span class="c1">;; of all skill levels.</span>


<span class="c1">;; Persist all customisations in a separate file called "custom.el".</span>
<span class="c1">;; It is in the same directory as the "init.el".</span>
<span class="c1">;;</span>
<span class="c1">;; Without the `custom-file', Emacs writes directly to the "init.el",</span>
<span class="c1">;; which can be confusing.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">custom-file</span> <span class="p">(</span><span class="nv">locate-user-emacs-file</span> <span class="s">"custom.el"</span><span class="p">))</span>
<span class="p">(</span><span class="nb">load</span> <span class="nv">custom-file</span> <span class="ss">:no-error-if-file-is-missing</span><span class="p">)</span>

<span class="p">(</span><span class="nb">use-package</span> <span class="nc">package</span>
  <span class="ss">:ensure</span> <span class="no">nil</span>
  <span class="ss">:config</span>
  <span class="c1">;; I am not using `add-to-list' here because the default "gnu" is</span>
  <span class="c1">;; confusing to people, given that "elpa" is the better known name</span>
  <span class="c1">;; for it.</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">package-archives</span>
        <span class="o">'</span><span class="p">((</span><span class="s">"gnu-elpa"</span> <span class="o">.</span> <span class="s">"https://elpa.gnu.org/packages/"</span><span class="p">)</span>
          <span class="p">(</span><span class="s">"nongnu"</span> <span class="o">.</span> <span class="s">"https://elpa.nongnu.org/nongnu/"</span><span class="p">)</span>
          <span class="p">(</span><span class="s">"melpa"</span> <span class="o">.</span> <span class="s">"https://melpa.org/packages/"</span><span class="p">)))</span>
  <span class="c1">;; Prefer GNU ELPA but accept the reality of MELPA's utility to the</span>
  <span class="c1">;; wider community.</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">package-archive-priorities</span>
        <span class="o">'</span><span class="p">((</span><span class="s">"gnu-elpa"</span> <span class="o">.</span> <span class="mi">3</span><span class="p">)</span>
          <span class="p">(</span><span class="s">"nongnu"</span> <span class="o">.</span> <span class="mi">2</span><span class="p">)</span>
          <span class="p">(</span><span class="s">"melpa"</span> <span class="o">.</span> <span class="mi">1</span><span class="p">))))</span>

<span class="c1">;;;; General options</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">emacs</span>
  <span class="ss">:ensure</span> <span class="no">nil</span>
  <span class="ss">:demand</span> <span class="no">t</span>
  <span class="ss">:init</span>
  <span class="p">(</span><span class="nb">defun</span> <span class="nv">prot/keyboard-quit-dwim</span> <span class="p">()</span>
    <span class="s">"Do-What-I-Mean behaviour for a general `keyboard-quit'.

The generic `keyboard-quit' does not do the expected thing when
the minibuffer is open.  Whereas we want it to close the
minibuffer, even without explicitly focusing it.

The DWIM behaviour of this command is as follows:

- When the region is active, disable it.
- When a minibuffer is open, but not focused, close the minibuffer.
- When the Completions buffer is selected, close it.
- In every other case use the regular `keyboard-quit'."</span>
    <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">cond</span>
     <span class="p">((</span><span class="nv">region-active-p</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">keyboard-quit</span><span class="p">))</span>
     <span class="p">((</span><span class="nv">derived-mode-p</span> <span class="ss">'completion-list-mode</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">delete-completion-window</span><span class="p">))</span>
     <span class="p">((</span><span class="nb">&gt;</span> <span class="p">(</span><span class="nv">minibuffer-depth</span><span class="p">)</span> <span class="mi">0</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">abort-recursive-edit</span><span class="p">))</span>
     <span class="p">(</span><span class="no">t</span>
      <span class="p">(</span><span class="nv">keyboard-quit</span><span class="p">))))</span>
  <span class="ss">:bind</span>
  <span class="p">(</span><span class="s">"C-g"</span> <span class="o">.</span> <span class="nv">prot/keyboard-quit-dwim</span><span class="p">)</span>
  <span class="ss">:config</span>
  <span class="c1">;; Set your favourite font family and height here.  The :height is</span>
  <span class="c1">;; 10x the point size you most commonly find on other applications.</span>
  <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:family</span> <span class="s">"Aporetic Sans Mono"</span> <span class="ss">:height</span> <span class="mi">160</span><span class="p">)</span>
  <span class="c1">;; Set your favourite font for elements that are designed to always</span>
  <span class="c1">;; be monospaced.  The height SHOULD BE a floating point, which is</span>
  <span class="c1">;; interpreted as relative to the `default'.</span>
  <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'fixed-pitch</span> <span class="no">nil</span> <span class="ss">:family</span> <span class="s">"Aporetic Serif Mono"</span> <span class="ss">:height</span> <span class="mf">1.0</span><span class="p">)</span>
  <span class="c1">;; Same as above for proportionately spaced elements.  Make any</span>
  <span class="c1">;; buffer proportionately spaced by enabling the `variable-pitch-mode'.</span>
  <span class="c1">;;</span>
  <span class="c1">;; [ NOTE: If you use the Modus themes or derivatives, set</span>
  <span class="c1">;;   `modus-themes-mixed-fonts', load the theme for the option to</span>
  <span class="c1">;;   take effect, and then enable `variable-pitch-mode':</span>
  <span class="c1">;;   spacing-sensitive elements like Org tables and code blocks will</span>
  <span class="c1">;;   remain monospaced. ]</span>
  <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'variable-pitch</span> <span class="no">nil</span> <span class="ss">:family</span> <span class="s">"Aporetic Sans"</span> <span class="ss">:height</span> <span class="mf">1.0</span><span class="p">)</span>

  <span class="c1">;; I have never seen a user say "no" to loading a theme they have</span>
  <span class="c1">;; downloaded.  Technically, any Elisp file can run arbitrary code,</span>
  <span class="c1">;; so this is not doing much on the security front.</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">custom-safe-themes</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">use-short-answers</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">read-answer-short</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">help-window-select</span> <span class="no">t</span><span class="p">)</span> <span class="c1">; also check `display-buffer-alist' below</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">help-window-keep-selected</span> <span class="no">t</span><span class="p">)</span> <span class="c1">; Emacs 29</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">find-library-include-other-files</span> <span class="no">nil</span><span class="p">)</span> <span class="c1">; Emacs 29</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">window-combination-resize</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">save-interprogram-paste-before-kill</span> <span class="no">t</span><span class="p">)</span>
  <span class="c1">;; Do not jump to the current line in `*occur*' buffers.  The reason</span>
  <span class="c1">;; is that you are already on that line: you want to do `occur' to</span>
  <span class="c1">;; get more than that (and, presumably, to do something with the</span>
  <span class="c1">;; results such as to edit them with `occur-edit-mode').</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">list-matching-lines-jump-to-current-line</span> <span class="no">nil</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">completion-category-defaults</span> <span class="no">nil</span><span class="p">))</span>

<span class="c1">;;;; Save minibuffer histories</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">savehist</span>
  <span class="ss">:ensure</span> <span class="no">nil</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="nv">savehist-mode</span> <span class="mi">1</span><span class="p">))</span>

<span class="c1">;;;; Delete the selected text when inserting new text</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">delsel</span>
  <span class="ss">:ensure</span> <span class="no">nil</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="nv">delete-selection-mode</span> <span class="mi">1</span><span class="p">))</span>

<span class="c1">;;;; Bookmarks</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">bookmark</span>
  <span class="ss">:ensure</span> <span class="no">nil</span>
  <span class="ss">:config</span>
  <span class="c1">;; Emacs 29 displays a bookmark icon on the fringe.  Many people</span>
  <span class="c1">;; have asked me what that thing is.  I also think it is confusing.</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">bookmark-fringe-mark</span> <span class="no">nil</span><span class="p">)</span>
  <span class="c1">;; Write changes to the bookmark file as soon as 1 modification is</span>
  <span class="c1">;; made (addition or deletion).  Otherwise Emacs will only save the</span>
  <span class="c1">;; bookmarks when it closes, which may never happen properly</span>
  <span class="c1">;; (e.g. power failure).</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">bookmark-save-flag</span> <span class="mi">1</span><span class="p">))</span>

<span class="c1">;;;; Dired</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">dired</span>
  <span class="ss">:ensure</span> <span class="no">nil</span>
  <span class="ss">:config</span>
  <span class="c1">;; Most people I have talked to prefer a single Dired buffer.</span>
  <span class="c1">;; Personally I like the many Dired buffers, but I understand why</span>
  <span class="c1">;; this feels overwhelming.</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">dired-kill-when-opening-new-dired-buffer</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">dired-auto-revert-buffer</span> <span class="nf">#'</span><span class="nv">dired-directory-changed-p</span><span class="p">)</span> <span class="c1">; also see `dired-do-revert-buffer'</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">dired-clean-up-buffers-too</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">dired-clean-confirm-killing-deleted-buffers</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">dired-recursive-copies</span> <span class="ss">'always</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">dired-recursive-deletes</span> <span class="ss">'always</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">delete-by-moving-to-trash</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">dired-create-destination-dirs</span> <span class="ss">'ask</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">dired-create-destination-dirs-on-trailing-dirsep</span> <span class="no">t</span><span class="p">)</span> <span class="c1">; Emacs 29</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">wdired-create-parent-directories</span> <span class="no">t</span><span class="p">))</span>

<span class="c1">;;;; Isearch</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">isearch</span>
  <span class="ss">:ensure</span> <span class="no">nil</span>
  <span class="ss">:config</span>
  <span class="c1">;; ;; Enable those to make "package install" match those words with</span>
  <span class="c1">;; ;; anything in between.  I think this is the single best tweak I</span>
  <span class="c1">;; ;; ever made.</span>
  <span class="c1">;;</span>
  <span class="c1">;; (setq search-whitespace-regexp ".*?")</span>
  <span class="c1">;; (setq isearch-lax-whitespace t)</span>
  <span class="c1">;; (setq isearch-regexp-lax-whitespace nil)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">isearch-lazy-count</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">lazy-count-prefix-format</span> <span class="s">"(%s/%s) "</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">lazy-count-suffix-format</span> <span class="no">nil</span><span class="p">))</span>

<span class="c1">;;;; Diff</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">diff</span>
  <span class="ss">:ensure</span>
  <span class="ss">:config</span>
  <span class="c1">;; You cannot expect the syntax highlighting of themes to look</span>
  <span class="c1">;; equally readabable against what typically are red and green</span>
  <span class="c1">;; backgrounds.  This should be opt-in by default, not opt-out.</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">diff-font-lock-syntax</span> <span class="no">nil</span><span class="p">))</span>

<span class="c1">;;;; Ediff</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">ediff</span>
  <span class="ss">:ensure</span> <span class="no">nil</span>
  <span class="ss">:config</span>
  <span class="c1">;; Ediff is virtually unusable without those.  Especially on tiling</span>
  <span class="c1">;; window managers.  But even on a regular desktop environment it is</span>
  <span class="c1">;; confusing and cumbersome to have the control panel in another</span>
  <span class="c1">;; frame.</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">ediff-split-window-function</span> <span class="ss">'split-window-horizontally</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">ediff-window-setup-function</span> <span class="ss">'ediff-setup-windows-plain</span><span class="p">))</span>

<span class="c1">;;;; SHR</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">shr</span>
  <span class="ss">:ensure</span> <span class="no">nil</span>
  <span class="ss">:config</span>
  <span class="c1">;; t is bad for accessibility and generally awkward for HTML email</span>
  <span class="c1">;; (especially with dark themes).</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">shr-use-colors</span> <span class="no">nil</span><span class="p">)</span>
  <span class="c1">;; This option should not exist, given `variable-pitch-mode'.</span>
  <span class="c1">;; Furthermore, its default value runs counter to almost everything</span>
  <span class="c1">;; else in Emacs which just uses the `default' face.</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">shr-use-fonts</span> <span class="no">nil</span><span class="p">))</span>

<span class="c1">;;;; Control the display of common ancillary windows</span>

<span class="c1">;; Always focus common ancillary windows.  Place them in a window</span>
<span class="c1">;; already occupied by their respective major mode or below the</span>
<span class="c1">;; current window.</span>
<span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'display-buffer-alist</span>
             <span class="o">'</span><span class="p">((</span><span class="nb">or</span> <span class="o">.</span> <span class="p">((</span><span class="nv">derived-mode</span> <span class="o">.</span> <span class="nv">occur-mode</span><span class="p">)</span>
                      <span class="p">(</span><span class="nv">derived-mode</span> <span class="o">.</span> <span class="nv">grep-mode</span><span class="p">)</span>
                      <span class="p">(</span><span class="nv">derived-mode</span> <span class="o">.</span> <span class="nv">Buffer-menu-mode</span><span class="p">)</span>
                      <span class="p">(</span><span class="nv">derived-mode</span> <span class="o">.</span> <span class="nv">log-view-mode</span><span class="p">)</span>
                      <span class="p">(</span><span class="nv">derived-mode</span> <span class="o">.</span> <span class="nv">help-mode</span><span class="p">)))</span>
               <span class="p">(</span><span class="nv">display-buffer-reuse-mode-window</span> <span class="nv">display-buffer-below-selected</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">body-function</span> <span class="o">.</span> <span class="nv">select-window</span><span class="p">)))</span>

<span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'display-buffer-alist</span>
             <span class="o">'</span><span class="p">(</span><span class="s">"\\`\\*\\(Org \\(Select\\|Note\\)\\|Agenda Commands\\)\\*\\'"</span> <span class="c1">; the `org-capture' key selection, `org-add-log-note', and agenda dispatcher</span>
               <span class="p">(</span><span class="nv">display-buffer-in-side-window</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">dedicated</span> <span class="o">.</span> <span class="no">t</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">side</span> <span class="o">.</span> <span class="nv">bottom</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">slot</span> <span class="o">.</span> <span class="mi">0</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">window-parameters</span> <span class="o">.</span> <span class="p">((</span><span class="nv">mode-line-format</span> <span class="o">.</span> <span class="nv">none</span><span class="p">)))))</span>

<span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'display-buffer-alist</span>
             <span class="o">'</span><span class="p">((</span><span class="nv">derived-mode</span> <span class="o">.</span> <span class="nv">calendar-mode</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">display-buffer-reuse-mode-window</span> <span class="nv">display-buffer-below-selected</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">mode</span> <span class="o">.</span> <span class="p">(</span><span class="nv">calendar-mode</span> <span class="nv">bookmark-edit-annotation-mode</span> <span class="nv">ert-results-mode</span><span class="p">))</span>
               <span class="p">(</span><span class="nv">inhibit-switch-frame</span> <span class="o">.</span> <span class="no">t</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">dedicated</span> <span class="o">.</span> <span class="no">t</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">window-height</span> <span class="o">.</span> <span class="nv">fit-window-to-buffer</span><span class="p">)))</span>

<span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'display-buffer-alist</span>
             <span class="o">'</span><span class="p">((</span><span class="nv">derived-mode</span> <span class="o">.</span> <span class="nv">reb-mode</span><span class="p">)</span> <span class="c1">; M-x re-builder</span>
               <span class="p">(</span><span class="nv">display-buffer-reuse-mode-window</span> <span class="nv">display-buffer-below-selected</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">inhibit-switch-frame</span> <span class="o">.</span> <span class="no">t</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">window-height</span> <span class="o">.</span> <span class="mi">4</span><span class="p">)</span> <span class="c1">; note this is literal lines, not relative</span>
               <span class="p">(</span><span class="nv">dedicated</span> <span class="o">.</span> <span class="no">t</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">preserve-size</span> <span class="o">.</span> <span class="p">(</span><span class="no">t</span> <span class="o">.</span> <span class="no">t</span><span class="p">))))</span>

<span class="c1">;;;; ESSENTIAL packages to install</span>

<span class="p">(</span><span class="nb">use-package</span> <span class="nv">vertico</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="nv">vertico-mode</span> <span class="mi">1</span><span class="p">))</span>

<span class="p">(</span><span class="nb">use-package</span> <span class="nv">marginalia</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="nv">marginalia-mode</span> <span class="mi">1</span><span class="p">))</span>

<span class="c1">;;;; VERY USEFUL but not essential packages</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">orderless</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">completion-styles</span> <span class="o">'</span><span class="p">(</span><span class="nv">orderless</span> <span class="nv">basic</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">use-package</span> <span class="nv">consult</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="c1">;; All commands have their utility, but those are commonly needed.</span>
  <span class="ss">:commands</span> <span class="p">(</span><span class="nv">consult-buffer</span> <span class="nv">consult-line</span> <span class="nv">consult-outline</span> <span class="nv">consult-find</span> <span class="nv">consult-grep</span><span class="p">))</span>

<span class="p">(</span><span class="nb">use-package</span> <span class="nv">embark</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="ss">:bind</span>
  <span class="c1">;; Embark is helpful in every context, though there are other ways</span>
  <span class="c1">;; to do what it does.  Where it stands out is in its ability to</span>
  <span class="c1">;; deal with all the minibuffer results.  The equivalent of those</span>
  <span class="c1">;; two commands should be a core Emacs functionality.</span>
  <span class="p">(</span> <span class="ss">:map</span> <span class="nv">minibuffer-local-map</span>
    <span class="p">(</span><span class="s">"C-c C-c"</span> <span class="o">.</span> <span class="nv">embark-collect</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"C-c C-e"</span> <span class="o">.</span> <span class="nv">embark-export</span><span class="p">))</span>
  <span class="ss">:config</span>
  <span class="c1">;; Needed for correct exporting while using Embark with Consult commands.</span>
  <span class="p">(</span><span class="nb">use-package</span> <span class="nv">embark-consult</span>
    <span class="ss">:ensure</span> <span class="no">t</span>
    <span class="ss">:after</span> <span class="nv">consult</span><span class="p">))</span>

<span class="c1">;; Useful when combined with `delete-by-moving-to-trash'.</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">trashed</span>
  <span class="ss">:ensure</span> <span class="no">t</span><span class="p">)</span>
</code></pre></div></div>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs spontaneous live stream on Denote, TMR, and more at 19:00 Europe/Athens</title>
      <description>I will continue my package maintenance work for Emacs, focusing on Denote and TMR.</description>
      <pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-04-23-emacs-spontaneous-live-denote-tmr/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-04-23-emacs-spontaneous-live-denote-tmr/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=5OSn7udx9LA">https://www.youtube.com/watch?v=5OSn7udx9LA</a></p>
         
         <p>[ The video will be recorded. ]</p>

<p>This is a spontaneous live stream. The stream starts in ~20 minutes. I
will continue maintaining my packages. My plan is to start with Denote
and then move to TMR. Depending on how I do, I will check some of my
other packages as well.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs live stream with Sacha Chua on 2026-04-30 17:30 Europe/Athens</title>
      <description>I will do a live stream together with Sacha Chua where we will do some programming on Emacs.</description>
      <pubDate>Wed, 22 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-04-22-emacs-live-with-sacha-chua/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-04-22-emacs-live-with-sacha-chua/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=z7pcLdwuyxE">https://www.youtube.com/watch?v=z7pcLdwuyxE</a></p>
         
         <p>Mark your calendar for next Thursday. I will do another live stream
with Sacha Chua. We will talk about Emacs and I will check on her
progress since our last meeting. I am looking forward to it!</p>

<p>Note that the event will be recorded.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: new modus-themes-exporter package live today @ 15:00 Europe/Athens</title>
      <description>I am doing a live stream where I will develop the new modus-themes-exporter package live.</description>
      <pubDate>Mon, 13 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-04-13-emacs-live-develop-modus-themes-exporter-package/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-04-13-emacs-live-develop-modus-themes-exporter-package/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=IVTqn9IgBN4">https://www.youtube.com/watch?v=IVTqn9IgBN4</a></p>
         
         <p><strong>UPDATE 2026-04-13 18:00 +0300:</strong> I wrote the package during the
stream: <a href="https://github.com/protesilaos/modus-themes-exporter">https://github.com/protesilaos/modus-themes-exporter</a>.</p>

<hr />

<p>[ The stream will be recorded. You can watch it later. ]</p>

<p>Today, the 13th of April 2026, at 15:00 Europe/Athens I will do a live
stream in which I will develop the new <code class="language-plaintext highlighter-rouge">modus-themes-exporter</code> package
for Emacs.</p>

<p>The idea for this package is based on an old experiment of mine: to
get the palette of a Modus theme and “export” it to another file
format for use in supported terminal emulators or, potentially, other
applications.</p>

<p>My focus today will be on writing the core functionality and testing
it with at least one target application.</p>

<p>Prior work of mine from my pre-Emacs days is the
<code class="language-plaintext highlighter-rouge">tempus-themes-generator</code>, which was written in Bash:
<a href="https://gitlab.com/protesilaos/tempus-themes-generator">https://gitlab.com/protesilaos/tempus-themes-generator</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs modus-themes live stream today @ 14:00 Europe/Athens</title>
      <description>I am doing a live stream related to Emacs, where I will write tests for my modus-themes.</description>
      <pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-04-10-emacs-spontaneous-live-modus-themes/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-04-10-emacs-spontaneous-live-modus-themes/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=xFQDYTCS1os">https://www.youtube.com/watch?v=xFQDYTCS1os</a></p>
         
         <p>[ The stream will be recorded. You can watch it later. ]</p>

<p>At 14:00 Europe/Athens I will hold a live stream about Emacs.
Specifically, I will work on my <code class="language-plaintext highlighter-rouge">modus-themes</code> package.</p>

<p>The idea is to write more tests and refine the relevant functions
along the way.</p>

<p>I am announcing this -45 minutes before I go live. I will keep the
chat open in case there are any questions.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs live stream for writing Denote tests and more on Monday 6 April @ 20:00 Europe/Athens</title>
      <description>I am doing a live stream related to Emacs, where I will write tests for Denote.</description>
      <pubDate>Mon, 06 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-04-06-emacs-spontaneous-live-tonight-denote/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-04-06-emacs-spontaneous-live-tonight-denote/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=Vunpn7ovEOc">https://www.youtube.com/watch?v=Vunpn7ovEOc</a></p>
         
         <p>[ The stream will be recorded. You can watch it later. ]</p>

<p>Tonight I will work on my <code class="language-plaintext highlighter-rouge">denote</code> package. There is a feature branch
I implemented this morning and am now ready to continue refining the
code. The immediate goals:</p>

<ul>
  <li>Update unit tests that are still calling deprecated functions.</li>
  <li>Write new tests, starting with the <code class="language-plaintext highlighter-rouge">denote-dired</code> command and all
its ancillary functions.</li>
  <li>Review all the commands that filter the query buffers (which are
produced by commands such as <code class="language-plaintext highlighter-rouge">denote-grep</code>, <code class="language-plaintext highlighter-rouge">denote-backlinks</code>,
<code class="language-plaintext highlighter-rouge">denote-query-contents-link</code>).</li>
  <li>Edit the manual accordingly.</li>
</ul>

<p>I expect the stream to go on for 2-3 hours, but we will see.</p>

<p>I will keep the chat open in case there are any comments. I am happy
to respond to them.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs live stream with Sacha Chua on 2026-04-16 17:30 Europe/Athens</title>
      <description>I will do a live together with Sacha Chua where we will do some programming on Emacs.</description>
      <pubDate>Sat, 04 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-04-04-emacs-live-with-sacha-chua/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-04-04-emacs-live-with-sacha-chua/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=djE_pVlgDHg">https://www.youtube.com/watch?v=djE_pVlgDHg</a></p>
         
         <p>The other day I had a coaching session with Sacha Chua. Sacha asked me
if she could record and publish it, to which I agreed. More here:
<a href="https://sachachua.com/blog/2026/04/yayemacs-10-emacs-coaching-with-prot-packaging-emacs-lisp/">https://sachachua.com/blog/2026/04/yayemacs-10-emacs-coaching-with-prot-packaging-emacs-lisp/</a>/.</p>

<p>Our next meeting will be done live on the 16th of April 2026 at 10:30
America/Toronto, 17:30 Europe/Athens time: <a href="https://youtube.com/live/djE_pVlgDHg">https://youtube.com/live/djE_pVlgDHg</a>.</p>

<p>I will check with Sacha how she imagines doing this. Though I am the
laissez faire type, so will adapt as we go.</p>

<p>[ Note that all my coaching sessions are private: I never share
  details of my meetings. This is an exception because Sacha asked me
  about it. ]</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: new sequence scheme for the ‘denote-sequence’ package</title>
      <description>Information about a new feature that I just added to the 'denote-sequence' package.</description>
      <pubDate>Fri, 03 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-04-03-emacs-denote-sequence-new-alphanumeric-delimited-scheme/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-04-03-emacs-denote-sequence-new-alphanumeric-delimited-scheme/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <code class="language-plaintext highlighter-rouge">denote-sequence</code> package is an optional extension to <code class="language-plaintext highlighter-rouge">denote</code>
that empowers users to write “sequence notes”, else “folgezettel”, in
the style of Niklas Luhmann.</p>

<p>Sequence notes are created in relation to other notes, as parent,
child, or sibling. <code class="language-plaintext highlighter-rouge">denote-sequence</code> communicates such relationships
by writing a “sequence” to the file name, in accordance with the
Denote file-naming scheme (technically, it uses the optional
<code class="language-plaintext highlighter-rouge">SIGNATURE</code> component of the file name, which is defined as a
free-form field for users to use as they see fit—so this is just one
application of it).</p>

<h2>The package supported two schemes before</h2>

<p>The exact presentation of such sequences is subject to the user option
<code class="language-plaintext highlighter-rouge">denote-sequence-scheme</code>. The package has hitherto supported two
schemes, the <code class="language-plaintext highlighter-rouge">numeric</code> and <code class="language-plaintext highlighter-rouge">alphanumeric</code>.</p>

<p>In the numeric scheme, each level of depth is delimited by the equals
sign. The sequence <code class="language-plaintext highlighter-rouge">1=2=3</code> thus has three levels of depth. It means
“the third child of the second child of the first parent”.</p>

<p>By contrast, the alphanumeric scheme relies on the alternation between
numbers and letters to communicate levels of depth. The above example
is thus expressed as <code class="language-plaintext highlighter-rouge">1b3</code>.</p>

<h2>The new <code class="language-plaintext highlighter-rouge">alphanumeric-delimited</code> scheme</h2>

<p>Many users have told me that the alphanumeric scheme looks cleaner.
Though I think it is hard to read when sequences get really long, like
<code class="language-plaintext highlighter-rouge">2a13c6d2a</code>. To this end, the new sequence scheme augments the
alphanumeric style with delimiters that are placed after the first
level of depth and every third level of depth thereafter. Thus:
<code class="language-plaintext highlighter-rouge">2=a13=c6d=2a</code>.</p>

<p>Users may find this easier to work with.</p>

<h2>Remember the <code class="language-plaintext highlighter-rouge">denote-sequence-convert</code> command</h2>

<p>This command has been part of the package since its inception. It can
convert from one sequence scheme to the others.</p>

<p><code class="language-plaintext highlighter-rouge">denote-sequence-convert</code> has a “do what I mean behaviour” with regard
to which file or files it should operate on:</p>

<ul>
  <li>
    <p>When called from inside a file with a Denote sequence, it operates
on the current file.</p>
  </li>
  <li>
    <p>When called from a Dired buffer, it operates on all the marked
files.</p>
  </li>
  <li>
    <p>When there are no marked files in the Dired buffer, it operates on
the file at point.</p>
  </li>
</ul>

<p>The target sequence scheme for the conversion is whatever is assigned
to the user option <code class="language-plaintext highlighter-rouge">denote-sequence-scheme</code>. If, however,
<code class="language-plaintext highlighter-rouge">denote-sequence-convert</code> is called with a prefix argument (<code class="language-plaintext highlighter-rouge">C-u</code> by
default), then it will prompt for the target sequence scheme.</p>

<h2>Coming in version 0.3.0</h2>

<p>I just merged the code into trunk. Users who are building the package
from source can try the new feature right away. Otherwise, it will be
available in the next stable version of the package. I hope to have
that ready some time in mid-April.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote-sequence</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote-sequence">https://protesilaos.com/emacs/denote-sequence</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/denote-sequence">https://github.com/protesilaos/denote-sequence</a></li>
  <li>Backronym: Denote… Sequences Efficiently Queue Unsorted Entries
Notwithstanding Curation Efforts.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs coaching with Sacha Chua</title>
      <description>I will do a coaching session with Sacha Chua. She wrote a blog post about it and I am making comments on it.</description>
      <pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-03-31-emacs-coaching-with-sacha-chua/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-03-31-emacs-coaching-with-sacha-chua/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Sacha Chua contacted me to schedule a coaching session later this
week. She wrote about it here:
<a href="https://sachachua.com/blog/2026/03/thinking-about-coaching-goals-with-prot/">https://sachachua.com/blog/2026/03/thinking-about-coaching-goals-with-prot/</a>.</p>

<p>I maintain a strict privacy policy with everyone I meet. Specifically,
I do not say anything about our meeting. But since Sacha has already
published this information, I am happy to do this in the open.</p>

<p>What follows are some comments on her post.</p>

<h2>Testing interactive functions</h2>

<blockquote>
  <p>writing tests, especially for things that are more interactive</p>
</blockquote>

<p>What helps here is to think of the interactive part as the way to get
the arguments. If the interactivity is more involved, then you want to
think how it can be broken down into smaller routines. Each routine
should eventually be reduced to a function that can be called
non-interactively with a certain argument. This way, your tests are
easier to reason about.</p>

<p>Consider this example:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-greet-person</span> <span class="p">(</span><span class="nv">name</span><span class="p">)</span>
  <span class="s">"Return Hello string to person with NAME."</span>
  <span class="p">(</span><span class="nb">format</span> <span class="s">"Hello %s"</span> <span class="nv">name</span><span class="p">))</span>
</code></pre></div></div>

<p>The substantive part of the test would be something like this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">name</span> <span class="s">"Sacha"</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">string=</span> <span class="p">(</span><span class="nv">my-greet-person</span> <span class="nv">name</span><span class="p">)</span> <span class="s">"Hello Sacha"</span><span class="p">))</span>
</code></pre></div></div>

<p>Now add interactivity to the function:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-greet-person</span> <span class="p">(</span><span class="nv">name</span><span class="p">)</span>
  <span class="s">"Return Hello string to person with NAME.
When called interactively, prompt for NAME.  Else NAME is a string."</span>
  <span class="p">(</span><span class="nv">interactive</span> <span class="p">(</span><span class="nb">list</span> <span class="p">(</span><span class="nv">read-string</span> <span class="s">"Whom to greet: "</span><span class="p">)))</span>
  <span class="p">(</span><span class="nb">format</span> <span class="s">"Hello %s"</span> <span class="nv">name</span><span class="p">))</span>
</code></pre></div></div>

<p>Even though this function can be called interactively, the test is the
same because the <code class="language-plaintext highlighter-rouge">interactive</code> simply sets the value of <code class="language-plaintext highlighter-rouge">name</code>.</p>

<p>There will, of course, be more complex scenaria. We can think how best
to approach them. Though this is the general idea.</p>

<h2>Navigating Lisp code across many files</h2>

<blockquote>
  <p>navigating code that might be scattered in literate config files or
in Emacs Lisp files</p>
</blockquote>

<p>What I find helpful:</p>

<ul>
  <li>Use the Emacs bookmarking system. I add a bookmark for anything I
visit frequently. Then I can find what I need with <code class="language-plaintext highlighter-rouge">bookmark-jump</code>
or <code class="language-plaintext highlighter-rouge">consult-buffer</code> (from Daniel Mendler’s <code class="language-plaintext highlighter-rouge">consult</code> package).</li>
  <li>Have a single root for all your programming projects. In my case
this is <code class="language-plaintext highlighter-rouge">~/Git/</code>.</li>
  <li>In that directory, create subdirectories with areas of interest. One
of them should be specific to the projects you maintain. For
example, I have <code class="language-plaintext highlighter-rouge">~/Git/emacs-community/</code> and <code class="language-plaintext highlighter-rouge">~/Git/Projects/</code>. The
latter consists of everything I develop/maintain.</li>
  <li>With these directories in place, you can always rely on a recursive
Grep to find what you need.</li>
  <li>Otherwise, we have <code class="language-plaintext highlighter-rouge">xref-find-definitions</code> as well as all the help
functions like <code class="language-plaintext highlighter-rouge">describe-function</code> which normally link to the file
where the definition is.</li>
</ul>

<h2>Sharing with others</h2>

<blockquote>
  <p>If I get better at sharing what I’m working on, I might be able to
connect with more people and bounce ideas around.</p>
</blockquote>

<p>Getting better is nice. I think here the goal is to structure what you
are sharing in a certain way. Then people can use it more easily. Once
that happens, you will receive more feedback.</p>

<blockquote>
  <p>Also, accountability might help me nudge this over the threshold.</p>
</blockquote>

<p>This is key. When we make a promise in earnest, we are motivated to
deliver on it. The fact that you have published this adds to the
effectiveness of it.</p>

<blockquote>
  <p>I’m curious about other people’s workflows for sharing. I like
joining meetups, but I tend to share stuff only if no one else has
anything planned, because I have my blog and my YouTube channel in
case I want to share anything with a wider group of people. I just
have to actually post things.</p>
</blockquote>

<p>Each person is different and there is no one answer to rule them all.
What I do, as someone who publishes on a number of topics, is to reach
a point that is an honest representation of my current level. This
point is not approaching perfection, as that is a trap. If it were
about perfection, I would never publish anything!</p>

<p>Once I do what is within my current level, I am casual about it. In
other words, I do not need to prove that I am worthy of it—I am
already there and this is my current normal state. This makes the
process of writing less emotionally challenging (well, not challenging
at all). It also opens me to learn more. I am not defensive or
argumentative because, fundamentally, I feel secure with what I have:
I am not hiding something and do not worry about what others may
think.</p>

<p>About your case, I get the impression that you are already improving
your content. It starts by recognising that there is improvement to be
had. Then, you write blog posts such as the one I am now commenting on,
which show that you have put thought into your processes. In other
words, you are mindful of your current state. Whatever I may point out
during our meeting will thus be easier for you to incorporate in your
thinking. Why? Because you already know the space, as it were, and
so you will have a good intuition of where to put the new thing.</p>

<h2>Getting used to streaming</h2>

<blockquote>
  <p>Streaming: Still need to get the hang of talking to myself or having
half-conversations with chat: can be worked around by scheduling a
session with Prot and opening it to the public</p>
</blockquote>

<p>I am happy to do this in public. Either as a coaching session or some
collaborative live stream. We can discuss the details.</p>

<p>At any rate, “practice makes perfect”. The only way to get used to
talking to the camera is to do it enough times. I can talk at length,
though I still find it hard to laugh when I am by myself, so I look
dead serious in all of my monologues. Whereas, say, in the “Prot Asks”
series I often laugh. This is because I have a natural response
towards someone. Talking to the selfie camera does not create in me
the same friendly emotions.</p>

<h2>Sharing code</h2>

<blockquote>
  <p>renaming things when I want to move them to a library</p>
</blockquote>

<p>Before finding a name, you need to have a clear vision for the
package: what is it meant to do. Then try to think about words that
describe either the goal or the workflow. Use phrases, like what you
have with “speech input”. Those work fine.</p>

<p>Come up with placeholder names if you are not sure. Then, once you are
ready to share the package, do a final round of thinking to check if
you can think of a more suitable name. Otherwise just use some
descriptive phrase.</p>

<p>This concerns the prefix for the entire package. Though your code may
still consist of different areas of focus. For example, in my <code class="language-plaintext highlighter-rouge">denote</code>
package there is a subset of functionality related to “rename”
operations. All of those share a compound prefix of the name of the
package plus the name of the area they are specialising in like this
helper function: <code class="language-plaintext highlighter-rouge">denote-rename-buffer--format</code>. By the name alone, I
can tell that it relates to the “rename” operation and, specifically,
is ancillary to <code class="language-plaintext highlighter-rouge">denote-rename-buffer</code>.</p>

<p>I can provide concrete suggestions for your code.</p>

<blockquote>
  <p>duplicating small functions (ex: simplify string)</p>
</blockquote>

<p>You may choose to put those in their own package. Though I personally
do not mind a little bit of duplication/repetition when that is easier
to maintain. The principle of not repeating yourself is good in
general, though there are cases where trying to avoid it is not worth
the effort.</p>

<blockquote>
  <p>figuring out how to make it possible for someone else to start using
my stuff</p>
</blockquote>

<p>For any non-trivial code you write, you want to treat it like its own
“package”. In other words, it exists in a file of its own, it has all
the <code class="language-plaintext highlighter-rouge">require</code> calls for its dependencies, defines <code class="language-plaintext highlighter-rouge">defcustom</code>
variables if it must, uses <code class="language-plaintext highlighter-rouge">autoload</code> where relevant, and has a
<code class="language-plaintext highlighter-rouge">provide</code> call at the end. Even if you never move it out of your
configuration, you have already done the work of clearing up your
thoughts/code. Others will already benefit from that, as they can now
copy the file with greater confidence in its utility.</p>

<h2>Questions for Prot</h2>

<blockquote>
  <p>Meta: what are people finding useful for coaching and behaviour
change, like learning new keyboard shortcuts or workflows?</p>
</blockquote>

<p>Each person has their own goals. Some enjoy a pair programming
session. Others like me to check on their progress and to provide
feedback. Plus, there is more than the purely Emacs component: I make
comments about matters of perspective, whether it is about some piece
of code or life in general.</p>

<p>Those granted, I do not collect any data about the people I meet. I do
not ask them for testimonials or feedback. I prefer not to do that
because I do not wish to ever have to handle private information. I
like my meetings to be nice and simple. Plus, I do not want to
manipulate or influence the behaviour of people.</p>

<blockquote>
  <p>Your literate config exports to individual .el files. I could
probably do something similar to separate my functions from my
personal config in order to make it easier for people to reuse parts
of my config. Is it worth doing so? Do people tell you that they use
those private Emacs Lisp files by loading them, or do they mostly
rely on your published packages?</p>
</blockquote>

<p>Most rely on my packages. I design those to be as flexible as possible
and maintain them accordingly.</p>

<p>The individual <code class="language-plaintext highlighter-rouge">.el</code> files of my configuration are helpful to me. I
stay in the flow of designing my code in a package-ready way. If
anybody needs to use it, then they already have something that is
close to an actual package.</p>

<blockquote>
  <p>Do you have some tweaks to make it easier to jump to function
definitions considering a literate configuration?</p>
</blockquote>

<p>No, I have not had a need for this. When I choose to work on some part
of my configuration, I navigate to the relevant heading (with
something like <code class="language-plaintext highlighter-rouge">consult-outline</code>) and then use <code class="language-plaintext highlighter-rouge">org-edit-special</code> to
edit the source block.</p>

<p>You will show me what you have been doing, which may give me some
ideas.</p>

<blockquote>
  <p>What’s your general process for migrating things from your config to
a repository or package?</p>
</blockquote>

<p>It all starts with splitting the code into many <code class="language-plaintext highlighter-rouge">.el</code> files. Make sure
one file is not entangled with other files. Or, at least, put in the
effort to list every other file as a dependency and write the
necessary <code class="language-plaintext highlighter-rouge">require</code> for it.</p>

<p>Have one such file for each area of focus. This way you can reason
about what you have and what may be missing. A clear initial idea will
determine the direction of the package long-term. The reason is that
it establishes boundaries: what to do and what not to do.</p>

<p>From there, you can decide if some file is of value to other users. If
you think it is, then start implementing <code class="language-plaintext highlighter-rouge">defcustom</code> variables for it,
define the commands that users would want, and have <code class="language-plaintext highlighter-rouge">autoload</code>
directives for them if they are meant as points of entry.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: spontaneous live stream Tuesday 24 March @ 21:30 Europe/Athens</title>
      <description>I am doing a live stream related to Emacs, where I will continue working on my denote-sequence package.</description>
      <pubDate>Tue, 24 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-03-24-emacs-another-spontaneous-live-stream/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-03-24-emacs-another-spontaneous-live-stream/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=rDJbPCjZiOI">https://www.youtube.com/watch?v=rDJbPCjZiOI</a></p>
         
         <p>[ The stream will be recorded. You can watch it later. ]</p>

<p>At 21:30 Europe/Athens time I will do a live stream (~30 minutes from
this writing). The plan is to continue some of the work I am doing on
my denote-sequence package for Emacs.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: spontaneous live stream Monday 23 March @ 17:00 Europe/Athens</title>
      <description>I am doing a live stream related to Emacs, where I will try to implement a new feature for the denote-sequence package.</description>
      <pubDate>Mon, 23 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-03-23-emacs-spontaneous-live-stream/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-03-23-emacs-spontaneous-live-stream/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=4RxFImWhNrI">https://www.youtube.com/watch?v=4RxFImWhNrI</a></p>
         
         <p>[ The stream will be recorded. You can watch it later. ]</p>

<p>I do not have any work this evening, so I will do a live stream. My
plan is to do some programming. I have a new idea for the
<code class="language-plaintext highlighter-rouge">denote-sequence</code> package that I will try to implement.</p>

<p>If there are any questions from the chat, I will answer them. They can
be about what I will be working on or any other topic.</p>

<p>Talk to you soon!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: doric-themes version 1.1.0</title>
      <description>Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate).</description>
      <pubDate>Mon, 23 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-03-23-emacs-doric-themes-1-1-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-03-23-emacs-doric-themes-1-1-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>These are my minimalist themes. They use few colours and will appear
mostly monochromatic in many contexts. Styles involve the careful use
of typography, such as italics and bold italics.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 1.1.0 on 2026-03-23</h2>

<p>This version introduces minor refinements to the underlying code as
well as four new themes.</p>

<p>The new themes are as follows:</p>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">doric-almond</code>: A light theme that combines green and magenta
colours. It evokes a feeling of early springtime, as the almond tree
is among the first to bloom.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">doric-coral</code>: A light theme with a warmer feel that combines red,
orange, and cyan colours against a sandy backdrop.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">doric-magma</code>: A dark theme with a dominant red and orange style.
The combination of those intense hues with lighter greys creates the
necessary balance.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">doric-walnut</code>: A dark theme with an overall green style, drawing
inspiration from the broad leaves of the walnut tree. The green
colours are combined with shades of brown and grey to make for a
pleasant presentation.</p>
  </li>
</ul>

<p>Enjoy!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Computing in freedom with GNU Emacs</title>
      <description>A holistic introduction to Emacs: how useful it is and how it champions free software.</description>
      <pubDate>Fri, 13 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-03-13-computing-in-freedom-with-gnu-emacs/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-03-13-computing-in-freedom-with-gnu-emacs/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=M6ZHDJeG-dI">https://www.youtube.com/watch?v=M6ZHDJeG-dI</a></p>
         
         <p>This is a holistic introduction to Emacs: how useful it is and how it
champions free software. It is a modified version of the talk I did
for the “FLOSS @ Oxford” event, organised by people at the University
of Oxford. This is the page I wrote about that event:
<a href="https://protesilaos.com/codelog/2026-03-12-my-emacs-talk-floss-oxford/">https://protesilaos.com/codelog/2026-03-12-my-emacs-talk-floss-oxford/</a>.</p>

<hr />

<h1>Table of Contents</h1>

<ol>
  <li><a href="#orgfd50a75">This is a holistic introduction to Emacs</a></li>
  <li><a href="#org3a4ba20">Emacs as a capable text editor</a></li>
  <li><a href="#org5591f88">Support for Unicode</a></li>
  <li><a href="#orgf1c4f01">Include several fonts on the same page</a></li>
  <li><a href="#orge4f335e">Emacs can display graphics alongside text</a></li>
  <li><a href="#orgf8c1b6f">Emacs is an extensible text editor</a></li>
  <li><a href="#org99a48c2">Extending Emacs creates a community</a></li>
  <li><a href="#orgd27848f">The extensibility of Emacs happens live</a></li>
  <li><a href="#org394a3f3">My view without the “presentation mode”</a></li>
  <li><a href="#org034b25d">Emacs puts you in control of your computing</a></li>
  <li><a href="#org64517ba">Your control extends to all workflows</a></li>
  <li><a href="#org06c4615">For an integrated computing environment</a></li>
  <li><a href="#org40d4ee4">Many apps do not combine nicely</a></li>
  <li><a href="#orgd541b5c">Emacs makes your workflow consistent</a></li>
  <li><a href="#orgff36a33">Integrated computing in practice</a></li>
  <li><a href="#org3c03994">Emacs makes integration easier</a></li>
  <li><a href="#org79e8a3a">Integration gives you emergent properties</a></li>
  <li><a href="#orgf9e4f44">This is plain text that works like a slideshow</a></li>
  <li><a href="#orgc31ae17">Consistency facilitates productivity</a></li>
  <li><a href="#org124b771">Consistency remove the cognitive burden</a></li>
  <li><a href="#orgb512578">The consistency of Emacs in action</a></li>
  <li><a href="#org0bd43c1">Use Emacs Lisp to configure everything</a></li>
  <li><a href="#org2e55e24">Learning Emacs Lisp improves the experience</a></li>
  <li><a href="#org614ea19">Emacs embodies software freedom</a></li>
  <li><a href="#org40d68c8">The freedom of Emacs helps with learning</a></li>
  <li><a href="#orge1d150b">Emacs is not only for programmers</a></li>
  <li><a href="#org2be826e">You benefit from all the Emacs extensions</a></li>
  <li><a href="#org9f08566">Some powerful extensions are built-in</a></li>
  <li><a href="#org370d80c">The documentation culture of Emacs</a></li>
  <li><a href="#org96add87">Most packages have high quality manuals</a></li>
  <li><a href="#org45b5677">Emacs has a steep learning curve</a></li>
  <li><a href="#org4460604">Do not skip the manuals</a></li>
  <li><a href="#org5ce2296">Adjust your expectations</a></li>
  <li><a href="#org3e35022">Why it is worth learning how to use Emacs</a></li>
  <li><a href="#org8a7c786">The initial effort pays off long-term</a></li>
  <li><a href="#org9b2bf6a">Good luck and have fun!</a></li>
</ol>

<p>Hello everyone! My name is Protesilaos, also known as “Prot”.</p>

<p>This presentation is a modified version of the talk I gave last night
at the <em>FLOSS @ Oxford</em> event:
<a href="https://ox.ogeer.org/event/computing-in-freedom-with-gnu-emacs-protesilaos-stavrou">https://ox.ogeer.org/event/computing-in-freedom-with-gnu-emacs-protesilaos-stavrou</a>.</p>

<p>It was an event organised by people from the University of Oxford. I
thank them for giving me the opportunity to participate in their
programme.</p>

<p>I want to have this modified version here for people who do not read
my website. They may not be aware that I talked at this Oxford event.</p>

<p>Having the video on this platform means that everyone can benefit from
it.</p>

<p><a id="orgfd50a75"></a></p>

<h1>1 This is a holistic introduction to Emacs</h1>

<p>In this presentation I will talk to you about GNU Emacs, or simply,
“Emacs”. Emacs is a program you run on your computer. I am using it
right now for this presentation.</p>

<p>Emacs is free or libre software. It allows you to read all of its
source code, to modify it, and to share it with your customisations.
Thus you contribute to—and benefit from—a community of
welcoming Emacs users.</p>

<p>I will tell you what all this means in practice and how you can
improve your computing experience by switching to Emacs.</p>

<p><a id="org3a4ba20"></a></p>

<h1>2 Emacs as a capable text editor</h1>

<p>When you first start using Emacs, it feels like a regular text editor
program.</p>

<p>You move the cursor around and edit text. Nothing obviously impressive
out-of-the-box.</p>

<p>As a text editor, Emacs is highly capable. It has all sorts of
keyboard shortcuts that let you efficiently operate on text.</p>

<p>You can control Emacs without relying on the mouse, if you want.</p>

<p><a id="org5591f88"></a></p>

<h1>3 Support for Unicode</h1>

<p>Emacs supports the Unicode standard, which is essential for
inclusivity of peoples.</p>

<p>The world’s scripts can be expressed in Emacs. I am a native Greek
speaker.</p>

<p>I can use functionality that is built into Emacs to switch to the
Greek alphabet in order to write something, such as to say
«καλησπέρα», which means “good evening”.</p>

<p>I can even spell out “Dao De Jing” (道德经), which is the title of a
book from ancient China.</p>

<p>Plus emoji: 🦚🦬🐉.</p>

<p><a id="orgf1c4f01"></a></p>

<h1>4 Include several fonts on the same page</h1>

<p>The multitude of scripts can be present in the same document.</p>

<p>This is an advantage for multilingual people like myself or those who
do research that involves many natural languages.</p>

<p>Emacs can combine several fonts in the same page as well as different
colours.</p>

<p>Each fonts can have its own attributes, such as for its relative size
and typographic intensity.</p>

<p>Same idea for colours.</p>

<p>On my screen right now, I am already combining two different font
styles: that of the heading and the body of the text.</p>

<p><a id="orge4f335e"></a></p>

<h1>5 Emacs can display graphics alongside text</h1>

<p>Emacs does not limit you to a text-only interface. It can also display
images and PDF documents. Below I have a link to an image file. I will
now type a keyboard shortcut to reveal this image. And I will do it
again to hide it.</p>

<p>This, by the way, is a spot somewhere in my mountains.</p>

<p><a id="orgf8c1b6f"></a></p>

<h1>6 Emacs is an extensible text editor</h1>

<p>Although you can benefit from using Emacs as a generic text editor,
what really appeals to people like me is the option to extend Emacs.</p>

<p>“Extend” here means to introduce new functionality; functionality that
is not available in the default program you install on your computer.</p>

<p>These extensions are written in the same programming language as most
of Emacs. It is a programming language called “Emacs Lisp” or “Elisp”.</p>

<p>You can extend Emacs on your own, by writing some program in Elisp, or
you can download an existing extension that the community has made
available.</p>

<p><a id="org99a48c2"></a></p>

<h1>7 Extending Emacs creates a community</h1>

<p>For example, when I create a new extension for Emacs, I publish it
under the terms of a free software license—the same terms that
Emacs uses.</p>

<p>Others can then download my extension and use it as they prefer. If
they want, they can make their own modifications on top, which may
introduce other extensions that I had not thought of in my original
implementation.</p>

<p>And if those users follow my example, then I can also benefit from
their additions once they publish them.</p>

<p>As such, there exists a community of enthusiastic users of Emacs who
care about sharing their works with the rest of the world.</p>

<p><a id="orgd27848f"></a></p>

<h1>8 The extensibility of Emacs happens live</h1>

<p>Users can extend Emacs by running some Emacs Lisp program. Such a
program can be as short as a single line. Or it can be as long as it
needs to be. It does not matter.</p>

<p>Users run the program and Emacs immediately does what the program
renders possible.</p>

<p>For example, I am doing this presentation inside of Emacs. But Emacs
does not have a “presentation mode” built into it. I thus developed my
own extension which empowers me to do what I am doing right now.</p>

<p>Let me toggle off my presentation mode to show you what I mean.</p>

<p><a id="org394a3f3"></a></p>

<h1>9 My view without the “presentation mode”</h1>

<p>Notice that the display has changed.My main font is monospaced now.</p>

<p>The headings are smaller than they were before: they are the same size
as the rest of the text. There is no number next to the heading
anymore.</p>

<p>Then, there is a bar at the bottom of my screen, with information
about what I am working on. On the side, there are line numbers,
indicating where my cursor is in this file. Plus, my current line is
highlighted with a distinct background colour. Let me shift it up and
down to illustrate this point.</p>

<p>All those elements are useful while I am programming. But they look
distracting when I wish to focus on some portion of text. So, I just
type the keyboard shortcut I have and—voilà!—I get the
style I prefer.</p>

<p><a id="org034b25d"></a></p>

<h1>10 Emacs puts you in control of your computing</h1>

<p>You may wonder: why do I even need a customisable text editor?</p>

<p>The answer is about control. You are in charge of what you use and how
you use it. You can piece together a workflow that works the way you
prefer.</p>

<p>This presentation mode I toggled on and off earlier behaves exactly
how I want. I decided which set of interface tweaks to apply. Another
user may have a different preference in this regard.</p>

<p>For instance, they may like having line numbers on the side of the
screen. There is no right or wrong answer. What matters is that Emacs
gives us the means to do what makes sense to us.</p>

<p><a id="org64517ba"></a></p>

<h1>11 Your control extends to all workflows</h1>

<p>Now apply this principle to everything you can use Emacs for: this
will generally be a text-centric project.</p>

<p>I run my agenda exclusively through Emacs.</p>

<p>I handle all my email correspondence with Emacs.</p>

<p>I do programming and I write prose, such as blog posts for my website
and books or technical manuals.</p>

<p>For each of these, I know that Emacs will empower me to perform my
tasks without arbitrary restrictions.</p>

<p>Emacs lets me use Elisp to modify how I do my emails, for instance,
and how I present tasks in my custom agenda view.</p>

<p><a id="org06c4615"></a></p>

<h1>12 For an integrated computing environment</h1>

<p>Without Emacs, I would not be in a position to control my computing
experience to the extent I do.</p>

<p>The reason is that I would be relying on many different applications.
Each application has its own interface and design paradigms.</p>

<p>Each application is configured, if at all, in a way that is specific
to it. Customisations in one application do not carry over to other
applications.</p>

<p>And, if we consider the important implementation details, each
application may configurable in its own programming language.</p>

<p>In other words, that is not an integrated computing experience.</p>

<p><a id="org40d4ee4"></a></p>

<h1>13 Many apps do not combine nicely</h1>

<p>To have the same degree of control that Emacs makes possible, I would
have to hope that somehow all those disparate applications would
conspire in my favour.</p>

<p>That is wishful thinking.</p>

<p>The reality is that piecing together many different applications is an
exercise in frustration and the path to a life of ever-distracting
context switching.</p>

<p><a id="orgd541b5c"></a></p>

<h1>14 Emacs makes your workflow consistent</h1>

<p>Having everything I need inside of Emacs ensures that things happen in
a manner that is consistent.</p>

<p>All customisations are written in the same programming language,
namely, Emacs Lisp.</p>

<p>What I define for one context, such as this “presentation mode”, can
be used in another context.</p>

<p>For example, I can have this presentation style enabled when I read
emails. Why?</p>

<p>Because it can make it more comfortable for me at a certain hour. And
I can even automate this with conditional logic, so it happens on its
own when I open a new email under certain circumstances.</p>

<p><a id="orgff36a33"></a></p>

<h1>15 Integrated computing in practice</h1>

<p>When you work with many applications that do not play nicely together,
you cannot do something that the developers have not envisaged.</p>

<p>For example, your email client likely does not have access to a
“presentation mode”. Same for your other applications.</p>

<p>Similarly, your many applications will not necessarily know how to
read and interpret the configurations you have in one application.</p>

<p>Suppose you define your favourite colour scheme for your email client.
You take the time to consider the harmonies and use precise typography
to your liking.</p>

<p>Now, you switch to your calendar application and none of that work
carries over: you have to do it again, assuming it is even possible.</p>

<p><a id="org3c03994"></a></p>

<h1>16 Emacs makes integration easier</h1>

<p>Colours and styles may seem like relatively small issues. But they are
indicative of something greater: disparate applications do not work
together seamlessly.</p>

<p>Emacs does not have this problem. You define something for one context
you have in mind and, eventually, it can be used in another context
that initially you had not even thought of.</p>

<p>For example, in my Emacs I wrote a small function to quickly copy the
“thing” at where the cursor is. This is useful when I do programming,
as the “thing” can be an entire expression, like the definition of a
function. But the “thing” may also be a link that I got in my email.</p>

<p>I had not thought of that use-case in advance. Yet it was trivial to
have my function do what I need in this once unforeseen situation.</p>

<p><a id="org79e8a3a"></a></p>

<h1>17 Integration gives you emergent properties</h1>

<p>The integrated computing environment of Emacs is more than the sum of
its parts.</p>

<p>This is because you can combine different pieces of functionality in
ways that the original developer had not foresaw.</p>

<p>You do not simply have your writing, your email, your agenda, et
cetera, in Emacs.</p>

<p>You have the functionality of one in tandem with the functionality of
another. And you draw linkages between them as you see fit.</p>

<p>Consider once again this presentation I am now doing. What I have in
front of me is the transcript of my talk. This is a plain text
document, which I can edit live. Let me CAPITALISE THIS to illustrate
the point.</p>

<p><a id="orgf9e4f44"></a></p>

<h1>18 This is plain text that works like a slideshow</h1>

<p>I have made this file look a little bit like a series of slides.</p>

<p>Notice that if I scroll up and down, which I will do shortly, you only
get the current section I am reading from: you do not have access to
the rest of the document. I will scroll up and down now.</p>

<p>This is a feature known as “narrowing”. Let me “widen” the view and
then try to scroll again. You will now be exposed to the rest of the
text.</p>

<p>The original developer of this “narrowing” facility did not know how
someone like me would make use of it.</p>

<p>I have it here for my presentation. Each heading becomes its own
pseudo-slide. I have narrowing for my emails, when I want to read a
portion of the text in a more focused way. It is all about how I
choose to do my computing.</p>

<p><a id="orgc31ae17"></a></p>

<h1>19 Consistency facilitates productivity</h1>

<p>For many years before switching to Emacs, I did not enjoy using the
computer.</p>

<p>I needed too much time to accomplish every single task.</p>

<p>I could never find any of my files in a timely fashion because there
was no program that would enforce on my behalf a predictable
file-naming scheme.</p>

<p>All my notes were eventually not retrievable. This made them useless.
Data you save is only good if you can find what you are searching for.</p>

<p>My music collection was inconsistent because I needed special software
to write the metadata… In short, I was not as productive as I
would like to be.</p>

<p>And, above all, it was not fun.</p>

<p><a id="org124b771"></a></p>

<h1>20 Consistency remove the cognitive burden</h1>

<p>Most of my work at the time was centred around the email client and a
word processor.</p>

<p>The email client had its own subsystem for handling reminders for
tasks. The format of those tasks was not interoperable with other
programs.</p>

<p>I could not access the tasks with my favourite text editor. I thus had
to use the clunky interface of the email client, which was never
designed for task management—and was not configurable.</p>

<p>And then I had all the cognitively burdensome annoyances of my two
applications looking quite different from each other.</p>

<p>My emails did not behave like my documents, which made it harder for
me to flip between the two and continue writing. I would roll my eyes
each time.</p>

<p><a id="orgb512578"></a></p>

<h1>21 The consistency of Emacs in action</h1>

<p>Emacs has elevated my computing experience.</p>

<p>I have been much more productive ever since I switched to it. Allow me
to demonstrate a tiny bit of what I do each day.</p>

<p>I will temporarily exit the presentation mode in this window.</p>

<p>Then, in the bottom half of my screen, I will open my email client to
read a message I got.</p>

<p>Once you follow my switch to the email client, I will hide the window
that shows this presentation.</p>

<p>After that I will switch to my agenda to record a task and review what
I have to do.</p>

<p>All this is done inside of Emacs. Time for action!</p>

<p><a id="org0bd43c1"></a></p>

<h1>22 Use Emacs Lisp to configure everything</h1>

<p>What I just demonstrated is a very small part of what I do every
single day.</p>

<p>There is much more, though I cannot cover it all in this presentation.</p>

<p>The point, however, is the consistency of the experience; consistency
throughout.</p>

<p>I have customised my email client by writing some Emacs Lisp code for
it. I have done the same for the custom agenda I have. And much more.</p>

<p>Every time I work with Emacs Lisp, I acquire skills that are
applicable outside the confines of the problem I am solving.</p>

<p>For example, by configuring email the way I want, I pick up
programming skills that I can then apply to the design of my custom
agenda.</p>

<p><a id="org2e55e24"></a></p>

<h1>23 Learning Emacs Lisp improves the experience</h1>

<p>This is an investment that pays off more and more.</p>

<p>Emacs will adapt to match my evolving needs. Each new workflow I
incorporate in my Emacs setup will thus benefit from all the knowledge
and features I have accumulated.</p>

<p>I do not have to relearn everything because I am not switching to
another application.</p>

<p>I do not have to throw away all the work I did all those years. It is
here to stay.</p>

<p>I do not feel the pressure to try the new shiny app of the day. I did
that many times and always regretted it. I lost my data and time in
the process.</p>

<p>Because I am rooted in this stability of Emacs, I remain productive
and efficient.</p>

<p><a id="org614ea19"></a></p>

<h1>24 Emacs embodies software freedom</h1>

<p>I mentioned earlier that Emacs is free or libre software. This means
that you can read its source code, modify it, and share your changes
with others.</p>

<p>Emacs has a license that gives users power. There is no corporation
that can take Emacs away from us. It belongs to the community and we
all tend to its wellness.</p>

<p>In the case of Emacs, software freedom is not just about the license.
It informs how you use the program. Emacs makes such freedom an
irriducible part of its functionality.</p>

<p>You can, at any moment, ask Emacs what does a keyboard shortcut
actually do. What is the definition of a function. What is the value
of a variable. And you may even access the source code to check for
yourself.</p>

<p>I will demonstrate this right now.</p>

<p><a id="org40d68c8"></a></p>

<h1>25 The freedom of Emacs helps with learning</h1>

<p>I actually learnt to program in Emacs Lisp by exercising this freedom.</p>

<p>I would tinker with Emacs and continuously check on its state. What
does this do? Which function is called by that keyboard shortcut? How
is a program able to determine if the file is not saved?</p>

<p>I wanted to learn how, for example, we move down a line. From there, I
learnt that we can move down many lines at once.</p>

<p>I then figured that we can move down the lines and then also do
something else, such as place the cursor at the end of the line and
create a pulse effect to bring attention to it.</p>

<p>Not only did I learn how to configure Emacs, I even wrote tens of
extensions for it. I have also authored a libre book titled “Emacs
Lisp Elements”. This freedom is not theoretical. I did not have a
background in programming, yet was empowered to act and to grow as a
person.</p>

<p><a id="orge1d150b"></a></p>

<h1>26 Emacs is not only for programmers</h1>

<p>Emacs is extended with Emacs Lisp. If you know how to program in that
language, you can be extra opinionated and particular about the way
Emacs facilitates your work.</p>

<p>But even without any expertise of this sort, you can still do much of
what you like. Remember that I started using Emacs without a
background in programming.</p>

<p>Emacs blurs the distinction between user and developer. Many of the
developers actually start out as users like myself. They learn along
the way and, eventually, they contribute to the development of Emacs.</p>

<p>I even have written code that is in core Emacs: my <code class="language-plaintext highlighter-rouge">modus-themes</code> as
well as several other smaller patches.</p>

<p><a id="org2be826e"></a></p>

<h1>27 You benefit from all the Emacs extensions</h1>

<p>The Emacs community has developed a rich corpus of extensions. You do
not need to invent anything right away in order to be productive.</p>

<p>We call these extensions “packages”, as they are distributed in a way
that makes them easy to install and then use directly.</p>

<p>The Emacs program you will download on your computer ships with plenty
of packages built-in.</p>

<p>Depending on your needs, you may not even have to install anything
from what the community has to offer.</p>

<p>Though if you want a package, it is fairly easy to get it and run it
on your system.</p>

<p>Emacs is not picky about how you should use it. You are empowered to
be opinionated.</p>

<p><a id="org9f08566"></a></p>

<h1>28 Some powerful extensions are built-in</h1>

<p>For example, Emacs ships with a package called <code class="language-plaintext highlighter-rouge">org</code> or “Org mode”. At
its core, this is a markup language. I am using it right now in this
document.</p>

<p>Notice how lines that start with an asterisk function as headings.
This is what the markup does.</p>

<p>Org lets you write documents, including books, handle your tasks,
organise your agenda, and much more. It is a powerhouse.</p>

<p>There are so many things to discover in Emacs as well as the broader
package ecosystem.</p>

<p>Emacs as a whole provides high quality documentation that explains
everything.</p>

<p><a id="org370d80c"></a></p>

<h1>29 The documentation culture of Emacs</h1>

<p>When you install Emacs, you get with it plenty of technical manuals.
There is also an interactive tutorial to help you make sense of the
basics.</p>

<p>Furthermore, when you ask Emacs for help about the definition of a
function or the value of a variable, you receive the documentation for
the thing you are looking for.</p>

<p>The expectation for all contributions to the official Emacs program is
that the code is well-documented and the manual is updated
accordingly.</p>

<p><a id="org96add87"></a></p>

<h1>30 Most packages have high quality manuals</h1>

<p>Core Emacs sets the standard of what good documentation looks like.
Package developers follow this practice.</p>

<p>For example, my <code class="language-plaintext highlighter-rouge">denote</code> package has a manual that is over 7500 lines
long. It exceeds 52000 words. In it users find detailed instructions
as well as code snippets that they can copy and use outright. And this
is not the exception. All my packages are like that, to the extent
necessary. Most other developers do the same.</p>

<p>As a community, we have access to so much knowledge for free and in
freedom. If we are committed enough, we can learn from others and thus
become better ourselves. We do so in a spirit of sharing and caring.
For me, specifically, all this was of great help. I am self-taught
because I received all those great resources from the community. I
consider it my duty to give back in kind.</p>

<p><a id="org45b5677"></a></p>

<h1>31 Emacs has a steep learning curve</h1>

<p>Because Emacs is extensible, there is practically no limit to what you
can do with it. At least this is the case for all tasks that are
text-heavy.</p>

<p>Emacs will just gracefully evolve to match your requirements, provided
you can extend it on your own or with a relevant package.</p>

<p>The downside, however, is that it is not easy to become proficient in
it. If you are committed, you can learn the basics within the first
few days.</p>

<p>Though you will need to invest a few weeks or months to become
skillful. It depends on how much effort you put into it, what sort of
work you are doing, and what your background is.</p>

<p>I learnt the basics within a few days. I started writing my own Emacs
Lisp within weeks. And within a year I had my <code class="language-plaintext highlighter-rouge">modus-themes</code> moved
into core Emacs.</p>

<p><a id="org4460604"></a></p>

<h1>32 Do not skip the manuals</h1>

<p>Several “starter kits” are available to help you get started. They set
things up so that you do not need to discover everything at the
outset.</p>

<p>The new version of Emacs (Emacs 31) will even come with a “newcomers
theme”, which configures several settings in advance.</p>

<p>These can make the learning curve a bit smoother. For me, anything
that improves the onboarding experiences is a plus.</p>

<p>Though I do not think that Emacs will ever become “plug and play”.
This is due to its sheer depth and extensibility. It does so much that
you still need to invest the time and effort into learning it.</p>

<p>However you start, the most reliable study involves the manuals. Those
are written for the benefit of the user. Read them carefully.</p>

<p><a id="org5ce2296"></a></p>

<h1>33 Adjust your expectations</h1>

<p>What I can say with confidence is that Emacs is not for tourists. You
cannot switch to it with the expectation that you will have a good
time right away.</p>

<p>No. That will not work. There simply is no shortcut to excellence.</p>

<p>I encourage you to take it one step at a time. Emacs will make you
more productive, provided you are patient enough to unlock its
virtually boundless potential.</p>

<p>Take it slow and be methodical. Rely on the official manual no matter
your starting point. Read from it and gradually incorporate its
insights into your workflow.</p>

<p>The community—myself included—has plenty of resources to
complement that study. Blog posts, video tutorials, books… But
do not skip the official manual. Learning it slowly means that you
will become proficient faster than you otherwise would.</p>

<p><a id="org3e35022"></a></p>

<h1>34 Why it is worth learning how to use Emacs</h1>

<p>I already talked about the technical side of things with regard to the
integrated computing environment. Now combine that with two facts:</p>

<ol>
  <li>Emacs is free software. This means that we as a community are its
custodians.</li>
  <li>GNU Emacs has been around since the 1980s. It will stay relevant
for decades to come.</li>
</ol>

<p>Emacs is not old, it is timeless. This is because it can be extended
in a spirit of freedom.</p>

<p>Whatever new technology or idea we have as a collective, we can
eventually bring it into Emacs.</p>

<p>This way, our integrated computing environment adapts with the times.</p>

<p>Thus Emacs remains ever-relevant.</p>

<p><a id="org8a7c786"></a></p>

<h1>35 The initial effort pays off long-term</h1>

<p>Couched in those terms, the initial effort you will put into learning
Emacs is actually not that much.</p>

<p>You have to maintain a longer-term view of this project.</p>

<p>If you are patient, Emacs will be one of the most reliable tools you
will ever use throughout your life. And I say this as a handy man
myself, someone who uses many tools for manual labour, having built
the house I am in, among others.</p>

<p>I switched to Emacs in the summer of 2019. It is almost 7 years
already. I see no reason not to use it for the next 7 years, if I can.</p>

<p>I will still want to write articles, do programming, maintain my
agenda, and probably make presentations like this one.</p>

<p><a id="org9b2bf6a"></a></p>

<h1>36 Good luck and have fun!</h1>

<p>Remember that you will not learn Emacs over the weekend. You are in it
for the long-term. Take it slow and you will enjoy the experience.</p>

<p>This is all I have for you today folks. Thank you very much for your
attention!</p>

<p>You can find this and everything else I publish on my website:
<a href="https://protesilaos.com">https://protesilaos.com</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>My Emacs talk for FLOSS @ Oxford</title>
      <description>I talked about how to do computing in freedom with GNU Emacs.</description>
      <pubDate>Thu, 12 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-03-12-my-emacs-talk-floss-oxford/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-03-12-my-emacs-talk-floss-oxford/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Earlier today, at 20:00 Europe/Athens time, I provided an introduction
to Emacs at the event <em>FLOSS @ Oxford</em>:
<a href="https://ox.ogeer.org/event/computing-in-freedom-with-gnu-emacs-protesilaos-stavrou">https://ox.ogeer.org/event/computing-in-freedom-with-gnu-emacs-protesilaos-stavrou</a>.</p>

<p>I had written the transcript ahead of time to make my presentation
more accessible. The event was held live as a Jitsi call. There were
questions from participants, which I answered. A recording of the
event will be available before the end of this week. I will update
this article to include a link to the video.</p>

<p><strong>UPDATE 2026-03-16 07:49 +0200:</strong> The video is here: <a href="https://ogeer.org/ox/rec/emacs/">https://ogeer.org/ox/rec/emacs/</a>.</p>

<p>Below is the text of my talk. It is titled “Computing in freedom with
GNU Emacs”. Note that some parts of my presentation only make sense in
the video format, though I tried to describe in the transcript what I
was demonstrating.</p>

<hr />

<h2>Table of Contents</h2>

<ol>
  <li><a href="#org0e4cb01">Emacs as a capable text editor</a></li>
  <li><a href="#orgdebea7c">Emacs can display graphics alongside text</a></li>
  <li><a href="#orgd2f5d4e">Emacs is an extensible text editor</a></li>
  <li><a href="#orga9b1321">The extensibility of Emacs happens live</a></li>
  <li><a href="#org5eb1f93">Emacs puts you in control of your computing</a></li>
  <li><a href="#org762fb96">The promise of an integrated computing environment</a></li>
  <li><a href="#org67eee16">The integrated computing environment in practice</a></li>
  <li><a href="#orgf22c1ca">Integration gives you emergent properties</a></li>
  <li><a href="#org8e5ca04">Consistency facilitates productivity</a></li>
  <li><a href="#orgec85da1">The consistency of Emacs in action</a></li>
  <li><a href="#org7b170ca">Use Emacs Lisp to configure everything</a></li>
  <li><a href="#org69f7675">Emacs is the embodiment of software freedom</a></li>
  <li><a href="#orgeca3b3b">You do not need to be a programmer to use Emacs</a></li>
  <li><a href="#org65643a6">The documentation culture of Emacs</a></li>
  <li><a href="#org78badb8">Emacs has a steep learning curve</a></li>
  <li><a href="#orge7a15c6">Why it is worth learning how to use Emacs</a></li>
  <li><a href="#org20e78ee">Good luck and have fun!</a></li>
</ol>

<p>Hello everyone! My name is Protesilaos, also known as “Prot”. I am
joining you from the mountains of Cyprus. Cyprus is an island in the
Eastern Mediterranean Sea.</p>

<p>In this presentation I will talk to you about GNU Emacs, or simply,
“Emacs”. Emacs is a program you run on your computer. I am using it
right now for this presentation.</p>

<p>Emacs is free or libre software. It allows you to read all of its
source code, to modify it, and to share it with your customisations.
Thus you contribute to—and benefit from—a community of
welcoming Emacs users.</p>

<p>I will tell you what all this means in practice and how you can
improve your computing experience by switching to Emacs.</p>

<p><a id="org0e4cb01"></a></p>

<h2>Emacs as a capable text editor</h2>

<p>When you first start using Emacs, it feels like a regular text editor
program. You move the cursor around and edit text. Nothing obviously
impressive out-of-the-box. As a text editor, Emacs is highly capable.
It has all sorts of keyboard shortcuts that let you efficiently
operate on text. You can control Emacs without relying on the mouse,
if you want.</p>

<p>Emacs supports the Unicode standard, which is essential for
inclusivity of peoples. The world’s scripts can be expressed in Emacs.
I am a native Greek speaker. I can use functionality that is built
into Emacs to switch to the Greek alphabet in order to write
something, such as to say «καλησπέρα», which means “good evening”. I
can even spell out “Dao De Jing” (道德经), which is the title of a
book from ancient China. Plus emoji: 🙃.</p>

<p>The multitude of scripts can be present in the same document. This is
an advantage for multilingual people or those who do research that
involves many natural languages.</p>

<p>Emacs can combine several fonts in the same page as well as different
colours. Each fonts can have its own attributes, such as for its
relative size and typographic intensity. Same idea for colours. On my
screen right now, I am already combining two different font styles:
that of the heading and the body of the text.</p>

<p><a id="orgdebea7c"></a></p>

<h2>Emacs can display graphics alongside text</h2>

<p>Emacs does not limit you to a text-only interface. It can also display
images and PDF documents. Below I have a link to an image file. I will
now type a keyboard shortcut to reveal this image. And I will do it
again to hide it.</p>

<p>[Here is an image that I do not need to reproduce on my website: the
specific image does not matter]</p>

<p>This, by the way, is a spot somewhere in my mountains.</p>

<p><a id="orgd2f5d4e"></a></p>

<h2>Emacs is an extensible text editor</h2>

<p>Although you can benefit from using Emacs as a generic text editor,
what really appeals to people like me is the option to extend Emacs.
“Extend” here means to introduce new functionality; functionality that
is not available in the default program you install on your computer.</p>

<p>These extensions are written in the same programming language as most
of Emacs. It is a programming language called “Emacs Lisp” or “Elisp”.
You can extend Emacs on your own, by writing some program in Elisp, or
you can download an existing extension that the community has made
available.</p>

<p>For example, when I create a new extension for Emacs, I publish it
under the terms of a free software license—the same terms that
Emacs uses. Others can then download my extension and use it as they
prefer. If they want, they can make their own modifications on top,
which may introduce other extensions that I had not thought of in my
original implementation. And if those users follow my example, then I
can also benefit from their additions once they publish them.</p>

<p>As such, there exists a community of enthusiastic users of Emacs who
care about sharing their works with the rest of the world.</p>

<p><a id="orga9b1321"></a></p>

<h2>The extensibility of Emacs happens live</h2>

<p>Users can extend Emacs by running some Emacs Lisp program. Such a
program can be as small as a single line. Or it can be as long as it
needs to be. It does not matter. Users run the program and Emacs
immediately does what the program renders possible.</p>

<p>For example, I am doing this presentation inside of Emacs. But Emacs
does not have a “presentation mode” built into it. I thus developed my
own extension which empowers me to do what I am doing right now. Let
me toggle off my presentation mode to show you what I mean.</p>

<p>Notice that the display has changed. My main font is monospaced now.
The headings are smaller than they were before: they are the same size
as the rest of the text. There is no number next to the heading
anymore. Then, there is a bar at the bottom of my screen, with
information about what I am working on. On the side, there are line
numbers, indicating where my cursor is in this file. Plus, my current
line is highlighted with a distinct background colour. Let me shift it
up and down to illustrate this point.</p>

<p>All those elements are useful while I am programming. But they look
distracting when I wish to focus on some portion of text. So, I just
type the keyboard shortcut I have and—voilà!—I get the
style I prefer.</p>

<p><a id="org5eb1f93"></a></p>

<h2>Emacs puts you in control of your computing</h2>

<p>You may wonder: why do I even need a customisable text editor? The
answer is about control. You are in charge of what you use and how you
use it. You can piece together a workflow that works the way you
prefer.</p>

<p>This presentation mode I toggled on and off earlier behaves exactly
how I want. I decided which set of interface tweaks to apply. Another
user may have a different preference in this regard. For instance,
they may like having line numbers on the side of the screen. There is
no right or wrong answer. What matters is that Emacs gives us the
means to do what makes sense to us.</p>

<p>Now apply this principle to everything you can use Emacs for: this
will generally be a text-centric project. I run my agenda exclusively
through Emacs. I handle all my email correspondence with Emacs. I do
programming and I write prose, such as blog posts for my website and
books or technical manuals.</p>

<p>For each of these, I know that Emacs will empower me to perform my
tasks without arbitrary restrictions. Emacs lets me use Elisp to
modify how I do my emails, for instance, and how I present tasks in my
custom agenda view.</p>

<p><a id="org762fb96"></a></p>

<h2>The promise of an integrated computing environment</h2>

<p>Without Emacs, I would not be in a position to control my computing
experience to the extent I do. The reason is that I would be relying
on many different applications. Each application has its own interface
and design paradigms. Each application is configured, if at all, in a
way that is specific to it. Customisations in one application do not
carry over to other applications. And, if we consider the important
implementation details, each application may configurable in its own
programming language.</p>

<p>In other words, that is not an integrated computing experience. To
have the same degree of control that Emacs makes possible, I would
have to hope that somehow all those disparate applications would
conspire in my favour. That is wishful thinking. The reality is that
piecing together many different applications is an exercise in
frustration and the path to a life of ever-distracting context
switching.</p>

<p>Having everything I need inside of Emacs ensures that things happen in
a manner that is consistent. All customisations are written in the
same programming language, namely, Emacs Lisp. What I define for one
context, such as this “presentation mode”, can be used in another
context. For example, I can have this presentation style enabled when
I read emails. Why? Because it can make it more comfortable for me at
a certain hour. And I can even automate this, so it happens on its own
when I open a new email.</p>

<p><a id="org67eee16"></a></p>

<h2>The integrated computing environment in practice</h2>

<p>When you work with many applications that do not play nicely together,
you cannot do something that the developers have not envisaged. For
example, your email client likely does not have access to a
“presentation mode”. Same for your other applications.</p>

<p>Similarly, your many applications will not necessarily know how to
read and interpret the configurations you have in one application.
Suppose you define your favourite colour scheme for your email client.
You take the time to consider the harmonies and use precise typography
to your liking. Now, you switch to your calendar application and none
of that work carries over: you have to do it again, assuming it is
even possible.</p>

<p>Colours and styles may seem like relatively small issues. But they are
indicative of something greater: disparate applications do not work
together seamlessly.</p>

<p>Emacs does not have this problem. You define something for one context
you have in mind and, eventually, it can be used in another context
that initially you had not even thought of. For example, in my Emacs I
wrote a small function to quickly copy the “thing” at where the cursor
is. This is useful when I do programming, as the “thing” can be an
entire expression, like the definition of a function. But the “thing”
may also be a link that I got in my email. I had not thought of that
use-case in advance.</p>

<p><a id="orgf22c1ca"></a></p>

<h2>Integration gives you emergent properties</h2>

<p>The integrated computing environment of Emacs is more than the sum of
its parts. This is because you can combine different pieces of
functionality in ways that the original developer had not foresaw. You
do not simply have your writing, your email, your agenda, et cetera,
in Emacs. You have the functionality of one in tandem with the
functionality of another. And you draw linkages between them as you
see fit.</p>

<p>Consider once again this presentation I am now doing. What I have in
front of me is the transcript of my talk. This is a plain text
document, which I can edit live. Let me CAPITALISE THIS to illustrate
the point. But I have made this file look a little bit like a series
of slides. Notice that if I scroll up and down, which I will do now,
you only get the current section I am reading from: you do not have
access to the rest of the document. This is a feature known as
“narrowing”. Let me “widen” the view and then try to scroll again. You
will now be exposed to the rest of the text.</p>

<p>The original developer of this “narrowing” facility did not know how
someone like me would make use of it. I have it here for my
presentation. Each heading becomes its own pseudo-slide. I have
narrowing for my emails, when I want to read a portion of the text in
a more focused way. It is all about how I choose to do my computing.</p>

<p><a id="org8e5ca04"></a></p>

<h2>Consistency facilitates productivity</h2>

<p>For many years before switching to Emacs, I did not enjoy using the
computer. I needed too much time to accomplish every single task. I
could never find any of my files in a timely fashion because there was
no program that would enforce on my behalf a predictable file-naming
scheme.</p>

<p>All my notes were eventually not retrievable. My music collection was
inconsistent because I needed special software to write the
metadata… In short, I was not as productive as I would like to
be. And, above all, it was not fun.</p>

<p>Most of my work at the time was centred around the email client and a
word processor. The email client had its own subsystem for handling
reminders for tasks. The format of those tasks was not interoperable
with other programs. I could not access it with my favourite text
editor. I thus had to use the clunky interface of the email client,
which was never designed for task management—and was not
configurable.</p>

<p>And then I had all the cognitively burdensome annoyances of my two
applications looking quite different from each other. My emails did
not behave like my documents, which made it harder for me to flip
between the two and continue writing.</p>

<p><a id="orgec85da1"></a></p>

<h2>The consistency of Emacs in action</h2>

<p>Emacs has elevated my computing experience. I have been much more
productive ever since I switched to it. Allow me to demonstrate a tiny
bit of what I do each day. I will temporarily exit the presentation
mode in this window. Then, in the bottom half of my screen, I will
open my email client to read a message I got. After that I will switch
to my agenda to record a task and review what I have to do. All this
is done inside of Emacs. Time for action!</p>

<p><a id="org7b170ca"></a></p>

<h2>Use Emacs Lisp to configure everything</h2>

<p>What I just demonstrated is a very small part of what I do every
single day. There is much more, though I cannot cover it all in this
presentation. The point, however, is the consistency of the
experience; consistency throughout.</p>

<p>I have customised my email client by writing some Emacs Lisp code for
it. I have done the same for the custom agenda I have. And much more.</p>

<p>Every time I work with Emacs Lisp, I acquire skills that are
applicable outside the confines of the problem I am solving. For
example, by configuring email the way I want, I pick up programming
skills that I can then apply to the design of my custom agenda.</p>

<p>This is an investment that pays off more and more. Emacs will grow or
shrink to match my evolving needs. Each new workflow I incorporate in
my Emacs setup will thus benefit from all the knowledge and features I
have accumulated.</p>

<p>I do not have to relearn everything. I do not have to throw away all
the work I did. It is here to stay. I do not feel the pressure to try
the new shiny app of the day. And, because I am rooted in this
stability, I remain productive and efficient.</p>

<p><a id="org69f7675"></a></p>

<h2>Emacs is the embodiment of software freedom</h2>

<p>I mentioned earlier that Emacs is free or libre software. This means
that you can read its source code, modify it, and share your changes
with others. Emacs has a license that gives users power. There is no
corporation that can take Emacs away from us. It belongs to the
community and we all tend to its wellness.</p>

<p>Software freedom is not just about the license. Emacs makes such
freedom an irriducible part of its functionality. You can, at any
moment, ask Emacs what does a keyboard shortcut actually do. What is
the definition of a function. What is the value of a variable. And you
may even access the source code to check for yourself.</p>

<p>I actually learnt to program in Emacs Lisp by exercising this freedom.
I would tinker with Emacs and continuously check on its state. I
wanted to learn how, for example, we move down a line. From there, I
learnt that we can move down many lines at once. I then figured that
we can move down the lines and then also do something else, such as
place the cursor at the end of the line and create a pulse effect to
bring attention to it.</p>

<p>Not only did I learn how to configure Emacs, I even wrote tens of
extensions for it. I have also authored a libre book titled “Emacs
Lisp Elements”. This freedom is not theoretical. I did not have a
background in programming, yet was empowered to act.</p>

<p><a id="orgeca3b3b"></a></p>

<h2>You do not need to be a programmer to use Emacs</h2>

<p>Emacs is extended with Emacs Lisp. If you know how to program in that
language, you can be extra opinionated and particular about the way
Emacs facilitates your work.</p>

<p>But even without any expertise of this sort, you can still do much of
what you like. This is because the Emacs community has developed a
rich corpus of extensions. We call these extensions “packages”, as
they are distributed in a way that makes them easy to install and then
use directly.</p>

<p>The Emacs program you will download on your computer ships with plenty
of packages built-in. Depending on your needs, you may not even have
to install anything from what the community has to offer.</p>

<p>For example, Emacs ships with a package called <code class="language-plaintext highlighter-rouge">org</code> or “Org mode”. At
its core, this is a markup language. I am using it right now in this
document. Notice how lines that start with an asterisk function as
headings. This is what the markup does. Org lets you write documents,
including books, handle your tasks, organise your agenda, and much
more. It is a powerhouse. There are so many things to discover. Emacs
provides high quality documentation that explains everything.</p>

<p><a id="org65643a6"></a></p>

<h2>The documentation culture of Emacs</h2>

<p>When you install Emacs, you get with it plenty of technical manuals.
There is also an interactive tutorial to help you make sense of the
basics. Furthermore, when you ask Emacs for help about the definition
of a function or the value of a variable, you receive the
documentation for the thing you are looking for.</p>

<p>The expectation for all contributions to the official Emacs program is
that the code is well-documented and the manual is updated
accordingly.</p>

<p>This is true also for packages that the community develops. For
example, my <code class="language-plaintext highlighter-rouge">denote</code> package has a manual that is over 7500 lines
long. It exceeds 52000 words. In it users find detailed instructions
as well as code snippets that they can copy and use outright. And this
is not the exception. All my packages are like that, to the extent
necessary. Most other developers do the same.</p>

<p>As a community, we have access to so much knowledge for free and in
freedom. If we are committed enough, we can learn from others and thus
become better ourselves. We do so in a spirit of sharing and caring.
For me, specifically, all this was of great help. I am self-taught
because I received all those great resources from the community. I
consider it my duty to give back in kind.</p>

<p><a id="org78badb8"></a></p>

<h2>Emacs has a steep learning curve</h2>

<p>Because Emacs is extensible, there is practically no limit to what you
can do with it. At least this is the case for all tasks that are
text-heavy. Emacs will just gracefully evolve to match your
requirements, provided you know how to extend it.</p>

<p>The downside, however, is that it is not easy to become proficient in
it. If you are committed, you can learn the basics within the first
few days. Though you will need to invest a few weeks or months to
become skillful. It depends on how much effort you put into it.</p>

<p>What I can say with confidence is that Emacs is not for tourists. You
cannot switch to it with the expectation that you will have a good
time right away. No. That will not work. There simply is no shortcut
to excellence.</p>

<p>I thus encourage you to adjust your expectations. Emacs will make you
more productive, provided you are patient enough to unlock its
virtually boundless potential. Take it slow and be methodical. Rely on
the official manual. Read from it and gradually incorporate its
insights into your workflow. The community has plenty of resources to
complement that study. But do not skip the official manual. Learning
it slowly means that you will become proficient faster than you
otherwise would.</p>

<p><a id="orge7a15c6"></a></p>

<h2>Why it is worth learning how to use Emacs</h2>

<p>I already talked about the technical side of things with regard to the
integrated computing environment. Now combine that with two facts:</p>

<ol>
  <li>Emacs is free software. This means that we as a community are its
custodians.</li>
  <li>GNU Emacs has been around since the 1980s. It will stay relevant
for decades to come.</li>
</ol>

<p>Emacs is not old, it is timeless. This is because it can be extended
in a spirit of freedom. Whatever new technology or idea we have as a
collective, we can eventually bring it into Emacs. This way, our
integrated computing environment adapts with the times.</p>

<p>Couched in those terms, the initial effort you will put into learning
Emacs is actually not that much. You have to maintain a longer-term
view of this project. If are patient, Emacs will be one of the most
reliable tools you will ever use throughout your life. And I say this
as a handy man myself, having built the house I am in, among others.</p>

<p>I switched to Emacs in the summer of 2019. It is almost 7 years
already. I see no reason not to use it for the next 7 years, if I can.
I will still want to write articles, do programming, maintain my
agenda, and probably make presentations like this one.</p>

<p><a id="org20e78ee"></a></p>

<h2>Good luck and have fun!</h2>

<p>Remember that you will not learn Emacs over the weekend. You are in it
for the long-term. Take it slow and you will enjoy the experience.</p>

<p>This is all I have for you today folks. Thank you very much for your
attention!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>This Thursday I will talk about Emacs @ OxFLOSS (FLOSS @ Oxford)</title>
      <description>In this upcoming event I will introduce GNU Emacs to people at the University of Oxford.</description>
      <pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-03-09-thursday-emacs-computing-freedom-oxfloss/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-03-09-thursday-emacs-computing-freedom-oxfloss/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This Thursday, the 12th of March, at 20:00 Europe/Athens time I will
do a live presentation of Emacs for OxFLOSS (FLOSS @ Oxford). This is
an event organised by people at the University of Oxford. My goal is
to introduce Emacs to a new audience by showing them a little of what
it can do while describing how exactly it gives users freedom.</p>

<p>The presentation will be about 40 minutes long. I will then answer any
questions from the audience. Anyone can participate: no registration
is required. The event will be recorded for future reference. The link
for the video call and further details are available here:
<a href="https://ox.ogeer.org/event/computing-in-freedom-with-gnu-emacs-protesilaos-stavrou">https://ox.ogeer.org/event/computing-in-freedom-with-gnu-emacs-protesilaos-stavrou</a>.</p>

<p>I will prepare a transcript for my talk. This way people can learn
about my presentation without having to access the video file.</p>

<p>Looking forward to it!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: four new themes are coming to the ‘doric-themes’</title>
      <description>I am developing four new themes for my minimalist 'doric-themes' package.</description>
      <pubDate>Sat, 07 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-03-07-emacs-four-new-doric-themes/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-03-07-emacs-four-new-doric-themes/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I am developing four new themes for my <code class="language-plaintext highlighter-rouge">doric-themes</code> package:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">doric-almond</code> (light)</li>
  <li><code class="language-plaintext highlighter-rouge">doric-coral</code> (light)</li>
  <li><code class="language-plaintext highlighter-rouge">doric-magma</code> (dark)</li>
  <li><code class="language-plaintext highlighter-rouge">doric-walnut</code> (dark)</li>
</ul>

<p>Each of them has its own character, while they all retain the
minimalist Doric style. Below are some screenshots. Remember that
these themes use few colours, relying on typography to establish a
visual rhythm.</p>

<h2>doric-almond</h2>

<p><a href="https://protesilaos.com/assets/images/doric/doric-almond.png"><img alt="doric-almond theme sample" src="https://protesilaos.com/assets/images/doric/doric-almond.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-almond-org.png"><img alt="doric-almond theme sample" src="https://protesilaos.com/assets/images/doric/doric-almond-org.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-almond-message.png"><img alt="doric-almond theme sample" src="https://protesilaos.com/assets/images/doric/doric-almond-message.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-almond-magit.png"><img alt="doric-almond theme sample" src="https://protesilaos.com/assets/images/doric/doric-almond-magit.png" /></a></p>

<h2>doric-coral</h2>

<p><a href="https://protesilaos.com/assets/images/doric/doric-coral.png"><img alt="doric-coral theme sample" src="https://protesilaos.com/assets/images/doric/doric-coral.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-coral-org.png"><img alt="doric-coral theme sample" src="https://protesilaos.com/assets/images/doric/doric-coral-org.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-coral-message.png"><img alt="doric-coral theme sample" src="https://protesilaos.com/assets/images/doric/doric-coral-message.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-coral-magit.png"><img alt="doric-coral theme sample" src="https://protesilaos.com/assets/images/doric/doric-coral-magit.png" /></a></p>

<h2>doric-magma</h2>

<p><a href="https://protesilaos.com/assets/images/doric/doric-magma.png"><img alt="doric-magma theme sample" src="https://protesilaos.com/assets/images/doric/doric-magma.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-magma-org.png"><img alt="doric-magma theme sample" src="https://protesilaos.com/assets/images/doric/doric-magma-org.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-magma-message.png"><img alt="doric-magma theme sample" src="https://protesilaos.com/assets/images/doric/doric-magma-message.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-magma-magit.png"><img alt="doric-magma theme sample" src="https://protesilaos.com/assets/images/doric/doric-magma-magit.png" /></a></p>

<h2>doric-walnut</h2>

<p><a href="https://protesilaos.com/assets/images/doric/doric-walnut.png"><img alt="doric-walnut theme sample" src="https://protesilaos.com/assets/images/doric/doric-walnut.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-walnut-org.png"><img alt="doric-walnut theme sample" src="https://protesilaos.com/assets/images/doric/doric-walnut-org.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-walnut-message.png"><img alt="doric-walnut theme sample" src="https://protesilaos.com/assets/images/doric/doric-walnut-message.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-walnut-magit.png"><img alt="doric-walnut theme sample" src="https://protesilaos.com/assets/images/doric/doric-walnut-magit.png" /></a></p>

<h2>Coming in version 1.1.0</h2>

<p>All four themes are in development. I may still make some minor
refinements to them, though I have already defined their overall
appearance. If you like the minimalism of the <code class="language-plaintext highlighter-rouge">doric-themes</code>, I think
you will appreciate these new additions.</p>

<h2>Sources</h2>

<p>The Doric themes use few colours and will appear monochromatic in many
contexts. They are my most minimalist themes. Styles involve the
careful use of typographic features and subtleties in colour gradients
to establish a consistent rhythm.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>I talk with Joshua Blais about Emacs and life issues</title>
      <description>I had a ~2-hour chat with Joshua Blais, a fellow Emacs user, about Emacs and philosophy.</description>
      <pubDate>Thu, 05 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-03-05-emacs-and-philosophy-chat-with-joshua-blais/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-03-05-emacs-and-philosophy-chat-with-joshua-blais/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=1vMlGFELajQ">https://www.youtube.com/watch?v=1vMlGFELajQ</a></p>
         
         <p>I had a ~2-hour chat with Joshua Blais, a fellow Emacs user, over at
the @JoshuaBlais YouTube channel: <a href="https://www.youtube.com/@JoshuaBlais">https://www.youtube.com/@JoshuaBlais</a>.
We covered Emacs at length and also talked about general life issues.</p>

<p>The first topic we cover is how to place constraints on yourself in
order to avoid backsliding into bad habits. This ties in to the themes
of discipline and productivity that we discuss in some further length.</p>

<p>Joshua asks me how I got into Emacs and how I started
writing/maintaining packages for it. We talk about how Emacs provides
for an integrated computing experience. Learning Emacs Lisp allows you
to have better control of Emacs.</p>

<p>In this light we comment on Guix and how it is also configurable in a
dialect of Lisp. Joshua is using Nix and I learn more about that
experience.</p>

<p>Coming back to Emacs, we comment on its relationship to the Unix
philosophy. I think Emacs is compatible with Unix. Though my main
point is how Emacs empowers us to use the computer in a productive
way. It augments the experience.</p>

<p>Simple living and financial independence is another topic we cover.
Joshua wants to know how I approach this issue. I explain how it is a
matter of controlling your wants. Figure out what the parts of your
lifestyle that you would not sacrifice. Then you know how much money
you need for that lifestyle.</p>

<p>Joshua makes a connection of the simple life to Emacs and Unix tools.
I comment on that as well. Once you start using Emacs and friends, you
learn to appreciate the essentials. This you can then apply to other
parts of your life.</p>

<p>We move to note-taking, where I comment about Denote. I explain how it
is a file-naming scheme, which can also be used to write notes. What
matters is how well we can retrieve information. Joshua explains how
pen and paper helps him express his thoughts.</p>

<p>Learning on your own is our next point. Being an autodidact myself, I
comment how it empowers you. You are able to have initiative and be
more independent.</p>

<p>We then explore how things have infinite depth. This is how everything
in the world is connected. This also relates to the point about the
simple living, since you can have relatively few things that you keep
understanding in depth.</p>

<p>Joshua asks me about discipline. This is a capacity we can build up. I
give some examples.</p>

<p>Next on our list are mechanical keyboards. Joshua and I are using a
split keyboard.</p>

<p>Then we explore the theme of using tools the right way. One example is
the Internet as a whole. Another is with LLMs. It helps to know “why
am I doing this”, as then you can understand when you are meeting your
goals and when you are moving away from them. We explore this in
further depth.</p>

<p>I comment on a common mistake we make where we think that the complex
must be sophisticated and profound. Whereas there is profundity in
simplicity.</p>

<p>We connect the dots through all these as we wrap things up.</p>

<p>Thanks to Joshua Blais for this chat. I had a good time and wish him
all the best!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: confirm package bugs with –init-directory</title>
      <description>Information on how to use the Emacs --init-directory flag to identify bugs with packages you rely on.</description>
      <pubDate>Wed, 18 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-02-18-emacs-confirm-package-bugs/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-02-18-emacs-confirm-package-bugs/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Much of the maintenance work I do for my packages involves
correspondence with users about potential bugs. Sometimes, a user will
encounter a problem that I cannot reproduce on my end. I thus try to
recreate the bug in a pristine environment and ask my correspondent to
do the same.</p>

<p>This has become easier since Emacs 29, which introduced a command-line
flag called <code class="language-plaintext highlighter-rouge">--init-directory</code>. It is responsible for loading the
<code class="language-plaintext highlighter-rouge">init.el</code> that is present in the given directory. For example:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># From a terminal or shell, run something like this:</span>
emacs <span class="nt">--init-directory</span><span class="o">=</span>/tmp/test-emacs/
</code></pre></div></div>

<p>In other words, you can keep your regular configuration intact while
launching Emacs with another set of options.</p>

<h2>Create the test init.el file</h2>

<p>Have a directory that is unrelated to your regular Emacs
configuration. Then write the <code class="language-plaintext highlighter-rouge">init.el</code> inside of it.</p>

<p>Because I do this frequently, I prefer to use the standard Linux path
<code class="language-plaintext highlighter-rouge">/tmp/</code>. Its files get deleted as soon as I switch off the computer,
which is exactly what I want in this case.</p>

<p>As such, if there is a bug with, say, the <code class="language-plaintext highlighter-rouge">modus-themes</code>, I will work
with this file path <code class="language-plaintext highlighter-rouge">/tmp/modus-themes/init.el</code>.</p>

<p>But the exact location of the directory does not matter, so choose
what makes sense to you.</p>

<h2>Write the minimum necessary code</h2>

<p>In that init file, include only the code that is needed to reproduce
the bug.</p>

<p>Since you want to have the package installed, it makes sense to write
a <code class="language-plaintext highlighter-rouge">use-package</code> declaration for it. Include the <code class="language-plaintext highlighter-rouge">:ensure t</code> directive
as it instructs the built-in package manager to install the package if
it is not already available.</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Contents of the init.el...</span>
<span class="p">(</span><span class="nb">use-package</span> <span class="nv">modus-themes</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">modus-themes-common-palette-overrides</span>
        <span class="o">'</span><span class="p">((</span><span class="nv">fringe</span> <span class="nv">unspecified</span><span class="p">)</span>
          <span class="p">(</span><span class="nv">border-mode-line-active</span> <span class="nv">unspecified</span><span class="p">)</span>
          <span class="p">(</span><span class="nv">border-mode-line-inactive</span> <span class="nv">unspecified</span><span class="p">)))</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">modus-vivendi-palette-overrides</span>
        <span class="o">'</span><span class="p">((</span><span class="nv">bg-main</span> <span class="s">"#1e1f22"</span><span class="p">)</span>
          <span class="p">(</span><span class="nv">fg-main</span> <span class="s">"#bcbec4"</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'modus-vivendi</span> <span class="no">t</span><span class="p">))</span>
</code></pre></div></div>

<h2>Install from source, if necessary</h2>

<p>If you are using an alternative to <code class="language-plaintext highlighter-rouge">package.el</code> like <code class="language-plaintext highlighter-rouge">straight</code> or
<code class="language-plaintext highlighter-rouge">elpaca</code>, then the aforementioned <code class="language-plaintext highlighter-rouge">:ensure t</code> will likely not suffice:
you need to build the package from source. To this end, Emacs has the
function <code class="language-plaintext highlighter-rouge">package-vc-install</code>. Some of my recent packages have sample
code that relies on this approach. For instance:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">gnome-accent-theme-switcher</span>
  <span class="ss">:demand</span> <span class="no">t</span>
  <span class="ss">:init</span>
  <span class="c1">;; Then upgrade it with the command `package-vc-upgrade' or `package-vc-upgrade-all'.</span>
  <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nv">package-installed-p</span> <span class="ss">'gnome-accent-theme-switcher</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">package-vc-install</span> <span class="s">"https://github.com/protesilaos/gnome-accent-theme-switcher.git"</span><span class="p">))</span>
  <span class="ss">:bind</span>
  <span class="p">((</span><span class="s">"&lt;f5&gt;"</span> <span class="o">.</span> <span class="nv">gnome-accent-theme-switcher-toggle-mode</span><span class="p">)</span>
   <span class="p">(</span><span class="s">"C-&lt;f5&gt;"</span> <span class="o">.</span> <span class="nv">gnome-accent-theme-switcher-change-accent</span><span class="p">))</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="nv">gnome-accent-theme-switcher-mode</span> <span class="mi">1</span><span class="p">))</span>
</code></pre></div></div>

<p>In the above snippet <code class="language-plaintext highlighter-rouge">package-vc-install</code> will pull the latest commit
from the main branch, though it can even get a specific commit. Read
its documentation with <code class="language-plaintext highlighter-rouge">M-x describe-function</code>.</p>

<p>What matters is that you fetch the version which you are running in
your personaly configuration.</p>

<h2>Launch Emacs with this configuration</h2>

<p>From the command-line, run something like the following:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>emacs <span class="nt">--init-directory</span><span class="o">=</span>/tmp/test-emacs/
</code></pre></div></div>

<p>This will launch a new instance of Emacs. The <code class="language-plaintext highlighter-rouge">use-package</code> you placed
there will do the work to install the package. After that you are
ready to reproduce the bug in this clean setup.</p>

<h2>Write down all the steps</h2>

<p>To help the maintainer identify the source of the trouble, keep a
record of all the steps you followed. Some bugs show up when the
package is loaded, but others are triggered only after a specific
action is performed.</p>

<p>Normally, Emacs will pop up a <code class="language-plaintext highlighter-rouge">*Backtrace*</code> buffer when it encounters
an error. Copy its contents and send them to the maintainer, together
with the <code class="language-plaintext highlighter-rouge">init.el</code> you used, and the list of the steps you followed.</p>

<h2>Sometimes you just need to re-install the package</h2>

<p>It sometimes happens that you install a package and it is completely
broken. Although this looks bad, it may not even be a bug, but an
issue with the old bytecode you had on your system from the previous
version of the package.</p>

<p>Do <code class="language-plaintext highlighter-rouge">M-x package-delete</code>, select the package, restart Emacs, and then
<code class="language-plaintext highlighter-rouge">M-x package-install</code> to install the package anew. If everything
works, then the problem is gone and you do not need to tell the
maintainer about it.</p>

<h2>Make it easier for maintainers to help you</h2>

<p>With this knowledge, you can provide high quality bug reports for the
packages you rely on. Good luck!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: I will talk about Emacs and free software (FLOSS @ Oxford)</title>
      <description>Information about my upcoming Emacs-related talk for the event 'FLOSS @ Oxford'.</description>
      <pubDate>Mon, 16 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-02-16-emacs-talk-oxford/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-02-16-emacs-talk-oxford/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>People from the University of Oxford are organising events related to
free software: <a href="https://ox.ogeer.org/">FLOSS @ Oxford</a>.</p>

<p>On Thursday, the 12th of March 2026, at 6 PM United Kingdom time (GMT)
I will give a talk titled <a href="https://ox.ogeer.org/event/computing-in-freedom-with-gnu-emacs-protesilaos-stavrou">Computing in freedom with GNU Emacs</a>.
My intention is to introduce Emacs to a wide audience. Participation
is open to everyone.</p>

<p>I will post a reminder as we get closer to the date of the event.
Looking forward to it!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: add custom entity (Austrian school) to my ‘institution-calendar’</title>
      <description>This is a guide on how to expand my institution-calendar package to work with your institution.</description>
      <pubDate>Sat, 14 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-02-14-emacs-institution-calendar-add-custom-entity/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-02-14-emacs-institution-calendar-add-custom-entity/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>My <code class="language-plaintext highlighter-rouge">institution-calendar</code> package for Emacs displays term+week
indicators in the <code class="language-plaintext highlighter-rouge">*Calendar*</code> buffer (which, by default, is produced
by the <code class="language-plaintext highlighter-rouge">calendar</code> command). This is useful, for example, for schools
who organise their work by terms, such as winter, spring, and summer,
with each having a set number of weeks. This is how the University of
Oxford will look like:</p>

<p><a href="https://protesilaos.com/assets/images/attachments/2026-01-09-oxford-calendar.png"><img alt="Oxford calendar for Emacs" src="https://protesilaos.com/assets/images/attachments/2026-01-09-oxford-calendar.png" /></a></p>

<p>The package supports the universities of Oxford and Cambridge
out-of-the-box, though users can define their own institutions. I have
two institutions there to provide concrete examples. I am happy to add
more, but the idea is for users to maintain their own data.</p>

<p>Below I show a complete example using data for a school in Austria.</p>

<h2>Write the calendar data</h2>

<p>To make this work, you first need to specify the data. This has the
same structure as <code class="language-plaintext highlighter-rouge">institution-calendar-oxford-university-dates</code> and
thus passes the test of <code class="language-plaintext highlighter-rouge">institution-calendar-valid-data-p</code>. Look at
the code for Oxford to get an idea. Here is a sample:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defvar</span> <span class="nv">my-austrian-school-dates</span>
  <span class="o">'</span><span class="p">((</span><span class="mi">2025</span> <span class="p">(</span><span class="nv">wintersemester</span> <span class="p">(</span> <span class="mi">9</span>  <span class="mi">8</span> <span class="mi">2025</span><span class="p">)</span> <span class="p">(</span> <span class="mi">2</span>  <span class="mi">6</span> <span class="mi">2026</span><span class="p">))</span>
          <span class="p">(</span><span class="nv">sommersemester</span> <span class="p">(</span> <span class="mi">2</span> <span class="mi">16</span> <span class="mi">2026</span><span class="p">)</span> <span class="p">(</span> <span class="mi">7</span> <span class="mi">10</span> <span class="mi">2026</span><span class="p">)))))</span>
</code></pre></div></div>

<p>This is an Austrian school that has two terms for the academic year
starting in 2025: <code class="language-plaintext highlighter-rouge">wintersemester</code> and <code class="language-plaintext highlighter-rouge">sommersemester</code>. The symbols
for those terms can be anything. Internally, the package uses the
first letter to form the week indicator, followed by the number of the
week within the given term.</p>

<p>Each term defines a start date and an end date as a list of integers
of the form <code class="language-plaintext highlighter-rouge">(MONTH DAY YEAR)</code>. I picked a form that is consistent
with the way <code class="language-plaintext highlighter-rouge">calendar.el</code> represents the date, otherwise I would have
used a different standard.</p>

<h2>Register your institution</h2>

<p>The variable <code class="language-plaintext highlighter-rouge">institution-calendar-user-entities</code> contains all
user-defined institutions and their corresponding calendar data. Each
entry is a cons cell of the form <code class="language-plaintext highlighter-rouge">(ENTITY . CALENDAR-DATA)</code>, where
<code class="language-plaintext highlighter-rouge">ENTITY</code> is an arbitrary symbol and <code class="language-plaintext highlighter-rouge">CALENDAR-DATA</code> is the symbol of a
variable that holds the data, as shown in the previous section.</p>

<p>Here is how we can add to this list:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'institution-calendar-user-entities</span> <span class="p">(</span><span class="nb">cons</span> <span class="ss">'austrian-school</span> <span class="ss">'my-austrian-school-dates</span><span class="p">))</span>
</code></pre></div></div>

<p>In this example, I am calling the newly registered institution
<code class="language-plaintext highlighter-rouge">austrian-school</code>, which is how I can refer to it elsewhere. I am
associating this <code class="language-plaintext highlighter-rouge">austrian-school</code> with the calendar data of the
variable <code class="language-plaintext highlighter-rouge">my-austrian-school-dates</code>.</p>

<h2>Make the <code class="language-plaintext highlighter-rouge">institution-calendar-mode</code> work for your institution</h2>

<p>With the aforementioned in place, the user option <code class="language-plaintext highlighter-rouge">institution-calendar-entity</code>
can be set to the value of <code class="language-plaintext highlighter-rouge">austrian-school</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">setopt</span> <span class="nv">institution-calendar-entity</span> <span class="ss">'austrian-school</span><span class="p">)</span>
</code></pre></div></div>

<p>If the <code class="language-plaintext highlighter-rouge">institution-calendar-mode</code> is enabled, then the regular
<code class="language-plaintext highlighter-rouge">calendar</code> command will display week indicators for this school. This
is good if you only need one calendar. But if you work with many
institutions and thus need to switch between their calendars, then
ignore this step and move to the next one. Or ignore it anyway if you
prefer to keep the <code class="language-plaintext highlighter-rouge">M-x calendar</code> intact.</p>

<h2>Define a custom command for your institution</h2>

<p>The macro <code class="language-plaintext highlighter-rouge">institution-calendar-define-convenience-command</code> makes it
trivial to define a command that produces a calendar buffer for the
given institution. This is like <code class="language-plaintext highlighter-rouge">M-x calendar</code> with the minor mode
<code class="language-plaintext highlighter-rouge">institution-calendar-mode</code> enabled, except it does not alter the
output of the <code class="language-plaintext highlighter-rouge">calendar</code>—so you can use them both (or, anyhow, use
as many as the institutions you care about).</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; This defines the command `institution-calendar-austrian-school'.</span>
<span class="c1">;; Call `institution-calendar-austrian-school' with M-x or bind it to a key.</span>
<span class="p">(</span><span class="nv">institution-calendar-define-convenience-command</span> <span class="nv">austrian-school</span><span class="p">)</span>
</code></pre></div></div>

<p>Once you evaluate this macro call, you will get the command
<code class="language-plaintext highlighter-rouge">institution-calendar-austrian-school</code>. Use that to produce a calendar
that works with the <code class="language-plaintext highlighter-rouge">austrian-school</code> in particular. If you are
curious, <code class="language-plaintext highlighter-rouge">M-x institution-calendar-oxford-university</code> will still do
the right thing for the University of Oxford. Same for the command
<code class="language-plaintext highlighter-rouge">institution-calendar-cambridge-university</code>.</p>

<h2>Use an intermonth header</h2>

<p>The user option <code class="language-plaintext highlighter-rouge">institution-calendar-include-intermonth-header</code> adds
a header above the week numbers. By default, this only works with the
universities of Oxford and Cambridge. Though you can extend the
package to support your institution by adding to the value of the
variable <code class="language-plaintext highlighter-rouge">institution-calendar-intermonth-headers</code>. Thus:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'institution-calendar-intermonth-headers</span> <span class="p">(</span><span class="nb">cons</span> <span class="ss">'austrian-school</span> <span class="s">"AU"</span><span class="p">))</span>
</code></pre></div></div>

<p>You can skip this step if you do not plan to display the intermonth
header. Those are not shown by default.</p>

<h2>Putting it all together</h2>

<p>This is how your configuration of the <code class="language-plaintext highlighter-rouge">institution-calendar</code> may look like:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">institution-calendar</span>
  <span class="ss">:ensure</span> <span class="no">nil</span> <span class="c1">; not in a package archive</span>
  <span class="ss">:init</span>
  <span class="c1">;; Install it from source.</span>
  <span class="c1">;; Then upgrade it with the command `package-vc-upgrade' or `package-vc-upgrade-all'.</span>
  <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nv">package-installed-p</span> <span class="ss">'institution-calendar</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">package-vc-install</span> <span class="s">"https://github.com/protesilaos/institution-calendar.git"</span><span class="p">))</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="nb">defvar</span> <span class="nv">my-austrian-school-dates</span>
    <span class="o">'</span><span class="p">((</span><span class="mi">2025</span> <span class="p">(</span><span class="nv">wintersemester</span> <span class="p">(</span> <span class="mi">9</span>  <span class="mi">8</span> <span class="mi">2025</span><span class="p">)</span> <span class="p">(</span> <span class="mi">2</span>  <span class="mi">6</span> <span class="mi">2026</span><span class="p">))</span>
            <span class="p">(</span><span class="nv">sommersemester</span> <span class="p">(</span> <span class="mi">2</span> <span class="mi">16</span> <span class="mi">2026</span><span class="p">)</span> <span class="p">(</span> <span class="mi">7</span> <span class="mi">10</span> <span class="mi">2026</span><span class="p">)))))</span>

  <span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'institution-calendar-user-entities</span> <span class="p">(</span><span class="nb">cons</span> <span class="ss">'austrian-school</span> <span class="ss">'my-austrian-school-dates</span><span class="p">))</span>

  <span class="c1">;; This defines the command `institution-calendar-austrian-school'.</span>
  <span class="c1">;; Call `institution-calendar-austrian-school' with M-x or bind it to a key.</span>
  <span class="p">(</span><span class="nv">institution-calendar-define-convenience-command</span> <span class="nv">austrian-school</span><span class="p">)</span>

  <span class="p">(</span><span class="nv">setopt</span> <span class="nv">institution-calendar-include-extra-week-numbers</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">setopt</span> <span class="nv">institution-calendar-include-intermonth-header</span> <span class="no">nil</span><span class="p">)</span>

  <span class="c1">;; These are optional, if you want `M-x calendar' to work for your institution.</span>
  <span class="p">(</span><span class="nv">setopt</span> <span class="nv">institution-calendar-entity</span> <span class="ss">'austrian-school</span><span class="p">)</span>

  <span class="p">(</span><span class="nv">institution-calendar-mode</span> <span class="mi">1</span><span class="p">))</span>
</code></pre></div></div>

<h2>Sources</h2>

<ul>
  <li>Git repository: <a href="https://github.com/protesilaos/institution-calendar">https://github.com/protesilaos/institution-calendar</a></li>
  <li>Screenshot: <a href="https://protesilaos.com/codelog/2026-02-11-emacs-institution-calendar/">https://protesilaos.com/codelog/2026-02-11-emacs-institution-calendar/</a></li>
  <li>Backronyms: Interestingly Nothing Serving Teachers Implement Term
Utilities Took Inspiration from Oxford Novices… calendar;
Institution … Cambridge Added Lent Entry Notwithstanding Dates
Already Recorded.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: my GNOME accent color theme switcher package</title>
      <description>Video demo of my new Emacs package that synchronises the theme with that of the GNOME desktop environment.</description>
      <pubDate>Fri, 13 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-02-13-emacs-gnome-accent-theme-switcher/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-02-13-emacs-gnome-accent-theme-switcher/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=atKuEh3_ArA">https://www.youtube.com/watch?v=atKuEh3_ArA</a></p>
         
         <p>In this short video I demonstate a new package for GNU Emacs that
synchronises the Emacs theme with the GNOME settings for accent color
and light/dark mode. Git repository here:
<a href="https://github.com/protesilaos/gnome-accent-theme-switcher">https://github.com/protesilaos/gnome-accent-theme-switcher</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: Lin version 2.0.0</title>
      <description>Information about the latest version of my lin package for GNU Emacs.</description>
      <pubDate>Thu, 12 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-02-12-emacs-lin-2-0-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-02-12-emacs-lin-2-0-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Lin is a stylistic enhancement for Emacs’ built-in <code class="language-plaintext highlighter-rouge">hl-line-mode</code>.  It
remaps the <code class="language-plaintext highlighter-rouge">hl-line</code> face (or equivalent) buffer-locally to a style that
is optimal for major modes where line selection is the primary mode of
interaction.</p>

<p>The idea is that <code class="language-plaintext highlighter-rouge">hl-line-mode</code> cannot work equally well for contexts
with competing priorities: (i) line selection, or (ii) simple line
highlight.  In the former case, the current line needs to be made
prominent because it carries a specific meaning of some significance in
the given context: the user has to select a line.  Whereas in the latter
case, the primary mode of interaction does not revolve around the line
highlight itself: it may be because the focus is on editing text or
reading through the buffer’s contents, so the current line highlight is
more of a reminder of the point’s location on the vertical axis.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">lin</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/lin">https://protesilaos.com/emacs/lin</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/lin-changelog">https://protesilaos.com/emacs/lin-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/lin">https://github.com/protesilaos/lin</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/lin">https://gitlab.com/protesilaos/lin</a></li>
    </ul>
  </li>
  <li>Backronym: LIN Is Noticeable.</li>
</ul>

<p>Below are the release notes</p>

<hr />

<h2>Version 2.0.0 on 2026-02-12</h2>

<p>This is the first tagged release since 2024-08-05. The package is in a
stable state: it does everything it is meant to. This version makes
some small refinements, mostly in how parts of the code are written.
Though there also are some nice user-facing changes:</p>

<ul>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">lin-gnome-accent-color-mode</code> synchronises the accent colour of
the GNOME desktop environment with Lin’ own <code class="language-plaintext highlighter-rouge">lin-face</code>. This happens
live, so any buffers that are already using the <code class="language-plaintext highlighter-rouge">lin-mode</code> (directly
or via <code class="language-plaintext highlighter-rouge">lin-global-mode</code>) will get the updated colour.</p>
  </li>
  <li>
    <p>The user option <code class="language-plaintext highlighter-rouge">lin-gnome-accent-color-override-foreground</code>
controls whether the faces that correspond to GNOME accent colours
should override the underlying text colour or not. This is useful
for improved colour contrast. The default is to not override the
foreground. Setting <code class="language-plaintext highlighter-rouge">lin-gnome-accent-color-override-foreground</code> to
non-<code class="language-plaintext highlighter-rouge">nil</code> changes that so, for example, the <code class="language-plaintext highlighter-rouge">lin-face</code> will be set
to <code class="language-plaintext highlighter-rouge">lin-red-override-fg</code> instead of <code class="language-plaintext highlighter-rouge">lin-red</code> (of course, faces can
be modified by users/themes to override the foreground anyway, so
this is about the default behaviour).</p>
  </li>
  <li>
    <p>New faces to style the current line when <code class="language-plaintext highlighter-rouge">lin-mode</code> is enabled
include <code class="language-plaintext highlighter-rouge">lin-purple</code>, <code class="language-plaintext highlighter-rouge">lin-orange</code>, and <code class="language-plaintext highlighter-rouge">lin-slate</code>. Those do not
override the underlying foreground colours by default. Whereas
<code class="language-plaintext highlighter-rouge">lin-purple-override-fg</code>, <code class="language-plaintext highlighter-rouge">lin-orange-override-fg</code>, and
<code class="language-plaintext highlighter-rouge">lin-slate-override-fg</code> apply their background while also setting
the foreground (remember that you always control which face to use
by changing the user option <code class="language-plaintext highlighter-rouge">lin-face</code>).</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">lin-global-mode</code> skips all private buffers. These are buffers
that users normally do not interact with directly. Their names are
prefixed with a space and, by default, are hidden from the view of
<code class="language-plaintext highlighter-rouge">switch-to-buffer</code> and related commands.</p>
  </li>
  <li>
    <p>The default value of the user option <code class="language-plaintext highlighter-rouge">lin-mode-hooks</code> now includes
the <code class="language-plaintext highlighter-rouge">world-clock-mode-hook</code> and <code class="language-plaintext highlighter-rouge">xref--xref-buffer-mode-hook</code>. The
former relates to the command <code class="language-plaintext highlighter-rouge">world-clock</code>, while the latter is
used by any command that produces Grep-like results via the built-in
Xref infrastructure (for example, my Denote package does that for a
few of its commands). The <code class="language-plaintext highlighter-rouge">lin-mode-hooks</code> is a list of hooks for
major modes that should use the Lin style for the selection line
highlight.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: institution-calendar package (University of Oxford/Cambridge, etc.)</title>
      <description>The institution-calendar package for GNU Emacs augments the calendar buffer with indicators about term weeks (e.g. for university semesters).</description>
      <pubDate>Wed, 11 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-02-11-emacs-institution-calendar/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-02-11-emacs-institution-calendar/</guid>
      <content:encoded>
        <![CDATA[
         
         <p><a href="https://protesilaos.com/assets/images/attachments/2026-01-09-oxford-calendar.png"><img alt="Oxford calendar for Emacs" src="https://protesilaos.com/assets/images/attachments/2026-01-09-oxford-calendar.png" /></a></p>

<p>This is about a new package of mine: <code class="language-plaintext highlighter-rouge">institution-calendar</code>. It is not
going to be available on GNU ELPA. Users will have to install it from
source (code for this is further below). The reason is that the
predecossor to this package, <code class="language-plaintext highlighter-rouge">oxford-calendar</code>, was not accepted:</p>

<ul>
  <li><a href="https://lists.gnu.org/archive/html/emacs-devel/2026-01/msg00337.html">https://lists.gnu.org/archive/html/emacs-devel/2026-01/msg00337.html</a>.</li>
  <li><a href="https://lists.gnu.org/archive/html/emacs-devel/2026-01/msg00401.html">https://lists.gnu.org/archive/html/emacs-devel/2026-01/msg00401.html</a>.</li>
</ul>

<p>I will consider my options going forward, with whatever that means for
all my packages.</p>

<h2>Overview</h2>

<p>The <code class="language-plaintext highlighter-rouge">institution-calendar</code> package augments the <code class="language-plaintext highlighter-rouge">M-x calendar</code> buffer
to include indicators about the applicable term. Each term has week
numbers, which are displayed on the side of the regular calendar data.</p>

<p>The user option <code class="language-plaintext highlighter-rouge">institution-calendar-entity</code> specifies which
institution’s data to use. Currently, the value can be either
<code class="language-plaintext highlighter-rouge">oxford-university</code> or <code class="language-plaintext highlighter-rouge">cambridge-university</code>. Contact me and I will
add support for your institution.</p>

<p>Each term shows the week numbers it formally defines. For example, the
University of Oxford has three terms of 8 weeks each. When the user
option <code class="language-plaintext highlighter-rouge">institution-calendar-include-extra-week-numbers</code> is set to a
non-<code class="language-plaintext highlighter-rouge">nil</code> value, then an additional two weeks are added: week 0 for
one week before the term starts and an extra number after the term
ends. This is useful for scheduling purposes, such as to arrange
meetings in preparation of the work ahead or to report on what
happened.</p>

<p>The user option <code class="language-plaintext highlighter-rouge">institution-calendar-include-intermonth-header</code>
writes text above the institution’s week indicators. This makes it a
bit easier to tell them apart from the regular calendar data.</p>

<h2>Showing the calendar</h2>

<p>Enable the minor mode <code class="language-plaintext highlighter-rouge">institution-calendar-mode</code> to make all future
calls to <code class="language-plaintext highlighter-rouge">M-x calendar</code> use the relevant institution data.</p>

<p>If you do not want to affect the <code class="language-plaintext highlighter-rouge">M-x calendar</code> output, then use the
command <code class="language-plaintext highlighter-rouge">institution-calendar</code>: it is functionally equivalent to
having the aforementioned minor mode enabled, except it has no
permanent effect on <code class="language-plaintext highlighter-rouge">M-x calendar</code>—that will keep its original
appearance.</p>

<p>If, for whatever reason, you need to check the calendar of a specific
institution, then do <code class="language-plaintext highlighter-rouge">M-x institution-calendar-cambridge-university</code>
or <code class="language-plaintext highlighter-rouge">M-x institution-calendar-oxford-university</code> (more such commands
will be available to match any other institutions that this package
will support).</p>

<h2>Installation and configuration</h2>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">institution-calendar</span>
  <span class="ss">:ensure</span> <span class="no">nil</span> <span class="c1">; not in a package archive</span>
  <span class="ss">:init</span>
  <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nv">package-installed-p</span> <span class="ss">'institution-calendar</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">package-vc-install</span> <span class="s">"https://github.com/protesilaos/institution-calendar.git"</span><span class="p">))</span>
  <span class="ss">:commands</span>
  <span class="p">(</span><span class="nv">institution-calendar</span>
   <span class="nv">institution-calendar-cambridge-university</span>
   <span class="nv">institution-calendar-oxford-university</span><span class="p">)</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="nv">setopt</span> <span class="nv">institution-calendar-entity</span> <span class="ss">'oxford-university</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">setopt</span> <span class="nv">institution-calendar-include-extra-week-numbers</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">setopt</span> <span class="nv">institution-calendar-include-intermonth-header</span> <span class="no">nil</span><span class="p">)</span>

  <span class="c1">;; If you want to permanently change what M-x calendar shows, enable</span>
  <span class="c1">;; this mode.  Otherwise, use the relevant command from the</span>
  <span class="c1">;; :commands listed above.</span>
  <span class="p">(</span><span class="nv">institution-calendar-mode</span> <span class="mi">1</span><span class="p">))</span>
</code></pre></div></div>

<h2>Sources</h2>

<ul>
  <li>Git repository: <a href="https://github.com/protesilaos/institution-calendar">https://github.com/protesilaos/institution-calendar</a></li>
  <li>Screenshot: <a href="https://protesilaos.com/codelog/2026-01-09-emacs-oxford-calendar-package/">https://protesilaos.com/codelog/2026-01-09-emacs-oxford-calendar-package/</a></li>
  <li>Backronyms: Interestingly Nothing Serving Teachers Implement Term
Utilities Took Inspiration from Oxford Novices… calendar;
Institution … Cambridge Added Lent Entry Notwithstanding Dates
Already Recorded (yes, I always have a lot of fun writing these!).</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: doric-themes version 1.0.0</title>
      <description>Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate).</description>
      <pubDate>Mon, 09 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-02-09-emacs-doric-themes-1-0-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-02-09-emacs-doric-themes-1-0-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>These are my minimalist themes. They use few colours and will appear
mostly monochromatic in many contexts. Styles involve the careful use
of typography, such as italics and bold italics.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 1.0.0 on 2026-02-09</h2>

<h3>Two new themes</h3>

<p><code class="language-plaintext highlighter-rouge">doric-jade</code> is a light theme with a predominantly green feel.</p>

<p><code class="language-plaintext highlighter-rouge">doric-copper</code> is a dark theme with orange, magenta, and cyan colours.</p>

<p>I have update all screenshots: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a>.</p>

<h3>Revised styles for Org TODO and DONE</h3>

<p>The relevant faces now use a colour-coding scheme where TODO states
are rendered in red while DONE are green.</p>

<p>This is done to ensure cross-theme consistency. Those faces
communicate a certain state and, therefore, it is better to not have
to relearn which colour means what while switching between the Doric
themes.</p>

<h3>Org <code class="language-plaintext highlighter-rouge">~code~</code> faces stand out more</h3>

<p>This is done to differentiate them from <code class="language-plaintext highlighter-rouge">=verbatim=</code>. It is especially
important for users who choose to hide the markup with the user option
<code class="language-plaintext highlighter-rouge">org-hide-emphasis-markers</code> (I used to do that but realised that the
ambiguity was a problem in many cases, because <code class="language-plaintext highlighter-rouge">~code~</code> and <code class="language-plaintext highlighter-rouge">=verbatim=</code>
have different semantics in some exported formats).</p>

<h3>Refinements to all Org heading or heading-like faces</h3>

<p>This covers the regular Org headings as well as anything that performs
the same function, such as in the Org agenda buffer.</p>

<p>All regular headings use the main foreground value. The document title
and the Org agenda equivalent of that are rendered in an accent colour
for greater effect.</p>

<p>Combined with the aforementioned revision of the TODO and DONE
states, Org buffers are easier to read and work with.</p>

<h3>Tweaks for the Org agenda faces</h3>

<p>The faces that communicate the current time and applicable filters are
made more intense. The idea is to spot them more quickly.</p>

<p>Faces that pertain to diary or diary-style events no longer use
italics to avoid exaggerations.</p>

<p>Blocked tasks are easier to spot.</p>

<p>The applicable query in the structure header is made more prominent.</p>

<p>Overall, Org agenda buffers should be easier to scan.</p>

<h3>More obvious style for Org exporting</h3>

<p>The active/available keys in the Org export dispatcher use more
intense colours and have greater padding around them. This is what I
also do with the Modus themes (and all derivatives) to improve the
legibility of those keys.</p>

<h3>Magit branch and author faces are redone</h3>

<p>The authors in log views and elsewhere have a distinct colour to stand
out a bit more. Branches use consistent typography, while the current
branch stands out more than the others.</p>

<h3>New colours for transient faces with background values</h3>

<p>Enabled and disabled keys use a green-red coding scheme.</p>

<p>Active values and arguments have a style that is the same across
themes for the same reason as Org TODO and DONE.</p>

<p>Transient headings use the main foreground colour to not draw more
attention than they need to.</p>

<h3>Git commit faces follow the aforementioned patterns</h3>

<p>Those are seen when writing a commit message in Magit.</p>

<h3>VC logs better differentiate the commit author</h3>

<p>The relevant face uses a distinct foreground. It no longer applies a
bold weight, as that had the effect of making the buffers much busier
than necessary.</p>

<h3>Colour-coded styles for Dired marks</h3>

<p>Items that are marked for selection are rendered in a green style,
while those marked for deletion are red.</p>

<p>This is done for cross-theme consistency, so that users do not have to
think twice before performing the relevant operations.</p>

<h3>The <code class="language-plaintext highlighter-rouge">doric-themes-with-colors</code> macro for advanced users</h3>

<p>This macro is effectively the same as a <code class="language-plaintext highlighter-rouge">let</code> for binding the colours
of the active Doric theme. Advanced users can rely on this macro to
write functions that, for example, set the theme-specific red colour
value of a given face.</p>

<h3>Miscellaneous</h3>

<p>Symlinks in Dired buffers are easier to spot. Same for visited links
in Info buffers.</p>

<p>Org definitions no longer override the foreground of any other face
present in them. Same for the notmuch header in view buffers.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: new Doric themes ‘doric-jade’ and ‘doric-copper’</title>
      <description>I am developing two new themes for my minimalistic 'doric-themes' package for Emacs.</description>
      <pubDate>Thu, 05 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-02-05-emacs-new-doric-themes-jade-copper/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-02-05-emacs-new-doric-themes-jade-copper/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I have added two new themes to my minimalist <code class="language-plaintext highlighter-rouge">doric-themes</code> package.
The collection is growing to cover styles that range from austere to
playful.</p>

<p><code class="language-plaintext highlighter-rouge">doric-jade</code> is a light theme with an emphais on green. <code class="language-plaintext highlighter-rouge">doric-copper</code>
is a dark theme with mostly orange accents and hints of patina. Both
themes retain the Doric quality of using few colours while relying on
typography to establish rhythm and structure.</p>

<p>Below are their samples.</p>

<p>[ Or just check all the pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a>. ]</p>

<h2>doric-jade</h2>

<p><a href="https://protesilaos.com/assets/images/doric/doric-jade.png"><img alt="doric-jade theme sample" src="https://protesilaos.com/assets/images/doric/doric-jade.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-jade-org.png"><img alt="doric-jade theme sample" src="https://protesilaos.com/assets/images/doric/doric-jade-org.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-jade-message.png"><img alt="doric-jade theme sample" src="https://protesilaos.com/assets/images/doric/doric-jade-message.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-jade-magit.png"><img alt="doric-jade theme sample" src="https://protesilaos.com/assets/images/doric/doric-jade-magit.png" /></a></p>

<h2>doric-copper</h2>

<p><a href="https://protesilaos.com/assets/images/doric/doric-copper.png"><img alt="doric-copper theme sample" src="https://protesilaos.com/assets/images/doric/doric-copper.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-copper-org.png"><img alt="doric-copper theme sample" src="https://protesilaos.com/assets/images/doric/doric-copper-org.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-copper-message.png"><img alt="doric-copper theme sample" src="https://protesilaos.com/assets/images/doric/doric-copper-message.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-copper-magit.png"><img alt="doric-copper theme sample" src="https://protesilaos.com/assets/images/doric/doric-copper-magit.png" /></a></p>

<h2>Coming in <code class="language-plaintext highlighter-rouge">doric-themes</code> version 0.7.0</h2>

<p>Both <code class="language-plaintext highlighter-rouge">doric-jade</code> and <code class="language-plaintext highlighter-rouge">doric-copper</code> are in-development. I have
already worked on their finer point, but may still make some tweaks
before publishing them as part of the next stable version of the
<code class="language-plaintext highlighter-rouge">doric-themes</code>.</p>

<h2>About the Doric themes</h2>

<p>The Doric themes use few colours and will appear monochromatic in many
contexts. They are my most minimalist themes. Styles involve the
careful use of typographic features and subtleties in colour gradients
to establish a consistent rhythm. Legibility is still high.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: beframe version 1.5.0</title>
      <description>Information about the latest version of my beframe package for GNU Emacs.</description>
      <pubDate>Wed, 04 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-02-04-emacs-beframe-1-5-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-02-04-emacs-beframe-1-5-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p><code class="language-plaintext highlighter-rouge">beframe</code> enables a frame-oriented Emacs workflow where each frame has
access only to the list of buffers visited therein. In the interest of
brevity, we call buffers that belong to frames “beframed”.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">beframe</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/beframe">https://protesilaos.com/emacs/beframe</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/beframe-changelog">https://protesilaos.com/emacs/beframe-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/beframe">https://github.com/protesilaos/beframe</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/beframe">https://gitlab.com/protesilaos/beframe</a></li>
    </ul>
  </li>
  <li>Video demo: <a href="https://protesilaos.com/codelog/2023-02-28-emacs-beframe-demo/">https://protesilaos.com/codelog/2023-02-28-emacs-beframe-demo/</a></li>
  <li>Backronym: Buffers Encapsulated in Frames Realise Advanced
Management of Emacs.</li>
</ul>

<p>Below are the release notes</p>

<hr />

<h2>Version 1.5.0 on 2026-02-04</h2>

<p>This version fixes two bugs and makes other minor tweaks.</p>

<p>The first bug pertains to the performance of the command
<code class="language-plaintext highlighter-rouge">beframe-switch-buffer</code> or the command <code class="language-plaintext highlighter-rouge">switch-to-buffer</code> when
<code class="language-plaintext highlighter-rouge">beframe-mode</code> is enabled: they were really slow when the list of
buffers was long. Now they are always fast. Thanks to Alexandre
Rousseau for reporting the problem in issue 17:
<a href="https://github.com/protesilaos/beframe/issues/17">https://github.com/protesilaos/beframe/issues/17</a>.</p>

<p>The second bug is more subtle. It is about persisting the completion
metadata <code class="language-plaintext highlighter-rouge">category</code> value in all prompts that read a buffer, when
<code class="language-plaintext highlighter-rouge">beframe-mode</code> is enabled. This change means that users who configure
the user option <code class="language-plaintext highlighter-rouge">completion-category-overrides</code> will not get the
expected results in buffer prompts affected by Beframe.</p>

<p>Thanks to Stefan Monnier for commenting on the initial implementation,
specifically telling me that <code class="language-plaintext highlighter-rouge">let</code> binding the metadata can affect
nested minibuffers, which we do not want. This was done on the
emacs-devel mailing list: <a href="https://lists.gnu.org/archive/html/emacs-devel/2025-12/msg00264.html">https://lists.gnu.org/archive/html/emacs-devel/2025-12/msg00264.html</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: ef-themes version 2.1.0</title>
      <description>Information about the latest version of my colourful-yet-legible themes for GNU Emacs.</description>
      <pubDate>Tue, 27 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-01-27-emacs-ef-themes-2-1-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-01-27-emacs-ef-themes-2-1-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <code class="language-plaintext highlighter-rouge">ef-themes</code> are a collection of light and dark themes for GNU
Emacs that provide colourful (“pretty”) yet legible options for users
who want something with a bit more flair than the <code class="language-plaintext highlighter-rouge">modus-themes</code> (also
designed by me).</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">ef-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/ef-themes">https://protesilaos.com/emacs/ef-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/ef-themes-changelog">https://protesilaos.com/emacs/ef-themes-changelog</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/ef-themes">https://github.com/protesilaos/ef-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/ef-themes">https://gitlab.com/protesilaos/ef-themes</a></li>
    </ul>
  </li>
  <li>Backronym: Eclectic Fashion in Themes Hides Exaggerated Markings,
Embellishments, and Sparkles.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 2.1.0 on 2026-01-27</h2>

<p>This version introduces two carefully designed, legible and colourful
themes: <code class="language-plaintext highlighter-rouge">ef-orange</code> (light) and <code class="language-plaintext highlighter-rouge">ef-fig</code> (dark). Both draw inspiration
from the fruits they are name after.</p>

<p>The convenience commands <code class="language-plaintext highlighter-rouge">ef-themes-select-dark</code> and
<code class="language-plaintext highlighter-rouge">ef-themes-select-light</code> use the minibuffer to select+load an Ef theme
that is either dark or light, respectively. The more general command
is <code class="language-plaintext highlighter-rouge">ef-themes-select</code>.</p>

<p>All screen shots of the themes are updated to reflect their current
status: <a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a>.</p>

<p>Remember that since version <code class="language-plaintext highlighter-rouge">2.0.0</code> the <code class="language-plaintext highlighter-rouge">ef-themes</code> are built on top
of my <code class="language-plaintext highlighter-rouge">modus-themes</code>. This means that most of the changes happen to
Modus and are inherited by Ef.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: tmr version 1.3.0</title>
      <description>Information about the latest version of my TMR package for GNU Emacs.</description>
      <pubDate>Sun, 25 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-01-25-emacs-tmr-1-3-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-01-25-emacs-tmr-1-3-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>TMR provides facilities for setting timers using a convenient
notation. Lots of commands are available to operate on timers, while
there also exists a tabulated view to display all timers in a nice
grid.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">tmr</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/tmr">https://protesilaos.com/emacs/tmr</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/tmr-changelog">https://protesilaos.com/emacs/tmr-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/tmr">https://github.com/protesilaos/tmr</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/tmr">https://gitlab.com/protesilaos/tmr</a></li>
    </ul>
  </li>
  <li>Video demonstration: <a href="https://protesilaos.com/codelog/2026-01-19-emacs-timers-tmr-demo/">https://protesilaos.com/codelog/2026-01-19-emacs-timers-tmr-demo/</a></li>
  <li>Backronym: TMR May Ring; Timer Must Run.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 1.3.0 on 2026-01-25</h2>

<p>This version adds some user options and new features to an already
stable package.</p>

<h3>Timers can be paused</h3>

<p>The command <code class="language-plaintext highlighter-rouge">tmr-toggle-pause</code> will prompt for a running timer and
pause it.</p>

<p>Users who have something like the following in their configuration,
have access to <code class="language-plaintext highlighter-rouge">tmr-toggle-pause</code> under the <code class="language-plaintext highlighter-rouge">P</code> key:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; All TMR commands are behind this prefix key.  So `tmr-toggle-pause' is C-c t P.</span>
<span class="p">(</span><span class="nv">define-key</span> <span class="nv">global-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-c t"</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">tmr-prefix-map</span><span class="p">)</span>
</code></pre></div></div>

<p>In the buffer produced by the command <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code> the pause
functionality applies to the timer at point. The <code class="language-plaintext highlighter-rouge">tmr-toggle-pause</code> is
invoked with the <code class="language-plaintext highlighter-rouge">P</code> key.</p>

<p>An extra column in the tabulated view shows whether a timer is paused
or not. Here is an example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Start      End        Duration   Remaining  Paused?  Acknowledge?   Description

08:49:41   09:19:46   30m        29m 17s    Yes                     Work on TMR for 30 minutes
08:49:31   08:54:31   5m         3m 53s                             Prepare tea
08:49:21   08:59:21   10m        8m 42s              Yes            Edit the description with this one instead
</code></pre></div></div>

<h3>Configure the confirmation text for acknowledgements</h3>

<p>When a timer is set to be acknowledged (i.e. the user must confirm
that they saw it elapse) it prompts for confirmation. The default
input text that confirms the acknowledgement is <code class="language-plaintext highlighter-rouge">ack</code>. This is now
subject to configuration via the user option <code class="language-plaintext highlighter-rouge">tmr-acknowledge-timer-text</code>.</p>

<h3>Change how frequently the tabulated list is refreshed</h3>

<p>The buffer produced by <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code> is set to automatically
refresh every 5 seconds by default. In previous versions this was every
1 second. The new user option <code class="language-plaintext highlighter-rouge">tmr-tabulated-refresh-interval</code> can be
set to a number of seconds or <code class="language-plaintext highlighter-rouge">nil</code>. In the latter case, the automatic
refresh is disabled.</p>

<h3>Removed the long-obsolete <code class="language-plaintext highlighter-rouge">tmr-tabulated.el</code></h3>

<p>Its code was merged into <code class="language-plaintext highlighter-rouge">tmr.el</code> on 2024-10-30 and all it was doing
thenceforth is issue a warning to those who would <code class="language-plaintext highlighter-rouge">require</code> the
<code class="language-plaintext highlighter-rouge">tmr-tabulated</code> feature. Now <code class="language-plaintext highlighter-rouge">(require 'tmr-tabulated)</code> produces an
error.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: easily set timers with TMR</title>
      <description>Video demo of my 'tmr' package for Emacs. It helps you set timers interactively and provides relevant utilities.</description>
      <pubDate>Mon, 19 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-01-19-emacs-timers-tmr-demo/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-01-19-emacs-timers-tmr-demo/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=vLuyt0hq4io">https://www.youtube.com/watch?v=vLuyt0hq4io</a></p>
         
         <p>In this ~15-minute video I demonstrate a package of mine called <code class="language-plaintext highlighter-rouge">tmr</code>
(pronounced as an acronym or as “timer”). It uses a simple notation to
set the duration of a timer at the minibuffer prompt. Once the timer
elapses, Emacs shows a notification. The desktop environment will also
include one, as well as an audio alert (those are configurable).
Timers can optionally have a description. They may also be listed in a
tabulated/grid view, which makes it easier to work with them (to edit
their description, reschedule them, etc.). Running timers may also be
displayed on the mode line.</p>

<h2>Sample configuration</h2>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">tmr</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="ss">:config</span>
  <span class="p">(</span><span class="nv">define-key</span> <span class="nv">global-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-c t"</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">tmr-prefix-map</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">tmr-sound-file</span> <span class="s">"/usr/share/sounds/freedesktop/stereo/alarm-clock-elapsed.oga"</span>
        <span class="nv">tmr-notification-urgency</span> <span class="ss">'normal</span>
        <span class="nv">tmr-description-list</span> <span class="ss">'tmr-description-history</span><span class="p">))</span>
</code></pre></div></div>

<h2>TMR sources</h2>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">tmr</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/tmr">https://protesilaos.com/emacs/tmr</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/tmr-changelog">https://protesilaos.com/emacs/tmr-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/tmr">https://github.com/protesilaos/tmr</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/tmr">https://gitlab.com/protesilaos/tmr</a></li>
    </ul>
  </li>
  <li>Backronym: TMR May Ring; Timer Must Run.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: notmuch-indicator version 1.3.0</title>
      <description>Information about my notmuch email counter for the mode line of GNU Emacs.</description>
      <pubDate>Sun, 18 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-01-18-emacs-notmuch-indicator-1-3-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-01-18-emacs-notmuch-indicator-1-3-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This package renders an indicator with an email count of the <code class="language-plaintext highlighter-rouge">notmuch</code>
index on the Emacs mode line. The underlying mechanism is that of
<code class="language-plaintext highlighter-rouge">notmuch-count(1)</code>, which is used to find the number of items that
match the given search terms. In practice, the user can define one or
more searches and display their counters. These form a string which
realistically is like: <code class="language-plaintext highlighter-rouge">@50 😱1000 ♥️0</code> for unread messages, bills, and
fan letters, respectively.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">notmuch-indicator</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/notmuch-indicator">https://protesilaos.com/emacs/notmuch-indicator</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/notmuch-indicator-changelog">https://protesilaos.com/emacs/notmuch-indicator-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/notmuch-indicator">https://github.com/protesilaos/notmuch-indicator</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/notmuch-indicator">https://gitlab.com/protesilaos/notmuch-indicator</a></li>
    </ul>
  </li>
  <li>Backronym: notmuch-… Interested in Neatly Displayed Indicators
that Count Any Terms Ordinarily Requested.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>1.3.0 on 2026-01-18</h2>

<p>This version adds quality-of-life refinements to a stable package.</p>

<h3>The <code class="language-plaintext highlighter-rouge">notmuch-indicator-mode</code> sets up the <code class="language-plaintext highlighter-rouge">notmuch-after-tag-hook</code></h3>

<p>The indicator will be updated whenever a message’s tags change. This
way users do not need to rely on the timer-based method that we have
always had.</p>

<h3>The <code class="language-plaintext highlighter-rouge">notmuch-indicator-refresh-count</code> can be set to <code class="language-plaintext highlighter-rouge">nil</code></h3>

<p>Doing so has the effect of disabling the timer-based refresh of the
indicator. It will now be updated only when some event happens, such
as with the aforementioned change to tags or after the invocation of
any of the commands listed in the user option <code class="language-plaintext highlighter-rouge">notmuch-indicator-force-refresh-commands</code>.</p>

<h3>More configuration file paths</h3>

<p>When checking for the <code class="language-plaintext highlighter-rouge">notmuch</code> configuration file, we now also
consider these two filesystem paths:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">$HOME/.config/notmuch/$NOTMUCH_PROFILE/config</code></li>
  <li><code class="language-plaintext highlighter-rouge">$HOME/.config/notmuch/default/config</code></li>
</ul>

<p>Thanks to Yejun Su for the contribution in pull request 6:
<a href="https://github.com/protesilaos/notmuch-indicator/pull/6">https://github.com/protesilaos/notmuch-indicator/pull/6</a>.</p>

<p>The change is small, meaning that Yejun Su does not need to assign
copyright to the Free Software Foundation.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: doric-themes version 0.6.0</title>
      <description>Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate).</description>
      <pubDate>Sat, 17 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-01-17-emacs-doric-themes-0-6-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-01-17-emacs-doric-themes-0-6-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>These are my minimalist themes. They use few colours and will appear
mostly monochromatic in many contexts. Styles involve the careful use
of typography, such as italics and bold italics.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 0.6.0 on 2026-01-17</h2>

<p>This version adds support for more packages, while it revises some of
the faces that were already covered.</p>

<h3>Enhanced completion interface</h3>

<p>The minibuffer prompt used by the command <code class="language-plaintext highlighter-rouge">doric-themes-select</code> now
groups themes by their light or dark type. The current theme is at the
top.</p>

<h3>Avy highlights are easier to spot</h3>

<p>The highlights generated by the various commands of the <code class="language-plaintext highlighter-rouge">avy</code> package
now have a slightly more intense background+foreground colour combination.
It should be easier to spot and to differentiate from other highlights
such as that of <code class="language-plaintext highlighter-rouge">hl-line-mode</code> and the mouse hover effect over links.</p>

<h3>Support for all the tmr faces</h3>

<p>My <code class="language-plaintext highlighter-rouge">tmr</code> package styles timers in its grid/tabulated interface as well
as on the mode line. All these now get colours that come directly from
the active Doric theme. Before, the colours were defined only in the
<code class="language-plaintext highlighter-rouge">tmr</code> source code: they were “okay” (because they are based on my
<code class="language-plaintext highlighter-rouge">modus-themes</code>) but not stylistically optimal.</p>

<h3>Support for <code class="language-plaintext highlighter-rouge">ruler-mode</code></h3>

<p>The built-in <code class="language-plaintext highlighter-rouge">ruler-mode</code> draws a ruler at the top of the current
buffer. All of its faces now use appropriate colours.</p>

<h3>Trailing spaces have a more refined colour</h3>

<p>All packages that have a face that is about highlighting trailing
spaces now get a red colour value that is more appropriate for each
Doric theme.</p>

<h3>SHR buffers can use proportionately spaced fonts</h3>

<p>I removed an override for the built-in <code class="language-plaintext highlighter-rouge">shr-text</code> face, which was
making the <code class="language-plaintext highlighter-rouge">nov</code> package display its buffers in a monospaced font.</p>

<p>Thanks to Marcus Kammer for telling that <code class="language-plaintext highlighter-rouge">nov-mode</code> buffers were not
proportionately spaced by default. This was done in issue 23:
<a href="https://github.com/protesilaos/doric-themes/issues/23">https://github.com/protesilaos/doric-themes/issues/23</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: my ‘oxford-calendar’ package</title>
      <description>My new package for Emacs to display Oxford University academic terms in the 'M-x calendar'.</description>
      <pubDate>Fri, 09 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-01-09-emacs-oxford-calendar-package/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-01-09-emacs-oxford-calendar-package/</guid>
      <content:encoded>
        <![CDATA[
         
         <p><strong>UPDATE 2026-02-11 23:08 +0200:</strong> This package is discontinued and
superseded by my <code class="language-plaintext highlighter-rouge">institution-calendar</code>:
<a href="https://protesilaos.com/codelog/2026-02-11-emacs-institution-calendar/">https://protesilaos.com/codelog/2026-02-11-emacs-institution-calendar/</a>.</p>

<hr />

<p>The <code class="language-plaintext highlighter-rouge">oxford-calendar</code> is a small package that is of interest to
students, academics, and staff of the University of Oxford. It
augments the <code class="language-plaintext highlighter-rouge">M-x calendar</code> buffer with indicators that show the
applicable term (Michaelmas, Hilary, Trinity) and week number.</p>

<p><a href="https://protesilaos.com/assets/images/attachments/2026-01-09-oxford-calendar.png"><img alt="Oxford calendar for Emacs" src="https://protesilaos.com/assets/images/attachments/2026-01-09-oxford-calendar.png" /></a></p>

<p>To show the indicators, enable the <code class="language-plaintext highlighter-rouge">oxford-calendar-mode</code>. By default,
it includes the extra weeks 0 and 9 at the boundaries of each term.
The idea is to make things easier for planning purposes. Remove those
extra weeks by setting <code class="language-plaintext highlighter-rouge">oxford-calendar-include-extra-week-numbers</code> to
<code class="language-plaintext highlighter-rouge">nil</code>.</p>

<p>To include a heading above the term indicators, set the user option
<code class="language-plaintext highlighter-rouge">oxford-calendar-include-intermonth-header</code> to a non-<code class="language-plaintext highlighter-rouge">nil</code> value.</p>

<p>I will now do the work to include the package on the GNU ELPA archive.</p>

<h2>Sources</h2>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">oxford-calendar</code> (!!! COMING SOON)</li>
  <li>Git repository: <a href="https://github.com/protesilaos/oxford-calendar">https://github.com/protesilaos/oxford-calendar</a></li>
  <li>Backronym: Overtly Xenial Feature Orders Relevant Dates … Calendar.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: Substitute version 0.5.0</title>
      <description>Information about the latest version of my 'substitute' package for Emacs.</description>
      <pubDate>Mon, 05 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-01-05-emacs-substitute-0-5-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-01-05-emacs-substitute-0-5-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Substitute provides a set of commands that perform text replacement
(i) throughout the buffer, (ii) limited to the current definition (per
<code class="language-plaintext highlighter-rouge">narrow-to-defun</code>), (iii) from point to the end of the buffer, and
(iv) from point to the beginning of the buffer. Variations of these
scopes are also available.</p>

<p>These substitutions are meant to be as quick as possible and, as such,
differ from the standard <code class="language-plaintext highlighter-rouge">query-replace</code> (which I still use when
necessary). The provided commands prompt for substitute text and
perform the substitution outright, without moving the point. The
target is the symbol/word at point or the text corresponding to the
currently marked region. All matches in the given scope are
highlighted by default.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">substitute</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/substitute">https://protesilaos.com/emacs/substitute</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/substitute">https://github.com/protesilaos/substitute</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/substitute">https://gitlab.com/protesilaos/substitute</a></li>
    </ul>
  </li>
  <li>Video demo: <a href="https://protesilaos.com/codelog/2023-01-16-emacs-substitute-package-demo/">https://protesilaos.com/codelog/2023-01-16-emacs-substitute-package-demo/</a></li>
  <li>Backronym: Substitutions Uniformly Beget Standardisation for Text Invariably Transfigured Unto This Entry.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 0.5.0 on 2026-01-05</h2>

<p>This is a small release that fixes a bug and adds a relevant user
option.</p>

<p>The bug pertained to the scope of the substitution when buffer
narrowing was in effect. All commands would ignore narrowing and also
fail to properly clear the highlights they apply (highlights are
transiently in effect to show what the target of the substitution is
while the minibuffer is waiting for user input).</p>

<p>Now all commands do the right thing with respect to buffer narrowing.
Though their exact behaviour depends on the value of the new user
option <code class="language-plaintext highlighter-rouge">substitute-ignore-narrowing</code>:</p>

<ul>
  <li>
    <p>When the value of <code class="language-plaintext highlighter-rouge">substitute-ignore-narrowing</code> is non-<code class="language-plaintext highlighter-rouge">nil</code>, then
substitutions apply to the actual scope of the given command. For
example, <code class="language-plaintext highlighter-rouge">substitute-target-in-buffer</code> will cover the whole buffer
from the absolute minimum position to the absolute maximum position
even if narrowing is in effect.</p>
  </li>
  <li>
    <p>When the value of <code class="language-plaintext highlighter-rouge">substitute-ignore-narrowing</code> is <code class="language-plaintext highlighter-rouge">nil</code>, then
substitutions apply to their scope subject to the boundaries of the
narrowed buffer. For example, <code class="language-plaintext highlighter-rouge">substitute-target-in-buffer</code> will
understand as “whole buffer” the region between the minimum and
maximum positions of the narrowed buffer.</p>
  </li>
</ul>

<p>Users can write small convenience commands that do either of those,
depending on preference. For example:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-substitute-target-in-buffer-with-narrowing</span> <span class="p">()</span>
  <span class="s">"Call `substitute-target-in-buffer' with `substitute-ignore-narrowing' as `nil'."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">substitute-ignore-narrowing</span> <span class="no">nil</span><span class="p">))</span>
    <span class="p">(</span><span class="nv">call-interactively</span> <span class="ss">'substitute-target-in-buffer</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">my-substitute-target-in-buffer-without-narrowing</span> <span class="p">()</span>
  <span class="s">"Call `substitute-target-in-buffer' with `substitute-ignore-narrowing' as non-`nil'."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">substitute-ignore-narrowing</span> <span class="no">t</span><span class="p">))</span>
    <span class="p">(</span><span class="nv">call-interactively</span> <span class="ss">'substitute-target-in-buffer</span><span class="p">)))</span>
</code></pre></div></div>

<p>Thanks to zauberen for reporting the bug in issue 11:
<a href="https://github.com/protesilaos/substitute/issues/11">https://github.com/protesilaos/substitute/issues/11</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: ef-orange and ef-fig are part of the ef-themes</title>
      <description>I added a new light and dark theme to my 'ef-themes' package for Emacs.</description>
      <pubDate>Sun, 04 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2026-01-04-emacs-ef-orange-fig-themes/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2026-01-04-emacs-ef-orange-fig-themes/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just added two new themes to my <code class="language-plaintext highlighter-rouge">ef-themes</code> package. <code class="language-plaintext highlighter-rouge">ef-orange</code> is
a light theme with a noticeably tinted background that combines
orange, yellow, and green hues. <code class="language-plaintext highlighter-rouge">ef-fig</code> is a dark theme with a dark
purple background that relies on green, yellow, and pink hues.</p>

<p>Sample pictures are available below. Check all the items here:
<a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a>. Always <strong>click to
enlarge the image</strong> for best results.</p>

<h3>ef-orange</h3>

<p><a href="https://protesilaos.com/assets/images/ef/ef-orange.png"><img alt="ef-orange theme sample" src="https://protesilaos.com/assets/images/ef/ef-orange.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-orange-git.png"><img alt="ef-orange theme git sample" src="https://protesilaos.com/assets/images/ef/ef-orange-git.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-orange-mail.png"><img alt="ef-orange theme mail sample" src="https://protesilaos.com/assets/images/ef/ef-orange-mail.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-orange-org.png"><img alt="ef-orange theme org sample" src="https://protesilaos.com/assets/images/ef/ef-orange-org.png" /></a></p>

<h3>ef-fig</h3>

<p><a href="https://protesilaos.com/assets/images/ef/ef-fig.png"><img alt="ef-fig theme sample" src="https://protesilaos.com/assets/images/ef/ef-fig.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-fig-git.png"><img alt="ef-fig theme git sample" src="https://protesilaos.com/assets/images/ef/ef-fig-git.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-fig-mail.png"><img alt="ef-fig theme mail sample" src="https://protesilaos.com/assets/images/ef/ef-fig-mail.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/ef/ef-fig-org.png"><img alt="ef-fig theme org sample" src="https://protesilaos.com/assets/images/ef/ef-fig-org.png" /></a></p>

<h2>Coming in version 2.1.0 (next stable release)</h2>

<p>Both themes are done. Though there may still be some minor
refinements. They will be widely available as part of the next stable
version of the <code class="language-plaintext highlighter-rouge">ef-themes</code> package (maybe end of January 2026).</p>

<p>Remember that since version <code class="language-plaintext highlighter-rouge">2.0.0</code>, the <code class="language-plaintext highlighter-rouge">ef-themes</code> are built on top
of my <code class="language-plaintext highlighter-rouge">modus-themes</code>. This means that they are highly customisable and
support a wide range of packages and face groups.</p>

<p>Enjoy!</p>

<hr />

<p>The <code class="language-plaintext highlighter-rouge">ef-themes</code> are a collection of light and dark themes for GNU
Emacs that provide colourful (“pretty”) yet legible options for users
who want something with a bit more flair than the <code class="language-plaintext highlighter-rouge">modus-themes</code> (also
designed by me).</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">ef-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/ef-themes">https://protesilaos.com/emacs/ef-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/ef-themes-changelog">https://protesilaos.com/emacs/ef-themes-changelog</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/ef-themes">https://github.com/protesilaos/ef-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/ef-themes">https://gitlab.com/protesilaos/ef-themes</a></li>
    </ul>
  </li>
  <li>Backronym: Eclectic Fashion in Themes Hides Exaggerated Markings,
Embellishments, and Sparkles.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: modus-themes version 5.2.0</title>
      <description>Information about the latest version of my highly accessible themes for GNU Emacs.</description>
      <pubDate>Wed, 31 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-12-31-emacs-modus-themes-5-2-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-12-31-emacs-modus-themes-5-2-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just published the latest stable release of <a href="https://protesilaos.com/emacs/modus-themes">the Modus
themes</a>. The change log
entry is reproduced further below. For any questions, you are welcome
to <a href="https://protesilaos.com/contact/">contact me</a>. I will now work to
apply these same changes to emacs.git, so please wait a little longer
for the updates to trickle down to you.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">modus-themes</code> (also built into Emacs 28+)</li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/modus-themes-changelog">https://protesilaos.com/emacs/modus-themes-changelog</a></li>
  <li>Colour palette: <a href="https://protesilaos.com/emacs/modus-themes-colors">https://protesilaos.com/emacs/modus-themes-colors</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/modus-themes-pictures">https://protesilaos.com/emacs/modus-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/modus-themes">https://github.com/protesilaos/modus-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/modus-themes">https://gitlab.com/protesilaos/modus-themes</a></li>
    </ul>
  </li>
  <li>Backronym: My Old Display Unexpectedly Sharpened … themes.</li>
</ul>

<hr />

<h2>5.2.0 on 2025-12-31</h2>

<p>This version fixes some bugs, adds a new feature for those who want to
derive a theme from Modus, and makes other small quality-of-life
refinements.</p>

<h3>The <code class="language-plaintext highlighter-rouge">modus-themes-with-colors</code> should work at all times</h3>

<p>In the transition to version <code class="language-plaintext highlighter-rouge">5.0.0</code>, I inadvertently introduced
regressions to the behaviour of the <code class="language-plaintext highlighter-rouge">modus-themes-with-colors</code> macro.
This macro <code class="language-plaintext highlighter-rouge">let</code> binds the current theme’s palette around arbitrary
Elisp expressions, which allows users to access the named colours
therein. In versions <code class="language-plaintext highlighter-rouge">5.0.0</code> and <code class="language-plaintext highlighter-rouge">5.1.0</code> the macro could not read
variables defined outside its scope. Users needed to write an <code class="language-plaintext highlighter-rouge">eval</code>
around it, which I did not like. Now the macro should not require such
workarounds: it basically is a <code class="language-plaintext highlighter-rouge">let</code> that should work as expected
everywhere.</p>

<p>This was fixed over a series of Git commits related to issue 170:
<a href="https://github.com/protesilaos/modus-themes/issues/170">https://github.com/protesilaos/modus-themes/issues/170</a>. Thanks to
Alexandr Semenov and realazy for reporting the problems and testing my
revisions.</p>

<h3>The <code class="language-plaintext highlighter-rouge">modus-themes-generate-palette</code> function to quickly get a palette</h3>

<p>Users or package developers who want to create a theme on top of Modus
can now get a kickstart by defining their palette with the help of the
new <code class="language-plaintext highlighter-rouge">modus-themes-generate-palette</code> function. This function is meant
to return a complete palette, given a list of basic colours. Users can
thus experiment with their new theme while knowing that what they got
contains all the definitions; definitions that they may then modify
further (e.g. to define different semantic mappings than the defaults
such as, for example, to have <code class="language-plaintext highlighter-rouge">(fg-heading-1 red-warmer)</code> instead of
what originally is <code class="language-plaintext highlighter-rouge">(fg-heading-1 fg-main)</code>).</p>

<p>I have written extensive documentation in the manual, which includes a
complete example of a Solarized theme that is built on top of Modus.
If you have any questions, you are welcome to contact me.</p>

<h3>Convenience commands to select only dark or light themes</h3>

<p>The commands <code class="language-plaintext highlighter-rouge">modus-themes-select-dark</code> and <code class="language-plaintext highlighter-rouge">modus-themes-select-light</code>
use minibuffer completion to load a theme. The completion candidates
are filtered to only dark or light themes, respectively.</p>

<p>This is effectively the same as calling the command <code class="language-plaintext highlighter-rouge">modus-themes-select</code>
with a prefix argument (<code class="language-plaintext highlighter-rouge">C-u</code> by default).</p>

<p>Remember that we also have the commands <code class="language-plaintext highlighter-rouge">modus-themes-load-random</code>,
<code class="language-plaintext highlighter-rouge">modus-themes-load-random-dark</code>, and <code class="language-plaintext highlighter-rouge">modus-themes-load-random-light</code>.
Otherwise use the command <code class="language-plaintext highlighter-rouge">modus-themes-rotate</code>.</p>

<h3>Improved prompt for theme selection</h3>

<p>The minibuffer prompt used by the various Modus commands to select a
theme now has a grouping function in place: it shows the current theme
at the top and then all other themes grouped by their dark or light
background. This makes it easier to find a relevant theme, especially
if lots of them are present, such as when <code class="language-plaintext highlighter-rouge">modus-themes-include-derivatives-mode</code>
is enabled and relevant packages/themes are available (e.g. my
<code class="language-plaintext highlighter-rouge">ef-themes</code> and <code class="language-plaintext highlighter-rouge">standard-themes</code>).</p>

<h3>Semantic colours for <code class="language-plaintext highlighter-rouge">transient.el</code> (e.g. in Magit)</h3>

<p>The <code class="language-plaintext highlighter-rouge">transient.el</code> concept of “semantic colours” is now supported.
This is used by default in Magit to denote the different types of
keys, such as those that exit the transient, keep it active, move to
another transient, and the like. Users who prefer the old style where
all key bindings looked the same must customise the user option
<code class="language-plaintext highlighter-rouge">transient-semantic-coloring</code>.</p>

<p>Note that the deuteranopia- and tritanopia- optimised themes adapt
gracefully to such “semantics”, owning to relevant internal
refinements I made. Those themes cannot rely on the full colour
spectrum to communicate such nuances.</p>

<h3>All <code class="language-plaintext highlighter-rouge">hl-todo-mode</code> faces use a bold weight if appropriate</h3>

<p>When the user option <code class="language-plaintext highlighter-rouge">modus-themes-bold-constructs</code> is set to a
non-<code class="language-plaintext highlighter-rouge">nil</code> value, then all keywords that <code class="language-plaintext highlighter-rouge">hl-todo-mode</code> highlights will
be rendered in a bold weight (technically, they inherit the <code class="language-plaintext highlighter-rouge">bold</code>
face). This is how we were doing it before until I undid it by
mistake. Thanks to Dominik Schrempf for reporting the bug in issue
177: <a href="https://github.com/protesilaos/modus-themes/issues/177">https://github.com/protesilaos/modus-themes/issues/177</a>.</p>

<h3>Theme-sensitive colours for Gnus mail groups</h3>

<p>The Gnus mail groups no longer have hardcoded colour values. They will
look different depending on the current Modus theme.</p>

<h3>Faces that set a <code class="language-plaintext highlighter-rouge">:box</code> attribute handle unspecified colours</h3>

<p>I updated all faces that use a <code class="language-plaintext highlighter-rouge">:box</code> attribute to account for the
scenario of a user writing palette overrides that unset the relevant
colour. Thanks to JD Smith for reporting a bug along those lines in
issue 9 of my <code class="language-plaintext highlighter-rouge">standard-themes</code> repository (they are derived from the
<code class="language-plaintext highlighter-rouge">modus-themes</code>, hence the changes here):
<a href="https://github.com/protesilaos/standard-themes/issues/9">https://github.com/protesilaos/standard-themes/issues/9</a>.</p>

<h3>The <code class="language-plaintext highlighter-rouge">calendar-today</code> and <code class="language-plaintext highlighter-rouge">org-date-selected</code> faces are disambiguated</h3>

<p>These two faces are no longer using the same styles. This is because
they can appear in the same buffer. Thanks to Rudolf Adamkovič for
discussing this with me in the context of the same change for my
<code class="language-plaintext highlighter-rouge">doric-themes</code> (issue 20 in doric-themes.git):
<a href="https://github.com/protesilaos/doric-themes/issues/20">https://github.com/protesilaos/doric-themes/issues/20</a>.</p>

<h3>The Modus “current theme” respects multiple enabled themes</h3>

<p>The Modus concept of “current theme” respects the user’s choice for
multiple themes loaded at once. It will return the first Modus theme
even if it is not at the front of the list.</p>

<p>[ Emacs will load multiple themes by default, which leads to awkward
  colour combinations, unless you know what you are doing—as such all
  the Modus commands that load a theme will disable all others, subject
  to the user option <code class="language-plaintext highlighter-rouge">modus-themes-disable-other-themes</code>. ]</p>

<p>Thanks to Pierre Téchoueyres for reporting the scenario where multiple
other themes are loaded on top of a Modus theme. This was done in
issue 182: <a href="https://github.com/protesilaos/modus-themes/issues/182">https://github.com/protesilaos/modus-themes/issues/182</a>.</p>

<p>Also thanks to Pierre for covering another snippet that I had missed.
This was done in pull request 184:
<a href="https://github.com/protesilaos/modus-themes/pull/184">https://github.com/protesilaos/modus-themes/pull/184</a>.</p>

<p>Pierre has assigned copyright to the Free Software Foundation.</p>

<h3>Fixed symbol of inherited AUCTeX face</h3>

<p>There was a typo which caused an error. Thanks to Rudolf Adamkovič for
the patch and also for providing a relevant unit test. This was done
in pull request 188: <a href="https://github.com/protesilaos/modus-themes/pull/188">https://github.com/protesilaos/modus-themes/pull/188</a>.</p>

<p>Rudolf has assigned copyright to the Free Software Foundation.</p>

<h3>Miscellaneous</h3>

<ul>
  <li>
    <p>Thanks to Basil L. Contovounesios for simplifying a couple of
expressions. This was done in pull request 190:
<a href="https://github.com/protesilaos/modus-themes/pull/190">https://github.com/protesilaos/modus-themes/pull/190</a>. Basil has
assigned copyright to the Free Software Foundation.</p>
  </li>
  <li>
    <p>The faces of the built-in <code class="language-plaintext highlighter-rouge">completion-preview-mode</code> are now
supported. Thanks to Kevin Fleming for asking me about this in issue
178: <a href="https://github.com/protesilaos/modus-themes/issues/178">https://github.com/protesilaos/modus-themes/issues/178</a>.</p>
  </li>
  <li>
    <p>Several faces that had a strike-through effect when they did not
really need it are revised to use a wavy underline instead. The idea
is to let the text be readable at all times, regardless of the
effective font family. With the strike-through effect, some fonts
completely obscure the underlying text.Thanks to Morgan Willcock for
discussing with me the use of the strike-through style in issue 169:
<a href="https://github.com/protesilaos/modus-themes/issues/169">https://github.com/protesilaos/modus-themes/issues/169</a>.</p>
  </li>
  <li>
    <p>All <code class="language-plaintext highlighter-rouge">symbol-overlay</code> faces are unique, fixing a mistake I had done
before.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">org-dispatcher-highlight</code>, which is used to highlight the keys
of the Org export interface, now uses the appropriate foreground
colour and is always rendered in a bold weight.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">org-habit</code> faces no longer call the function
<code class="language-plaintext highlighter-rouge">readable-foreground-color</code>. This is because that function does not
work if the theme is loaded via the <code class="language-plaintext highlighter-rouge">early-init.el</code>. Thanks to
Gaston Cabotin for reporting the problem in issue 174:
<a href="https://github.com/protesilaos/modus-themes/issues/174">https://github.com/protesilaos/modus-themes/issues/174</a>.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">gnus-button</code>, which Gnus uses in all sorts of places to mark
some text as clickable, is styled with a less intense underline and
will no longer follow the style of links, including possible palette
overrides. This way, Gnus article buffers will not have visual
noise. Thanks to Morgan Willcock for discussing this with me in
issue 140: <a href="https://github.com/protesilaos/modus-themes/issues/140">https://github.com/protesilaos/modus-themes/issues/140</a>.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs Lisp Elements: EPUB and PDF versions now available</title>
      <description>My free book on the Emacs Lisp programming language is now available in EPUB and PDF formats.</description>
      <pubDate>Sat, 27 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-12-27-emacs-lisp-elements-epub-pdf/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-12-27-emacs-lisp-elements-epub-pdf/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just added <code class="language-plaintext highlighter-rouge">.epub</code> and <code class="language-plaintext highlighter-rouge">.pdf</code> versions of my free book <em>Emacs Lisp Elements</em>. All files are available in the Git repository: <a href="https://github.com/protesilaos/emacs-lisp-elements">https://github.com/protesilaos/emacs-lisp-elements</a>.</p>

<p>I produced both of those from the source Org file. Here are the steps for posterity:</p>

<ul>
  <li>From the <code class="language-plaintext highlighter-rouge">elispelem.org</code> use the Org export mechanism to generate an Info manual (by default: <code class="language-plaintext highlighter-rouge">C-c C-e i i</code>).</li>
  <li>This will generate a <code class="language-plaintext highlighter-rouge">.texi</code> file, which is then used as the source for the <code class="language-plaintext highlighter-rouge">.info</code> file.</li>
  <li>From the command-line do <code class="language-plaintext highlighter-rouge">texi2any --epub elispelem.texi</code> to get the EPUB file.</li>
  <li>For the PDF, install the dependencies with something like <code class="language-plaintext highlighter-rouge">sudo apt install texlive</code>.</li>
  <li>Finally, run <code class="language-plaintext highlighter-rouge">texi2any --pdf elispelem.texi</code>.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: refinements to the Denote file prompt</title>
      <description>Information about the new Denote file prompt and a screenshot of how it looks like.</description>
      <pubDate>Tue, 16 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-12-16-emacs-denote-file-prompt-refinements/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-12-16-emacs-denote-file-prompt-refinements/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>As part of the current development cycle of Denote, I am refining the
file prompt. It now has the following:</p>

<ul>
  <li><strong>Sorting:</strong> Files are sorted by last modified.</li>
  <li><strong>Grouping:</strong> Files are organised by type (remember that the Denote
file-naming scheme can be applied to any file—I do so for videos,
pictures, PDFs, …).</li>
  <li><strong>Affixating:</strong> Files have their date identifier as a prefix and
their keywords as a suffix.</li>
</ul>

<p>The file prompt is used when linking to a file, like with the
<code class="language-plaintext highlighter-rouge">denote-link</code> command, or when calling the command
<code class="language-plaintext highlighter-rouge">denote-open-or-create</code> (and related).</p>

<h2>The old style</h2>

<p>File names were presented as relative paths without further
modifications. This style relies on the Denote file-naming scheme to
narrow down the list by typing. For example <code class="language-plaintext highlighter-rouge">202512</code> finds all files
with that in their identifier (i.e. their creation date by default),
<code class="language-plaintext highlighter-rouge">_emacs</code> finds all files with the given keyword, and <code class="language-plaintext highlighter-rouge">-word</code> with that
word in their title.</p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-12-16-denote-file-prompt-old.png"><img alt="Denote old file prompt" src="https://protesilaos.com/assets/images/attachments/2025-12-16-denote-file-prompt-old.png" /></a></p>

<h2>The new style</h2>

<p>The file names are still the same behind the scenes, but their data is
presented in a more readable way. There is no loss of functionality,
meaning that users can still match <code class="language-plaintext highlighter-rouge">_keyword</code>, <code class="language-plaintext highlighter-rouge">-title</code>, and the like,
per the Denote file-naming scheme.</p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-12-16-denote-file-prompt-new.png"><img alt="Denote new file prompt" src="https://protesilaos.com/assets/images/attachments/2025-12-16-denote-file-prompt-new.png" /></a></p>

<h2>Part of development</h2>

<p>I might make further changes, though the idea is clear. Expect to get
similar features in my other packages, such as <code class="language-plaintext highlighter-rouge">consult-denote</code>,
<code class="language-plaintext highlighter-rouge">denote-sequence</code>, <code class="language-plaintext highlighter-rouge">denote-journal</code>.</p>

<p>For the <code class="language-plaintext highlighter-rouge">denote-sequence</code> package, in particular, the file prompt it
uses shows sequences instead of identifiers as the prefix of each
file. This is because that prompt is relevant for tasks where the user
needs to know the exact sequence, such as when they create a note that
is the child of another.</p>

<p>Power users can study the functions stored in the variable
<code class="language-plaintext highlighter-rouge">denote-file-prompt-extra-metadata</code> (same idea for the
<code class="language-plaintext highlighter-rouge">denote-sequence</code> package: <code class="language-plaintext highlighter-rouge">denote-sequence-file-prompt-extra-metadata</code>).</p>

<h2>About Denote</h2>

<p>Denote is a simple note-taking tool for Emacs.  It is based on the idea
that notes should follow a predictable and descriptive file-naming
scheme.  The file name must offer a clear indication of what the note is
about, without reference to any other metadata.  Denote basically
streamlines the creation of such files while providing facilities to
link between them.</p>

<p>Denote’s file-naming scheme is not limited to “notes”.  It can be used
for all types of file, including those that are not editable in Emacs,
such as videos.  Naming files in a consistent way makes their
filtering and retrieval considerably easier.  Denote provides relevant
facilities to rename files, regardless of file type.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote">https://protesilaos.com/emacs/denote</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/denote-changelog">https://protesilaos.com/emacs/denote-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/denote">https://github.com/protesilaos/denote</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/denote">https://gitlab.com/protesilaos/denote</a></li>
    </ul>
  </li>
  <li>Video demo: <a href="https://protesilaos.com/codelog/2022-06-18-denote-demo/">https://protesilaos.com/codelog/2022-06-18-denote-demo/</a></li>
  <li>Backronyms: Denote Everything Neatly; Omit The Excesses.  Don’t Ever
Note Only The Epiphenomenal.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: spacious-padding version 0.8.0</title>
      <description>Information about the latest version of my 'spacious-padding' package for GNU Emacs.</description>
      <pubDate>Sat, 13 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-12-13-emacs-spacious-padding-0-8-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-12-13-emacs-spacious-padding-0-8-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This package provides a global minor mode to increase the
spacing/padding of Emacs windows and frames.  The idea is to make
editing and reading feel more comfortable.  Enable the mode with <code class="language-plaintext highlighter-rouge">M-x
spacious-padding-mode</code>.  Adjust the exact spacing values by modifying
the user option <code class="language-plaintext highlighter-rouge">spacious-padding-widths</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">spacious-padding</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/spacious-padding">https://protesilaos.com/emacs/spacious-padding</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/spacious-padding">https://protesilaos.com/emacs/spacious-padding</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/spacious-padding">https://github.com/protesilaos/spacious-padding</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/spacious-padding">https://gitlab.com/protesilaos/spacious-padding</a></li>
    </ul>
  </li>
  <li>Sample images:
    <ul>
      <li><a href="https://protesilaos.com/codelog/2023-06-03-emacs-spacious-padding/">https://protesilaos.com/codelog/2023-06-03-emacs-spacious-padding/</a></li>
      <li><a href="https://protesilaos.com/codelog/2023-11-15-spacious-padding-extra-ui-dev/">https://protesilaos.com/codelog/2023-11-15-spacious-padding-extra-ui-dev/</a></li>
    </ul>
  </li>
  <li>Backronyms: Space Perception Adjusted Consistently Impacts Overall
Usability State … padding; Spacious … Precise Adjustments to
Desktop Divider Internals Neatly Generated.</li>
</ul>

<hr />

<p>This release introduces some nice refinements and fixes a couple of
subtle bugs.</p>

<h3>Subtle mode and header line</h3>

<p>The new user option <code class="language-plaintext highlighter-rouge">spacious-padding-subtle-frame-lines</code> supersedes
the <code class="language-plaintext highlighter-rouge">~spacious-padding-subtle-mode-line</code>. It does the same thing,
namely, of making the mode lines use only a thin line instead of a
background. Though it extends this feature to header lines as well.</p>

<p>The documentation string of <code class="language-plaintext highlighter-rouge">spacious-padding-subtle-frame-lines</code>
describes the technicalities and includes examples. In short, we can
associate a keyword with either a face that has a foreground color or
a color value directly. For the convenience of the user, the package
also defines the faces <code class="language-plaintext highlighter-rouge">spacious-padding-line-active</code> and
<code class="language-plaintext highlighter-rouge">spacious-padding-line-inactive</code>. Here is a sample configuration:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Read the doc string of `spacious-padding-subtle-mode-line' as it</span>
<span class="c1">;; is very flexible.  Here we make the mode lines be a single</span>
<span class="c1">;; overline, while header lines have an underline.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">spacious-padding-subtle-frame-lines</span>
      <span class="o">'</span><span class="p">(</span> <span class="ss">:mode-line-active</span> <span class="nv">spacious-padding-line-active</span>
         <span class="ss">:mode-line-inactive</span> <span class="nv">spacious-padding-line-inactive</span>
         <span class="ss">:header-line-active</span> <span class="nv">spacious-padding-line-active</span>
         <span class="ss">:header-line-inactive</span> <span class="nv">spacious-padding-line-inactive</span><span class="p">))</span>
</code></pre></div></div>

<p>In the future, we might decide that other elements can benefit from
this style.</p>

<h3>The header line underline is spaced further away from the text</h3>

<p>As noted above, when <code class="language-plaintext highlighter-rouge">spacious-padding-subtle-frame-lines</code> is
configured to cover header lines, those will be drawn with an
underline. This will not intersect with the text of the header line.</p>

<p>Normally, underlines cut through letters that descend below the
baseline, such as the letters <code class="language-plaintext highlighter-rouge">g</code> and <code class="language-plaintext highlighter-rouge">y</code>. We choose to avoid that
because it makes for a cleaner interface (though I personally think it
is not a good style for paragraph text, because of the rivers of
negative space it introduces).</p>

<p>This specific design is available for Emacs version 29 or higher.
Users of Emacs 28 must set <code class="language-plaintext highlighter-rouge">x-underline-at-descent-line</code> to a
non-<code class="language-plaintext highlighter-rouge">nil</code> value. Though note that this has a global effect: we cannot
limit it to a single face.</p>

<p>Thanks to Steven Allen for covering this in pull request 37:
<a href="https://github.com/protesilaos/spacious-padding/pull/37">https://github.com/protesilaos/spacious-padding/pull/37</a>. Steven has
assigned copyright to the Free Software Foundation.</p>

<h3>The <code class="language-plaintext highlighter-rouge">spacious-padding-widths</code> can affect Custom buttons</h3>

<p>This is about the buttons we find in buffers of the Custom system. For
example, we get such a buffer after we do <code class="language-plaintext highlighter-rouge">M-x customize</code>.</p>

<p>The relevant keyword is <code class="language-plaintext highlighter-rouge">:custom-button-width</code>. It is set to a number
of spaces for padding. Here is the default value and, as always, the
documentation cover the details:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">spacious-padding-widths</span>
      <span class="o">'</span><span class="p">(</span> <span class="ss">:internal-border-width</span> <span class="mi">15</span>
         <span class="ss">:header-line-width</span> <span class="mi">4</span>
         <span class="ss">:mode-line-width</span> <span class="mi">6</span>
         <span class="ss">:custom-button-width</span> <span class="mi">3</span> <span class="c1">; the new one</span>
         <span class="ss">:tab-width</span> <span class="mi">4</span>
         <span class="ss">:right-divider-width</span> <span class="mi">30</span>
         <span class="ss">:scroll-bar-width</span> <span class="mi">8</span>
         <span class="ss">:fringe-width</span> <span class="mi">8</span><span class="p">))</span>
</code></pre></div></div>

<h3>Fixes for the Emacs daemon</h3>

<p>There were reports about incorrect face specifications that could
happen when Emacs was started as a daemon process. I made the relevant
changes. Also thanks to kaibagley for covering a line I had missed.
This was done in pull request 43: <a href="https://github.com/protesilaos/spacious-padding/pull/43">https://github.com/protesilaos/spacious-padding/pull/43</a>.</p>

<p>Related threads:</p>

<ul>
  <li>Issue 35, as reported by Chinmay Dalal: <a href="https://github.com/protesilaos/spacious-padding/issues/35">https://github.com/protesilaos/spacious-padding/issues/35</a>.</li>
  <li>Issue 41, as reported by zealotrush: <a href="https://github.com/protesilaos/spacious-padding/issues/41">https://github.com/protesilaos/spacious-padding/issues/41</a>.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>‘Emacs Lisp Elements’ book version 2</title>
      <description>Information about the latest version of my 'Emacs Lisp Elements' book.</description>
      <pubDate>Wed, 10 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-12-10-emacs-lisp-elements-book-version-2/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-12-10-emacs-lisp-elements-book-version-2/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just published a new version of my <em>Emacs Lisp Elements</em>. Below are
the release notes.</p>

<ul>
  <li>Official page: <a href="https://protesilaos.com/emacs/emacs-lisp-elements">https://protesilaos.com/emacs/emacs-lisp-elements</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/emacs-lisp-elements">https://github.com/protesilaos/emacs-lisp-elements</a></li>
</ul>

<hr />

<h2>Emacs Lisp Elements version 2.0.0</h2>

<p>This is a major rewrite of the book. It has almost doubled in word
count. I explain more concepts and do it from the ground up. Every
single one of the original chapters is redone. They now contain
insights into functionality they would previously hint at, such as how
<code class="language-plaintext highlighter-rouge">apply</code> works in practice, what a non-local exit is, and how recursive
editing is done.</p>

<p>I have also added several new chapters. As before, chapters have
cross references, so you will benefit from revisiting relevant topics.</p>

<p>If you read the Info version of the book, note that all functions,
variables, and concepts have their own indices. Use those as another
means of navigating the book’s contents. To read the Info version,
clone the Git repository, use <code class="language-plaintext highlighter-rouge">M-x dired</code> to open its directory,
move the cursor over the file <code class="language-plaintext highlighter-rouge">elispelem.info</code> and do <code class="language-plaintext highlighter-rouge">M-x dired-info</code>.</p>

<p>What follows is a brief description of the new chapters.</p>

<ul>
  <li>
    <p>Basics of how Lisp works: A step-by-step guide to how Lisp code is
written and how Emacs can tell apart a function call from a variable
even when those have the same symbol.</p>
  </li>
  <li>
    <p>Introspecting Emacs: Explores some of the ways we can learn about
the present state of Emacs. The idea is to develop the habit of
asking Emacs about itself before we do an online search. This way we
can also expose ourselves to Elisp code, which helps us become
better programmers.</p>
  </li>
  <li>
    <p>Add metadata to symbols: An explanation of how we can associate
symbols with data that can then be used for further computations.</p>
  </li>
  <li>
    <p>What are major and minor modes: Presents the basics of modes in
Emacs. It explains what major and minor modes have in common and how
they differ, while also discussing relevant concepts of precedence.</p>
  </li>
  <li>
    <p>Hooks and the advice mechanism: Explains what are hooks and how
they work. It also covers the powerful advice mechanism, as some
uses of it as similar to what hooks are supposed to do.</p>
  </li>
  <li>
    <p>Autoloading symbols: Shows how Emacs manages to “lazy load” code
when it needs to. This is especially helpful for package developers.</p>
  </li>
  <li>
    <p>Emacs as a computing environment: A more general view of Emacs
that helps us appreciate the value of Emacs Lisp. The more time we
put into learning this programming language, the better we will get
at controlling large parts of our computing life through Emacs.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: pulsar version 1.3.0</title>
      <description>Information about the latest version of my pulsar package for GNU Emacs.</description>
      <pubDate>Sun, 30 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-30-emacs-pulsar-1-3-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-30-emacs-pulsar-1-3-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This is a small Emacs package that automatically highlights the current
line after certain functions are invoked. It can also highlight a line
or region on demand. The idea is to make it easier to find where the
point is, what was affected, and also to bring attention to something
in a buffer. <a href="https://protesilaos.com/codelog/2022-03-14-emacs-pulsar-demo/">Watch the original demo</a> (2022-03-14).</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">pulsar</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/pulsar">https://protesilaos.com/emacs/pulsar</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/pulsar-changelog">https://protesilaos.com/emacs/pulsar-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/pulsar">https://github.com/protesilaos/pulsar</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/pulsar">https://gitlab.com/protesilaos/pulsar</a></li>
    </ul>
  </li>
  <li>Backronym: Pulsar Unquestionably Luminates, Strictly Absent the Radiation.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h1>Version 1.3.0 on 2025-11-30</h1>

<p>This version introduces a new feature and makes small refinements to
an already reliable base.</p>

<h2>Permanent static highlight for a line or region</h2>

<p>In the most common use-case, Pulsar produces a highlight that fades in
and out of view after a certain amount of time. The idea with such a
“pulse effect” is to quickly get a sense of where the cursor is when
some change occurs (e.g. switching to another window).</p>

<p>The permanent static highlights differ from pulse effects in two ways:
(i) they do not have a fade-in and fade-out phase and (ii) are not
removed automatically. These highlights stick around either until the
user removes them or their underlying text is deleted. They are meant
to be used as intentional highlights, such as to draw attention to a
certain statement while doing a presentation.</p>

<p>The command <code class="language-plaintext highlighter-rouge">pulsar-highlight-permanently</code> adds a permanent static
highlight to the current line. When the region is active, the
highlight is applied from the beginning to the end of the region.</p>

<p>The command <code class="language-plaintext highlighter-rouge">pulsar-highlight-permanently-remove</code> removes permanent
static highlights from the active region or current line. This command
operates on the entire buffer when it is called with a universal
prefix argument (<code class="language-plaintext highlighter-rouge">C-u</code> by default).</p>

<p>The command <code class="language-plaintext highlighter-rouge">pulsar-highlight-permanently-dwim</code> adds a permanent
static highlight if there is none or removes it if there is one. It
operates on the currently active region or line at point.</p>

<p>Permanent static highlights are rendered with the face specified in
the user option <code class="language-plaintext highlighter-rouge">pulsar-highlight-face</code>.</p>

<h2>New name for temporary static highlights</h2>

<p>The commands <code class="language-plaintext highlighter-rouge">pulsar-highlight-dwim</code> and <code class="language-plaintext highlighter-rouge">pulsar-highlight-line</code> are
obsolete aliases for <code class="language-plaintext highlighter-rouge">pulsar-highlight-temporarily</code>.</p>

<p>Temporary static highlights do not have a fade-in and fade-out phase.
They are automatically removed as soon as an action occurs. They are
an alternative to the aforementioned permanent static highlights.</p>

<p>The command <code class="language-plaintext highlighter-rouge">pulsar-highlight-temporarily</code> will operate on the active
region or the current line.</p>

<h2>Miscellaneous</h2>

<ul>
  <li>
    <p>Thanks to Koloszár Gergely for reporting an intermediate bug where
the pulse effect actually did not pulse under certain conditions.
This was done in issue 31: <a href="https://github.com/protesilaos/pulsar/issues/31">https://github.com/protesilaos/pulsar/issues/31</a>.</p>
  </li>
  <li>
    <p>Parts of the code are rewritten in the interest of clarity.</p>
  </li>
  <li>
    <p>The entire manual is redone to better organise the documentation.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: Substitute version 0.4.0</title>
      <description>Information about the latest version of my 'substitute' package for Emacs.</description>
      <pubDate>Sat, 29 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-29-emacs-substitute-0-4-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-29-emacs-substitute-0-4-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Substitute is a set of commands that perform text replacement (i)
throughout the buffer, (ii) limited to the current definition (per
<code class="language-plaintext highlighter-rouge">narrow-to-defun</code>), (iii) from point to the end of the buffer, and
(iv) from point to the beginning of the buffer. Variations of these
scopes are also available.</p>

<p>These substitutions are meant to be as quick as possible and, as such,
differ from the standard <code class="language-plaintext highlighter-rouge">query-replace</code> (which I still use when
necessary). The provided commands prompt for substitute text and
perform the substitution outright, without moving the point. The
target is the symbol/word at point or the text corresponding to the
currently marked region. All matches in the given scope are
highlighted by default.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">substitute</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/substitute">https://protesilaos.com/emacs/substitute</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/substitute">https://github.com/protesilaos/substitute</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/substitute">https://gitlab.com/protesilaos/substitute</a></li>
    </ul>
  </li>
  <li>Video demo: <a href="https://protesilaos.com/codelog/2023-01-16-emacs-substitute-package-demo/">https://protesilaos.com/codelog/2023-01-16-emacs-substitute-package-demo/</a></li>
  <li>Backronym: Substitutions Uniformly Beget Standardisation for Text Invariably Transfigured Unto This Entry.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 0.4.0 on 2025-11-29</h2>

<p>This version iterates on an already stable package. It introduces a
few new commands while making minor internal refinements.</p>

<p>The new commands work exactly like those already on offer, except for
their scope of application. Remember that Substitute targets either
the symbol/word at point or any occurrences of the currently marked
characters/text within the given scope and replaces them with the
user’s input. The scope is something like “current function
definition”, “current paragraph”, “from here to the end of the
buffer”, et cetera. The substitution does not move the cursor.</p>

<p>The new commands:</p>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">substitute-target-in-outline</code>: Substitute the target across the
current outline level. The outline is determined by the buffer-local
value of the variable <code class="language-plaintext highlighter-rouge">outline-regexp</code>. For example, in Org mode the
current outline level includes the heading and any text below it but
not any subheadings.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">substitute-target-in-page</code>: Like the above for the boundaries of
the current page. A page is determined by the buffer-local value of
the variable <code class="language-plaintext highlighter-rouge">page-delimiter</code>.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">substitute-target-in-paragraph</code>: As above for the current
paragraph. Note that in programming modes a “paragraph” is not
necessarily the same as with prose (where, in their simplest form,
paragraphs are delimited by empty lines). Substitute highlights all
matches by default, so users should notice the difference right
away.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">substitute-target-in-defun-and-below</code>: This works in the scope of
the current definition (per <code class="language-plaintext highlighter-rouge">narrow-to-defun</code>) but only from point
onwards. It is the counterpart to the commands we always had in
<code class="language-plaintext highlighter-rouge">substitute-target-in-defun</code>.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: new Modus themes tool to generate a complete palette</title>
      <description>There is a new function I wrote for my modus-themes that makes it easier for users to create derivative Modus themes palettes.</description>
      <pubDate>Tue, 25 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-25-emacs-modus-tools-to-generate-complete-palette/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-25-emacs-modus-tools-to-generate-complete-palette/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>[ This is of interest to users who want to create a new theme on top of
  Modus (for private purposes or as a package). ]</p>

<p>The current development target of the Modus themes includes the
function <code class="language-plaintext highlighter-rouge">modus-themes-generate-palette</code>. I have updated the manual
with a detailed, step-by-step guide on how to use that function to
derive a custom theme. I am doing it with Solarized, since it is
well-known. Start here: <a href="https://protesilaos.com/emacs/modus-themes#h:3a7ede17-f0d4-4322-8e69-1804ed69012b">https://protesilaos.com/emacs/modus-themes#h:3a7ede17-f0d4-4322-8e69-1804ed69012b</a></p>

<p>The reason I wrote this function is to make it easier for users to get
started with their Modus ports. The common workflow is for someone to
copy a colour scheme from their favourite terminal emulator and use it
as a starting point for their Emacs theme. Modus will do the heavy
lifting in the background.</p>

<p><code class="language-plaintext highlighter-rouge">modus-themes-generate-palette</code> returns a fully fledged Modus palette:
the literal hundreds of entries are all defined, even if we only give
it a couple of colour values. The more colours we specify, the more
defined the character of the resulting palette will be—and we have
complete control, as the manual demonstrates.</p>

<p>A good starting point is to provide values for the main background (<code class="language-plaintext highlighter-rouge">bg-main</code>),
main foreground (<code class="language-plaintext highlighter-rouge">fg-main</code>), and the basic hues of <code class="language-plaintext highlighter-rouge">red</code>, <code class="language-plaintext highlighter-rouge">green</code>,
<code class="language-plaintext highlighter-rouge">yellow</code>, <code class="language-plaintext highlighter-rouge">blue</code>, <code class="language-plaintext highlighter-rouge">magenta</code>, and <code class="language-plaintext highlighter-rouge">cyan</code>.</p>

<p>Options for power users are available. Though the point is to lower
the barrier to entry for those who want to start with something
tolerable. Then they can trust that I cover everything they need to
gradually evolve their theme to be as complete as core Modus.</p>

<p>In the manual I used Solarized as an example, with usable code
snippets that you can copy+paste. Those yield a theme, if you try
them. Below is a complete, albeit generic, Modus+Solarized theme. It
is a decent starting point.</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Modus+Solarized dark</span>
<span class="p">(</span><span class="nb">defvar</span> <span class="nv">modus-solarized-dark-palette</span>
  <span class="p">(</span><span class="nv">modus-themes-generate-palette</span>
   <span class="o">'</span><span class="p">((</span><span class="nv">bg-main</span> <span class="s">"#073642"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">fg-main</span> <span class="s">"#EEE8D5"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">red</span> <span class="s">"#DC322F"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">green</span> <span class="s">"#859900"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">yellow</span> <span class="s">"#B58900"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">blue</span> <span class="s">"#268BD2"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">magenta</span> <span class="s">"#D33682"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">cyan</span> <span class="s">"#2AA198"</span><span class="p">))))</span>

<span class="p">(</span><span class="nv">modus-themes-theme</span>
 <span class="ss">'modus-solarized-dark</span>
 <span class="ss">'modus-solarized-themes</span>
 <span class="s">"Sample of a basic Solarized dark port."</span>
 <span class="ss">'dark</span>
 <span class="ss">'modus-solarized-dark-palette</span>
 <span class="no">nil</span>
 <span class="no">nil</span><span class="p">)</span>
</code></pre></div></div>

<p>Do not rush to play around with this snippet. The chapter in the
manual I linked to above has much more about this topic. Take some
time to read through it. You can extend the port to also map out all
the colors you want. Thus:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Modus+Solarized dark</span>
<span class="p">(</span><span class="nb">defvar</span> <span class="nv">modus-solarized-dark-palette</span>
  <span class="p">(</span><span class="nv">modus-themes-generate-palette</span>
   <span class="c1">;; We provide the two base colors of Solarized, plus most of its</span>
   <span class="c1">;; accents.  These form the BASE-COLORS we pass as an argument.</span>
   <span class="c1">;; All other color values come from those.  The BASE-COLORS here</span>
   <span class="c1">;; are enough to generate a new palatte that has no traces of, say,</span>
   <span class="c1">;; the `modus-vivendi' color values.</span>
   <span class="o">'</span><span class="p">((</span><span class="nv">bg-main</span> <span class="s">"#073642"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">fg-main</span> <span class="s">"#EEE8D5"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">red</span> <span class="s">"#DC322F"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">green</span> <span class="s">"#859900"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">yellow</span> <span class="s">"#B58900"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">blue</span> <span class="s">"#268BD2"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">magenta</span> <span class="s">"#D33682"</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">cyan</span> <span class="s">"#2AA198"</span><span class="p">))</span>
   <span class="c1">;; The COOL-OR-WARM-PREFERENCE is derived internally based on</span>
   <span class="c1">;; `bg-main'.  We can pass it here if we feel strongly about it.</span>
   <span class="no">nil</span>
   <span class="c1">;; If we need to specify the CORE-PALETTE from where to inherit any</span>
   <span class="c1">;; missing colors and/or semantic mappings, we can give it here.</span>
   <span class="c1">;; Though nil is the appropriate starting point, as the code will</span>
   <span class="c1">;; handle things internally.</span>
   <span class="no">nil</span>
   <span class="c1">;; And here are our MAPPINGS where we can specify what values apply</span>
   <span class="c1">;; to which semantic color.  The `modus-themes-list-colors' shows</span>
   <span class="c1">;; them all.</span>
   <span class="c1">;;</span>
   <span class="c1">;; Note that in our BASE-COLORS above we never wrote what, say,</span>
   <span class="c1">;; `magenta-warmer' is: it is derived programmatically from the</span>
   <span class="c1">;; `magenta' we have there.  Absent that, it would be taken from</span>
   <span class="c1">;; the CORE-PALETTE.</span>
   <span class="o">'</span><span class="p">((</span><span class="nv">cursor</span> <span class="nv">magenta-warmer</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">bg-hl-line</span> <span class="nv">bg-blue-nuanced</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">bg-paren-match</span> <span class="nv">bg-magenta-subtle</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">bg-region</span> <span class="nv">bg-blue-intense</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">fg-region</span> <span class="nv">fg-dim</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">bg-mode-line-active</span> <span class="nv">bg-blue-nuanced</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">fg-mode-line-active</span> <span class="nv">blue-warmer</span><span class="p">)</span>
     <span class="p">(</span><span class="nv">border-mode-line-active</span> <span class="nv">blue-cooler</span><span class="p">))))</span>

<span class="p">(</span><span class="nv">modus-themes-theme</span>
 <span class="ss">'modus-solarized-dark</span>
 <span class="ss">'modus-solarized-themes</span>
 <span class="s">"Sample of a basic Solarized dark port."</span>
 <span class="ss">'dark</span>
 <span class="ss">'modus-solarized-dark-palette</span>
 <span class="no">nil</span>
 <span class="no">nil</span><span class="p">)</span>
</code></pre></div></div>

<p>Using this infrastructure, I am confident that we can implement any
colour scheme as a Modus theme—and, again, we can configure every
part of it.</p>

<p>The manual is extensive, though remember that I remain at your
disposal in case something is unclear: open an issue in the Modus
themes repository or <a href="https://protesilaos.com/contact/">contact me</a>
and I will help you.</p>

<h2>Sources</h2>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">modus-themes</code> (also built into Emacs)</li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/modus-themes-changelog">https://protesilaos.com/emacs/modus-themes-changelog</a></li>
  <li>Colour palette: <a href="https://protesilaos.com/emacs/modus-themes-colors">https://protesilaos.com/emacs/modus-themes-colors</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/modus-themes-pictures">https://protesilaos.com/emacs/modus-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/modus-themes">https://github.com/protesilaos/modus-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/modus-themes">https://gitlab.com/protesilaos/modus-themes</a></li>
    </ul>
  </li>
  <li>Backronym: My Old Display Unexpectedly Sharpened … themes.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: doric-themes version 0.5.0</title>
      <description>Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate).</description>
      <pubDate>Sun, 23 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-23-doric-themes-0-5-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-23-doric-themes-0-5-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>These are my minimalist themes. They use few colours and will appear
mostly monochromatic in many contexts. Styles involve the careful use
of typography, such as italics and bold italics.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Update to doric-themes 0.5.0</h2>

<h3>Enjoy the two new members of the collection</h3>

<p>These are <code class="language-plaintext highlighter-rouge">doric-siren</code> and <code class="language-plaintext highlighter-rouge">doric-mermaid</code>. The former is a light
theme while the latter is dark. Both themes offer a marine vibe
combined with warm hues. Check the updated screenshots of all the
Doric themes: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a>.</p>

<h3>Support for transient.el semantic faces</h3>

<p>Those are used when the user option <code class="language-plaintext highlighter-rouge">transient-semantic-coloring</code> is
set to a non-<code class="language-plaintext highlighter-rouge">nil</code> value (the default). They are designed to indicate
different types of key, such as those that keep the transient in place
as opposed to exiting it.</p>

<p>The old style of making all key bindings look the same is still
available if <code class="language-plaintext highlighter-rouge">transient-semantic-coloring</code> is set to <code class="language-plaintext highlighter-rouge">nil</code>.</p>

<h3>Semantic Emacs Lisp faces</h3>

<p>This is a new feature coming in Emacs 31. Users can opt in to it by
setting the user option <code class="language-plaintext highlighter-rouge">elisp-fontify-semantically</code> to a non-<code class="language-plaintext highlighter-rouge">nil</code>
value. When active, Emacs Lisp buffers will apply highlights to more
elements of the syntax. Those will still conform with the minimalist
style of the Doric themes, but users at least get the benefits of
<code class="language-plaintext highlighter-rouge">elisp-add-help-echo</code>.</p>

<h3>Font-lock faces for function calls and use of variables</h3>

<p>Those are typically applied by major modes that are power by
tree-sitter. Again, the styles are minimalist.</p>

<h3>More faces or face groups are covered</h3>

<p>These include:</p>

<ul>
  <li>ibuffer’s Emacs 31 faces (patched by me in emacs.git)</li>
  <li>flymake’s Emacs 31 faces (again, my patch in core)</li>
  <li>diff-hl package</li>
  <li>git-gutter package</li>
  <li>org-habit</li>
  <li>minibuffer-nonselected for Emacs 31</li>
  <li>eglot-highlight-symbol-face</li>
  <li><code class="language-plaintext highlighter-rouge">ert-test-result-unexpected</code> and <code class="language-plaintext highlighter-rouge">ert-test-result-expected</code>,
courtesy of Rudolf Adamkovič in pull request 19:
<a href="https://github.com/protesilaos/doric-themes/pull/19">https://github.com/protesilaos/doric-themes/pull/19</a>.</li>
</ul>

<h3>Refinements to already supported faces</h3>

<ul>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">calendar-today</code> and <code class="language-plaintext highlighter-rouge">org-date-selected</code> are similar but
different enough to stand apart. I initially made them look identical
because I thought they would never appear in the same context. Thanks
to Rudolf Adamkovič for telling me they could actually be collocated,
hence their disambiguation. This was done in issue 20:
<a href="https://github.com/protesilaos/doric-themes/issues/20">https://github.com/protesilaos/doric-themes/issues/20</a>.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">transient-argument</code> and <code class="language-plaintext highlighter-rouge">transient-value</code> have a background to
make them easier to spot. This is because they convey information
about the state of the transient interface, which typically is important.</p>
  </li>
  <li>
    <p>Transient’s mismatching keys are dimmed out instead of being
underlined, because this looks better in context.</p>
  </li>
  <li>
    <p>Similarly, <code class="language-plaintext highlighter-rouge">org-agenda-clocking</code> has a more pronounced background.</p>
  </li>
  <li>
    <p>Idem for <code class="language-plaintext highlighter-rouge">eldoc-highlight-function-argument</code> and its counterparts in
<code class="language-plaintext highlighter-rouge">lsp-mode</code> and <code class="language-plaintext highlighter-rouge">geiser</code>.</p>
  </li>
  <li>
    <p>The Org check boxes are rendered with a bold weight, while quote
blocks are in italics. Thanks to Rudolf Adamkovič for the patch in
pull request 18: <a href="https://github.com/protesilaos/doric-themes/pull/18">https://github.com/protesilaos/doric-themes/pull/18</a>.</p>
  </li>
  <li>
    <p>All Notmuch cryptography-related faces have more refined styles to
both stand out better while avoiding exaggerations.</p>
  </li>
  <li>
    <p>The Custom user interface buttons inherit from <code class="language-plaintext highlighter-rouge">variable-pitch</code>.</p>
  </li>
  <li>
    <p>The current line number in <code class="language-plaintext highlighter-rouge">display-line-numbers-mode</code> uses just a
bold weight to avoid exaggerations.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: new ‘denote-merge’ package</title>
      <description>Information about my new optional extension to Denote that streamlines the work of merging contents from one file to another.</description>
      <pubDate>Sat, 22 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-22-new-emacs-denote-merge/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-22-new-emacs-denote-merge/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <code class="language-plaintext highlighter-rouge">denote-merge</code> package is an optional extension to <code class="language-plaintext highlighter-rouge">denote</code>. I am
providing it in response to requests for functionality that
streamlines the work of merging contents from one file into another.
Thanks to Sia Piperea for reminding me about it, making a suggestion
for region-related functions, and for testing my prototype:</p>

<ul>
  <li><a href="https://github.com/protesilaos/denote-org/issues/16">https://github.com/protesilaos/denote-org/issues/16</a>.</li>
  <li><a href="https://github.com/protesilaos/denote/issues/649">https://github.com/protesilaos/denote/issues/649</a>.</li>
  <li><a href="https://github.com/protesilaos/denote-merge/issues/1">https://github.com/protesilaos/denote-merge/issues/1</a>.</li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">denote-merge</code> package is a more refined implementation of those
ideas, plus more. As of now, the package provides support for two
broad kinds of “merging”:</p>

<ul>
  <li>Merge one file into another.</li>
  <li>Merge a region into a file.</li>
</ul>

<p>For merging a region, in particular, there are options and concomitant
convenience commands to format the region in a certain way, such as an
Org source block, a Markdown blockquote, a plain indented region, and
the like.</p>

<p>The official manual describes the technicalities. In short, I have
taken care to make the relevant commands do the right thing, including
to update backlinks, annotate the contents, and establish links, where
relevant.</p>

<p>Note that the GNU ELPA package is not available yet. I have prepared
the relevant patch and am expecting everything to be done in the near
future.</p>

<p>Please stay tuned.</p>

<h2>Sources</h2>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote-merge</code> (Coming soon!!!)</li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote-merge">https://protesilaos.com/emacs/denote-merge</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/denote-merge">https://github.com/protesilaos/denote-merge</a></li>
  <li>Backronym: Denote… Merging Eventually Reformats the Given Entries.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: new Doric themes ‘doric-siren’ and ‘doric-mermaid’</title>
      <description>I am developing two new themes for my minimalistic 'doric-themes' package for Emacs. These combine marine hues with some warmer accents.</description>
      <pubDate>Mon, 17 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-17-emacs-new-doric-themes-siren-mermaid/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-17-emacs-new-doric-themes-siren-mermaid/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I am developing two new themes for my minimalistic <code class="language-plaintext highlighter-rouge">doric-themes</code>
package for Emacs. These combine marine hues with some warmer accents,
cast on a fairly prominent backdrop. <code class="language-plaintext highlighter-rouge">doric-siren</code> is a light theme,
while <code class="language-plaintext highlighter-rouge">doric-mermaid</code> is dark. Below are some screenshots to give you
an idea of what to expect.</p>

<p>[ Or just check all the pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a>. ]</p>

<h2>doric-siren</h2>

<p><a href="https://protesilaos.com/assets/images/doric/doric-siren.png"><img alt="doric-siren theme sample" src="https://protesilaos.com/assets/images/doric/doric-siren.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-siren-org.png"><img alt="doric-siren theme sample" src="https://protesilaos.com/assets/images/doric/doric-siren-org.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-siren-message.png"><img alt="doric-siren theme sample" src="https://protesilaos.com/assets/images/doric/doric-siren-message.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-siren-magit.png"><img alt="doric-siren theme sample" src="https://protesilaos.com/assets/images/doric/doric-siren-magit.png" /></a></p>

<h2>doric-mermaid</h2>

<p><a href="https://protesilaos.com/assets/images/doric/doric-mermaid.png"><img alt="doric-mermaid theme sample" src="https://protesilaos.com/assets/images/doric/doric-mermaid.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-mermaid-org.png"><img alt="doric-mermaid theme sample" src="https://protesilaos.com/assets/images/doric/doric-mermaid-org.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-mermaid-message.png"><img alt="doric-mermaid theme sample" src="https://protesilaos.com/assets/images/doric/doric-mermaid-message.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-mermaid-magit.png"><img alt="doric-mermaid theme sample" src="https://protesilaos.com/assets/images/doric/doric-mermaid-magit.png" /></a></p>

<h2>Coming in <code class="language-plaintext highlighter-rouge">doric-themes</code> version 0.5.0</h2>

<p>The character of the themes is established and, in principle, I will
not change them further. Though I am giving it a few more days of
further testing to confirm I did not miss something. Expect these and
other improvements to be available in the next stable version of the
<code class="language-plaintext highlighter-rouge">doric-themes</code>, which I expect to publish before the end of November.</p>

<h2>About the Doric themes</h2>

<p>The Doric themes use few colours and will appear monochromatic in many
contexts. They are my most minimalist themes. Styles involve the
careful use of typographic features and subtleties in colour gradients
to establish a consistent rhythm. Legibility is still high.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: complete examples for Modus themes derivatives</title>
      <description>I updated the manual of the Modus themes with complete step-by-step instructions and code samples that can be copy-pasted directly.</description>
      <pubDate>Mon, 10 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-10-emacs-modus-themes-derivatives-more-doc-examples/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-10-emacs-modus-themes-derivatives-more-doc-examples/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just expanded the manual of the <code class="language-plaintext highlighter-rouge">modus-themes</code> with complete
step-by-step examples on how to define a derivative theme. Here is the
commit:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>commit c94938ff794d043447ed4ffe9b55f1031039f667
Author: Protesilaos Stavrou &lt;info@protesilaos.com&gt;
Date:   Mon Nov 10 13:02:49 2025 +0200

  Greatly expand the manual with complete examples of creating Modus derivatives

  This covers the basic and more advanced use cases. It also is for both
  private use and making new packages.

 doc/modus-themes.info | 588 +++++++++++++++++++++++++++++++++++++-------------
 doc/modus-themes.org  | 278 +++++++++++++++++++++++-
 2 files changed, 711 insertions(+), 155 deletions(-)
</code></pre></div></div>

<p>The relevant sections and their structure:</p>

<ul>
  <li><a href="https://protesilaos.com/emacs/modus-themes#h:86eb375b-9be4-43ce-879a-0686a524a63b">Build on top of the Modus themes</a>
    <ul>
      <li><a href="https://protesilaos.com/emacs/modus-themes#h:bd47fea9-416d-481e-a504-82850b8c2a58">Complete example of a Modus derivative theme</a>
        <ul>
          <li><a href="https://protesilaos.com/emacs/modus-themes#h:f2757848-ea41-4cd7-a04d-7e650555a59b">Complete example of a package that is derived from Modus</a></li>
          <li><a href="https://protesilaos.com/emacs/modus-themes#h:48e391a6-831b-48ec-b92d-4e7e6871b043">Complete example of a private theme derived from Modus</a></li>
          <li><a href="https://protesilaos.com/emacs/modus-themes#h:ca3031b5-5f7a-46d4-bc83-e84e8bed038c">Complete example of a custom theme with its own palette</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<p>If something is unclear, you are welcome to contact me.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: ‘standard-themes’ version 3.0.0</title>
      <description>Release notes for the latest version of my 'standard-themes' for GNU Emacs.</description>
      <pubDate>Sun, 09 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-09-emacs-standard-themes-3-0-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-09-emacs-standard-themes-3-0-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <code class="language-plaintext highlighter-rouge">standard-themes</code> are a collection of light and dark themes for
GNU Emacs. The <code class="language-plaintext highlighter-rouge">standard-light</code> and <code class="language-plaintext highlighter-rouge">standard-dark</code> emulate the
out-of-the-box looks of Emacs (which technically do NOT constitute a
theme) while bringing to them thematic consistency, customizability,
and extensibility. Other themes are stylistic variations of those.</p>

<p>In practice, the Standard themes take the default style of the
font-lock and Org faces, complement it with a wider and harmonious
colour palette, address many inconsistencies, and apply established
semantic patterns across all interfaces by supporting a large number
of packages.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">standard-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/standard-themes">https://protesilaos.com/emacs/standard-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/standard-themes-changelog">https://protesilaos.com/emacs/standard-themes-changelog</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/standard-themes-pictures">https://protesilaos.com/emacs/standard-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/standard-themes">https://github.com/protesilaos/standard-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/standard-themes">https://gitlab.com/protesilaos/standard-themes</a></li>
    </ul>
  </li>
  <li>Backronym: Standard Themes Are Not Derivatives but the
Affectionately Reimagined Default … themes.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 3.0.0 on 2025-11-09</h2>

<p>This major version makes Standard build on top of my Modus themes. The
latter provides extensive face/package coverage and a wide range of
customisation options. As a result, the Standard themes retain their
design while giving more control to the user.</p>

<p>These release notes are essentially the same as what I wrote earlier
today for my <code class="language-plaintext highlighter-rouge">ef-themes</code> package, which is now also built on top of my
Modus themes: <a href="https://protesilaos.com/codelog/2025-11-09-emacs-ef-themes-2-0-0/">https://protesilaos.com/codelog/2025-11-09-emacs-ef-themes-2-0-0/</a>.</p>

<p>In short:</p>

<ul>
  <li>User options that were provided by the Standard themes are now mere
aliases for their Modus counterparts.</li>
  <li>Commands that were defined by the Standard themes are now reduced to
convenience wrappers that build on top of Modus.</li>
  <li>The new minor mode <code class="language-plaintext highlighter-rouge">standard-themes-take-over-modus-themes-mode</code> can
be enabled to make all Modus commands that load a theme only
consider the Standard themes. This is effectively the opposite of
enabling the <code class="language-plaintext highlighter-rouge">modus-themes-include-derivatives-mode</code> or using one of
the Standard commands to load just a Standard theme (like
<code class="language-plaintext highlighter-rouge">standard-themes-rotate</code>).</li>
  <li>The manual of the Modus themes covers everything from the basics to
advanced topics on how to use and customise the themes. Evaluate
<code class="language-plaintext highlighter-rouge">(info "(modus-themes) Top")</code> or visit <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a>.</li>
</ul>

<p>You are welcome to contact me if something is unclear.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: ef-themes version 2.0.0</title>
      <description>Information about the latest version of my colourful-yet-legible themes for GNU Emacs.</description>
      <pubDate>Sun, 09 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-09-emacs-ef-themes-2-0-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-09-emacs-ef-themes-2-0-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <code class="language-plaintext highlighter-rouge">ef-themes</code> are a collection of light and dark themes for GNU
Emacs that provide colourful (“pretty”) yet legible options for users
who want something with a bit more flair than the <code class="language-plaintext highlighter-rouge">modus-themes</code> (also
designed by me).</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">ef-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/ef-themes">https://protesilaos.com/emacs/ef-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/ef-themes-changelog">https://protesilaos.com/emacs/ef-themes-changelog</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/ef-themes">https://github.com/protesilaos/ef-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/ef-themes">https://gitlab.com/protesilaos/ef-themes</a></li>
    </ul>
  </li>
  <li>Backronym: Eclectic Fashion in Themes Hides Exaggerated Markings,
Embellishments, and Sparkles.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 2.0.0 on 2025-11-09</h2>

<p>The Ef themes are now derived from my Modus themes. This means that
they inherit the wide face coverage and extensive customisability of
Modus, while retaining their stylistic flair.</p>

<p>The Ef themes no longer provide any user options of their own. Each of
the options we had before is now an alias for the Modus equivalent. As
part of this transition, the Ef themes actually gain new customisation
options, which are documented herein.</p>

<p>Furthermore, the Ef themes do not define any commands to load a theme.
What we had before is once again an alias for the equivalent Modus
command.</p>

<p>The manual of the Ef themes describes these compatibility
arrangements. Further documentation and code samples are available in
the manual of the Modus themes:</p>

<ul>
  <li><strong>Info page:</strong> Evaluate  <code class="language-plaintext highlighter-rouge">(info "(modus-themes) Top")</code>.</li>
  <li><strong>Weg page:</strong> Visit <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a>.</li>
</ul>

<h3>Old user options and hooks are mere aliases for Modus options</h3>

<table>
  <thead>
    <tr>
      <th>Old name</th>
      <th>Is alias for CURRENT NAME</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>ef-themes-disable-other-themes</td>
      <td>modus-themes-disable-other-themes</td>
    </tr>
    <tr>
      <td>ef-themes-to-toggle</td>
      <td>modus-themes-to-toggle</td>
    </tr>
    <tr>
      <td>ef-themes-to-rotate</td>
      <td>modus-themes-to-rotate</td>
    </tr>
    <tr>
      <td>ef-themes-italic-constructs</td>
      <td>modus-themes-italic-constructs</td>
    </tr>
    <tr>
      <td>ef-themes-bold-constructs</td>
      <td>modus-themes-bold-constructs</td>
    </tr>
    <tr>
      <td>ef-themes-variable-pitch-ui</td>
      <td>modus-themes-variable-pitch-ui</td>
    </tr>
    <tr>
      <td>ef-themes-mixed-fonts</td>
      <td>modus-themes-mixed-fonts</td>
    </tr>
    <tr>
      <td>ef-themes-headings</td>
      <td>modus-themes-headings</td>
    </tr>
    <tr>
      <td>ef-themes-completions</td>
      <td>modus-themes-completions</td>
    </tr>
    <tr>
      <td>ef-themes-prompts</td>
      <td>modus-themes-prompts</td>
    </tr>
    <tr>
      <td>ef-themes-common-palette-overrides</td>
      <td>modus-themes-common-palette-overrides</td>
    </tr>
    <tr>
      <td>ef-themes-post-load-hook</td>
      <td>modus-themes-after-load-theme-hook</td>
    </tr>
    <tr>
      <td>ef-themes-after-load-theme-hook</td>
      <td>modus-themes-after-load-theme-hook</td>
    </tr>
  </tbody>
</table>

<p>Please read their respective documentation strings.</p>

<p>If you use Ef and possibly other Modus derivatives, you may prefer to
switch all your user options to the Modus ones. This way you can keep
a unified configuration for all your themes.</p>

<h3>Fewer bold and italic faces by default, more as an opt-in clause</h3>

<p>In the past, the Ef themes did not provide an option to disable the
extensive use of a bold font weight and italic font slant. Whereas now
those are controlled by the user options <code class="language-plaintext highlighter-rouge">modus-themes-bold-constructs</code>
and <code class="language-plaintext highlighter-rouge">modus-themes-italic-constructs</code>. By default, when they are <code class="language-plaintext highlighter-rouge">nil</code>,
bold and italics are used only when necessary. Set these user options
to <code class="language-plaintext highlighter-rouge">t</code> to have bold and italics in more places.</p>

<p><a id="h:00ba7745-7d69-4e96-b81a-b0269d83ce0f"></a></p>

<h3>Loading only Ef themes with the convenience wrappers we provide</h3>

<p>All the old commands Ef provided for loading one of its themes will
still work as before, meaning that they will only ever show and load a
theme that belongs to the Ef collection.</p>

<p>Internally, these commands are now using the Modus infrastructure and
are then limiting the set of themes to the Ef collection. They are
thus convenience wrappers around the equivalent Modus commands.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">ef-themes-toggle</code></li>
  <li><code class="language-plaintext highlighter-rouge">ef-themes-rotate</code></li>
  <li><code class="language-plaintext highlighter-rouge">ef-themes-select</code></li>
  <li><code class="language-plaintext highlighter-rouge">ef-themes-load-random</code></li>
  <li><code class="language-plaintext highlighter-rouge">ef-themes-load-random-dark</code></li>
  <li><code class="language-plaintext highlighter-rouge">ef-themes-load-random-light</code></li>
</ul>

<p>Additionally, the commands <code class="language-plaintext highlighter-rouge">ef-themes-list-colors</code> and
<code class="language-plaintext highlighter-rouge">ef-themes-list-colors-current</code> use the relevant Modus functionality
under the hood while working only with the Ef themes.</p>

<p><a id="h:a51893c3-9a52-4707-8a1e-3ff4642de6cf"></a></p>

<h3>Combining core Modus themes with all their derivatives</h3>

<p>The minor mode <code class="language-plaintext highlighter-rouge">modus-themes-include-derivatives-mode</code> makes all the
theme-loading commands that Modus defines consider all core and
derivative themes. This means that something like <code class="language-plaintext highlighter-rouge">modus-themes-select</code>
will offer <code class="language-plaintext highlighter-rouge">modus-operandi</code> and <code class="language-plaintext highlighter-rouge">ef-summer</code> as two of the many
possible candidates.</p>

<p>In this scenario, the Modus and Ef collections become part of a larger
family of themes as opposed to only considering one or the other
(<a href="#h:00ba7745-7d69-4e96-b81a-b0269d83ce0f">Loading only Ef themes with the convenience wrappers we provide</a>).
Enable <code class="language-plaintext highlighter-rouge">modus-themes-include-derivatives-mode</code> and then access them
all with the following commands:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-toggle</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-rotate</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-select</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-load-random</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-load-random-dark</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-load-random-light</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-list-colors</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-list-colors-current</code></li>
</ul>

<p>Consult the manual of the Modus themes for further details and/or read
the documentation string of each command.</p>

<h3>Taking over the Modus commands altogether</h3>

<p>The minor mode <code class="language-plaintext highlighter-rouge">ef-themes-take-over-modus-themes-mode</code> makes all Modus
commands that load a theme consider only Ef themes. This is the
opposite of allowing different theme collections to be blended
together (<a href="#h:a51893c3-9a52-4707-8a1e-3ff4642de6cf">Combining core Modus themes with all their derivatives</a>).
It effectively is the same as using one of the convenience wrapper
commands we already provide (<a href="#h:00ba7745-7d69-4e96-b81a-b0269d83ce0f">Loading only Ef themes with the convenience wrappers we provide</a>).</p>

<p>This minor mode exists to accommodate the needs of users who install
both the Modus and Ef theme packages (and possibly other Modus
derivatives). They can maintain a single/shared configuration and then
decide when to enable <code class="language-plaintext highlighter-rouge">ef-themes-take-over-modus-themes-mode</code> to
switch to using just the Ef themes.</p>

<p>For example, in the morning the user only wants to consider the Modus
themes, but during the evening they only likee the Ef themes. In this
scenario, a key binding to, say, <code class="language-plaintext highlighter-rouge">modus-themes-rotate</code> does not need
to be updated: it internally reads only Ef themes when
<code class="language-plaintext highlighter-rouge">ef-themes-take-over-modus-themes-mode</code> is enable. When this minor
mode is disabled, that same key binding will revert to doing what it
did before (load only a core Modus theme or Modus plus derivatives if
<code class="language-plaintext highlighter-rouge">modus-themes-include-derivatives-mode</code> is enabled).</p>

<h3>More semantic palette mappings</h3>

<p>Modus has always had a more comprehensive palette than Ef. Now they
are on par. Concretely, this means that users can customise more of
the theme’s style to their liking. Use the commands that list/preview
a palette to learn about all the available options.</p>

<p>The manual of the Modus themes covers the palette and user-defined
overrides at great length. It also includes code samples that you can
use as a starting point. And if something is unclear, you are welcome
to contact me.</p>

<h3>Many more faces are covered</h3>

<p>The wide face/package coverage of Modus is now inherited by the Ef
themes. If some interface you are using does not look right, then the
underlying faces are probably not supported yet. Contact me and I will
take care of it right away.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: modus-themes version 5.1.0</title>
      <description>Information about the latest version of my highly accessible themes for GNU Emacs.</description>
      <pubDate>Fri, 07 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-07-emacs-modus-themes-5-1-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-07-emacs-modus-themes-5-1-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just published the latest stable release of <a href="https://protesilaos.com/emacs/modus-themes">the Modus
themes</a>. The change log
entry is reproduced further below. For any questions, you are welcome
to <a href="https://protesilaos.com/contact/">contact me</a>. I will now work to
apply these same changes to emacs.git, so please wait a little longer
for the updates to trickle down to you.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">modus-themes</code> (also built into Emacs 28+)</li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/modus-themes-changelog">https://protesilaos.com/emacs/modus-themes-changelog</a></li>
  <li>Colour palette: <a href="https://protesilaos.com/emacs/modus-themes-colors">https://protesilaos.com/emacs/modus-themes-colors</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/modus-themes-pictures">https://protesilaos.com/emacs/modus-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/modus-themes">https://github.com/protesilaos/modus-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/modus-themes">https://gitlab.com/protesilaos/modus-themes</a></li>
    </ul>
  </li>
  <li>Backronym: My Old Display Unexpectedly Sharpened … themes.</li>
</ul>

<hr />

<h2>5.1.0 on 2025-11-07</h2>

<p>This version fixes a critical bug in the <code class="language-plaintext highlighter-rouge">modus-themes-with-colors</code>
macro. In short, it was not working as before or was not working at
all. Now it should do the right thing.</p>

<p>Thanks to Alexandr Semenov for reporting a relevant bug in issue 170
and for helping me test the results: <a href="https://github.com/protesilaos/modus-themes/issues/170">https://github.com/protesilaos/modus-themes/issues/170</a>.</p>

<p>Thanks to Stéphane Marks for testing some configurations with the
latest stable Emacs version as well as with builds from emacs.git.
This was done via a private channel and I am sharing this information
with permission.</p>

<p>Also thanks to Stefan Monnier for monitoring my commits as I was
trying to refactor the <code class="language-plaintext highlighter-rouge">modus-themes-with-colors</code> macro. Some comments
were posted on the emacs-devel mailing list, as well as a patch that I
ended up applying and then reverting (check the commit log for the
technicalities): <a href="https://lists.gnu.org/archive/html/emacs-devel/2025-11/msg00114.html">https://lists.gnu.org/archive/html/emacs-devel/2025-11/msg00114.html</a>.</p>

<p>Apologies to everyone for the inconvenience! This was a tricky bug.
The good thing is that it compelled me to improve several parts of the
code.</p>

<p>This version also includes a clarification in the manual about
building a theme on top of Modus:</p>

<ul>
  <li><strong>Web page:</strong> Visit <a href="https://protesilaos.com/emacs/modus-themes#h:86eb375b-9be4-43ce-879a-0686a524a63b">https://protesilaos.com/emacs/modus-themes#h:86eb375b-9be4-43ce-879a-0686a524a63b</a>.</li>
  <li><strong>Info manual:</strong> Evaluate <code class="language-plaintext highlighter-rouge">(info "(modus-themes) Build on top of the Modus themes")</code>.</li>
</ul>

<p>In short, it mentions that a theme exists in an appropriately named
file that is part of the <code class="language-plaintext highlighter-rouge">custom-theme-load-path</code>. Thanks to Ashton
Wiersdorf for asking a related question in issue 171:
<a href="https://github.com/protesilaos/modus-themes/issues/171">https://github.com/protesilaos/modus-themes/issues/171</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: modus-themes version 5.0.0</title>
      <description>Information about the latest version of my highly accessible themes for GNU Emacs.</description>
      <pubDate>Sat, 01 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-11-01-emacs-modus-themes-5-0-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-11-01-emacs-modus-themes-5-0-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just published the latest stable release of <a href="https://protesilaos.com/emacs/modus-themes">the Modus
themes</a>. The change log
entry is reproduced further below. For any questions, you are welcome
to <a href="https://protesilaos.com/contact/">contact me</a>. I will now work to
apply these same changes to emacs.git, so please wait a little longer
for the updates to trickle down to you.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">modus-themes</code> (also built into Emacs 28+)</li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/modus-themes-changelog">https://protesilaos.com/emacs/modus-themes-changelog</a></li>
  <li>Colour palette: <a href="https://protesilaos.com/emacs/modus-themes-colors">https://protesilaos.com/emacs/modus-themes-colors</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/modus-themes-pictures">https://protesilaos.com/emacs/modus-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/modus-themes">https://github.com/protesilaos/modus-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/modus-themes">https://gitlab.com/protesilaos/modus-themes</a></li>
    </ul>
  </li>
  <li>Backronym: My Old Display Unexpectedly Sharpened … themes.</li>
</ul>

<hr />

<h2>5.0.0 on 2025-11-01</h2>

<p>This is a major release. There are some small breaking changes. The
big new feature is that Modus can be used as the basis for other theme
projects. Two of my other theme packages, the <code class="language-plaintext highlighter-rouge">ef-themes</code> and the
<code class="language-plaintext highlighter-rouge">standard-themes</code> are already done in this way: their next major
versions will formalise what I have been developing for a while now
(though the <code class="language-plaintext highlighter-rouge">doric-themes</code> will remain their own thing for the time
being).</p>

<h3>Build on top of Modus</h3>

<p>This is of immediate interest to package developers or advanced users.
It changes nothing for existing users of the Modus themes. Please
refer to the manual on the matter and feel welcome to contact me if
you have any questions—I am happy to help.</p>

<p>Evaluate:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">info</span> <span class="s">"(modus-themes) Build on top of the Modus themes"</span><span class="p">)</span>
</code></pre></div></div>

<p>Or visit: <a href="https://protesilaos.com/emacs/modus-themes#h:86eb375b-9be4-43ce-879a-0686a524a63b">https://protesilaos.com/emacs/modus-themes#h:86eb375b-9be4-43ce-879a-0686a524a63b</a>.</p>

<p>Why build on top of Modus? To benefit from (i) the wide face coverage
and extensive detail-oriented testing, (ii) the use of palette
mappings, (iii) the palette preview done with
<code class="language-plaintext highlighter-rouge">modus-themes-list-colors</code> or related, (iv) the inclusion of the
derivative theme in the workings of all Modus commands that load a
theme, like <code class="language-plaintext highlighter-rouge">modus-themes-rotate</code> and <code class="language-plaintext highlighter-rouge">modus-themes-select</code> (see the
new minor mode <code class="language-plaintext highlighter-rouge">modus-themes-include-derivatives-mode</code>).</p>

<p>Derivative themes can be as simple as a few extra colours on top of,
say, <code class="language-plaintext highlighter-rouge">modus-operandi</code>. They can also be more involved, with new
palette mappings and custom faces that use them. Such themes can
define commands which load only their own themes (see
<code class="language-plaintext highlighter-rouge">modus-themes-define-derivative-command</code>) and they can even take over
the Modus themes completely, in terms of becoming the only ones that
are exposed to the commands that load a theme, like
<code class="language-plaintext highlighter-rouge">modus-themes-rotate</code> and <code class="language-plaintext highlighter-rouge">modus-themes-select</code>.</p>

<p>Thanks to Suleyman Boyar for fixing an intermediate omission with an
earlier version of the code that derives a theme. I did eventually
change the whole approach to use a function instead of a macro, but
Suleyman’s contribution was still useful at the time. This was done in
pull request 156: <a href="https://github.com/protesilaos/modus-themes/pull/156">https://github.com/protesilaos/modus-themes/pull/156</a>.
The change is small, meaning that Suleyman does not need to assign
copyright to the Free Software Foundation.</p>

<h3>Colours can be copied from the palette preview buffer</h3>

<p>The commands <code class="language-plaintext highlighter-rouge">modus-themes-list-colors</code> and <code class="language-plaintext highlighter-rouge">modus-themes-list-colors-current</code>
display the given theme’s palette in a tabulated listing. Each line
visualises the colour it references. From that buffer it is now
possible to call the following commands (bound to the <code class="language-plaintext highlighter-rouge">modus-themes-preview-mode-map</code>):</p>

<table>
  <thead>
    <tr>
      <th>Default key binding</th>
      <th>Name of the command</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">w</code></td>
      <td><code class="language-plaintext highlighter-rouge">modus-themes-preview-mode-copy-color</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">W</code></td>
      <td><code class="language-plaintext highlighter-rouge">modus-themes-preview-mode-copy-entry</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">m</code></td>
      <td><code class="language-plaintext highlighter-rouge">modus-themes-preview-mode-mark</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">M</code></td>
      <td><code class="language-plaintext highlighter-rouge">modus-themes-preview-mode-mark-all</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">u</code></td>
      <td><code class="language-plaintext highlighter-rouge">modus-themes-preview-mode-unmark</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">U</code></td>
      <td><code class="language-plaintext highlighter-rouge">modus-themes-preview-mode-unmark-all</code></td>
    </tr>
  </tbody>
</table>

<p>The <code class="language-plaintext highlighter-rouge">modus-themes-preview-mode-copy-color</code> and its
<code class="language-plaintext highlighter-rouge">modus-themes-preview-mode-copy-entry</code> counterpart work on the line at
point or those that are marked. The first copies the resolved colour
value, as a string (“resolved” here means that it will find what a
palette mapping actually stands for). The second gets the complete
palette entry, as it appears in the underlying definition. This is a
starting point for writing palette overrides.</p>

<p>Thanks to shimeike for reporting a problem with a regression I
introduced by mistake in one of the development versions of the
function that handles the creation of the tabulated list. This was
done in issue 163: <a href="https://github.com/protesilaos/modus-themes/issues/163">https://github.com/protesilaos/modus-themes/issues/163</a>.</p>

<h3>New semantic palette mappings for programming contexts</h3>

<p>The <code class="language-plaintext highlighter-rouge">fnname-call</code> and <code class="language-plaintext highlighter-rouge">variable-use</code> are now available. They are
applied to faces that are used by major modes which build on top of
<code class="language-plaintext highlighter-rouge">tree-sitter</code> program as well as the Emacs Lisp semantic highlighting
feature of Emacs 31.</p>

<p>By default, these colours are more subtle than their <code class="language-plaintext highlighter-rouge">fnname</code> and
<code class="language-plaintext highlighter-rouge">variable</code> counterparts. The reason is that I want to avoid
exaggerations with the wanton application of colour (“avoiding
exaggerations” is one of the design principles of the Modus themes).</p>

<p>Because of the commitment to the highest legibility standard for
colour contrast, we are using colours that stand out in their context,
yet are still harmonious with each other. This is due to (i) careful
consideration of colour harmonies, (ii) enforced uniformity of styles
where necessary to avoid emphasising the emphasis or stating the
obvious, and (ii) the fact that not too many intense colours appear in
close proximity to each other in most Emacs major modes. If a major
mode or other feature adds colours virtually everywhere, then the
Modus themes are no longer true to their character and become
borderline unusable.</p>

<p>The more subtle colours for <code class="language-plaintext highlighter-rouge">fnname-call</code> and <code class="language-plaintext highlighter-rouge">variable-use</code> do not
prevent exaggerations, though they do make them less egregious.</p>

<p>[ Note that themes do not control which face is applied where. That is
  the job of a major mode or specialised minor modes. When in doubt,
  work with the rule that fewer colours are better than many. ]</p>

<h3>Support for Emacs Lisp semantic highlighting</h3>

<p>This is built into Emacs version 31. What it does is make different
parts of the Elisp syntax stand out visually. It also augments them
with a mouse tooltip (technically a <code class="language-plaintext highlighter-rouge">help-echo</code>) that provides
valuable insights about what the thing is.</p>

<p>Thanks to Eshel Yaron, the author of this feature, for (i) asking me
to review the relevant faces, (ii) helping me understand what
“semantic highlighting” is intended for, and (iii) explaining to me
how some faces are meant to be used. This was done in the context of
Emacs bug 79677 and in an aside about a change to my minimalist
<code class="language-plaintext highlighter-rouge">doric-themes</code> package:</p>

<ul>
  <li><a href="https://lists.gnu.org/archive/html/bug-gnu-emacs/2025-10/msg01156.html">https://lists.gnu.org/archive/html/bug-gnu-emacs/2025-10/msg01156.html</a>.</li>
  <li><a href="https://lists.gnu.org/archive/html/emacs-devel/2025-10/msg00728.html">https://lists.gnu.org/archive/html/emacs-devel/2025-10/msg00728.html</a>.</li>
</ul>

<p>I wrote to Eshel that I do not want many colours clustered together.
This design is more suitable to themes with low intensity. All my
themes exacerbate the effect of dense colouration due to their primary
design goal: legibility.</p>

<p>Currently the added colouration of semantic highlighting is noticeable
far more than I like. This is a compromise on my end. Future versions
of the themes might set more semantic faces to <code class="language-plaintext highlighter-rouge">nil</code> (or anyhow make
them subtle), subject to further review and user feedback.</p>

<p>This is not a position against semantic highlighting, but a comment on
inconsiderate themes.</p>

<h3>More elements are optionally bold or italic</h3>

<p>I have revised all supported faces to make them more conservative
about when they apply typographic qualities that deviate from the
default font. Many faces that were unconditionally rendered with a
bold weight or an italic slant are now subject to the user options
<code class="language-plaintext highlighter-rouge">modus-themes-bold-constructs</code> and <code class="language-plaintext highlighter-rouge">modus-themes-italic-constructs</code>.</p>

<p>This means that they are like the default font family by default and
will become bold/italic if the relevant user option is set to a
non-<code class="language-plaintext highlighter-rouge">nil</code> value.</p>

<p>Faces that are semantically bold or italic and/or which genuinely
benefit from such typographic attributes out-of-the-box are exempt
from this.</p>

<p>Headings are also exempt because they are anyway subject to the user
option <code class="language-plaintext highlighter-rouge">modus-themes-headings</code> which covers the height and weight of
each heading level’s text.</p>

<p>Thanks to chainedghost for reporting a regression in one of the
commits I made. This was done in issue 167:
<a href="https://github.com/protesilaos/modus-themes/issues/167">https://github.com/protesilaos/modus-themes/issues/167</a></p>

<h3>Support for <code class="language-plaintext highlighter-rouge">lsp-mode</code> and <code class="language-plaintext highlighter-rouge">lsp-ui</code> packages</h3>

<p>Thanks to Jimmy Yuen Ho Wong for the initial contribution in pull
request 142: <a href="https://github.com/protesilaos/modus-themes/pull/142">https://github.com/protesilaos/modus-themes/pull/142</a>.
I made some changes on top to use semantic palette mappings, where
applicable, and other such tweaks.</p>

<h3>The <code class="language-plaintext highlighter-rouge">minibuffer-nonselected</code> face is supported</h3>

<p>This is coming in Emacs version 31: it highlights the active
minibuffer when the cursor is in another window. The face is designed
to be as noticeable as possible because this kind of scenario usually
leads to mistakes or confusion.</p>

<h3>Refinements to supported packages or face groups</h3>

<ul>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">markdown-code-face</code> uses the same semantic palette mapping as
<code class="language-plaintext highlighter-rouge">org-block</code>. This was always the intent. Thanks to Frédéric Giquel
for the fix in pull request 160: <a href="https://github.com/protesilaos/modus-themes/pull/160">https://github.com/protesilaos/modus-themes/pull/160</a>.
The change is small and thus does not require copyright assignment
to the Free Software Foundation.</p>
  </li>
  <li>
    <p>Fixed a word in the symbol of the <code class="language-plaintext highlighter-rouge">flymake-warning-echo-at-eol</code>. Thanks to
Eric Ottosson for the patch in pull request 145: <a href="https://github.com/protesilaos/modus-themes/pull/145">https://github.com/protesilaos/modus-themes/pull/145</a>.
No copyright assignment is required.</p>
  </li>
  <li>
    <p>The two new Emacs 31 faces for packages that are marked for
installation or deletion in the <code class="language-plaintext highlighter-rouge">M-x list-packages</code> buffer are now
included. Thanks to Gautier Ponsinet for sending me the patch.
Gautier has assigned copyright to the Free Software Foundation.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">hs-ellipsis</code> in Emacs 31 from the built-in <code class="language-plaintext highlighter-rouge">hideshow</code> package
is also covered. It is made to conform with established patterns
across conceptually equivalent faces (e.g. Org folded headings)
rather than do its own thing.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">widget-field</code> uses an underline to be easier to spot. On
supported Emacs displays (generally graphical Emacs) the underline
is at the descent line, meaning that it does not cross through
characters with descenders like <code class="language-plaintext highlighter-rouge">g</code>.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">git-commit</code> and <code class="language-plaintext highlighter-rouge">log-edit</code> faces for writing commit messages in
Magit and VC are tweaked to avoid exaggerations.</p>
  </li>
  <li>
    <p>The Magit section headings have a slightly modified foreground
value.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">org-list-dt</code> face for list definition terms has a slightly
modified foreground value to (i) be easier to spot while (ii) being
less intense overall.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">calendar-today</code> in the <code class="language-plaintext highlighter-rouge">M-x calendar</code> interface now has a box
around it on supported displays (graphical Emacs) to better stand
out from its context. On unsupported displays, the face still gets
an appropriate background value.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">org-date-selected</code> and <code class="language-plaintext highlighter-rouge">calendar-today</code> should look the same,
contrary to how they did before. This is done in the interest of
theme-wide consistency (i.e. the kind of detail you appreciate once
it is no longer there).</p>
  </li>
  <li>
    <p>The mode lines use an underline on displays that cannot render a
box. This way, the faces remain distinct from their context.</p>
  </li>
  <li>
    <p>All interface buttons, like those that appear in the Custom buffers,
will be rendered with an underline on displays that cannot handle
boxes.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">notmuch-message-summary-face</code>, which is used in threaded
message views, now has an overline on supported displays (graphical
Emacs). Individual messages in the thread should thus be more
discernible.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">tab-bar-tab-highlight</code> is directly covered to make sure all
mouse hover effects are consistent across similar interfaces.</p>
  </li>
  <li>
    <p>Some faces that had specific colour values (e.g. <code class="language-plaintext highlighter-rouge">cyan-cooler</code>) are
revised to use semantic palette mappings instead. This ensures
thematic consistency. The most obvious beneficiaries are users of
the deuteranopia- and tritanopia- optimised themes
(deuteranopia-friendly themes cannot work with red and green while
tritanopia-friendly themes must not rely on yellow and blue).</p>
  </li>
</ul>

<h3>The <code class="language-plaintext highlighter-rouge">modus-themes-custom-auto-reload</code> is obsolete</h3>

<p>Plus all our user options no longer specify a <code class="language-plaintext highlighter-rouge">:set</code> function. This
means that the theme will never be reloaded automatically when using
the Custom interface or <code class="language-plaintext highlighter-rouge">setopt</code> to configure one of the theme’s user
options. Reloading the theme is what applies the new styles. The idea
of this feature is good, but the implementation was problematic. Maybe
I will reinstate it in the future, though I cannot let it block this
major release.</p>

<h3>Several <code class="language-plaintext highlighter-rouge">modus-themes-*</code> faces are obsolete</h3>

<p>In previous versions I was defining faces that were used to apply
uniform styles across many packages. This was the old way of doing
things before version <code class="language-plaintext highlighter-rouge">4.0.0</code> of the themes that introduced palettes
with semantic mappings and, optionally, user-defined overrides to
them.</p>

<p>I have deprecated all of the following and made all the necessary
changes (i.e. several thousands of them), to make palette mappings the
norm everywhere. In general, I encourage you not to rely on any faces
defined by Modus: they are really intended for internal use.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-blue</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-blue-cooler</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-blue-faint</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-blue-intense</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-blue-warmer</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-cyan</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-cyan-cooler</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-cyan-faint</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-cyan-intense</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-cyan-warmer</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-green</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-green-cooler</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-green-faint</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-green-intense</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-green-warmer</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-magenta</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-magenta-cooler</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-magenta-faint</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-magenta-intense</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-magenta-warmer</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-red</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-red-cooler</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-red-faint</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-red-intense</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-red-warmer</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-yellow</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-yellow-cooler</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-yellow-faint</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-yellow-intense</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-fg-yellow-warmer</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-intense-blue</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-intense-cyan</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-intense-green</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-intense-magenta</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-intense-red</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-intense-yellow</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-key-binding</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-lang-error</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-lang-note</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-lang-warning</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-mark-alt</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-mark-del</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-mark-sel</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-nuanced-blue</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-nuanced-cyan</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-nuanced-green</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-nuanced-magenta</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-nuanced-red</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-nuanced-yellow</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-prominent-error</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-prominent-note</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-prominent-warning</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-prose-code</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-prose-macro</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-prose-verbatim</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-search-current</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-search-lazy</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-search-replace</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-search-rx-group-0</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-search-rx-group-1</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-search-rx-group-2</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-search-rx-group-3</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-search-static</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-subtle-blue</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-subtle-cyan</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-subtle-green</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-subtle-magenta</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-subtle-red</code></li>
  <li><code class="language-plaintext highlighter-rouge">modus-themes-subtle-yellow</code></li>
</ul>

<p>Thanks to Kevin Fleming and Jimmy Yuen Ho Wong for fixing two cases of
unbalanced/faulty parentheses caused by the aforementioned. These were
done as pull requests 166 and 168, respectively:</p>

<ul>
  <li><a href="https://github.com/protesilaos/modus-themes/pull/166">https://github.com/protesilaos/modus-themes/pull/166</a>.</li>
  <li><a href="https://github.com/protesilaos/modus-themes/pull/168">https://github.com/protesilaos/modus-themes/pull/168</a>.</li>
</ul>

<p>Both changes are small: no copyright assignment to the Free Software
Foundation is needed (and I think both authors are covered, anyway).</p>

<h3>All <code class="language-plaintext highlighter-rouge">:inherit</code> face attributes are reviewed and kept to a minimum</h3>

<p>The themes now use the <code class="language-plaintext highlighter-rouge">:inherit</code> attribute much more cautiously than
before. This is because of the reliance on semantic palette mappings:
those give us more control and usually are explicit about the desired
result.</p>

<p>Face inheritance can become circular in some cases. Newer Emacs
versions throw an error accordingly. This was discussed in Emacs bug
79672, with participation from Eli Zaretskii, JD Smith, Manuel Giraud,
Stephane Marks, and Steven Allen: <a href="https://debbugs.gnu.org/cgi/bugreport.cgi?bug=79672">https://debbugs.gnu.org/cgi/bugreport.cgi?bug=79672</a>.</p>

<p>Thanks to everybody involved!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: Denote version 4.1.0</title>
      <description>Information about the latest version of my Denote package for GNU Emacs.</description>
      <pubDate>Fri, 17 Oct 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-10-17-emacs-denote-4-1-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-10-17-emacs-denote-4-1-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Denote aims to be a simple-to-use, focused-in-scope, and effective
note-taking and file-naming tool for Emacs.</p>

<p>Denote is based on the idea that files should follow a predictable and
descriptive file-naming scheme.  The file name must offer a clear
indication of what the contents are about, without reference to any
other metadata.  Denote basically streamlines the creation of such
files or file names while providing facilities to link between them
(where those files are editable).</p>

<p>Denote’s file-naming scheme is not limited to “notes”.  It can be used
for all types of file, including those that are not editable in Emacs,
such as videos.  Naming files in a constistent way makes their
filtering and retrieval considerably easier.  Denote provides relevant
facilities to rename files, regardless of file type.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote">https://protesilaos.com/emacs/denote</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/denote-changelog">https://protesilaos.com/emacs/denote-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/denote">https://github.com/protesilaos/denote</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/denote">https://gitlab.com/protesilaos/denote</a></li>
    </ul>
  </li>
  <li>Video demo: <a href="https://protesilaos.com/codelog/2022-06-18-denote-demo/">https://protesilaos.com/codelog/2022-06-18-denote-demo/</a></li>
  <li>Backronyms: Denote Everything Neatly; Omit The Excesses.  Don’t Ever
Note Only The Epiphenomenal.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 4.1.0 on 2025-10-17</h2>

<p>The overarching theme of version <code class="language-plaintext highlighter-rouge">4.1.0</code> is that of continuing to
deliver on the highly hackable/flexible/powerful potential of Denote.
All the core functionality is the same as before and you still only
need a tiny configuration to use Denote productively. We are adding
more refinements and subtle improvements under the hood, while making
it even easier for advanced users/developers to piece together a
workflow that matches their particular needs.</p>

<p>Since version <code class="language-plaintext highlighter-rouge">4.0.0</code>, we have moved the “Denote extras” files into
their own packages. I cover their changes further down after I
elaborate on all the changes to the core Denote package:</p>

<ul>
  <li><a href="#h:ce5befb1-0401-4b06-ad4f-64c567b15b91"><code class="language-plaintext highlighter-rouge">denote-journal</code> version 0.2.0</a></li>
  <li><a href="#h:1403c3b9-280d-4033-a930-5364bf7b5e90"><code class="language-plaintext highlighter-rouge">denote-org</code> version 0.2.0</a></li>
  <li><a href="#h:d2e18b7d-dc8d-48ad-a0d7-71f291d5aa7c"><code class="language-plaintext highlighter-rouge">denote-sequence</code> version 0.2.0</a></li>
</ul>

<p>Note that I write all the release notes by hand. The reason is that I
consider this process an essential part of my role as a maintainer.
Taking the time to review and document everything ensures that (i) I am
well informed about the state of the package, (ii) I did not forget
anything about this development cycle, and (iii) I take another look
at the changes we made to ensure everything is in order.</p>

<h3>Overview of the new features for core Denote</h3>

<ul>
  <li>
    <p>The user option <code class="language-plaintext highlighter-rouge">denote-directory</code> can be assigned to a list of
directories. The original string value is also acceptable and
remains the default.</p>
  </li>
  <li>
    <p>Advanced users can define a completely custom scheme for
identifiers. This can be as simple as automatically assigned ordinal
numbers to increasingly complex patterns that may also involve user
input.</p>
  </li>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">denote-find-backlink-with-location</code> is like
<code class="language-plaintext highlighter-rouge">denote-find-backlink</code> except it also moves to the exact location of
the link in the corresponding file.</p>
  </li>
  <li>
    <p>All Denote buffer names share a common prefix, which is subject to
the user option <code class="language-plaintext highlighter-rouge">denote-buffer-name-prefix</code>. This makes it easier to
spot them in the buffer list.</p>
  </li>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">denote-dired</code> (alias <code class="language-plaintext highlighter-rouge">denote-sort-dired</code>) can sort
files by <code class="language-plaintext highlighter-rouge">random</code> and <code class="language-plaintext highlighter-rouge">last-modified</code> in addition to the methods
that involve Denote file name components.</p>
  </li>
  <li>
    <p>The user option <code class="language-plaintext highlighter-rouge">denote-query-sorting</code> controls how files in all
query buffers are sorted by default. This covers backlinks, query
links for file contents, and any buffer produced by the
<code class="language-plaintext highlighter-rouge">denote-grep</code> command. It benefits from the internal “Denote sort”
mechanism, which is also used by <code class="language-plaintext highlighter-rouge">denote-dired</code> and the Org dynamic
blocks of the <code class="language-plaintext highlighter-rouge">denote-org</code> package.</p>
  </li>
</ul>

<p>Remember that the release notes are true only at the time of
publication. The single source of truth always is the official manual.</p>

<p><a id="h:60ed9223-a092-4d2a-a6b6-3ba72150648b"></a></p>

<h3>Set <code class="language-plaintext highlighter-rouge">denote-directory</code> to a list of directories</h3>

<p>The user option <code class="language-plaintext highlighter-rouge">denote-directory</code> can optionally be bound to a list
of file system paths, each of which represents a directory root, such
as <code class="language-plaintext highlighter-rouge">'("/home/prot/Documents/work/" "=/home/prot/Git/hut/")</code> (Denote
has always supported subdirectories, even for a singular <code class="language-plaintext highlighter-rouge">denote-directory</code>).</p>

<p>When creating new files, such as with the <code class="language-plaintext highlighter-rouge">denote</code> command, the first
directory on the list will be selected. This can be changed by
modifying the <code class="language-plaintext highlighter-rouge">denote-prompts</code> user option so that it asks for a
directory or subdirectory thereof. Or by writing small wrapper
commands that put files in a predefined directory, like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(defun my-denote-for-work ()
  "Like `denote' but always use the ~/Documents/work/ directory."
  (interactive)
  (let ((denote-use-directory "~/Documents/work/"))
    (call-interactively 'denote)))
</code></pre></div></div>

<p>Why have many directories as part of the <code class="language-plaintext highlighter-rouge">denote-directory</code>? Some
users want to maintain separate directories with Denote files, while
retaining the option of establishing links between (unlike the concept
of “silos” we support, where the directories are self-contained).
Those two directories can be their own Git repositories, for example,
and have different syncing policies for access across multiple
devices.</p>

<p>Thanks to Jean-Philippe Gagné Guay for providing the core
functionality in pull request 609: <a href="https://github.com/protesilaos/denote/pull/609">https://github.com/protesilaos/denote/pull/609</a>.</p>

<p>Jean-Philippe is a long-time contributor who has assigned copyright to
the Free Software Foundation. I made several changes on top, such as
to allow <code class="language-plaintext highlighter-rouge">denote-dired</code> (alias <code class="language-plaintext highlighter-rouge">denote-sort-dired</code>) to work with many
directories, by finding their common root (which would ultimately be
<code class="language-plaintext highlighter-rouge">/</code>).</p>

<h3>Define completely custom Denote identifiers</h3>

<p>The default Denote identifier should work for most people in most
cases. I have considered the Denote file-naming scheme carefully and
know it is reliable. Advanced users who have a clear use-case of
something out-of-the-ordinary can now get “Denoted” file names with
arbitrary identifiers. Since this is an advanced feature, I will not
elaborate here on the technicalities. Though I have taken the time to
write at length in the manual about it, with concrete examples ranging
from simple to more complex scenaria. Start with this introduction:
<a href="https://protesilaos.com/emacs/denote#h:3048f558-7d84-45d6-9ef2-53055483e801">https://protesilaos.com/emacs/denote#h:3048f558-7d84-45d6-9ef2-53055483e801</a>.</p>

<p>This feature has been discussed and requested for a long time, across
several related issues:</p>

<ul>
  <li><a href="https://github.com/protesilaos/denote/issues/278">https://github.com/protesilaos/denote/issues/278</a>.</li>
  <li><a href="https://github.com/protesilaos/denote/issues/474">https://github.com/protesilaos/denote/issues/474</a>.</li>
  <li><a href="https://github.com/protesilaos/denote/issues/581">https://github.com/protesilaos/denote/issues/581</a>.</li>
</ul>

<p>Thanks, in no particular order, to mentalisttraceur, juh2, Christian
Tietze, and Jean-Philippe Gagné Guay for sharing their thoughts. Also
thanks to Jean-Philippe Gagné Guay for contributing the patches that
made this possible, the last of which is in pull request 586:
<a href="https://github.com/protesilaos/denote/issues/586">https://github.com/protesilaos/denote/issues/586</a>.</p>

<h3>Find a backlink at its exact location in the file</h3>

<p>Denote has two ways of working with backlinks: (i) to display them in
a dedicated buffer and (ii) to use a minibuffer prompt that supports
completion in order to pick one file out of the list. The new command
<code class="language-plaintext highlighter-rouge">denote-find-backlink-with-location</code> is of the latter kind. Like its
more generic <code class="language-plaintext highlighter-rouge">denote-find-backlink</code> counterpart, it uses the
minibuffer to pick a file that links to the current one. Then, it also
moves the cursor to where the link is.</p>

<p>I did this is in response to issue 471 as reported by johkneisl:
<a href="https://github.com/protesilaos/denote/issues/471">https://github.com/protesilaos/denote/issues/471</a>.</p>

<h3>Denote buffer names use the <code class="language-plaintext highlighter-rouge">denote-buffer-name-prefix</code></h3>

<p>This is a new user option that takes an arbitrary string. Its value is
<code class="language-plaintext highlighter-rouge">"[D]"</code> by default. It consolidates how we name all of our buffers.
Out-of-the-box, this applies to special buffers, like those produced
by the commands <code class="language-plaintext highlighter-rouge">denote-backlinks</code> and <code class="language-plaintext highlighter-rouge">denote-dired</code>. When the
optional minor mode <code class="language-plaintext highlighter-rouge">denote-rename-buffer-mode</code> is enabled, all
buffers whose file naming scheme is that of Denote will get the
<code class="language-plaintext highlighter-rouge">denote-buffer-name-prefix</code> in addition to their own <code class="language-plaintext highlighter-rouge">denote-rename-buffer-format</code>.</p>

<p>This is related to pull request 597 by James Kalyan:
<a href="https://github.com/protesilaos/denote/pull/597">https://github.com/protesilaos/denote/pull/597</a>. James has assigned
copyright to the Free Software Foundation.</p>

<p><a id="h:f6ea4714-1ed4-4db7-ad4b-c040b6c60c6d"></a></p>

<h3>The Denote sort mechanism can sort by <code class="language-plaintext highlighter-rouge">random</code> and <code class="language-plaintext highlighter-rouge">last-modified</code></h3>

<p>In core Denote, this is used internally by the <code class="language-plaintext highlighter-rouge">denote-dired</code> command
(alias <code class="language-plaintext highlighter-rouge">denote-sort-dired</code>) and the query buffers (more in the next
section). By default, <code class="language-plaintext highlighter-rouge">denote-dired</code> prompts for the sort method and
whether to reverse the order. Though there are user options to tweak
its behaviour (consult the manual). The Org dynamic blocks of the
<code class="language-plaintext highlighter-rouge">denote-org</code> package also rely on this mechanism (<a href="#h:1403c3b9-280d-4033-a930-5364bf7b5e90"><code class="language-plaintext highlighter-rouge">denote-org</code> version 0.2.0</a>).</p>

<h3>Control the default sort of files in query buffers</h3>

<p>Query buffers are those of <code class="language-plaintext highlighter-rouge">denote-backlinks</code>, <code class="language-plaintext highlighter-rouge">denote-grep</code>, and
<code class="language-plaintext highlighter-rouge">denote-query-contents-link</code> (in the latter case, the query buffer is
produced when you click on the link). Users can now modify how they
sort matching files via the option <code class="language-plaintext highlighter-rouge">denote-query-sorting</code>. The sorting
methods are by any of the Denote file names components (per
<code class="language-plaintext highlighter-rouge">denote-sort-components</code>), random order, last modified, or an
arbitrary function.</p>

<p>Thanks to Lucas Quintana for the contribution in pull request 594:
<a href="https://github.com/protesilaos/denote/pull/594">https://github.com/protesilaos/denote/pull/594</a>. Lucas has assigned
copyright to the Free Software Foundation.</p>

<h3>Miscellaneous for core Denote</h3>

<ul>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-dired</code> command (alias <code class="language-plaintext highlighter-rouge">denote-sort-dired</code>) sets up its
<code class="language-plaintext highlighter-rouge">revert-buffer-function</code> in a more robust way, such that it does not
affect the window layout under certain conditions.</p>
  </li>
  <li>
    <p>Fixed a bug with the menu entry of Denote that broke
<code class="language-plaintext highlighter-rouge">context-menu-mode</code>. It addresses issue 592, as reported by artelse:
<a href="https://github.com/protesilaos/denote/issues/592">https://github.com/protesilaos/denote/issues/592</a>. Thanks to Lucas
Quintana for the patch. Lucas has assigned copyright to the Free
Software Foundation.</p>
  </li>
  <li>Thanks to ryota for refining the documentation of the variable
<code class="language-plaintext highlighter-rouge">denote-use-template</code> and its potential interference with
<code class="language-plaintext highlighter-rouge">denote-org-capture-identifiers</code> in custom user code. We discussed
this in issue 545 and the patch was sent as pull request 598:
    <ul>
      <li><a href="https://github.com/protesilaos/denote/issues/545">https://github.com/protesilaos/denote/issues/545</a>.</li>
      <li><a href="https://github.com/protesilaos/denote/pull/598">https://github.com/protesilaos/denote/pull/598</a>. The change is
small, meaning that ryota does not need to assign copyright to
the Free Software Foundation.</li>
    </ul>
  </li>
  <li>
    <p>An internal check to determine if a file has backlinks is now faster
than before: it exits with a non-<code class="language-plaintext highlighter-rouge">nil</code> value as soon as it finds one
match, instead of trying to collect all the backlinks. Thanks to
Yann Dutrieux for addressing an omission of mine in the original
implementation and then for discussing with me some further
refinements. Yann’s contribution was sent as pull request 637:
<a href="https://github.com/protesilaos/denote/pull/637">https://github.com/protesilaos/denote/pull/637</a>.</p>
  </li>
  <li>Thanks to Alan Schmitt and Ashish Panigrahi for fixing a couple of
typos, in pull requests 623 and 626, respectively:
    <ul>
      <li><a href="https://github.com/protesilaos/denote/pull/623">https://github.com/protesilaos/denote/pull/623</a>.</li>
      <li><a href="https://github.com/protesilaos/denote/pull/626">https://github.com/protesilaos/denote/pull/626</a>.</li>
    </ul>
  </li>
</ul>

<h3>Git commits for core Denote</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/Git/Projects/denote $ git shortlog 4.0.0..4.1.0  --summary --numbered
   156	Protesilaos Stavrou
    29	Jean-Philippe Gagné Guay
     4	Lucas Quintana
     2	James Kalyan
     1	Alan Schmitt
     1	Ashish Panigrahi
     1	Hanwen Guo
     1	Ryota
     1	Yann Dutrieux
</code></pre></div></div>

<h3>Changes to the extensions of Denote I maintain</h3>

<p>This concerns all the former “Denote extras” that were shipped with
core Denote as well as <code class="language-plaintext highlighter-rouge">consult-denote</code>.</p>

<h4><code class="language-plaintext highlighter-rouge">consult-denote</code> version 0.4.0</h4>

<ul>
  <li>
    <p>The commands <code class="language-plaintext highlighter-rouge">consult-denote-grep</code> and <code class="language-plaintext highlighter-rouge">consult-denote-find</code> also
work when <code class="language-plaintext highlighter-rouge">denote-directory</code> is set to a list value, as explained
further above (<a href="#h:60ed9223-a092-4d2a-a6b6-3ba72150648b">Set <code class="language-plaintext highlighter-rouge">denote-directory</code> to a list of directories</a>).</p>
  </li>
  <li>
    <p>There is a Consult-powered counterpart to the
<code class="language-plaintext highlighter-rouge">denote-sequence-file-prompt</code>. It is for users of the
<code class="language-plaintext highlighter-rouge">denote-sequence</code> package and comes into effect when the
<code class="language-plaintext highlighter-rouge">consult-denote-mode</code> is enabled (that mode “Consults” all relevant
minibuffer prompts Denote uses so they get the familiar preview
functionality). The <code class="language-plaintext highlighter-rouge">denote-sequence-file-prompt</code> is used by
commands such as <code class="language-plaintext highlighter-rouge">denote-sequence</code>, <code class="language-plaintext highlighter-rouge">denote-sequence-find</code>, and
<code class="language-plaintext highlighter-rouge">denote-sequence-link</code>, among others (<a href="#h:d2e18b7d-dc8d-48ad-a0d7-71f291d5aa7c"><code class="language-plaintext highlighter-rouge">denote-sequence</code> version 0.2.0</a>).</p>
  </li>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">consult-denote-find</code> sorts its files by default. We
discussed this with Gianluca Della Vedova and Gianluca implemented
the tweak in pull request 18:
<a href="https://github.com/protesilaos/consult-denote/pull/18">https://github.com/protesilaos/consult-denote/pull/18</a>. The change
is small, meaning that Gianluca does not need to assign copyright to
the Free Software Foundation.</p>
  </li>
</ul>

<p><a id="h:ce5befb1-0401-4b06-ad4f-64c567b15b91"></a></p>

<h4><code class="language-plaintext highlighter-rouge">denote-journal</code> version 0.2.0</h4>

<ul>
  <li>It is now possible to specify the desired interval used by the
command <code class="language-plaintext highlighter-rouge">denote-journal-new-or-existing-entry</code> to determine what
“new” and “existing” mean. Users may want to, for example, maintain
one file per month, with daily entries as headings or as free-form
text. The user option <code class="language-plaintext highlighter-rouge">denote-journal-interval</code> specifies the
interval as a symbol among <code class="language-plaintext highlighter-rouge">daily</code>, <code class="language-plaintext highlighter-rouge">weekly</code>, <code class="language-plaintext highlighter-rouge">monthly</code>, and
<code class="language-plaintext highlighter-rouge">yearly</code>. Thanks to Ning Xu for floating the idea of non-daily
journaling in issue 18: <a href="https://github.com/protesilaos/denote-journal/issues/18">https://github.com/protesilaos/denote-journal/issues/18</a>.
    <ul>
      <li>Thanks to Alan Schmitt for catching a couple of errors in my
original implementation and for suggesting fixes in pull requests
20 and 21. Also thanks to Abdelhak Bougouffa for addressing
another problem in pull request 23. Further changes by me.
        <ul>
          <li><a href="https://github.com/protesilaos/denote-journal/pull/20">https://github.com/protesilaos/denote-journal/pull/20</a>.</li>
          <li><a href="https://github.com/protesilaos/denote-journal/pull/21">https://github.com/protesilaos/denote-journal/pull/21</a>.</li>
          <li><a href="https://github.com/protesilaos/denote-journal/pull/23">https://github.com/protesilaos/denote-journal/pull/23</a>.</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <p>The new user option <code class="language-plaintext highlighter-rouge">denote-journal-signature</code> specifies a signature
that will be applied to all new journal entries. It is the
counterpart of <code class="language-plaintext highlighter-rouge">denote-journal-keyword</code>. Possible values are <code class="language-plaintext highlighter-rouge">nil</code>,
for no predefined signature, a string for a constant signature, and a
function that returns a string which is then used as-is. Thanks to
Halogen3576 for suggesting an option for a signature in issue 13:
<a href="https://github.com/protesilaos/denote-journal/issues/13">https://github.com/protesilaos/denote-journal/issues/13</a>.</p>

    <p>In the case of a function value, users may wish to integrate the
<code class="language-plaintext highlighter-rouge">denote-journal</code> package with the <code class="language-plaintext highlighter-rouge">denote-sequence</code> package
(<a href="#h:d2e18b7d-dc8d-48ad-a0d7-71f291d5aa7c"><code class="language-plaintext highlighter-rouge">denote-sequence</code> version 0.2.0</a>). For example, each new journal
entry should be defined as a new parent sequence. Thus:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(setq denote-journal-signature
      (lambda ()
        (denote-sequence-get-new 'parent)))
</code></pre></div>    </div>
  </li>
  <li>
    <p>The user option <code class="language-plaintext highlighter-rouge">denote-journal-keyword</code> is extended to support a
function value which should return a string or list of strings.</p>
  </li>
  <li>
    <p>The integration with <code class="language-plaintext highlighter-rouge">M-x calendar</code> (when the minor mode
<code class="language-plaintext highlighter-rouge">denote-journal-calendar-mode</code> is enabled) is more robust when
highlighting dates that have a Denote journal entry. Thanks to Alan
Schmitt for the patch that improves the check for visible dates
only. This was done in pull request 12: <a href="https://github.com/protesilaos/denote-journal/pull/12">https://github.com/protesilaos/denote-journal/pull/12</a>.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-journal-calendar</code> face is extended to also work when
Emacs is ran in a TTY. Thanks to Ettore Berardi for the original
contribution and for discussing this with me. It was done in pull
request 14: <a href="https://github.com/protesilaos/denote-journal/pull/14">https://github.com/protesilaos/denote-journal/pull/14</a>.
The contribution is less than 15 lines of code, meaning that Ettore
does not need to assign copyright to the Free Software Foundation.</p>
  </li>
  <li>
    <p>The function <code class="language-plaintext highlighter-rouge">denote-journal-path-to-new-or-existing-entry</code> is
tweaked to not kill the buffer of the new file it might generate.
Thanks to jbwfu for the change in pull request 17:
<a href="https://github.com/protesilaos/denote-journal/pull/17">https://github.com/protesilaos/denote-journal/pull/17</a>. The change
is small, meaning that the author does not need to assign copyright
to the Free Software Foundation.</p>
  </li>
  <li>
    <p>Dates with a single digit in the title of a new journal entry no
longer have a space where the second digit normally is. So something
like <code class="language-plaintext highlighter-rouge">October 1</code> instead of <code class="language-plaintext highlighter-rouge">October  1</code>. Thanks to Josh Kingsley for
the patch. The change is small, meaning that Josh does not need to
assign copyright to the Free Software Foundation. It was done in
pull request 24: <a href="https://github.com/protesilaos/denote-journal/pull/24">https://github.com/protesilaos/denote-journal/pull/24</a>.</p>
  </li>
  <li>
    <p>Thanks to gk2803 for renaming a couple of old symbols to their
current names in the commentary of the package. This was done in
pull request 10: <a href="https://github.com/protesilaos/denote-journal/pull/10">https://github.com/protesilaos/denote-journal/pull/10</a>.</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/Git/Projects/denote-journal $ git shortlog 0.1.0..0.2.0  --summary --numbered
    35	Protesilaos Stavrou
     3	Alan Schmitt
     2	Ettore Berardi
     1	Abdelhak Bougouffa
     1	Josh Kingsley
     1	gk2803
     1	jbwfu
</code></pre></div>    </div>
  </li>
</ul>

<p><a id="h:1403c3b9-280d-4033-a930-5364bf7b5e90"></a></p>

<h4><code class="language-plaintext highlighter-rouge">denote-org</code> version 0.2.0</h4>

<ul>
  <li>A new Org dynamic block integrates with the <code class="language-plaintext highlighter-rouge">denote-sequence</code>
package (<a href="#h:d2e18b7d-dc8d-48ad-a0d7-71f291d5aa7c"><code class="language-plaintext highlighter-rouge">denote-sequence</code> version 0.2.0</a>). The block is called
<code class="language-plaintext highlighter-rouge">denote-sequence</code> and can be inserted at point with the command
<code class="language-plaintext highlighter-rouge">denote-org-dblock-insert-sequence</code>. What this block does is list
the descendants of a given sequence up to a maximum depth. The
presentation is a typographic list of lists to visualise the
hierarchy of the complete sequence, with each set of children nested
under its parent. Thanks to Peter Prevos for the original
implementation in pull request 9 and for subsequent tweaks in pull
request 13. Other changes by me are done to ensure tighter
integration with the <code class="language-plaintext highlighter-rouge">denote-sequence</code> package.
    <ul>
      <li><a href="https://github.com/protesilaos/denote-org/pull/9">https://github.com/protesilaos/denote-org/pull/9</a>.</li>
      <li><a href="https://github.com/protesilaos/denote-org/pull/13">https://github.com/protesilaos/denote-org/pull/13</a>.</li>
    </ul>
  </li>
  <li>
    <p>All Org dynamic blocks that have a <code class="language-plaintext highlighter-rouge">:sort-by-component</code> parameter
can now sort by <code class="language-plaintext highlighter-rouge">random</code> and <code class="language-plaintext highlighter-rouge">last-modified</code>. This is made possible
by the aforementioned improvements to the core Denote sort mechanism
(<a href="#h:f6ea4714-1ed4-4db7-ad4b-c040b6c60c6d">The Denote sort mechanism can sort by <code class="language-plaintext highlighter-rouge">random</code> and <code class="language-plaintext highlighter-rouge">last-modified</code></a>).</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-missing-links</code> Org dynamic block, which can be inserted
at point with the command <code class="language-plaintext highlighter-rouge">denote-org-dblock-insert-missing-links</code>
takes an optional <code class="language-plaintext highlighter-rouge">:not-regexp</code> parameter. This is a regular
expression of files to omit from the results. Same for the
<code class="language-plaintext highlighter-rouge">denote-backlinks</code> block, which can be inserted at point with the
command <code class="language-plaintext highlighter-rouge">denote-org-dblock-insert-backlinks</code>.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-files-as-headings</code> Org dynamic block, which can be
inserted at point with the command <code class="language-plaintext highlighter-rouge">denote-org-dblock-insert-files-as-headings</code>
now also accepts an optional <code class="language-plaintext highlighter-rouge">:exclude-tags</code> parameter. It is either
<code class="language-plaintext highlighter-rouge">nil</code> or non-<code class="language-plaintext highlighter-rouge">nil</code> and determines whether the heading will have the
file’s <code class="language-plaintext highlighter-rouge">#+filetags</code> as its own tags. Thanks to Matt Nolan for
suggesting this idea in issue 14: <a href="https://github.com/protesilaos/denote-org/issues/14">https://github.com/protesilaos/denote-org/issues/14</a>.</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/Git/Projects/denote-org $ git shortlog 0.1.0..0.2.0  --summary --numbered
    42	Protesilaos Stavrou
     8	Peter Prevos
</code></pre></div>    </div>
  </li>
</ul>

<p><a id="h:d2e18b7d-dc8d-48ad-a0d7-71f291d5aa7c"></a></p>

<h4><code class="language-plaintext highlighter-rouge">denote-sequence</code> version 0.2.0</h4>

<ul>
  <li>
    <p>The new commands <code class="language-plaintext highlighter-rouge">denote-sequence-find-next-sibling</code> and
<code class="language-plaintext highlighter-rouge">denote-sequence-find-previous-sibling</code> move to the next or previous
sibling in the given sequence. When called interactively, they work
relative to the current file. When called from Lisp, they expect a
<code class="language-plaintext highlighter-rouge">SEQUENCE</code> argument and its corresponding <code class="language-plaintext highlighter-rouge">RELATIVES</code>.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-sequence-dired</code> command is updated to (i) work with a
list value for <code class="language-plaintext highlighter-rouge">denote-directory</code> (<a href="#h:60ed9223-a092-4d2a-a6b6-3ba72150648b">Set <code class="language-plaintext highlighter-rouge">denote-directory</code> to a list of directories</a>),
as noted further above and (ii) benefit from the refinements done to
<code class="language-plaintext highlighter-rouge">denote-dired</code> with regard to its <code class="language-plaintext highlighter-rouge">revert-buffer-function</code>.</p>
  </li>
  <li>
    <p>The new command <code class="language-plaintext highlighter-rouge">denote-sequence-rename-as-parent</code> makes it easier
to apply the Denote file-naming scheme to an existing file and make
it a new parent sequence. Thanks to Alex Carney for requesting
something along those lines in issue 4:
<a href="https://github.com/protesilaos/denote-sequence/issues/4">https://github.com/protesilaos/denote-sequence/issues/4</a>.</p>

    <p>[ Remember that Denote is highly adaptable/hackable, meaning that
  many of these convenience commands build on top of the core with small
  extensions to it. The body of <code class="language-plaintext highlighter-rouge">denote-sequence-rename-as-parent</code> is
  only 4 lines long, two of which are for an error check. This is
  typical of much of what we provide and is how users can always
  extend Denote to do something slightly different than what we
  support out-of-the-box. ]</p>
  </li>
  <li>
    <p>Made several other refinements under the hood, including the
addition of more tests. In this regard, thanks to Rory Molinari,
Peter Prevos, and Ashton Wiersdorf for fixing three bugs in pull
requests 5, 8, and 11, respectively:</p>
    <ul>
      <li><a href="https://github.com/protesilaos/denote-sequence/pull/5">https://github.com/protesilaos/denote-sequence/pull/5</a>.</li>
      <li><a href="https://github.com/protesilaos/denote-sequence/pull/8">https://github.com/protesilaos/denote-sequence/pull/8</a>.</li>
      <li><a href="https://github.com/protesilaos/denote-sequence/pull/11">https://github.com/protesilaos/denote-sequence/pull/11</a>.</li>
    </ul>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/Git/Projects/denote-sequence $ git shortlog 0.1.0..0.2.0  --summary --numbered
    61	Protesilaos Stavrou
     1	Ashton Wiersdorf
     1	Peter Prevos
     1	Rory Molinari
</code></pre></div>    </div>
  </li>
</ul>

<h4>Changes to <code class="language-plaintext highlighter-rouge">denote-markdown</code></h4>

<p>Nothing of substance.</p>

<h4>Changes to <code class="language-plaintext highlighter-rouge">denote-silo</code></h4>

<p>Nothing of substance.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: tmr version 1.2.0</title>
      <description>Information about the latest version of my TMR package for GNU Emacs.</description>
      <pubDate>Mon, 06 Oct 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-10-06-emacs-tmr-1-2-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-10-06-emacs-tmr-1-2-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>TMR provides facilities for setting timers using a convenient
notation. Lots of commands are available to operate on timers, while
there also exists a tabulated view to display all timers in a nice
grid.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">tmr</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/tmr">https://protesilaos.com/emacs/tmr</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/tmr-changelog">https://protesilaos.com/emacs/tmr-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/tmr">https://github.com/protesilaos/tmr</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/tmr">https://gitlab.com/protesilaos/tmr</a></li>
    </ul>
  </li>
  <li>Backronym: TMR May Ring; Timer Must Run.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 1.2.0 on 2025-10-06</h2>

<p>This release introduces several quality-of-life refinements to an
already stable and featureful package.</p>

<h3>Timers can now appear on the modeline</h3>

<p>The new minor mode <code class="language-plaintext highlighter-rouge">tmr-mode-line-mode</code> controls whether running
timers are displayed on the mode line. More specifically, they are
displayed in the <code class="language-plaintext highlighter-rouge">global-mode-string</code>, which can also be set in the
<code class="language-plaintext highlighter-rouge">tab-bar-mode</code> (this way the information appears in one place instead
of all the mode lines, assuming default settings).</p>

<p>The exact format of a timer on display is controlled by the user
option <code class="language-plaintext highlighter-rouge">tmr-mode-line-format</code>. The number of timers is set with the
option <code class="language-plaintext highlighter-rouge">tmr-mode-line-max-timers</code>. The separator between multiple
timers is <code class="language-plaintext highlighter-rouge">tmr-mode-line-separator</code>. The length of each timer’s
optional description is subject to <code class="language-plaintext highlighter-rouge">tmr-mode-line-max-desc-length</code>.
While the entire indicator can have a prefix, per <code class="language-plaintext highlighter-rouge">tmr-mode-line-prefix</code>.</p>

<p>Thanks to Steven Allen for contributing the original version of this
feature in pull request 2: <a href="https://github.com/protesilaos/tmr/pull/2">https://github.com/protesilaos/tmr/pull/2</a>.
Steven has assigned copyright to the Free Software Foundation. Further
changes by me, such as to make the timers on the mode line clickable
(which produces a tabulated view, per <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code>).</p>

<h3>Notifications for more operating systems</h3>

<p>Timers can optionally trigger a system notification, via the abnormal
hook <code class="language-plaintext highlighter-rouge">tmr-timer-finished-functions</code>. The relevant function is
<code class="language-plaintext highlighter-rouge">tmr-notification-notify</code>. It used to only support Linux. Now it is
extended to handle Android, Windows, and Haiku.</p>

<p>Thanks to Lucas Quintana for the contribution in pull request 10:
<a href="https://github.com/protesilaos/tmr/pull/10">https://github.com/protesilaos/tmr/pull/10</a>. Lucas has assigned
copyright to the Free Software Foundation.</p>

<h3>The tabulated timers have a “duration” column</h3>

<p>The <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code> command (alias <code class="language-plaintext highlighter-rouge">tmr-list-timers</code>) now
includes a “duration” column, in addition to all the other informative
data on display.</p>

<p>[ Remember that the tabulated view can be used to create, duplicate,
  edit, etc. the timers. ]</p>

<p>Thanks to jpg for suggesting this in issue 11:
<a href="https://github.com/protesilaos/tmr/issues/11">https://github.com/protesilaos/tmr/issues/11</a>.</p>

<h3>Miscellaneous</h3>

<ul>
  <li>
    <p>System notifications specify the <code class="language-plaintext highlighter-rouge">:app-icon</code> of Emacs. It will be
displayed, if the underlying software supports it (I see it on
Linux, anyway).</p>
  </li>
  <li>
    <p>The option to play the <code class="language-plaintext highlighter-rouge">tmr-sound-file</code> via the abnormal hook
<code class="language-plaintext highlighter-rouge">tmr-timer-finished-functions</code> is redone to not rely on the system
shell (implicitly <code class="language-plaintext highlighter-rouge">bash</code>). This way, users who use exotic shell
alternatives will not run into any trouble. This is done in response
to a relevant problem that g-gundam was facing with the <code class="language-plaintext highlighter-rouge">nushell</code>:
<a href="https://github.com/protesilaos/tmr/pull/7">https://github.com/protesilaos/tmr/pull/7</a>.</p>
  </li>
  <li>
    <p>The function <code class="language-plaintext highlighter-rouge">tmr-notification-notify</code> is better at informing the
user that it has produced the warning about the lack of DBUS
support. Before, the notification did not identity itself as
belonging to the <code class="language-plaintext highlighter-rouge">tmr</code> package.</p>
  </li>
  <li>
    <p>The function <code class="language-plaintext highlighter-rouge">tmr-running-timers-p</code> is now available as a standalone
function to do what was done before inside other functions. This is
useful for anyone writing custom code on top of <code class="language-plaintext highlighter-rouge">tmr</code>. Thanks to
Eugene Mikhaylov for suggesting the idea in issue 9:
<a href="https://github.com/protesilaos/tmr/issues/9">https://github.com/protesilaos/tmr/issues/9</a>.</p>
  </li>
  <li>
    <p>The manual is updated to include whatever necessary from the
aforementioned.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: the ‘standard-themes’ are also built on top of the ‘modus-themes’</title>
      <description>My 'standard-themes' for Emacs are refactored to work on top of my 'modus-themes', thus inheriting their extensive face coverage and customisability.</description>
      <pubDate>Fri, 03 Oct 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-10-03-emacs-standard-themes-on-top-modus/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-10-03-emacs-standard-themes-on-top-modus/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>In previous entries I explained how I have reworked the <code class="language-plaintext highlighter-rouge">modus-themes</code>
to optionally work as the basis for other theme packages. The official
documentation is in the manual of the Modus themes (my manuals are the
only source of truth; blog posts—including this one—become outdated):
<a href="https://protesilaos.com/emacs/modus-themes#h:86eb375b-9be4-43ce-879a-0686a524a63b">https://protesilaos.com/emacs/modus-themes#h:86eb375b-9be4-43ce-879a-0686a524a63b</a>.</p>

<p>I already mentioned how version <code class="language-plaintext highlighter-rouge">2.0.0</code> of the <code class="language-plaintext highlighter-rouge">ef-themes</code> will be
done this way. I am happy to announce that as of this morning the same
is true for my <code class="language-plaintext highlighter-rouge">standard-themes</code>. Specifically, version <code class="language-plaintext highlighter-rouge">3.0.0</code> of the
Standard themes will be built on top of the <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<p>Users are now expected to customise the themes via the user options
provided by Modus and to load the themes with the relevant Modus
commands. Here is a sample configuration:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">standard-themes</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="ss">:init</span>
  <span class="c1">;; This makes the Modus commands listed below consider only the</span>
  <span class="c1">;; Standard themes.  For an alternative that includes Modus and all</span>
  <span class="c1">;; derivative themes (like Standard), enable the</span>
  <span class="c1">;; `modus-themes-include-derivatives-mode' instead.</span>
  <span class="p">(</span><span class="nv">standard-themes-take-over-modus-themes-mode</span> <span class="mi">1</span><span class="p">)</span>
  <span class="ss">:bind</span>
  <span class="p">((</span><span class="s">"&lt;f5&gt;"</span> <span class="o">.</span> <span class="nv">modus-themes-rotate</span><span class="p">)</span>
   <span class="p">(</span><span class="s">"C-&lt;f5&gt;"</span> <span class="o">.</span> <span class="nv">modus-themes-select</span><span class="p">)</span>
   <span class="p">(</span><span class="s">"M-&lt;f5&gt;"</span> <span class="o">.</span> <span class="nv">modus-themes-load-random</span><span class="p">))</span>
  <span class="ss">:config</span>
  <span class="c1">;; All customisations here.</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">modus-themes-mixed-fonts</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">modus-themes-italic-constructs</span> <span class="no">t</span><span class="p">)</span>

  <span class="c1">;; Finally, load your theme of choice (or a random one with</span>
  <span class="c1">;; `modus-themes-load-random', `modus-themes-load-random-dark',</span>
  <span class="c1">;; `modus-themes-load-random-light').</span>
  <span class="p">(</span><span class="nv">modus-themes-load-theme</span> <span class="ss">'standard-light-tinted</span><span class="p">))</span>
</code></pre></div></div>

<h2>The <code class="language-plaintext highlighter-rouge">modus-themes-theme</code> macro is flexible</h2>

<p>This morning, I extended the <code class="language-plaintext highlighter-rouge">modus-themes-theme</code> macro to optionally
accept custom faces and user options that complement or override those
provided by core Modus (the <code class="language-plaintext highlighter-rouge">modus-themes-theme</code> macro is documented
at length with concrete examples in the aforementioned link to the
manual). For the <code class="language-plaintext highlighter-rouge">standard-themes</code>, this means that we can inherit all
the goodies from Modus but still deviate stylistically in important
ways wherever necessary. One case where this is evident is the design
of the active mode line: Modus has a flat appearance, while Standard
uses a 3D effect.</p>

<p>Standard does not need to deviate substantively from Modus, though
there is no technical constraint in this regard. A derivative theme
can implement all the requisite deviations to achieve the exact design
it aims for, all while reusing Modus.</p>

<p>My plan is to release all new theme versions in the coming days,
depending on my availability. Please let me know if you have any
questions or want some things to change.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: ‘modus-themes’ as a basis for other themes; ‘ef-themes’ is first</title>
      <description>Update on changes I making to allow the modus-themes to be used as a basis for other other projects. My ef-themes is the first of that kind.</description>
      <pubDate>Wed, 01 Oct 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-10-01-emacs-modus-framework-ef-built-on-top/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-10-01-emacs-modus-framework-ef-built-on-top/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>[ This is a development note. Things might change before the release
  of <code class="language-plaintext highlighter-rouge">modus-themes</code> version <code class="language-plaintext highlighter-rouge">5.0.0</code> and <code class="language-plaintext highlighter-rouge">ef-themes</code> version <code class="language-plaintext highlighter-rouge">2.0.0</code>. ]</p>

<p>In previous entries, I outlined how my <code class="language-plaintext highlighter-rouge">ef-themes</code> will be built on
top of my <code class="language-plaintext highlighter-rouge">modus-themes</code> and then how the <code class="language-plaintext highlighter-rouge">modus-themes</code> are partly
redesigned to enable such an arrangement:</p>

<ul>
  <li><a href="https://protesilaos.com/codelog/2025-09-27-emacs-next-ef-themes-built-on-modus/">Emacs: the next ‘ef-themes’ will build on top of the ‘modus-themes’</a> (offers just the big picture view)</li>
  <li><a href="https://protesilaos.com/codelog/2025-09-30-emacs-building-on-top-modus-themes/">Emacs: building on top of the Modus themes</a> (describes some technicalities)</li>
</ul>

<p>I have now finalised the details and merged the changes in the
respective <code class="language-plaintext highlighter-rouge">main</code> branch of each Git repository. If you are building
the packages from their latest commit, you might need to delete and
then re-install the package. Otherwise, I expect things to work as
expected. The <code class="language-plaintext highlighter-rouge">modus-themes</code>, in particular, should have no obvious
change to its users.</p>

<p>The <code class="language-plaintext highlighter-rouge">ef-themes</code> have undergone substantial changes. All of their user
options are deprecated and will no longer have any effect. User
options from the Modus themes now take their place. Furthermore, all
the Ef commands to load a theme are discontinued. The plan is to
re-use the infrastructure of the Modus themes throughout. Concretely,
users must change their configuration to at least this minimal setup:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">ef-themes</span>
  <span class="ss">:init</span>
  <span class="c1">;; This is essential to let the Ef themes take over the Modus themes commands.</span>
  <span class="p">(</span><span class="nv">ef-themes-take-over-modus-themes-mode</span> <span class="mi">1</span><span class="p">))</span>
</code></pre></div></div>

<p>Or this sort, if they want some key bindings and customisations:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">ef-themes</span>
  <span class="ss">:init</span>
  <span class="p">(</span><span class="nv">ef-themes-take-over-modus-themes-mode</span> <span class="mi">1</span><span class="p">)</span>
  <span class="ss">:bind</span>
  <span class="p">((</span><span class="s">"&lt;f5&gt;"</span> <span class="o">.</span> <span class="nv">modus-themes-rotate</span><span class="p">)</span>
   <span class="p">(</span><span class="s">"C-&lt;f5&gt;"</span> <span class="o">.</span> <span class="nv">modus-themes-select</span><span class="p">)</span>
   <span class="p">(</span><span class="s">"M-&lt;f5&gt;"</span> <span class="o">.</span> <span class="nv">modus-themes-load-random</span><span class="p">))</span>
  <span class="ss">:config</span>
  <span class="c1">;; All customisations here.</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">modus-themes-mixed-fonts</span> <span class="no">t</span><span class="p">))</span>
</code></pre></div></div>

<h2>Load a theme</h2>

<p>The commands <code class="language-plaintext highlighter-rouge">modus-themes-rotate</code>, <code class="language-plaintext highlighter-rouge">modus-themes-select</code>,
<code class="language-plaintext highlighter-rouge">modus-themes-toggle</code>, and <code class="language-plaintext highlighter-rouge">modus-themes-load-random</code> will also load a
theme interactively.</p>

<p>Loading a specific theme from Lisp works as expected:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'ef-cyprus</span> <span class="ss">:no-confirm</span><span class="p">)</span>
</code></pre></div></div>

<p>To do the same while also triggering the
<code class="language-plaintext highlighter-rouge">modus-themes-after-load-theme-hook</code> as well as the
<code class="language-plaintext highlighter-rouge">modus-themes-disable-other-themes</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">modus-themes-load-theme</span> <span class="ss">'ef-summer</span><span class="p">)</span>
</code></pre></div></div>

<p>To load a theme at random, do this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">modus-themes-load-random</span><span class="p">)</span>
<span class="p">(</span><span class="nv">modus-themes-load-random</span> <span class="ss">'dark</span><span class="p">)</span> <span class="c1">; dark only (alternative `modus-themes-load-dark')</span>
<span class="p">(</span><span class="nv">modus-themes-load-random</span> <span class="ss">'light</span><span class="p">)</span> <span class="c1">; light only (alternative `modus-themes-load-light')</span>
</code></pre></div></div>

<h2>Use both Ef and Modus themes</h2>

<p>To not take over the Modus themes completely and to instead allow the
Modus commands to act on both Modus and Ef themes, enable this minor
mode instead:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">modus-themes-include-derivatives-mode</span> <span class="mi">1</span><span class="p">)</span>
</code></pre></div></div>

<p>And <strong>make sure you disable</strong> <code class="language-plaintext highlighter-rouge">ef-themes-take-over-modus-themes-mode</code>
in this case.</p>

<h2>More customisation for the Ef themes</h2>

<p>All the user options of the Modus themes are now available. For
example, there was no option in the past to disable bold and italic
styles from the Ef themes. They are now disabled by default, unless
the user sets <code class="language-plaintext highlighter-rouge">modus-themes-bold-constructs</code> and <code class="language-plaintext highlighter-rouge">modus-themes-italic-constructs</code>
to non-nil values.</p>

<p>Additionally, the Ef themes now enjoy wider face/package support.</p>

<h2>Everything else should be as expected</h2>

<p>Advanced users who were relying on the <code class="language-plaintext highlighter-rouge">ef-themes-with-colors</code> or any
other Ef functionality will have to do the same with the Modus
framework. Everything is possible, plus I am happy to help with the
transition if you have any questions.</p>

<p>The Modus themes benefit from this redesign because their code is made
to be more generic and to not hardcode certain assumptions. It also
makes sense for them to be useful as a dependency for other themes, as
they are part of core Emacs, which is convenient.</p>

<p>Remember that everything is still in development. I will expand the
manuals and make sure everything is in order for the next major
version of each of these two projects.</p>

<p>If everything goes well, expect my <code class="language-plaintext highlighter-rouge">standard-themes</code> to be redone on
top of the <code class="language-plaintext highlighter-rouge">modus-themes</code>. But not for the <code class="language-plaintext highlighter-rouge">doric-themes</code>: those are
quite different in style and overall design.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: building on top of the Modus themes</title>
      <description>A big picture view of how the Modus themes can be used by other theme packages.</description>
      <pubDate>Tue, 30 Sep 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-09-30-emacs-building-on-top-modus-themes/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-09-30-emacs-building-on-top-modus-themes/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I have been doing a lot of work these days on my themes. The immediate
goal is two-fold: (i) make the <code class="language-plaintext highlighter-rouge">modus-themes</code> more flexible so they
can be used as a the basis for other theme packages and (ii) make the
<code class="language-plaintext highlighter-rouge">ef-themes</code> the first project to benefit from this development. Having
the Modus themes as a foundation gives us all of their customisability
and extensive face coverage for little extra work. The themes are well
tested and are also shipped with core Emacs. It all fits together.</p>

<p>In this article, I give you the big picture view of how this is
supposed to work. Remember that the only source of truth for my
packages is their corresponding manual. Any blog post is useful the
time it is written but will eventually go out of date.</p>

<h2>Symbol properties for themes</h2>

<p>When we define a theme, we essentially add properties to a symbol. In
its simplest form, this is how:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">put</span> <span class="ss">'my-test-symbol</span> <span class="ss">'my-test-proerty</span> <span class="s">"Hello world test value"</span><span class="p">)</span>
</code></pre></div></div>

<p>Evaluate the above and then try the following:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">get</span> <span class="ss">'my-test-symbol</span> <span class="ss">'my-test-proerty</span><span class="p">)</span>
<span class="c1">;; =&gt; "Hello world test value"</span>
</code></pre></div></div>

<p>The function <code class="language-plaintext highlighter-rouge">custom-declare-theme</code> does the heavy lifting, while the
<code class="language-plaintext highlighter-rouge">deftheme</code> macro streamlines most of that work. Still, the point is
that we have symbols whose properties we can access and, thus, we can
filter by any given property. To make things even better, we can add
arbitrary properties to a theme. Here is a real scenario of
<strong>_in-development code that might change</strong>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">get</span> <span class="ss">'modus-operandi</span> <span class="ss">'theme-properties</span><span class="p">)</span>
<span class="c1">;; =&gt; (:kind color-scheme :background-mode light :family modus-themes :modus-core-palette modus-themes-operandi-palette :modus-user-palette modus-operandi-palette-user :modus-overrides-palette modus-operandi-palette-overrides)</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">theme-properties</code> has as a plist value. Its Modus-specific
properties are references to variables that we can use to do our work,
such as to put together a theme palette that combines the relevant
overrides with the core entries.</p>

<h2>Getting a list of themes based on their properties</h2>

<p>When we declare a theme with <code class="language-plaintext highlighter-rouge">custom-declare-theme</code>, we make it known
to Emacs by adding it to the <code class="language-plaintext highlighter-rouge">custom-known-themes</code>. When we eventually
load a theme, its symbol gets stored in the <code class="language-plaintext highlighter-rouge">custom-enabled-themes</code>.
Knowing that themes have properties, we can filter those lists
accordingly. With my current development code, I can do this, for
example:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-demo-is-modus-p</span> <span class="p">(</span><span class="nv">theme</span><span class="p">)</span>
  <span class="s">"Return non-nil if THEME has `modus-themes' :family property."</span>
  <span class="p">(</span><span class="nv">when-let*</span> <span class="p">((</span><span class="nv">properties</span> <span class="p">(</span><span class="nb">get</span> <span class="nv">theme</span> <span class="ss">'theme-properties</span><span class="p">))</span>
              <span class="p">(</span><span class="nv">family</span> <span class="p">(</span><span class="nv">plist-get</span> <span class="nv">properties</span> <span class="ss">:family</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">eq</span> <span class="nv">family</span> <span class="ss">'modus-themes</span><span class="p">)))</span>

<span class="p">(</span><span class="nv">seq-filter</span> <span class="nf">#'</span><span class="nv">my-demo-is-modus-p</span> <span class="nv">custom-known-themes</span><span class="p">)</span>
<span class="c1">;; =&gt; (modus-vivendi-tritanopia modus-vivendi-tinted modus-vivendi modus-vivendi-deuteranopia modus-operandi-tritanopia modus-operandi-tinted modus-operandi modus-operandi-deuteranopia)</span>
</code></pre></div></div>

<p>The next step from here is to make all the Modus infrastructure rely
on generic functions and methods for working with themes. Then any
package can provides its own method for returning a list of desired
themes.</p>

<h2>Generic function and methods for getting a list of themes</h2>

<p>Emacs Lisp has a concept of generic functions, which it borrows from
Common Lisp. The general idea is to have a single symbol, like
<code class="language-plaintext highlighter-rouge">modus-themes-get-themes</code> whose implementation details are
instantiated via specialised methods. For example, when a minor mode
is active, a given method takes effect, thus changing what
<code class="language-plaintext highlighter-rouge">modus-themes-get-themes</code> actually does.</p>

<p>The default implementation is this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">cl-defgeneric</span> <span class="nv">modus-themes-get-themes</span> <span class="p">()</span>
  <span class="s">"Return a list of all themes with `modus-themes' :family property."</span>
  <span class="p">(</span><span class="nv">modus-themes-get-all-known-themes</span> <span class="ss">'modus-themes</span><span class="p">))</span>
</code></pre></div></div>

<p>The function <code class="language-plaintext highlighter-rouge">modus-themes-get-all-known-themes</code> has a filter like the
one I demonstrated in the code block further above. By default, this
is what I get when I run the aforementioned generic function:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">modus-themes-get-themes</span><span class="p">)</span>
<span class="c1">;; =&gt; (modus-operandi modus-operandi-tinted modus-operandi-deuteranopia modus-operandi-tritanopia modus-vivendi modus-vivendi-tinted modus-vivendi-deuteranopia modus-vivendi-tritanopia)</span>
</code></pre></div></div>

<p>The beauty of this design is that another package can define a method
to make the same code return something else. This is how I do it in
the current development target of the <code class="language-plaintext highlighter-rouge">ef-themes</code> (again, the actual
code might change):</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">cl-defmethod</span> <span class="nv">modus-themes-get-themes</span> <span class="p">(</span><span class="nv">&amp;context</span> <span class="p">(</span><span class="nv">ef-themes-take-over-modus-themes-mode</span> <span class="p">(</span><span class="nb">eql</span> <span class="no">t</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">modus-themes-get-all-known-themes</span> <span class="ss">'ef-themes</span><span class="p">))</span>
</code></pre></div></div>

<p>Notice that this method has a <code class="language-plaintext highlighter-rouge">&amp;context</code>, which is the scenario in
which it is relevant. In this case, we have a minor mode that
activates the method when it is enabled:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">define-minor-mode</span> <span class="nv">ef-themes-take-over-modus-themes-mode</span>
  <span class="s">"When enabled, all Modus themes commands consider only Ef themes."</span>
  <span class="ss">:global</span> <span class="no">t</span>
  <span class="ss">:init-value</span> <span class="no">nil</span><span class="p">)</span>
</code></pre></div></div>

<p>This minor mode does not have anything in its body. It does not need
to, because the <code class="language-plaintext highlighter-rouge">define-minor-mode</code> macro already instantiates the
parts we care about. Namely, when we call the function defined by the
minor mode (i.e. <code class="language-plaintext highlighter-rouge">ef-themes-take-over-modus-themes-mode</code>), it toggles
the value of the variable <code class="language-plaintext highlighter-rouge">ef-themes-take-over-modus-themes-mode</code>
(functions and variables have separate namespaces in Emacs Lisp and
thus the same symbol can be in both places). Our method then becomes
relevant when the user enables the minor mode:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">ef-themes-take-over-modus-themes-mode</span> <span class="mi">1</span><span class="p">)</span>
</code></pre></div></div>

<p>And now the generic function <code class="language-plaintext highlighter-rouge">modus-themes-get-themes</code> does something
else:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">modus-themes-get-themes</span><span class="p">)</span>
<span class="c1">;; =&gt; (ef-winter ef-tritanopia-light ef-tritanopia-dark ef-trio-light ef-trio-dark ef-symbiosis ef-summer ef-spring ef-rosa ef-reverie ef-owl ef-night ef-melissa-light ef-melissa-dark ef-maris-light ef-maris-dark ef-light ef-kassio ef-frost ef-elea-light ef-elea-dark ef-eagle ef-duo-light ef-duo-dark ef-dream ef-deuteranopia-light ef-deuteranopia-dark ef-day ef-dark ef-cyprus ef-cherie ef-bio ef-autumn ef-arbutus)</span>
</code></pre></div></div>

<p>Since all the Modus functions are redesigned to work with this generic
function, we can now use commands like <code class="language-plaintext highlighter-rouge">modus-themes-select</code> or even
<code class="language-plaintext highlighter-rouge">modus-themes-list-colors</code> for any of those themes.</p>

<p>As a bonus, we can now seamlessly blend Modus themes with their
derivatives. Imagine a user who wants to invoke the command
<code class="language-plaintext highlighter-rouge">modus-themes-load-random</code> (or its variants for light and dark themes)
and have it consider the likes of <code class="language-plaintext highlighter-rouge">modus-operandi</code> and <code class="language-plaintext highlighter-rouge">ef-dream</code>.
Users can opt in to this feature via the minor mode that the Modus
themes provide called <code class="language-plaintext highlighter-rouge">modus-themes-include-derivatives-mode</code>. It is
the same ideas as the minor mode for the Ef themes, mentioned above:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">define-minor-mode</span> <span class="nv">modus-themes-include-derivatives-mode</span>
  <span class="s">"When enabled, all Modus themes commands cover derivatives as well.
Otherwise, they only consider the `modus-themes-items'.

Derivative theme projects can implement the equivalent of this minor
mode plus a method for `modus-themes-get-themes' to filter themes
accordingly."</span>
  <span class="ss">:global</span> <span class="no">t</span>
  <span class="ss">:init-value</span> <span class="no">nil</span><span class="p">)</span>

<span class="p">(</span><span class="nv">cl-defmethod</span> <span class="nv">modus-themes-get-themes</span> <span class="p">(</span><span class="nv">&amp;context</span> <span class="p">(</span><span class="nv">modus-themes-include-derivatives-mode</span> <span class="p">(</span><span class="nb">eql</span> <span class="no">t</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">modus-themes-get-all-known-themes</span> <span class="no">nil</span><span class="p">))</span>
</code></pre></div></div>

<p>This is what happens when I load both the <code class="language-plaintext highlighter-rouge">modus-themes</code> and the
<code class="language-plaintext highlighter-rouge">ef-themes</code> and enable this “all good ones fit” minor mode:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">modus-themes-include-derivatives-mode</span> <span class="mi">1</span><span class="p">)</span>

<span class="p">(</span><span class="nv">modus-themes-get-themes</span><span class="p">)</span>
<span class="c1">;; =&gt; (modus-operandi modus-operandi-tinted modus-operandi-deuteranopia modus-operandi-tritanopia modus-vivendi modus-vivendi-tinted modus-vivendi-deuteranopia modus-vivendi-tritanopia ef-winter ef-tritanopia-light ef-tritanopia-dark ef-trio-light ef-trio-dark ef-symbiosis ef-summer ef-spring ef-rosa ef-reverie ef-owl ef-night ef-melissa-light ef-melissa-dark ef-maris-light ef-maris-dark ef-light ef-kassio ef-frost ef-elea-light ef-elea-dark ef-eagle ef-duo-light ef-duo-dark ef-dream ef-deuteranopia-light ef-deuteranopia-dark ef-day ef-dark ef-cyprus ef-cherie ef-bio ef-autumn ef-arbutus)</span>
</code></pre></div></div>

<p>And when I no longer want to include everything, I just disable the
minor mode:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">modus-themes-include-derivatives-mode</span> <span class="mi">-1</span><span class="p">)</span>

<span class="p">(</span><span class="nv">modus-themes-get-themes</span><span class="p">)</span>
<span class="c1">;; =&gt; (modus-operandi modus-operandi-tinted modus-operandi-deuteranopia modus-operandi-tritanopia modus-vivendi modus-vivendi-tinted modus-vivendi-deuteranopia modus-vivendi-tritanopia)</span>
</code></pre></div></div>

<p>It is a thing of beauty!</p>

<h2>Finalising the implementation details</h2>

<p>I am still experimenting with some of the technicalities involved. In
principle, derivative themes will (i) depend on the <code class="language-plaintext highlighter-rouge">modus-themes</code>,
(ii) define each of their themes using the <code class="language-plaintext highlighter-rouge">modus-themes-theme</code> macro,
and (iii) specify how/when they affect the behaviour of the generic
function <code class="language-plaintext highlighter-rouge">modus-themes-get-themes</code>.</p>

<p>The code I am working on will soon be available in the respective
<code class="language-plaintext highlighter-rouge">main</code> branch of <code class="language-plaintext highlighter-rouge">modus-themes.git</code> and <code class="language-plaintext highlighter-rouge">ef-themes.git</code>. I think this
gives us the tools to realise the full potential of the Modus themes.</p>

<p>Finally, it is not just package authors that can benefit from this
development. Users may also curate their themes with something as
basic as this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">cl-defmethod</span> <span class="nv">modus-themes-get-themes</span> <span class="p">()</span>
  <span class="o">'</span><span class="p">(</span><span class="nv">modus-operandi</span> <span class="nv">ef-eagle</span> <span class="nv">modus-vivendi-tinted</span> <span class="nv">ef-melissa-dark</span><span class="p">))</span>

<span class="p">(</span><span class="nv">modus-themes-get-themes</span><span class="p">)</span>
<span class="c1">;; =&gt; (modus-operandi ef-eagle modus-vivendi-tinted ef-melissa-dark)</span>
</code></pre></div></div>

<p>In this method, there is no function involved for returning a list of
themes nor an opt-in clause. It simply hardcodes a list of themes. The
point is that it works! The approach with the minor mode will usually
be better and is easy enough. It is all a matter of empowering
personal preference, which is the Emacs-y outlook, after all. I expect
users to define their own collections, as they see fit.</p>

<p>Have fun!</p>

<h2>About the Modus themes</h2>

<p>Highly accessible themes, conforming with the highest standard for
colour contrast between background and foreground values (WCAG AAA).
They also are optimised for users with red-green or blue-yellow colour
deficiency.</p>

<p>The themes are very customisable and provide support for a wide range
of packages.  Their manual is detailed so that new users can get
started, while it also provides custom code for all sorts of more
advanced customisations.</p>

<p>Since August 2020, the original Modus themes (<code class="language-plaintext highlighter-rouge">modus-operandi</code>,
<code class="language-plaintext highlighter-rouge">modus-vivendi</code>) are built into Emacs version 28 or higher. Emacs 28
ships with <code class="language-plaintext highlighter-rouge">modus-themes</code> version <code class="language-plaintext highlighter-rouge">1.6.0</code>. Emacs 29 includes version
<code class="language-plaintext highlighter-rouge">3.0.0</code>. Emacs 30 provides version <code class="language-plaintext highlighter-rouge">4.4.0</code>. Version 4 is a major
refactoring of how the themes are implemented and customised. Such
major versions are not backward-compatible due to the limited
resources at my disposal to support multiple versions of Emacs and of
the themes across the years.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">modus-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/modus-themes-changelog">https://protesilaos.com/emacs/modus-themes-changelog</a></li>
  <li>Colour palette: <a href="https://protesilaos.com/emacs/modus-themes-colors">https://protesilaos.com/emacs/modus-themes-colors</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/modus-themes-pictures">https://protesilaos.com/emacs/modus-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/modus-themes">https://github.com/protesilaos/modus-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/modus-themes">https://gitlab.com/protesilaos/modus-themes</a></li>
    </ul>
  </li>
  <li>Backronym: My Old Display Unexpectedly Sharpened … themes.</li>
</ul>

<h2>About the Ef themes</h2>

<p>The <code class="language-plaintext highlighter-rouge">ef-themes</code> are a collection of light and dark themes for GNU
Emacs that provide colourful (“pretty”) yet legible options for users
who want something with a bit more flair than the <code class="language-plaintext highlighter-rouge">modus-themes</code> (also
designed by me).</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">ef-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/ef-themes">https://protesilaos.com/emacs/ef-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/ef-themes-changelog">https://protesilaos.com/emacs/ef-themes-changelog</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/ef-themes">https://github.com/protesilaos/ef-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/ef-themes">https://gitlab.com/protesilaos/ef-themes</a></li>
    </ul>
  </li>
  <li>Backronym: Eclectic Fashion in Themes Hides Exaggerated Markings,
Embellishments, and Sparkles.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: the next ‘ef-themes’ will build on top of the ‘modus-themes’</title>
      <description>Announcement about the changes coming to the next major version of the Ef themes.</description>
      <pubDate>Sat, 27 Sep 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-09-27-emacs-next-ef-themes-built-on-modus/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-09-27-emacs-next-ef-themes-built-on-modus/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Since version <code class="language-plaintext highlighter-rouge">4.0.0</code> of my <code class="language-plaintext highlighter-rouge">modus-themes</code>, users can override the
palette of one or all the themes. They can change the applicable
colours and how those are mapped to semantic elements. For example,
“heading level 1” will apply to Org, Markdown, Info, and anything else
that defines a relevant face. In principle, Modus can derive any
theme. The advantage is that we get battle tested support for a wide
range of packages, theme-wide consistency and attention to detail, and
all the familiar flexibility of customisation, while only defining new
colour values and/or their mappings. Plus, the Modus themes are built
into Emacs.</p>

<p>When I first designed the <code class="language-plaintext highlighter-rouge">ef-themes</code>, Modus did not have the
aforementioned capabilities. As such, Ef had to be implemented from
scratch. Over time, the two projects have converged in terms of
overall approach. There still are some notable differences, namely, Ef
is less customisable and extensive than Modus. This is about to change.</p>

<p>I am working on a thoroughgoing redesign of the Ef themes to make them
essentially load either <code class="language-plaintext highlighter-rouge">modus-operandi</code> (main light theme) or
<code class="language-plaintext highlighter-rouge">modus-vivendi</code> (main dark theme) with the relevant palette overrides.
All the Ef themes will look the same as they do now, but under the
hood things will become much simpler. What is currently a standalone
“theme” object will be reduced to a palette definition, essentially an
alist.</p>

<p>In a future publication, I will document all the breaking changes. In
short, all customisation shall be done via the Modus user options. Ef
will only implement its palettes. As for my <code class="language-plaintext highlighter-rouge">doric-themes</code> and
<code class="language-plaintext highlighter-rouge">standard-themes</code> those will remain unchanged for the time being.
Standard might go the way of Ef, but Doric will probably continue to
be its own thing. At any rate, these issues will be examined when
their time is right.</p>

<p>Stay tuned for more. In the meantime, enjoy version <code class="language-plaintext highlighter-rouge">1.11.0</code> of the Ef
themes that I released earlier this week!</p>

<h2>About the Ef themes</h2>

<p>The <code class="language-plaintext highlighter-rouge">ef-themes</code> are a collection of light and dark themes for GNU
Emacs that provide colourful (“pretty”) yet legible options for users
who want something with a bit more flair than the <code class="language-plaintext highlighter-rouge">modus-themes</code> (also
designed by me).</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">ef-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/ef-themes">https://protesilaos.com/emacs/ef-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/ef-themes-changelog">https://protesilaos.com/emacs/ef-themes-changelog</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/ef-themes">https://github.com/protesilaos/ef-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/ef-themes">https://gitlab.com/protesilaos/ef-themes</a></li>
    </ul>
  </li>
  <li>Backronym: Eclectic Fashion in Themes Hides Exaggerated Markings,
Embellishments, and Sparkles.</li>
</ul>

<h2>About the Modus themes</h2>

<p>Highly accessible themes, conforming with the highest standard for
colour contrast between background and foreground values (WCAG AAA).
They also are optimised for users with red-green or blue-yellow colour
deficiency.</p>

<p>The themes are very customisable and provide support for a wide range
of packages.  Their manual is detailed so that new users can get
started, while it also provides custom code for all sorts of more
advanced customisations.</p>

<p>Since August 2020, the original Modus themes (<code class="language-plaintext highlighter-rouge">modus-operandi</code>,
<code class="language-plaintext highlighter-rouge">modus-vivendi</code>) are built into Emacs version 28 or higher. Emacs 28
ships with <code class="language-plaintext highlighter-rouge">modus-themes</code> version <code class="language-plaintext highlighter-rouge">1.6.0</code>. Emacs 29 includes version
<code class="language-plaintext highlighter-rouge">3.0.0</code>. Emacs 30 provides version <code class="language-plaintext highlighter-rouge">4.4.0</code>. Version 4 is a major
refactoring of how the themes are implemented and customised. Such
major versions are not backward-compatible due to the limited
resources at my disposal to support multiple versions of Emacs and of
the themes across the years.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">modus-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/modus-themes-changelog">https://protesilaos.com/emacs/modus-themes-changelog</a></li>
  <li>Colour palette: <a href="https://protesilaos.com/emacs/modus-themes-colors">https://protesilaos.com/emacs/modus-themes-colors</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/modus-themes-pictures">https://protesilaos.com/emacs/modus-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/modus-themes">https://github.com/protesilaos/modus-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/modus-themes">https://gitlab.com/protesilaos/modus-themes</a></li>
    </ul>
  </li>
  <li>Backronym: My Old Display Unexpectedly Sharpened … themes.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: ef-themes version 1.11.0</title>
      <description>Information about the latest version of my colourful-yet-legible themes for GNU Emacs.</description>
      <pubDate>Thu, 25 Sep 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-09-25-emacs-ef-themes-1-11-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-09-25-emacs-ef-themes-1-11-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <code class="language-plaintext highlighter-rouge">ef-themes</code> are a collection of light and dark themes for GNU
Emacs that provide colourful (“pretty”) yet legible options for users
who want something with a bit more flair than the <code class="language-plaintext highlighter-rouge">modus-themes</code> (also
designed by me).</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">ef-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/ef-themes">https://protesilaos.com/emacs/ef-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/ef-themes-changelog">https://protesilaos.com/emacs/ef-themes-changelog</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/ef-themes">https://github.com/protesilaos/ef-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/ef-themes">https://gitlab.com/protesilaos/ef-themes</a></li>
    </ul>
  </li>
  <li>Backronym: Eclectic Fashion in Themes Hides Exaggerated Markings,
Embellishments, and Sparkles.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 1.11.0 on 2025-09-25</h2>

<p>This version introduces minor refinements to a stable package.</p>

<h3>Support for faces added to Emacs 31</h3>

<p>Emacs 31 is the current development target of Emacs. The new faces are
<code class="language-plaintext highlighter-rouge">header-line-inactive</code>, <code class="language-plaintext highlighter-rouge">package-mark-delete-face</code>, <code class="language-plaintext highlighter-rouge">package-mark-install-face</code>,
<code class="language-plaintext highlighter-rouge">minibuffer-nonselected</code>.</p>

<h3>Mode lines are a bit easier to spot</h3>

<p>The active and inactive mode lines now have a subtle box/border around
them on graphical Emacs. In non-graphical sessions, an underline is
applied instead. This makes mode lines easier to stand out even when
the buffer is showing a background that is of a similar colour to
their own background.</p>

<h3>The Custom interface buttons are more refined</h3>

<p>These are the buttons that appear in the Custom buffers that we reach
through various means such as <code class="language-plaintext highlighter-rouge">M-x customize</code>. Like with the mode
lines, they use a box/border around where possible, else fall back to
an underline.</p>

<h3>The current date in the <code class="language-plaintext highlighter-rouge">M-x calendar</code> always looks the same</h3>

<p>Before, it would look different if the Calendar was produced via <code class="language-plaintext highlighter-rouge">M-x
calendar</code> as opposed to the Org date selection interface. This is
because they apply different faces to the current date. Those are now
reworked to look the same.</p>

<h3>Notmuch message summary headers have clear dividers</h3>

<p>In the Notmuch email client, the messages in a thread can be
collapsed/minimised to just a heading. Those used to have only a
subtle background, which would be enough to differentiate them from
the body of the email but not from each other when all were collapsed.
Now the themes add an overline to each heading, if supported by the
underlying display engine (i.e. graphical Emacs), which should make it
easier to spot them.</p>

<h3>Links in the header line of Info buffers do not have an underline</h3>

<p>This is because the header line has a distinct background already, so
we want to avoid exaggerations.</p>

<h3>The commands <code class="language-plaintext highlighter-rouge">ef-themes-rotate</code> and <code class="language-plaintext highlighter-rouge">ef-themes-load-random</code> can be silent</h3>

<p>They now accept an optional <code class="language-plaintext highlighter-rouge">SILENT</code> parameter that inhibits the
message they otherwise print. Thanks to Sean Devlin for the
contribution in pull request 59: <a href="https://github.com/protesilaos/ef-themes/pull/59">https://github.com/protesilaos/ef-themes/pull/59</a>.</p>

<p>Note that any function can be silenced with something like this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-wrapper-of-some-function</span> <span class="p">()</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">inhibit-message</span> <span class="no">t</span><span class="p">))</span>
    <span class="p">(</span><span class="nv">some-function</span><span class="p">)))</span>
</code></pre></div></div>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: example of a custom Denote identifier to include day of week data</title>
      <description>I explain how Denote can use custom identifiers and discuss the technicalities of the code.</description>
      <pubDate>Wed, 24 Sep 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-09-24-emacs-example-denote-custom-identifier/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-09-24-emacs-example-denote-custom-identifier/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>As I wrote in a recent entry, the forthcoming version <code class="language-plaintext highlighter-rouge">4.1.0</code> of
<a href="https://protesilaos.com/codelog/2025-09-20-emacs-denote-custom-identifiers/">Denote will provide the option to define custom identifier schemes</a>.
Here I explain one of the examples I have included in the manual,
specifically, the idea of recording the day of the week as part of the
date+time stamp. Monday is <code class="language-plaintext highlighter-rouge">A</code>, Tuesday is <code class="language-plaintext highlighter-rouge">B</code>, and so on.</p>

<p>The default Denote identifier is a compact representation of the date
and time, with the letter <code class="language-plaintext highlighter-rouge">T</code> in between. For example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>20250924T190920
</code></pre></div></div>

<p>The letter <code class="language-plaintext highlighter-rouge">T</code> does not have any special meaning. It simply delimits
the two constituents of the identifier. Users who want to record the
day of the week can ultimately derive identifiers that look like these:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>20250922A082941
20250923B140652
20250924C191038
</code></pre></div></div>

<p>And with some spaces for didactic purposes:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2025 09 22   A   08 29 41
2025 09 23   B   14 06 52
2025 09 24   C   19 10 38
</code></pre></div></div>

<p>[ Actually, users can produce identifiers with such spaces, but I will
  leave this as an exercise for interested parties. ]</p>

<h2>Get the day of the week as a capital letter</h2>

<p>To get the day of the week as a string that holds a number, we use the
<code class="language-plaintext highlighter-rouge">%u</code> format specifier of the function <code class="language-plaintext highlighter-rouge">format-time-string</code>. Today is
Wednesday, thus:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">format-time-string</span> <span class="s">"%u"</span><span class="p">)</span>
<span class="c1">;; =&gt; "3"</span>
</code></pre></div></div>

<p>Based on this, we know that we need a function that takes such a
string and returns the corresponding capital letter. Here is one way
of achieving as much:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-denote-get-day-of-week-as-alpha</span> <span class="p">(</span><span class="nv">day</span><span class="p">)</span>
  <span class="s">"Return the corresponding capital letter for DAY.
DAY is a string holding a number, as the return value of the %u
specifier in `format-time-string'.

If DAY is a number, convert it to a string and then return its
corresponding letter."</span>
  <span class="p">(</span><span class="nv">pcase</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">numberp</span> <span class="nv">day</span><span class="p">)</span> <span class="p">(</span><span class="nv">number-to-string</span> <span class="nv">day</span><span class="p">)</span> <span class="nv">day</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"1"</span> <span class="s">"A"</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"2"</span> <span class="s">"B"</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"3"</span> <span class="s">"C"</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"4"</span> <span class="s">"D"</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"5"</span> <span class="s">"E"</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"6"</span> <span class="s">"F"</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"7"</span> <span class="s">"G"</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">_</span> <span class="p">(</span><span class="nb">error</span> <span class="s">"The day `%S' is not among 1-7"</span> <span class="nv">day</span><span class="p">))))</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">pcase</code> macro does the heavy lifting here. We basically test for
string equality and return a new string or throw an error. Testing the
code, I get these results:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">my-denote-get-day-of-week-as-alpha</span> <span class="s">"3"</span><span class="p">)</span>
<span class="c1">;; =&gt; "C"</span>

<span class="p">(</span><span class="nv">my-denote-get-day-of-week-as-alpha</span> <span class="mi">3</span><span class="p">)</span>
<span class="c1">;; =&gt; "C"</span>

<span class="p">(</span><span class="nv">my-denote-get-day-of-week-as-alpha</span> <span class="s">"10"</span><span class="p">)</span>
<span class="c1">;; =&gt; ERROR</span>

<span class="p">(</span><span class="nv">my-denote-get-day-of-week-as-alpha</span> <span class="mi">10</span><span class="p">)</span>
<span class="c1">;; =&gt; ERROR</span>
</code></pre></div></div>

<h2>Tweak the Denote identifier format to pass the <code class="language-plaintext highlighter-rouge">%u</code> specifier</h2>

<p>Denote stores the <code class="language-plaintext highlighter-rouge">format-time-string</code> specifiers for its default
identifier in the variable <code class="language-plaintext highlighter-rouge">denote-date-identifier-format</code>. The value
is <code class="language-plaintext highlighter-rouge">"%Y%m%dT%H%M%S"</code>, which is what derives the aforementioned
standard identifier.</p>

<p>We already noted that we do not want that literal <code class="language-plaintext highlighter-rouge">T</code> over there. So
let us make our format the same as the original one except that we
include <code class="language-plaintext highlighter-rouge">%u</code> in place of <code class="language-plaintext highlighter-rouge">T</code>. A function call that would yield the
desired result is this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">replace-regexp-in-string</span> <span class="s">"T"</span> <span class="s">" %u "</span> <span class="nv">denote-date-identifier-format</span> <span class="no">t</span><span class="p">)</span>
<span class="c1">;; =&gt; "%Y%m%d %u %H%M%S"</span>
</code></pre></div></div>

<p>Notice that I add a space before and after the <code class="language-plaintext highlighter-rouge">%u</code>. These are
delimiters that we will use to split the string more easily into its
<code class="language-plaintext highlighter-rouge">DATE</code>, <code class="language-plaintext highlighter-rouge">DAY</code>, <code class="language-plaintext highlighter-rouge">TIME</code> components. But one step at a time. We first
need to define this as a variable:</p>

<p>[ Technically, this is not a normal variable because of <code class="language-plaintext highlighter-rouge">defconst</code>
  instead of the more common <code class="language-plaintext highlighter-rouge">defvar</code>, but we do not need to consider
  such details. ]</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">defconst</span> <span class="nv">my-denote-date-identifier-format</span>
  <span class="p">(</span><span class="nv">replace-regexp-in-string</span> <span class="s">"T"</span> <span class="s">" %u "</span> <span class="nv">denote-date-identifier-format</span> <span class="no">t</span><span class="p">))</span>
</code></pre></div></div>

<h2>Format a date using the new identifier scheme</h2>

<p>Our next task is to write a small function that takes a date argument
and returns a string whose pattern follows what we did in the previous
section. For example, if the current date is <code class="language-plaintext highlighter-rouge">2025-09-24</code>, the day is
Wednesday, and the time is <code class="language-plaintext highlighter-rouge">19:30:00</code>, we expect an identifier like
<code class="language-plaintext highlighter-rouge">20250924C193000</code>.</p>

<p>To keep things simple, we will not go into how Emacs represents dates
internally. It does not matter, anyway, because Denote handles that
part internally. All we need to test our function is to use the return
value of the function <code class="language-plaintext highlighter-rouge">current-time</code>. Actually, even that is optional
because <code class="language-plaintext highlighter-rouge">format-time-string</code> defaults to that if it is not given an
explicit date as an argument.</p>

<p>As such, here is how we get the string <code class="language-plaintext highlighter-rouge">"DATE DAY TIME"</code>, based on
what we have:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">format-time-string</span> <span class="nv">my-denote-date-identifier-format</span><span class="p">)</span>
<span class="c1">;; =&gt; "20250924 3 193347"</span>
</code></pre></div></div>

<p>Remember those spaces from earlier? We need them now to split this
string into a list of three strings, so that we can isolate the day in
the middle. Once we have just the day, we can pass it to the function
we wrote earlier that gives us the corresponding capital letter.</p>

<p>To split a string at the spaces, we do this (read the <code class="language-plaintext highlighter-rouge">split-string</code>
doc string for further details):</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">split-string</span> <span class="nv">STRING</span><span class="p">)</span>
</code></pre></div></div>

<p>Which means:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">split-string</span> <span class="p">(</span><span class="nv">format-time-string</span> <span class="nv">my-denote-date-identifier-format</span><span class="p">))</span>
<span class="c1">;; =&gt; ("20250924" "3" "193626")</span>
</code></pre></div></div>

<p>We get back a list of strings, so the day is retrieved thus:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">nth</span> <span class="mi">1</span> <span class="o">'</span><span class="p">(</span><span class="s">"20250924"</span> <span class="s">"3"</span> <span class="s">"193626"</span><span class="p">))</span>
<span class="c1">;; =&gt; "3"</span>
</code></pre></div></div>

<p>Use <code class="language-plaintext highlighter-rouge">(nth 0 ...)</code> for the date and <code class="language-plaintext highlighter-rouge">(nth 2 ...)</code> for the time.</p>

<p>Now that we know all this, we can piece it together into a single
function. Here is what we will do, which I shall explain in further
detail below:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-denote-format-date</span> <span class="p">(</span><span class="nv">date</span><span class="p">)</span>
  <span class="s">"Format DATE using `my-denote-date-identifier-format'.
Represent the day of the week with `my-denote-get-day-of-week-as-alpha'."</span>
  <span class="p">(</span><span class="nv">pcase-let*</span> <span class="p">((</span><span class="nv">identifier-string</span> <span class="p">(</span><span class="nv">format-time-string</span> <span class="nv">my-denote-date-identifier-format</span> <span class="nv">date</span><span class="p">))</span>
               <span class="p">(</span><span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="nv">date</span> <span class="o">,</span><span class="nv">day</span> <span class="o">,</span><span class="nb">time</span><span class="p">)</span> <span class="p">(</span><span class="nv">split-string</span> <span class="nv">identifier-string</span><span class="p">))</span>
               <span class="p">(</span><span class="nv">day-as-letter</span> <span class="p">(</span><span class="nv">my-denote-get-day-of-week-as-alpha</span> <span class="nv">day</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">concat</span> <span class="nv">date</span> <span class="nv">day-as-letter</span> <span class="nb">time</span><span class="p">)))</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">pcase-let*</code> macro uses “destructuring” to pattern match the return
value and bind it to the variables we name (also see my free (gratis and
libre) book: <a href="https://protesilaos.com/emacs/emacs-lisp-elements">Emacs Lisp Elements</a>).
This is the short way of doing the following:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-denote-format-date</span> <span class="p">(</span><span class="nv">date</span><span class="p">)</span>
  <span class="s">"Format DATE using `my-denote-date-identifier-format'."</span>
  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">identifier-string</span> <span class="p">(</span><span class="nv">format-time-string</span> <span class="nv">my-denote-date-identifier-format</span> <span class="nv">date</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">strings</span> <span class="p">(</span><span class="nv">split-string</span> <span class="nv">identifier-string</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">date</span> <span class="p">(</span><span class="nb">nth</span> <span class="mi">0</span> <span class="nv">strings</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">day</span> <span class="p">(</span><span class="nb">nth</span> <span class="mi">1</span> <span class="nv">strings</span><span class="p">))</span>
         <span class="p">(</span><span class="nb">time</span> <span class="p">(</span><span class="nb">nth</span> <span class="mi">2</span> <span class="nv">strings</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">day-as-letter</span> <span class="p">(</span><span class="nv">my-denote-get-day-of-week-as-alpha</span> <span class="nv">day</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">concat</span> <span class="nv">date</span> <span class="nv">day-as-letter</span> <span class="nb">time</span><span class="p">)))</span>
</code></pre></div></div>

<p>Use whichever style you prefer.</p>

<p>The point is that we (i) take the return value of <code class="language-plaintext highlighter-rouge">format-time-string</code>
with the spaces, as I showed above, (ii) split it at the spaces into
three strings, (iii) assign each of those strings to a variable local
to this function, (iv) convert the day from a number to a capital
letter, and (v) put it all back together without those spaces. The
result is this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">my-denote-format-date</span> <span class="p">(</span><span class="nv">current-time</span><span class="p">))</span>
<span class="c1">;; =&gt; "20250924C194219"</span>
</code></pre></div></div>

<h2>Write and then use the custom <code class="language-plaintext highlighter-rouge">denote-get-identifier-function</code></h2>

<p>The variable <code class="language-plaintext highlighter-rouge">denote-get-identifier-function</code> has the symbol of a
function as its value. Its documentation describes the technicalities.
Though, again, we do not need to understand the finer points to
achieve our goal. Since our custom identifier is almost the same as
the default, we can copy the original function that Denote relies on
and make a small change to it so that it uses the <code class="language-plaintext highlighter-rouge">my-denote-format-date</code>
we just wrote. Behold:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-denote-generate-identifier-as-date</span> <span class="p">(</span><span class="nv">initial-identifier</span> <span class="nv">date</span><span class="p">)</span>
  <span class="s">"Generate an identifier based on DATE.

If INITIAL-IDENTIFIER is not already used, return it.  Else, if it is
possible to derive an identifier from it, return this identifier.

Else, use the DATE.  If it is nil, use `current-time'.

Slightly modified version of `denote-generate-identifier-as-date'."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">denote-used-identifiers</span> <span class="p">(</span><span class="nb">or</span> <span class="nv">denote-used-identifiers</span> <span class="p">(</span><span class="nv">denote--get-all-used-ids</span><span class="p">))))</span>
    <span class="p">(</span><span class="nb">cond</span> <span class="p">((</span><span class="nb">and</span> <span class="nv">initial-identifier</span>
                <span class="p">(</span><span class="nb">not</span> <span class="p">(</span><span class="nb">gethash</span> <span class="nv">initial-identifier</span> <span class="nv">denote-used-identifiers</span><span class="p">)))</span>
           <span class="nv">initial-identifier</span><span class="p">)</span>
          <span class="p">((</span><span class="nb">and</span> <span class="nv">initial-identifier</span>
                <span class="p">(</span><span class="nv">string-match-p</span> <span class="nv">denote-date-identifier-regexp</span> <span class="nv">initial-identifier</span><span class="p">)</span>
                <span class="p">(</span><span class="nv">date-to-time</span> <span class="nv">initial-identifier</span><span class="p">))</span>
           <span class="p">(</span><span class="nv">denote--find-first-unused-id-as-date</span> <span class="nv">initial-identifier</span><span class="p">))</span>
          <span class="p">(</span><span class="no">t</span>
           <span class="p">(</span><span class="nv">denote--find-first-unused-id-as-date</span>
            <span class="p">(</span><span class="nv">my-denote-format-date</span> <span class="p">(</span><span class="nb">or</span> <span class="nv">date</span> <span class="p">(</span><span class="nv">current-time</span><span class="p">))))))))</span>
</code></pre></div></div>

<p>The internal workings do not matter right now, though I am happy to
explain them elsewhere. Our priority is to find where <code class="language-plaintext highlighter-rouge">my-denote-format-date</code>
is used. The only difference between what we have here and the
original is that our final line uses <code class="language-plaintext highlighter-rouge">my-denote-format-date</code>, while
the original does a <code class="language-plaintext highlighter-rouge">format-time-string</code> with the <code class="language-plaintext highlighter-rouge">denote-date-identifier-format</code>
(which we saw further above when we replaced <code class="language-plaintext highlighter-rouge">T</code> with <code class="language-plaintext highlighter-rouge">%u</code>).</p>

<p>Finally, bind <code class="language-plaintext highlighter-rouge">denote-get-identifier-function</code> to the symbol of the
custom function to start using it:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">denote-get-identifier-function</span> <span class="nf">#'</span><span class="nv">my-denote-generate-identifier-as-date</span><span class="p">)</span>
</code></pre></div></div>

<p>All Denote files will henceforth look like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@@20250924C190301--this-is-a-test__denote_testing.txt
</code></pre></div></div>

<p>Remember that the <code class="language-plaintext highlighter-rouge">@@</code> exists for custom identifiers and that all the
components of the file name can be reordered.</p>

<p>This covers it! The manual has more examples and I always am eager to
help anyone who needs to do something a little bit differently.</p>

<h2>About Denote</h2>

<p>Denote is a simple note-taking tool for Emacs. It is based on the idea
that notes should follow a predictable and descriptive file-naming
scheme. The file name must offer a clear indication of what the note
is about, without reference to any other metadata. Denote basically
streamlines the creation of such files while providing facilities to
link between them.</p>

<p>Denote’s file-naming scheme is not limited to “notes”. It can be used
for all types of file, including those that are not editable in Emacs,
such as videos. Naming files in a consistent way makes their filtering
and retrieval considerably easier. Denote provides relevant facilities
to rename files, regardless of file type.</p>

<p>[ I have a page with all my Emacs packages, which includes all the
  Denote extensions I maintain: <a href="https://protesilaos.com/emacs">https://protesilaos.com/emacs</a>. ]</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote">https://protesilaos.com/emacs/denote</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/denote-changelog">https://protesilaos.com/emacs/denote-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/denote">https://github.com/protesilaos/denote</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/denote">https://gitlab.com/protesilaos/denote</a></li>
    </ul>
  </li>
  <li>Video demo: <a href="https://protesilaos.com/codelog/2022-06-18-denote-demo/">https://protesilaos.com/codelog/2022-06-18-denote-demo/</a></li>
  <li>Backronyms: Denote Everything Neatly; Omit The Excesses.  Don’t Ever
Note Only The Epiphenomenal.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: the next version of Denote will support custom identifiers</title>
      <description>Information about the upcoming release of Denote that will allow advanced users or developers to use custom identifiers.</description>
      <pubDate>Sat, 20 Sep 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-09-20-emacs-denote-custom-identifiers/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-09-20-emacs-denote-custom-identifiers/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>There are a lot of developments happening in <code class="language-plaintext highlighter-rouge">denote</code> and the various
other extensions for it that I maintain. I will share more details in
the release notes, hopefully before the end of this month. Just to
give you a forewarning about a potentially massive boost for advanced
users or developers: the ability to specify a completely custom
identifier scheme for Denote file names.</p>

<p>By default, Denote constructs a file name to have, at minimum, an
identifier as a compact representation of the date and time. It looks
like this: <code class="language-plaintext highlighter-rouge">20250920T120924</code>. The default file will also have a title
and keywords, based on user input at the relevant minibuffer prompts,
so it will look like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>20250920T120924--denote-custom-identifiers__emacs_programming.txt
</code></pre></div></div>

<p>Instead of hardcoding the scheme of an identifier as a compact
representation of a date and time, we provide the variable
<code class="language-plaintext highlighter-rouge">denote-get-identifier-function</code>. Its value is the symbol of a
function, which is called to yield an identifier, as a string.</p>

<p>I have written a few examples of this in the Denote manual, grouped
under this section: <a href="https://protesilaos.com/emacs/denote#h:3048f558-7d84-45d6-9ef2-53055483e801">https://protesilaos.com/emacs/denote#h:3048f558-7d84-45d6-9ef2-53055483e801</a>.
Read the documentation of <code class="language-plaintext highlighter-rouge">denote-get-identifier-function</code> for the
remaining technicalities.</p>

<p>The identifier can be anything from an automatic incremental numbering
scheme to something that always asks for user input to produce a more
information-dense result. To illustrate the potential of the latter
concept, the manual elaborates on the use-case of recording data about
academic publications, such as the editor, authors, and publisher,
through a series of minibuffer prompts. The end result is a unique
identifier with the help of some extra helper functions.</p>

<p>Custom identifiers are prefixed with the <code class="language-plaintext highlighter-rouge">@@</code> file name component
separator. This way they are unambiguous and can be retrieved with
certainty. More so since the Denote file name components can be
presented in any order, per the user option <code class="language-plaintext highlighter-rouge">denote-file-name-components-order</code>.</p>

<p>Custom identifiers are the culmination of many changes over the years
to make the Denote file-naming scheme as flexible as possible. It is
super effective out-of-the-box and can then be particularised to
specific workflows with ease. These are not mutually exclusive, as
users can still rely on the regular Denote functionality for most
cases and only deviate from it with bespoke functions where necessary.
For instance, to have a special variant of <code class="language-plaintext highlighter-rouge">denote-rename-file</code> that
applies a custom identifier scheme instead of the default, users can
write a wrapper command like this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-denote-rename-file-with-my-custom-identifier</span> <span class="p">()</span>
  <span class="s">"Like `denote-rename-file' but use `my-denote-get-custom-identifier' instead."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">denote-get-identifier-function</span> <span class="nf">#'</span><span class="nv">my-denote-get-custom-identifier</span><span class="p">))</span>
    <span class="p">(</span><span class="nv">call-interactively</span> <span class="ss">'denote-rename-file</span><span class="p">)))</span>
</code></pre></div></div>

<p>Imagine doing this for files in a specific folder where the standard
identifier provided by Denote does not add much value (beside being a
unique match for the linking mechanism, that is).</p>

<p>The Denote manual is full of examples like the above. These sort of
small and elegant extensions are possible owning to the design of the
code into easily adaptable functions.</p>

<p>We keep going from strength to strength and I am delighted with the
results. I hope you make good use of the tools on offer. Let me know
if there is anything more you need: I am confident we can make it
happen.</p>

<p>Much of the thought and work that went is to this project is thanks to
user mentalisttraceur and long-time contributor Jean-Philippe Gagné
Guay.</p>

<h2>About Denote</h2>

<p>Denote is a simple note-taking tool for Emacs. It is based on the idea
that notes should follow a predictable and descriptive file-naming
scheme. The file name must offer a clear indication of what the note
is about, without reference to any other metadata. Denote basically
streamlines the creation of such files while providing facilities to
link between them.</p>

<p>Denote’s file-naming scheme is not limited to “notes”. It can be used
for all types of file, including those that are not editable in Emacs,
such as videos. Naming files in a consistent way makes their filtering
and retrieval considerably easier. Denote provides relevant facilities
to rename files, regardless of file type.</p>

<p>[ I have a page with all my Emacs packages, which includes all the
  Denote extensions I maintain: <a href="https://protesilaos.com/emacs">https://protesilaos.com/emacs</a>. ]</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/denote">https://protesilaos.com/emacs/denote</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/denote-changelog">https://protesilaos.com/emacs/denote-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/denote">https://github.com/protesilaos/denote</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/denote">https://gitlab.com/protesilaos/denote</a></li>
    </ul>
  </li>
  <li>Video demo: <a href="https://protesilaos.com/codelog/2022-06-18-denote-demo/">https://protesilaos.com/codelog/2022-06-18-denote-demo/</a></li>
  <li>Backronyms: Denote Everything Neatly; Omit The Excesses.  Don’t Ever
Note Only The Epiphenomenal.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: show-font version 1.0.0</title>
      <description>Information about the latest version of my show-font package for GNU Emacs.</description>
      <pubDate>Sun, 07 Sep 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-09-07-emacs-show-font-1-0-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-09-07-emacs-show-font-1-0-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This package lets you preview a font inside of Emacs. It does so in
three ways:</p>

<ul>
  <li>Prompt for a font on the system and display it in a buffer.</li>
  <li>List all known fonts in a buffer, with a short preview for each.</li>
  <li>Provide a major mode to preview a font whose file is among the
installed ones.</li>
</ul>

<p>Sources:</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">show-font</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/show-font">https://protesilaos.com/emacs/show-font</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/show-font-changelog">https://protesilaos.com/emacs/show-font-changelog</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/show-font">https://github.com/protesilaos/show-font</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/codelog/2024-09-10-emacs-show-font-0-1-0/">https://protesilaos.com/codelog/2024-09-10-emacs-show-font-0-1-0/</a></li>
  <li>Backronym: Should Highlight Only With the Family Of the Named Typeface.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 1.0.0 on 2025-09-07</h2>

<p>This major update introduces support for fonts that cover more than
the Latin script. It also expands the available functionality with
quality-of-life refinements.</p>

<h3>Support for Arabic, Chinese, Greek, Japanese, Korean, Russian</h3>

<p>The commands <code class="language-plaintext highlighter-rouge">show-font-tabulated</code> (alias <code class="language-plaintext highlighter-rouge">show-font-list</code>) and
<code class="language-plaintext highlighter-rouge">show-font-select-preview</code> can now generate a preview for fonts that
are optimised to display the aforementioned languages. Each language
provides its own user option to control the sample text it displays.
The naming pattern <code class="language-plaintext highlighter-rouge">show-font-LANGUAGE-sample</code>.</p>

<p>Of those, I only know Greek and thus wrote the value of
<code class="language-plaintext highlighter-rouge">show-font-greek-sample</code>, namely: <code class="language-plaintext highlighter-rouge">"Πρωτεσίλαος ο φιλόσοφος του οποίου
τα έργα βρίθουν αστειισμών"</code>. For the others I used translation
software to get the equivalent of <code class="language-plaintext highlighter-rouge">"Protesilaos does not read
LANGUAGE"</code>. Please let me know if there are any mistakes in this
regard. I was thinking of writing something a bit more funny, but was
concerned the joke may not translate well.</p>

<h3>Checking for language support among known families</h3>

<p>While I have written functions that test if a given font can display a
range of characters, this approach is computationally intensive if we
need to check for many code points across multiple fonts.</p>

<p>The alternative is to maintain lists of known font families that are
meant to work with the given language. Those generally support Latin
as well, but the idea is to let them shine in the language they are
meant to be used for.</p>

<p>For example, here is how we know that a font family is meant to
display Arabic script:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">defconst</span> <span class="nv">show-font-arabic-families</span>
  <span class="o">'</span><span class="p">(</span><span class="s">"AlArabiya"</span> <span class="s">"AlBattar"</span> <span class="s">"AlHor"</span> <span class="s">"AlManzomah"</span> <span class="s">"AlYarmook"</span>
    <span class="s">"Dimnah"</span> <span class="s">"Hani"</span> <span class="s">"Haramain"</span> <span class="s">"Hor"</span> <span class="s">"Kayrawan"</span> <span class="s">"Khalid"</span> <span class="s">"Mashq"</span>
    <span class="s">"Nagham"</span> <span class="s">"Noto Kufi Arabic"</span> <span class="s">"Noto Naskh Arabic"</span> <span class="s">"Noto Sans Arabic"</span>
    <span class="s">"Rehan"</span> <span class="s">"Sharjah"</span> <span class="s">"Sindbad"</span><span class="p">)</span>
  <span class="s">"List of families that specialise in Arabic.
Also see `show-font-greek-families' for the rationale of grouping font
families in distinct variables."</span><span class="p">)</span>
</code></pre></div></div>

<p>The list is not exhaustive and I am always eager to expand it. Just
let me know.</p>

<p>I learnt about these font families through trial and error by (i)
installing them on my Debian system and (ii) searching online for
common samples of them. Do <code class="language-plaintext highlighter-rouge">apt search -n fonts-</code> to check the
relevant packages.</p>

<h3>Support for music notation, mathematics, and other symbols</h3>

<p>As with the natural languages, there are some fonts that specialise in
displaying symbols. For example, MathJax has a bunch of fonts for
showing those fancy formulas in the processed output of LaTeX
documents. Again, there is a <code class="language-plaintext highlighter-rouge">defconst</code> for each of those types of
font listing the known families. The concomitant user options are:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">show-font-mathematics-sample</code></li>
  <li><code class="language-plaintext highlighter-rouge">show-font-music-sample</code></li>
  <li><code class="language-plaintext highlighter-rouge">show-font-symbols-sample</code></li>
</ul>

<h3>Problematic fonts are hidden from the list view</h3>

<p>The <code class="language-plaintext highlighter-rouge">show-font-hidden-families</code> lists the fonts that are not known to
cause problems. They do not render properly any of the supported
samples and I am not sure even when they claim to support a certain
set of characters (e.g. <code class="language-plaintext highlighter-rouge">show-font--displays-latin-p</code> returns
non-<code class="language-plaintext highlighter-rouge">nil</code>). If you think there is a mistake here, please contact me.</p>

<h3>Show a full preview from the list view</h3>

<p>While in the buffer produced by <code class="language-plaintext highlighter-rouge">show-font-tabulated</code> (alias
<code class="language-plaintext highlighter-rouge">show-font-list</code>), type <code class="language-plaintext highlighter-rouge">RET</code> to get a complete preview of the font
family of the current line. This is the same as invoking the command
<code class="language-plaintext highlighter-rouge">show-font-select-preview</code> and then selecting the given family.</p>

<p>The command called by that key binding is <code class="language-plaintext highlighter-rouge">show-font-tabulated-select-preview</code>.
A hint of it is also shown in the tabulated list header.</p>

<h3>Quickly copy the name of the font in the list view</h3>

<p>As above, type <code class="language-plaintext highlighter-rouge">w</code> in the tabulated view to copy the name of the font
family to the <code class="language-plaintext highlighter-rouge">kill-ring</code>. The command is <code class="language-plaintext highlighter-rouge">show-font-tabulated-copy-name</code>
and there is also a hint of it in the tabulated list header.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: doric-themes version 0.4.0</title>
      <description>Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate).</description>
      <pubDate>Mon, 01 Sep 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-09-01-emacs-doric-themes-0-4-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-09-01-emacs-doric-themes-0-4-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>These are my minimalist themes. They use few colours and will appear
mostly monochromatic in many contexts. Styles involve the careful use
of typography, such as italics and bold italics.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Update to doric-themes version 0.4.0</h2>

<p>This version brings several refinements to the package, as well as two
new themes.</p>

<h3>Enjoy doric-beach and doric-valley</h3>

<p>Most of the Doric themes feel monochromatic. By contrast, the
<code class="language-plaintext highlighter-rouge">doric-beach</code> (light) and <code class="language-plaintext highlighter-rouge">doric-valley</code> (dark) are dichromatic: they
combine warm hues, such as orange, with cold hues like teal. They
still are minimalistic, like the rest of the family, but appear a bit
more playful than their more austere counterparts.</p>

<p>[ The <code class="language-plaintext highlighter-rouge">doric-oak</code> and <code class="language-plaintext highlighter-rouge">doric-pine</code> are similar in this regard. ]</p>

<h3>Refashioned diffs</h3>

<p>All diff interfaces, including Magit, diff-mode, and Ediff now rely on
a comprehensive new subset of colours. They use colour-coded
backgrounds throughout, whereas before they had just colour-coded
text. The problem with highlighting only text is that it is harder
to (i) discern the colour and thus (ii) quickly estimate the
boundaries of a change.</p>

<p>For Magit in particular, there are distinct styles for the
highlighted/current diff hunk, all other diff hunks, as well as the
common word-wise (“refined”) diffs that all interfaces share.</p>

<h3>Org agenda and dates are more consistent</h3>

<p>The changes here are subtle but should contribute to a more pleasant
experience, owning to the more careful emphasis of information.
“Scheduled” entries are easier to notice, as they are distinct from
other events. Date headings also have a more clear distinction from
the tasks they contain.</p>

<p>For the M-x calendar, in particular, month and date headings are
revised to be consistent with the Org agenda, while the diary and
holiday faces are redone to look harmonious in context. Thanks to Amin
Bandali for checking those and suggesting some tweaks.</p>

<h3>Certain header-like faces stand out more</h3>

<p>In various contexts, such as in git-mode commit message comments or
Dired buffers, there are pieces of text that conceptually are
headings. Those are rendered in a distinct style than other generic
“bold” faces, to better perform their function.</p>

<h3>Flymake fringe indicators are easier to spot</h3>

<p>Those now have a fine background colour, coded to the type of warning.</p>

<h3>Support for the <code class="language-plaintext highlighter-rouge">lin</code> and <code class="language-plaintext highlighter-rouge">pulsar</code> packages</h3>

<p>Those define faces that affect the background of a line. These
packages now feel right when used in tandem with the doric-themes.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: show-font version 0.4.0</title>
      <description>Information about the latest version of my show-font package for GNU Emacs.</description>
      <pubDate>Tue, 26 Aug 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-08-26-emacs-show-font-0-4-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-08-26-emacs-show-font-0-4-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This package lets you preview a font inside of Emacs. It does so in
three ways:</p>

<ul>
  <li>Prompt for a font on the system and display it in a buffer.</li>
  <li>List all known fonts in a buffer, with a short preview for each.</li>
  <li>Provide a major mode to preview a font whose file is among the
installed ones.</li>
</ul>

<p>Sources:</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">show-font</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/show-font">https://protesilaos.com/emacs/show-font</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/show-font-changelog">https://protesilaos.com/emacs/show-font-changelog</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/show-font">https://github.com/protesilaos/show-font</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/codelog/2024-09-10-emacs-show-font-0-1-0/">https://protesilaos.com/codelog/2024-09-10-emacs-show-font-0-1-0/</a></li>
  <li>Backronym: Should Highlight Only With the Family Of the Named Typeface.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 0.4.0 on 2025-08-26</h2>

<p>This version expands the capabilities of the font preview mechanism to
handle emoji and icon fonts (i.e. those with codepoints in the Unicode
Private Use Area).</p>

<p>Both the <code class="language-plaintext highlighter-rouge">show-font-select-preview</code> and <code class="language-plaintext highlighter-rouge">show-font-tabulated</code> commands
now handle these types of font.</p>

<p>Previews for emoji or icon fonts are done using the string of
characters set to the variable <code class="language-plaintext highlighter-rouge">show-font-emoji-sample</code> or
<code class="language-plaintext highlighter-rouge">show-font-icon-sample</code>. These symbols are user options.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: in-development ‘doric-beach’ and ‘doric-valley’ themes</title>
      <description>I am developing two new themes for my minimalistic 'doric-themes' package for Emacs. These combine gold with teal hues.</description>
      <pubDate>Sun, 17 Aug 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-08-17-emacs-doric-beach-and-doric-valley-themes/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-08-17-emacs-doric-beach-and-doric-valley-themes/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I am developing two new themes for my minimalistic <code class="language-plaintext highlighter-rouge">doric-themes</code>
package for Emacs. These combine gold with teal hues. <code class="language-plaintext highlighter-rouge">doric-beach</code> is
the light theme and <code class="language-plaintext highlighter-rouge">doric-valley</code> is its dark counterpart. Here are
the screenshots:</p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-beach.png"><img alt="doric-beach theme sample" src="https://protesilaos.com/assets/images/doric/doric-beach.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-valley.png"><img alt="doric-valley theme sample" src="https://protesilaos.com/assets/images/doric/doric-valley.png" /></a></p>

<h2>Coming in version 0.4.0</h2>

<p>The character of the themes is well-defined, though I may still make some small tweaks. Expect these and other improvements to be available in the next stable version of the <code class="language-plaintext highlighter-rouge">doric-themes</code>, which I expect to publish some time before the end of August.</p>

<h2>About the Doric themes</h2>

<p>The Doric themes use few colours and will appear monochromatic in many
contexts. They are my most minimalist themes. Styles involve the
careful use of typographic features and subtleties in colour gradients
to establish a consistent rhythm.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: sxhkdrc-mode version 1.2.0</title>
      <description>Information about the latest version of my Emacs major mode for editing the Simple X Hot Key Daemon files.</description>
      <pubDate>Thu, 14 Aug 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-08-14-emacs-sxhkdrc-mode-1-2-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-08-14-emacs-sxhkdrc-mode-1-2-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This is a major mode for editing <code class="language-plaintext highlighter-rouge">sxhkdrc</code> files. SXHKD is the Simple
X Hot Key Daemon which is commonly used in minimalist desktop sessions
on Xorg (I use it with bspwm, herbstluftwm, and i3wm). The <code class="language-plaintext highlighter-rouge">sxhkdrc</code>
file configures key chords, binding them to commands. For the
technicalities, read the man page <code class="language-plaintext highlighter-rouge">sxhkd(1)</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">sxhkdrc-mode</code></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/sxhkdrc-mode">https://github.com/protesilaos/sxhkdrc-mode</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/sxhkdrc-mode">https://gitlab.com/protesilaos/sxhkdrc-mode</a></li>
    </ul>
  </li>
  <li>Backronym: Such Xenotropic Hot Keys Demonstrate Robustness and
Configurability … mode.</li>
</ul>

<hr />

<h2>1.2.0 on 2025-08-14</h2>

<p>The package is stable and gets the job done. This version introduces a
small new feature to restart the daemon from inside Emacs. Thanks to
Jonathan Neidel for making the suggestion in issue 1:
<a href="https://github.com/protesilaos/sxhkdrc-mode/issues/1">https://github.com/protesilaos/sxhkdrc-mode/issues/1</a>.</p>

<h3>Reload the SXHKD daemon on demand</h3>

<p>The command <code class="language-plaintext highlighter-rouge">sxhkdrc-mode-restart</code> sends a signal to the <code class="language-plaintext highlighter-rouge">sxhkd</code>
process which causes it to restart, thus reloading its configuration
file. Use this after modifying the <code class="language-plaintext highlighter-rouge">sxhkdrc</code> to make the new changes
available.</p>

<h3>Automatically reload the daemon on file save</h3>

<p>The function <code class="language-plaintext highlighter-rouge">sxhkdrc-mode-auto-restart</code> can be assigned to the
<code class="language-plaintext highlighter-rouge">sxhkdrc-mode-hook</code> to automatically reload the daemon after the
<code class="language-plaintext highlighter-rouge">sxhkdrc</code> file is saved (well, technically, after the file which is
using the <code class="language-plaintext highlighter-rouge">sxhkdrc-mode</code> is saved).</p>

<h3>Sample configuration with <code class="language-plaintext highlighter-rouge">use-package</code></h3>

<p>The project’s <code class="language-plaintext highlighter-rouge">README.md</code> includes this sample configuration:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">sxhkdrc-mode</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="ss">:mode</span> <span class="s">"sxhkdrc.*"</span> <span class="c1">; if you want more than just "sxhkdrc"</span>
  <span class="ss">:commands</span> <span class="p">(</span><span class="nv">sxhkdrc-mode-restart</span><span class="p">)</span>
  <span class="ss">:hook</span> <span class="p">(</span><span class="nv">sxhkdrc-mode</span> <span class="o">.</span> <span class="nv">sxhkdrc-mode-auto-restart</span><span class="p">))</span>
</code></pre></div></div>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: doric-themes version 0.3.0</title>
      <description>Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate).</description>
      <pubDate>Mon, 11 Aug 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-08-11-emacs-doric-themes-0-3-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-08-11-emacs-doric-themes-0-3-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>These are my minimalist themes. They use few colours and will appear
mostly monochromatic in many contexts. Styles involve the careful use
of typography, such as italics and bold italics.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>The new <code class="language-plaintext highlighter-rouge">oak</code> and <code class="language-plaintext highlighter-rouge">pine</code> themes</h2>

<p>These explore the woody+earthly style:</p>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">doric-oak</code> has dark text against an ochre background, with accents
of green.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">doric-pine</code> uses light text against a dark green background, with
accents of brown.</p>
  </li>
</ul>

<h2>Background colours for diffs</h2>

<p>All diff-related interfaces, including Magit, diff-mode, and Ediff,
now use colour-coded background values where appropriate. This is done
to improve usability, as it otherwise can be hard to discern the
boundaries of individual diff hunks.</p>

<h2>Alternating foreground values for message/email quotes</h2>

<p>In <code class="language-plaintext highlighter-rouge">message-mode</code>, Gnus, and related interfaces all quoted/cited
message level now conforming with an odd VS even colouring scheme. The
style is still subtle, but now the individual levels of depths are
easier to spot.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>I got the Emacs Writing Studio (EWS) book</title>
      <description>I have the Emacs Writing Studio paperback version of the book. It is nice and shows that we can use Emacs for publishing.</description>
      <pubDate>Wed, 06 Aug 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-08-06-emacs-writing-studio-book/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-08-06-emacs-writing-studio-book/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <em>Emacs Writing Studio</em> (EWS) by Peter Prevos is a configuration
for Emacs designed for writers, researchers, and scientists. It
provides an integrated environment to express one’s thoughts and
publish them in multiple formats. The book, which is produced using
EWS, documents the setup, describes relevant methods or workflows, and
explains how everything is pieced together. I contributed the foreword.</p>

<p>This morning, I got the paperback version of the book. It is a thing
of beauty!</p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-08-06-ews-front-cover.jpg"><img alt="EWS front cover" src="https://protesilaos.com/assets/images/attachments/2025-08-06-ews-front-cover.jpg" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-08-06-ews-dedication.jpg"><img alt="EWS dedication" src="https://protesilaos.com/assets/images/attachments/2025-08-06-ews-dedication.jpg" /></a></p>

<p>Thanks to Peter for working on this and for showing how Emacs can also
be used as a professional publishing tool.</p>

<h2>Emacs Writing Studio sources</h2>

<p>Buy the book, check the source code, and watch the videos:</p>

<ul>
  <li>Payhip: <a href="https://payhip.com/b/alhIJ">https://payhip.com/b/alhIJ</a></li>
  <li>e-readers: <a href="https://books2read.com/u/4NpgQ9?format=ebook">https://books2read.com/u/4NpgQ9?format=ebook</a></li>
  <li>Paperback: <a href="https://books2read.com/u/4NpgQ9?format=print">https://books2read.com/u/4NpgQ9?format=print</a></li>
  <li>LeanPub: <a href="https://leanpub.com/emacswritingstudio">https://leanpub.com/emacswritingstudio</a></li>
  <li>GitHub: <a href="https://github.com/pprevos/emacs-writing-studio/">https://github.com/pprevos/emacs-writing-studio/</a></li>
  <li>YouTube: <a href="https://www.youtube.com/playlist?list=PLGx4TR_jvOQDIT878vGDe1ElUlij3UEKI">https://www.youtube.com/playlist?list=PLGx4TR_jvOQDIT878vGDe1ElUlij3UEKI</a></li>
</ul>

<p>Also read the <em>Why Use Emacs</em> essay on Peter’s website: <a href="https://lucidmanager.org/productivity/why-use-emacs/">https://lucidmanager.org/productivity/why-use-emacs/</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: new ‘oak’ and ‘pine’ doric-themes</title>
      <description>These are two new themes for my minimalist doric-themes package for Emacs.</description>
      <pubDate>Mon, 04 Aug 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-08-04-emacs-doric-oak-pine-themes/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-08-04-emacs-doric-oak-pine-themes/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I am working on two new themes for my minimalist <code class="language-plaintext highlighter-rouge">doric-themes</code>
collection. Both explore the woody, earthly, chthonic motif. Here they
are:</p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-oak.png"><img alt="doric-oak theme sample" src="https://protesilaos.com/assets/images/doric/doric-oak.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/doric/doric-pine.png"><img alt="doric-pine theme sample" src="https://protesilaos.com/assets/images/doric/doric-pine.png" /></a></p>

<p>I may still make further refinements, though the character of the
themes is set. Once I am done, I will publish them as part of version
<code class="language-plaintext highlighter-rouge">0.3.0</code> of the package.</p>

<h2>About the Doric themes</h2>

<p>The Doric themes use few colours and will appear monochromatic in many
contexts. They are my most minimalist themes. Styles involve the
careful use of typographic features and subtleties in colour gradients
to establish a consistent rhythm.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Deep dive with @linkarzu about Emacs, NeoVim, Linux, keyboards, and philosophy</title>
      <description>A discussion for more than 2 hours with Christian in which we discuss Emacs and many other interesting topics.</description>
      <pubDate>Fri, 01 Aug 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-08-01-linkarzu-chat-emacs-neovim-philosophy/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-08-01-linkarzu-chat-emacs-neovim-philosophy/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=b4nV0jCHwGQ">https://www.youtube.com/watch?v=b4nV0jCHwGQ</a></p>
         
         <p>I had a ~2-hour-and-30-minute discussion with Christian from the
@linkarzu YouTube channel: <a href="https://www.youtube.com/@linkarzu">https://www.youtube.com/@linkarzu</a>.</p>

<p>We talked about Emacs, the underlying idea of an integrated computing
environment, how NeoVim effectively took the source of Vim and infused
with the spirit of Emacs, thinking in terms of extensibility and
cohesion, why purists cannot impose an arbitrary limit to
extensibility, and more.</p>

<p>We also discuss other interesting topics, such as Debian and Arch
Linux, how free software emphasises freedom, why it is okay to earn an
income while contributing to free software, custom keyboards and
ergonomics, my journey into computing, alcohol and substance abuse,
and other issues of everyday life.</p>

<p>Thanks to Christian for inviting me to this chat! I had a good time
and wish all the best with the @linkarzu channel!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>All my videos are mirrored on the Internet Archive (thanks to Amin Bandali)</title>
      <description>All my videos are now available on a hosting platform that respects user freedom.</description>
      <pubDate>Tue, 29 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-07-29-videos-internet-archive/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-07-29-videos-internet-archive/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>A few days ago, Amin Bandali contacted me about the prospect of
mirroring my videos to the Internet Archive. The idea is to have the
option of a video hosting platform that respects user freedom. I
agreed and confirmed the free/libre copyleft terms I share all my
publications under (GNU GPLv3+ for code, Creative Common BY-SA 4.0 for
prose, GNU FDL for my technical manuals).</p>

<p>Amin has since done the work and documented it here:
<a href="https://kelar.org/~bandali/2025/07/25/protesilaos-videos-archive.html">https://kelar.org/~bandali/2025/07/25/protesilaos-videos-archive.html</a>.
The publication also points to the Python script which performs the
requisite operations. The script relies on the source code of my
website to extract the relevant data. Amin describes the underlying
technical considerations, given the large number of videos that needed
to be downloaded from YouTube and uploaded to the Internet Archive.</p>

<p>On my part, I made a small change to the template of my website that
produces the HTML output of entries with an embedded video. Those have
links to the source on YouTube and, now, to the corresponding Internet
Archive page. For example, my latest “Prot Asks” video with Ihor, the
Emacs Org mode maintainer, is available here:
<a href="https://archive.org/details/prot-codelog-2025-07-26-prot-asks-ihor-emacs-org-maintainer-history-travel-material-science/">https://archive.org/details/prot-codelog-2025-07-26-prot-asks-ihor-emacs-org-maintainer-history-travel-material-science/</a>.</p>

<p>These “raw links”, as opposed to the embedded frame, are also helpful
for users who receive my publications via RSS/Atom feeds (and I do
share the entire blog post, by the way, rather than an excerpt because
that is the most convenient way to read RSS).</p>

<p>Thanks to Amin for this initiative!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>I will talk about Emacs on the @linkarzu YouTube channel</title>
      <description>An exchange with Christian of the @linkarzu channel on YouTube about Emacs and how I use it every day.</description>
      <pubDate>Sun, 27 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-07-27-talk-emacs-linkarzu-youtube-channel/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-07-27-talk-emacs-linkarzu-youtube-channel/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The @linkarzu channel on YouTube covers topics related to NeoVim,
terminal emulators, and Emacs, among others:
<a href="https://www.youtube.com/@linkarzu">https://www.youtube.com/@linkarzu</a>. They recently had a roundtable
about “NeoVim versus Emacs” in which two members on the side of either
community shared their thoughts and had a fun time together:
<a href="https://www.youtube.com/watch?v=SnhcXR9CKno">https://www.youtube.com/watch?v=SnhcXR9CKno</a>.</p>

<p>Christian, the author of @linkarzu, learnt about me via feedback about
the roundtable and contacted me shortly thereafter. We agreed to have
a video exchange focused on Emacs. The idea is for me to share my
thoughts on the matter and demonstrate my day-to-day workflow.</p>

<p>The live event is for paying members of @linkarzu and can be checked
here: <a href="https://www.youtube.com/live/KD9uiDdQDzI">https://www.youtube.com/live/KD9uiDdQDzI</a> (Thursday, July 31 at
15:00 Europe/Athens). The recording of the video will be available to
everyone shortly afterwards and will be free of charge.</p>

<p>Christian wanted to check with me if this practice is acceptable. I
confirmed that it is fine by me and am looking forward to a nice chat!</p>

<p>Once the video is published, I will also share it on my website.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: cursory version 1.2.0</title>
      <description>Information about the latest version of my Cursory package for GNU Emacs.</description>
      <pubDate>Tue, 22 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-07-22-emacs-cursory-1-2-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-07-22-emacs-cursory-1-2-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Cursory lets users define preset configurations for the cursor. Those
cover the style of the cursor (e.g. box or bar), whether it is
blinking or not, and how fast, as well as the colour it uses. Having
distinct presets makes it easy to switch between, say, a “reading
mode” with an ambient cursor and a “presentation mode” with a cursor
that is more noticeable and thus easier to spot.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">cursory</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/cursory">https://protesilaos.com/emacs/cursory</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/cursory-changelog">https://protesilaos.com/emacs/cursory-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/cursory">https://github.com/protesilaos/cursory</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/cursory">https://gitlab.com/protesilaos/cursory</a></li>
    </ul>
  </li>
  <li>Backronym: Cursor Usability Requires Styles Objectively Rated Yearlong.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 1.2.0 on 2025-07-22</h2>

<p>This version contains small additions to a stable package.</p>

<h3>Set the last preset when starting up Emacs</h3>

<p>The new function <code class="language-plaintext highlighter-rouge">cursory-set-last-or-fallback</code> makes it easier to set
the last known preset when starting Emacs or via a hook such as <code class="language-plaintext highlighter-rouge">after-init-hook</code>.
Internally, it takes care to fall back to a set of default values that
always work.</p>

<p>Before the introduction of <code class="language-plaintext highlighter-rouge">cursory-set-last-or-fallback</code> users had to
do something like this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Old way of setting a preset:</span>
<span class="p">(</span><span class="nv">cursory-set-preset</span> <span class="p">(</span><span class="nb">or</span> <span class="nv">cursory-last-selected-preset</span> <span class="nv">cursory-recovered-preset</span> <span class="ss">'box</span><span class="p">))</span>

<span class="c1">;; Old way of doing the above via a hook:</span>
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">()</span> <span class="p">(</span><span class="nv">cursory-set-preset</span> <span class="p">(</span><span class="nb">or</span> <span class="nv">cursory-last-selected-preset</span> <span class="nv">cursory-recovered-preset</span> <span class="ss">'box</span><span class="p">))))</span>
</code></pre></div></div>

<p>Those would also fail if the named preset did not exist (<code class="language-plaintext highlighter-rouge">box</code> in the
above example). Whereas the addition of a fallback preset guarantees a
result that works.</p>

<p>Note that I am defining the <code class="language-plaintext highlighter-rouge">cursory-fallback-preset</code> using <code class="language-plaintext highlighter-rouge">defconst</code>
instead of exposing it as a user option. This is to avoid a scenario
where the values are accidentally set incorrectly.</p>

<h3>Presets can define a <code class="language-plaintext highlighter-rouge">:cursor-color</code></h3>

<p>This is a new attribute which corresponds to the background value of
the <code class="language-plaintext highlighter-rouge">cursor</code> face.</p>

<ul>
  <li>
    <p>When the value is nil or <code class="language-plaintext highlighter-rouge">unspecified</code> (the default), Cursory does
not modify the <code class="language-plaintext highlighter-rouge">cursor</code> face.</p>
  </li>
  <li>
    <p>When the value is a hexadecimal RGB color value, like <code class="language-plaintext highlighter-rouge">#123456</code> it
is used as-is. Same if it is a named color among those produced by
the command <code class="language-plaintext highlighter-rouge">list-colors-display</code>.</p>
  </li>
  <li>
    <p>When the value is the symbol of a face (unquoted), then the
foreground of that face is used for the <code class="language-plaintext highlighter-rouge">cursor</code> face, falling back
to <code class="language-plaintext highlighter-rouge">default</code>.</p>
  </li>
</ul>

<p>Concretely, users can have something like this in their configuration:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">cursory-presets</span>
      <span class="o">'</span><span class="p">((</span><span class="nv">box</span>
         <span class="ss">:cursor-color</span> <span class="s">"#21439f"</span>
         <span class="ss">:blink-cursor-interval</span> <span class="mf">1.2</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">baring</span>
         <span class="ss">:cursor-type</span> <span class="p">(</span><span class="nv">bar</span> <span class="o">.</span> <span class="mi">2</span><span class="p">)</span>
         <span class="ss">:cursor-color</span> <span class="nb">error</span> <span class="c1">; the `error' face will typically be red (see `list-faces-display')</span>
         <span class="ss">:blink-cursor-interval</span> <span class="mf">0.8</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">underscore</span>
         <span class="ss">:cursor-color</span> <span class="s">"green"</span> <span class="c1">; see `list-colors-display'</span>
         <span class="ss">:cursor-type</span> <span class="p">(</span><span class="nv">hbar</span> <span class="o">.</span> <span class="mi">1</span><span class="p">)</span>
         <span class="ss">:blink-cursor-interval</span> <span class="mf">0.3</span>
         <span class="ss">:blink-cursor-blinks</span> <span class="mi">50</span><span class="p">)</span>
        <span class="p">(</span><span class="no">t</span> <span class="c1">; the default values</span>
         <span class="ss">:cursor-color</span> <span class="nv">unspecified</span> <span class="c1">; use the theme's original</span>
         <span class="ss">:cursor-type</span> <span class="nv">box</span>
         <span class="ss">:cursor-in-non-selected-windows</span> <span class="nv">hollow</span>
         <span class="ss">:blink-cursor-mode</span> <span class="mi">1</span>
         <span class="ss">:blink-cursor-blinks</span> <span class="mi">10</span>
         <span class="ss">:blink-cursor-interval</span> <span class="mf">0.2</span>
         <span class="ss">:blink-cursor-delay</span> <span class="mf">0.2</span><span class="p">)))</span>
</code></pre></div></div>

<p>Remember to read the documentation of <code class="language-plaintext highlighter-rouge">cursory-presets</code> for all the rest.</p>

<h3>The <code class="language-plaintext highlighter-rouge">cursory-mode</code> persists the <code class="language-plaintext highlighter-rouge">:cursor-color</code> while changing themes</h3>

<p>Before, the <code class="language-plaintext highlighter-rouge">cursory-mode</code> would only take care to save the last
selected preset and to persist it across Emacs sessions. In addition
to that, it now also ensures that loading a new theme does not
override the <code class="language-plaintext highlighter-rouge">:cursor-color</code>.</p>

<h3>The <code class="language-plaintext highlighter-rouge">cursory-set-preset</code> prompt is smarter about its default value</h3>

<p>When the <code class="language-plaintext highlighter-rouge">cursory-set-preset</code> is called interactively, it uses the
minibuffer to prompt for a preset among the <code class="language-plaintext highlighter-rouge">cursory-presets</code>.</p>

<p>In the past, its default value would simply be the last selected
preset. Cursory would not check whether that symbol was still a member
of the <code class="language-plaintext highlighter-rouge">cursory-presets</code>. This had the potential to set the wrong
configurations.</p>

<p>Now the prompt only uses as its default value the last selected and
existing preset among those found in the history of selections. It
will not provide a default if it cannot find any.</p>

<p>Note that the “default value” in the context of the minibuffer refers
to the input that will normally be provided if the user types <code class="language-plaintext highlighter-rouge">RET</code>
without writing anything into the minibuffer.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: dired-preview version 0.6.0</title>
      <description>Information about the latest version of my dired-preview package for GNU Emacs.</description>
      <pubDate>Fri, 18 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-07-18-emacs-dired-preview-0-6-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-07-18-emacs-dired-preview-0-6-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This is a simple package to automatically preview in a window the file
at point in Dired buffers. Preview windows are closed when they are no
longer relevant, while preview buffers are killed if they have not
been used for other purposes beside previewing. The package provides
several customisation options to control its behaviour.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">dired-preview</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/dired-preview">https://protesilaos.com/emacs/dired-preview</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/dired-preview">https://github.com/protesilaos/dired-preview</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/dired-preview">https://gitlab.com/protesilaos/dired-preview</a></li>
    </ul>
  </li>
  <li>Backronym: Directories Invariably Render Everything Decently …
preview; dired … PDFs Require Extra Viewing Instructions for Emacs
to Work.</li>
</ul>

<p>Below are the release notes</p>

<hr />

<h2>Version 0.6.0 on 2025-07-18</h2>

<p>This is a small release that provides quality-of-life refinements.</p>

<h3>Optionally do not trigger a preview when entering the directory</h3>

<p>The new user option <code class="language-plaintext highlighter-rouge">dired-preview-trigger-on-start</code> controls whether
a preview is produced automatically when (i) entering a directory
while (ii) the <code class="language-plaintext highlighter-rouge">dired-preview-mode</code> or its global counterpart is
enabled.</p>

<p>The default value is non-<code class="language-plaintext highlighter-rouge">nil</code>, which preserves the behaviour we have
always had of previewing outright. When set to <code class="language-plaintext highlighter-rouge">nil</code>, the preview does
not happen upon entering a directory and is triggered only after one
of the commands in <code class="language-plaintext highlighter-rouge">denote-preview-trigger-commands</code> is invoked.</p>

<p>I did this is in response to issue 31 by dasoju: <a href="https://github.com/protesilaos/dired-preview/issues/31">https://github.com/protesilaos/dired-preview/issues/31</a>.</p>

<h3>Define which commands trigger a preview</h3>

<p>The <code class="language-plaintext highlighter-rouge">denote-preview-trigger-commands</code> is now declared as a “user
option” rather than a generic variable, meaning that users are
encouraged to customise it (and it technically is available via the
Custom interface and related). Everything should otherwise work the
same as before.</p>

<h3>The preview does not interfere with <code class="language-plaintext highlighter-rouge">dired-dwim-target</code></h3>

<p>Previous versions would make <code class="language-plaintext highlighter-rouge">dired-dwim-target</code> not return the
directory of the other window. Whereas we want the preview to not
influence how Dired behaves when copying or renaming files.</p>

<p>The bug was addressed in patch release <code class="language-plaintext highlighter-rouge">0.5.2</code>.</p>

<h3>Fixed a temporary bug in <code class="language-plaintext highlighter-rouge">dired-preview-page-up</code></h3>

<p>It was missing the macro we define to perform operations in the
preview window.</p>

<p>Thanks to Alex Popescu for telling me that the command was not
working. This was done in issue 28: <a href="https://github.com/protesilaos/dired-preview/issues/28">https://github.com/protesilaos/dired-preview/issues/28</a>.</p>

<p>The bug was addressed in patch release <code class="language-plaintext highlighter-rouge">0.5.1</code>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: reorder Denote file name components</title>
      <description>Video where I explain how to use the 'denote-file-name-components-order' and retroactively make all your Denote files follow your preference.</description>
      <pubDate>Wed, 09 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-07-09-emacs-denote-reorder-components/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-07-09-emacs-denote-reorder-components/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=30uvxQMVqhg">https://www.youtube.com/watch?v=30uvxQMVqhg</a></p>
         
         <p>In this ~13-minute video I explain how to use the Denote user option
<code class="language-plaintext highlighter-rouge">denote-file-name-components-order</code>. Then I show how to retroactively
rename all the files that have the Denote file-naming scheme so that
they follow the desired order. In the process, I cover the command
<code class="language-plaintext highlighter-rouge">denote-sort-dired</code> (alias <code class="language-plaintext highlighter-rouge">denote-dired</code>), which helps produce a flat
listing of Denote files, even if they exist in subdirectories of the
<code class="language-plaintext highlighter-rouge">denote-directory</code>.</p>

<p>The code used in this video:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; The default:</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">denote-file-name-components-order</span> <span class="o">'</span><span class="p">(</span><span class="nv">identifier</span> <span class="nv">signature</span> <span class="nv">title</span> <span class="nv">keywords</span><span class="p">))</span>

<span class="c1">;; Any order will work.  Here is the one I am using for this demonstation:</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">denote-file-name-components-order</span> <span class="o">'</span><span class="p">(</span><span class="nv">identifier</span> <span class="nv">signature</span> <span class="nv">keywords</span> <span class="nv">title</span><span class="p">))</span>

<span class="c1">;; And here is another:</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">denote-file-name-components-order</span> <span class="o">'</span><span class="p">(</span><span class="nv">identifier</span> <span class="nv">keywords</span> <span class="nv">title</span> <span class="nv">signature</span><span class="p">))</span>

<span class="c1">;; And yet another one for the sake of completeness:</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">denote-file-name-components-order</span> <span class="o">'</span><span class="p">(</span><span class="nv">title</span> <span class="nv">keywords</span> <span class="nv">signature</span> <span class="nv">identifier</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot/denote-rename-all-to-reorder-components</span> <span class="p">()</span>
  <span class="s">"Call `denote-dired-rename-files' without any prompts.
In other words, preserve the value of each Denote file name component.

Use this command if you wish to modify the user option
`denote-file-name-components-order' and then want your existing Denote
files to retroactively follow that order."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">denote-prompts</span> <span class="no">nil</span><span class="p">))</span>
    <span class="p">(</span><span class="nv">call-interactively</span> <span class="ss">'denote-dired-rename-files</span><span class="p">)))</span>
</code></pre></div></div>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: mct version 1.1.0</title>
      <description>Information about the latest version of my mct package for GNU Emacs.</description>
      <pubDate>Mon, 07 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-07-07-emacs-mct-1-1-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-07-07-emacs-mct-1-1-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Opinionated changes and enhancements to the default minibuffer
completion UI of Emacs:</p>

<ul>
  <li>
    <p>Live completions to update the results as you type.</p>
  </li>
  <li>
    <p>Passlist and blocklist of commands or completion categories to
control whether the <code class="language-plaintext highlighter-rouge">*Completions*</code> buffer shows up eagerly.</p>
  </li>
  <li>
    <p>Other relevant options to control when the <code class="language-plaintext highlighter-rouge">*Completions*</code> are
displayed.</p>
  </li>
  <li>
    <p>Per command or completion category sorting methods.</p>
  </li>
  <li>
    <p>A cleaner <code class="language-plaintext highlighter-rouge">*Completions*</code> buffer, optionally without a mode line.</p>
  </li>
  <li>
    <p>Commands to cycle from the minibuffer to the <code class="language-plaintext highlighter-rouge">*Completions*</code> and
vice versa.</p>
  </li>
</ul>

<p>In essence, MCT is (i) a layer of interactivity on top of the
out-of-the-box completion experience, and (ii) glue code that
combines built-in functionalities to make the default completion
framework work like that of more featureful third-party options.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">mct</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/mct">https://protesilaos.com/emacs/mct</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/mct-changelog">https://protesilaos.com/emacs/mct-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/mct">https://github.com/protesilaos/mct</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/mct">https://gitlab.com/protesilaos/mct</a></li>
    </ul>
  </li>
  <li>Video demo: <a href="https://protesilaos.com/codelog/2021-10-22-emacs-mct-demo/">https://protesilaos.com/codelog/2021-10-22-emacs-mct-demo/</a></li>
  <li>Backronym: Minibuffer Confines Transcended; Minibuffer and
Completions in Tandem.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 1.1.0 on 2025-07-07</h2>

<p>This version contains several refinements to an already stable package.</p>

<h3>Sort by command or completion category</h3>

<p>The new user option <code class="language-plaintext highlighter-rouge">mct-sort-by-command-or-category</code> determines how
completion candidates are sorted.</p>

<p>This is an alist where each element is of the form <code class="language-plaintext highlighter-rouge">(SYMBOLS . SORT-FUNCTION)</code>.</p>

<p><code class="language-plaintext highlighter-rouge">SYMBOLS</code> is either a symbol or a list of symbols. <code class="language-plaintext highlighter-rouge">SYMBOLS</code> can refer
to the symbol of a function or completion category. It can also be <code class="language-plaintext highlighter-rouge">t</code>,
which refers to the fallback value.</p>

<p><code class="language-plaintext highlighter-rouge">SORT-FUNCTION</code> is a function that takes a list of strings and returns a
list of strings, sorting them accordingly.  Examples of a <code class="language-plaintext highlighter-rouge">SORT-FUNCTION</code>
are:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">mct-sort-by-alpha</code></li>
  <li><code class="language-plaintext highlighter-rouge">mct-sort-by-alpha-then-by-length</code></li>
  <li><code class="language-plaintext highlighter-rouge">mct-sort-by-history</code></li>
  <li><code class="language-plaintext highlighter-rouge">mct-sort-by-directory-then-by-file</code></li>
</ul>

<p>To not perform any sorting on the completion candidates that match
<code class="language-plaintext highlighter-rouge">SYMBOLS</code> set <code class="language-plaintext highlighter-rouge">SORT-FUNCTION</code> to nil.</p>

<p>If there are conflicting configurations between a <code class="language-plaintext highlighter-rouge">SYMBOLS</code> function and
completion category, then the function takes precedence (for example
<code class="language-plaintext highlighter-rouge">find-file</code> is set to sort directories first whereas the <code class="language-plaintext highlighter-rouge">file</code>
completion category is set to sort by history).</p>

<h3>Optional indicator for <code class="language-plaintext highlighter-rouge">completing-read-multiple</code></h3>

<p>Users of Emacs prior to version 31 do not have a built-in way to
inform them when they are dealing with a <code class="language-plaintext highlighter-rouge">completing-read-multiple</code>
minibuffer prompt. Emacs 31 introduces the user option <code class="language-plaintext highlighter-rouge">crm-prompt</code>
and its related functionality to tell the user what they need to know.</p>

<p>The <code class="language-plaintext highlighter-rouge">mct-completing-read-multiple-indicator</code> can be used in the
meantime to achieve the same results. It is set to a non-nil value by
default. Opt out by changing it to nil.</p>

<h3>The <code class="language-plaintext highlighter-rouge">*Completions*</code> are persistent when needed</h3>

<p>This concerns the case where a command or completion category is part
of the <code class="language-plaintext highlighter-rouge">mct-completion-passlist</code> or when the user option
<code class="language-plaintext highlighter-rouge">mct-live-completion</code> is set to non-nil or <code class="language-plaintext highlighter-rouge">visible</code>. In such cases,
the completion candidates are on display and we want to keep them
there while performing a dynamic completion, such as with the
<code class="language-plaintext highlighter-rouge">find-file</code> command (“dynamic” in the sense that it returns a new list
of candidates to match the current path).</p>

<p>Persisting the <code class="language-plaintext highlighter-rouge">*Completions*</code> means that as we narrow the list, we
still see all the matching results.</p>

<p>In the past, we provided the option <code class="language-plaintext highlighter-rouge">mct-persist-dynamic-completion</code>
though we do not need it anymore.</p>

<p>I was inspired to make this change in response to a question posed by
Ryan Davis regarding the behaviour of <code class="language-plaintext highlighter-rouge">mct-persist-dynamic-completion</code>.
This was done in issue 7: <a href="https://github.com/protesilaos/mct/issues/7">https://github.com/protesilaos/mct/issues/7</a>.</p>

<h3>Miscellaneous</h3>

<ul>
  <li>
    <p>Vertical alignment of the <code class="language-plaintext highlighter-rouge">*Completions*</code> buffer is more precise.
Thanks to Jessie Hu for the contribution in pull request 6:
<a href="https://github.com/protesilaos/mct/pull/6">https://github.com/protesilaos/mct/pull/6</a>.</p>
  </li>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">mct-choose-completion-exit</code> no longer tries to expand
further. In the previous implementation it would try to match the
last known selection from the history when using a file prompt. For
example we have this workflow:</p>

    <ul>
      <li>In the previous prompt we type <code class="language-plaintext highlighter-rouge">/path/to/file/</code> and exit.</li>
      <li>Now we type <code class="language-plaintext highlighter-rouge">/pa</code>, the completions pop up, we select <code class="language-plaintext highlighter-rouge">/path</code> and
invoke <code class="language-plaintext highlighter-rouge">mct-choose-completion-exit</code>. This wrongly expands into
<code class="language-plaintext highlighter-rouge">/path/foo/</code> instead of taking just <code class="language-plaintext highlighter-rouge">/path</code> (given that it has no
further input to determine an extension of that string).</li>
    </ul>

    <p>Now the command will do the right thing based on the user’s input.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: doric-themes version 0.2.0</title>
      <description>Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate).</description>
      <pubDate>Sat, 05 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-07-05-emacs-doric-themes-0-2-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-07-05-emacs-doric-themes-0-2-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>These are my minimalist themes. They use few colours and will appear
mostly monochromatic in many contexts. Styles involve the careful use
of typography, such as italics and bold italics.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 0.2.0 on 2025-07-05</h2>

<p>This version introduces several refinements to the individual themes
comprising the Doric themes collection. Changes pertain to the
intensity of colours in use. While each tweak is small, their
cumulative effect contributes to a more consistent design.</p>

<p>Users who are interested in the contrast ratio values and relevant
colour distance can refer to the <code class="language-plaintext highlighter-rouge">contrasts.org</code> file that is part of
the project’s Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a>.</p>

<p>I extended support for several faces or face groups including:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">ace-window</code></li>
  <li><code class="language-plaintext highlighter-rouge">dictionary</code></li>
  <li><code class="language-plaintext highlighter-rouge">embark-keybinding</code></li>
  <li><code class="language-plaintext highlighter-rouge">man</code></li>
  <li><code class="language-plaintext highlighter-rouge">markdown-metadata-key-face</code></li>
  <li><code class="language-plaintext highlighter-rouge">package-mark-delete-line</code></li>
  <li><code class="language-plaintext highlighter-rouge">package-mark-install-line</code></li>
  <li><code class="language-plaintext highlighter-rouge">read-multiple-choice-face</code></li>
  <li><code class="language-plaintext highlighter-rouge">rcirc</code></li>
  <li><code class="language-plaintext highlighter-rouge">spacious-padding</code></li>
  <li><code class="language-plaintext highlighter-rouge">textsec-suspicious</code></li>
  <li><code class="language-plaintext highlighter-rouge">which-key-key-face</code></li>
  <li><code class="language-plaintext highlighter-rouge">woman</code></li>
</ul>

<p>Some other faces that were already covered are revised in the interest
of theme-wide consistency. Again, changes are subtle.</p>

<p>The colour of the directory icons in <code class="language-plaintext highlighter-rouge">all-the-icons</code> and <code class="language-plaintext highlighter-rouge">nerd-icons</code>
packages is toned down a little bit to avoid exaggerations.</p>

<p>Several spacing-sensitive faces, like Org tables and code blocks,
unconditionally inherit the <code class="language-plaintext highlighter-rouge">fixed-pitch</code> face. This means that, in
principle, they are rendered in a monospaced font even when the user
activates <code class="language-plaintext highlighter-rouge">variable-pitch-mode</code> or sets the <code class="language-plaintext highlighter-rouge">default</code> face to a
proportionately spaced typeface. Users who need to specify the
applicable font family can either use the following, mutatis mutandis,
or take a look at my <code class="language-plaintext highlighter-rouge">fontaine</code> package:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:family</span> <span class="s">"Aporetic Sans Mono"</span> <span class="ss">:height</span> <span class="mi">160</span><span class="p">)</span>
<span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'variable-pitch</span> <span class="no">nil</span> <span class="ss">:family</span> <span class="s">"Aporetic Sans"</span> <span class="ss">:height</span> <span class="mf">1.0</span><span class="p">)</span>
<span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'fixed-pitch</span> <span class="no">nil</span> <span class="ss">:family</span> <span class="s">"Aporetic Sans Mono"</span> <span class="ss">:height</span> <span class="mf">1.0</span><span class="p">)</span>
</code></pre></div></div>

<p>Other theme packages of mine have an option for “mixed fonts” (like
<code class="language-plaintext highlighter-rouge">modus-themes-mixed-fonts</code>), but I think I will not be providing
options for the Doric themes. At least not for the time being while I
explore the design space for minimalist themes.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: beframe version 1.4.0</title>
      <description>Information about the latest version of my beframe package for GNU Emacs.</description>
      <pubDate>Sat, 28 Jun 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-06-28-emacs-beframe-1-4-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-06-28-emacs-beframe-1-4-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p><code class="language-plaintext highlighter-rouge">beframe</code> enables a frame-oriented Emacs workflow where each frame has
access only to the list of buffers visited therein. In the interest of
brevity, we call buffers that belong to frames “beframed”.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">beframe</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/beframe">https://protesilaos.com/emacs/beframe</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/beframe-changelog">https://protesilaos.com/emacs/beframe-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/beframe">https://github.com/protesilaos/beframe</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/beframe">https://gitlab.com/protesilaos/beframe</a></li>
    </ul>
  </li>
  <li>Video demo: <a href="https://protesilaos.com/codelog/2023-02-28-emacs-beframe-demo/">https://protesilaos.com/codelog/2023-02-28-emacs-beframe-demo/</a></li>
  <li>Backronym: Buffers Encapsulated in Frames Realise Advanced
Management of Emacs.</li>
</ul>

<p>Below are the release notes</p>

<hr />

<h2>Version 1.4.0 on 2025-06-28</h2>

<p>This version adds some minor improvements to a stable package.</p>

<h3>Per-frame Xref histories</h3>

<p>The built-in Xref mechanism is typically used to navigate to the
definition of the symbol at point in a programming major mode. The
command <code class="language-plaintext highlighter-rouge">xref-find-definitions</code> (<code class="language-plaintext highlighter-rouge">M-.</code> by default) jumps to the
source, while <code class="language-plaintext highlighter-rouge">xref-go-back</code> (<code class="language-plaintext highlighter-rouge">M-,</code> by default) goes back in the
history of visited positions until it reaches the starting point.</p>

<p>When <code class="language-plaintext highlighter-rouge">beframe-mode</code> is enabled, each new frame has its own Xref
history. This means that finding a definition in one frame does not
interfere with the Xref history of another frame.</p>

<h3>“Beframed” buffer prompt text is now optional</h3>

<p>When <code class="language-plaintext highlighter-rouge">beframe-mode</code> is enabled, it sets the standard
<code class="language-plaintext highlighter-rouge">read-buffer-function</code> to one that filters buffers by frame. Any
command that uses that, such as <code class="language-plaintext highlighter-rouge">switch-to-buffer</code> (<code class="language-plaintext highlighter-rouge">C-x b</code> by
default) is thus beframing its completion candidates.</p>

<p>Such prompts get a prefix to inform the user of their behaviour. By
default this is <code class="language-plaintext highlighter-rouge">[Beframed]</code>: it is subject to the user option <code class="language-plaintext highlighter-rouge">beframe-prompt-prefix</code>.
Users who do not wish to have any prefix can set this option to nil or
an empty string.</p>

<p>When there is a string, it is styled with the face <code class="language-plaintext highlighter-rouge">beframe-face-prompt-prefix</code>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: modus-themes version 4.8.0</title>
      <description>Information about the latest version of my highly accessible themes for GNU Emacs.</description>
      <pubDate>Wed, 11 Jun 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-06-11-emacs-modus-themes-4-8-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-06-11-emacs-modus-themes-4-8-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just published the latest stable release of <a href="https://protesilaos.com/emacs/modus-themes">the Modus
themes</a>. The change log
entry is reproduced further below. For any questions, you are welcome
to <a href="https://protesilaos.com/contact/">contact me</a>. I will now work to
apply these same changes to emacs.git, so please wait a little longer
for the updates to trickle down to you.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">modus-themes</code> (also built into Emacs 28+)</li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/modus-themes-changelog">https://protesilaos.com/emacs/modus-themes-changelog</a></li>
  <li>Colour palette: <a href="https://protesilaos.com/emacs/modus-themes-colors">https://protesilaos.com/emacs/modus-themes-colors</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/modus-themes-pictures">https://protesilaos.com/emacs/modus-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/modus-themes">https://github.com/protesilaos/modus-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/modus-themes">https://gitlab.com/protesilaos/modus-themes</a></li>
    </ul>
  </li>
  <li>Backronym: My Old Display Unexpectedly Sharpened … themes.</li>
</ul>

<hr />

<h2>4.8.0 on 2025-06-11</h2>

<p>This is a small release that corrects a mistake I made in the previous
version. It also introduces some minor refinements.</p>

<h3>Matching parentheses are easy to spot</h3>

<p>In version <code class="language-plaintext highlighter-rouge">4.7.0</code>, I made the mistake of merging some stylistic
tweaks to <code class="language-plaintext highlighter-rouge">show-paren-mode</code> that I was experimenting with. The idea
was to get a feel for how the subtle colouration of matching
delimiters affects the usability of the themes. In short, it is not a
good default for our purposes (though users have the option to
override the applicable colours, as explained in the Modus themes
manual).</p>

<p>Thanks to Morgan Willcock for reporting the unwanted change in issue
139: <a href="https://github.com/protesilaos/modus-themes/issues/139">https://github.com/protesilaos/modus-themes/issues/139</a>.</p>

<h3>The <code class="language-plaintext highlighter-rouge">bg-paren-match</code> of <code class="language-plaintext highlighter-rouge">modus-vivendi-tinted</code> is a bit greener</h3>

<p>We go from <code class="language-plaintext highlighter-rouge">#5f789f</code> to <code class="language-plaintext highlighter-rouge">#4f7f9f</code>. The latter fits better with the
rest of the theme.</p>

<h3>Refined the “mail” semantic mappings of the tinted themes</h3>

<p>This concerns <code class="language-plaintext highlighter-rouge">message.el</code> and anything building on top of it, like
Gnus, Mu4e, and Notmuch. I made <code class="language-plaintext highlighter-rouge">modus-operandi-tinted</code> and
<code class="language-plaintext highlighter-rouge">modus-vivendi-tinted</code> use two colours that are more in line with the
established patterns of their respective theme. The changes are small,
but contribute to a more consistent experience.</p>

<h3>A new <code class="language-plaintext highlighter-rouge">property</code> semantic mapping is available</h3>

<p>By default, it uses the same colour as the <code class="language-plaintext highlighter-rouge">variable</code>. Users who want
to have more refined colouration in supported modes (typically
involving tree-sitter), can change the relevant “palette overrides”
user option we provide, such as <code class="language-plaintext highlighter-rouge">modus-themes-common-palette-overrides</code>
or <code class="language-plaintext highlighter-rouge">modus-operandi-palette-overrides</code> and related.</p>

<p>Thanks to Alexandr Semenov for requesting this in issue 141:
<a href="https://github.com/protesilaos/modus-themes/issues/141">https://github.com/protesilaos/modus-themes/issues/141</a>.</p>

<h3>My <code class="language-plaintext highlighter-rouge">tmr</code> package is now supported</h3>

<p>Its faces were already consistent with the Modus themes, though now I
cover them at the theme level to subject them to palette overrides.</p>

<h3>The “ancient” Gnus messages are styled properly</h3>

<p>Those are only ever seen if the user configures Gnus in a certain way
and follows a specific workflow. They now get a subtle foreground
value. This is in response to the issue 119 by sivaramn:
<a href="https://github.com/protesilaos/modus-themes/issues/119">https://github.com/protesilaos/modus-themes/issues/119</a>.</p>

<h3>The <code class="language-plaintext highlighter-rouge">modus-themes-rotate</code> command can now go backwards</h3>

<p>When called with a prefix argument (<code class="language-plaintext highlighter-rouge">C-u</code> by default), this command
will rotate the <code class="language-plaintext highlighter-rouge">modus-themes-to-rotate</code> from right to left.
Otherwise, it goes from left to right.</p>

<p>Thanks to Jacob S. Gordon for the contribution. It was sent as a
patch as part of issue 143:
<a href="https://github.com/protesilaos/modus-themes/issues/143">https://github.com/protesilaos/modus-themes/issues/143</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: spacious-padding version 0.7.0</title>
      <description>Information about the latest version of my 'spacious-padding' package for GNU Emacs.</description>
      <pubDate>Sun, 01 Jun 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-06-01-emacs-spacious-padding-0-7-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-06-01-emacs-spacious-padding-0-7-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This is a small release that makes <code class="language-plaintext highlighter-rouge">spacious-padding-mode</code> work as
intended when used in tandem with the Emacs daemon and subsequent
calls to <code class="language-plaintext highlighter-rouge">emacsclient -c</code>. I made the function responsible for
triggering the “spacious padding” effects work with individual frames
and then I responded to issue 33 by Lou Woell about integrating that
with the <code class="language-plaintext highlighter-rouge">server-after-make-frame-hook</code>: <a href="https://github.com/protesilaos/spacious-padding/issues/33">https://github.com/protesilaos/spacious-padding/issues/33</a>.</p>

<p>Additionally, the package now defines two faces that can be used to
configure the user option <code class="language-plaintext highlighter-rouge">spacious-padding-subtle-mode-line</code> (read
its documentation string for all the possible values it accepts).</p>

<p>Here is how they can be set (default value is <code class="language-plaintext highlighter-rouge">nil</code>):</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">spacious-padding-subtle-mode-line</span>
      <span class="o">'</span><span class="p">(</span> <span class="ss">:mode-line-active</span> <span class="nv">spacious-padding-subtle-mode-line-active</span>
         <span class="ss">:mode-line-inactive</span> <span class="nv">spacious-padding-subtle-mode-line-inactive</span><span class="p">))</span>
</code></pre></div></div>

<p>Reload the <code class="language-plaintext highlighter-rouge">spacious-padding-mode</code> for changes to take effect.</p>

<p>When configured this way and with default styles they make the mode
line use a minimalist overline with no background colour. The active
mode line has a more noticeable border than the inactive ones. All my
themes are designed to support this aesthetic (though themes can style
those faces as they see fit).</p>

<h2>About Spacious Padding</h2>

<p>This package provides a global minor mode to increase the
spacing/padding of Emacs windows and frames.  The idea is to make
editing and reading feel more comfortable.  Enable the mode with <code class="language-plaintext highlighter-rouge">M-x
spacious-padding-mode</code>.  Adjust the exact spacing values by modifying
the user option <code class="language-plaintext highlighter-rouge">spacious-padding-widths</code>.</p>

<p>Inspiration for this package comes from <a href="https://github.com/rougier">Nicolas Rougier’s impressive
designs</a> and <a href="https://github.com/minad/org-modern">Daniel Mendler’s
<code class="language-plaintext highlighter-rouge">org-modern</code> package</a>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">spacious-padding</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/spacious-padding">https://protesilaos.com/emacs/spacious-padding</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/spacious-padding">https://protesilaos.com/emacs/spacious-padding</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/spacious-padding">https://github.com/protesilaos/spacious-padding</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/spacious-padding">https://gitlab.com/protesilaos/spacious-padding</a></li>
    </ul>
  </li>
  <li>Sample images:
    <ul>
      <li><a href="https://protesilaos.com/codelog/2023-06-03-emacs-spacious-padding/">https://protesilaos.com/codelog/2023-06-03-emacs-spacious-padding/</a></li>
      <li><a href="https://protesilaos.com/codelog/2023-11-15-spacious-padding-extra-ui-dev/">https://protesilaos.com/codelog/2023-11-15-spacious-padding-extra-ui-dev/</a></li>
    </ul>
  </li>
  <li>Backronyms: Space Perception Adjusted Consistently Impacts Overall
Usability State … padding; Spacious … Precise Adjustments to
Desktop Divider Internals Neatly Generated.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: doric-themes version 0.1.0</title>
      <description>Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate).</description>
      <pubDate>Tue, 27 May 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-05-27-emacs-doric-themes-0-1-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-05-27-emacs-doric-themes-0-1-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just published the first stable version of my new minimalist themes
for Emascs. The Doric themes use few colours and will appear
monochromatic in many contexts. Styles involve the careful use of
typographic features and subtleties in colour gradients to establish a
consistent rhythm.</p>

<p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code>
package. For something in-between, which I would consider the best
“default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li>
  <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li>
  <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li>
</ul>

<p>Below are sample screen shots. The typefaces on display come from my
<a href="https://github.com/protesilaos/aporetic">Aporetic fonts</a>.</p>

<h2>Samples</h2>

<h3>doric-cherry</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-cherry.png"><img alt="doric-cherry theme sample" src="https://protesilaos.com/assets/images/doric/doric-cherry.png" /></a></p>

<h3>doric-earth</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-earth.png"><img alt="doric-earth theme sample" src="https://protesilaos.com/assets/images/doric/doric-earth.png" /></a></p>

<h3>doric-light</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-light.png"><img alt="doric-light theme sample" src="https://protesilaos.com/assets/images/doric/doric-light.png" /></a></p>

<h3>doric-marble</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-marble.png"><img alt="doric-marble theme sample" src="https://protesilaos.com/assets/images/doric/doric-marble.png" /></a></p>

<h3>doric-wind</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-wind.png"><img alt="doric-wind theme sample" src="https://protesilaos.com/assets/images/doric/doric-wind.png" /></a></p>

<h3>doric-dark</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-dark.png"><img alt="doric-dark theme sample" src="https://protesilaos.com/assets/images/doric/doric-dark.png" /></a></p>

<h3>doric-fire</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-fire.png"><img alt="doric-fire theme sample" src="https://protesilaos.com/assets/images/doric/doric-fire.png" /></a></p>

<h3>doric-obsidian</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-obsidian.png"><img alt="doric-obsidian theme sample" src="https://protesilaos.com/assets/images/doric/doric-obsidian.png" /></a></p>

<h3>doric-plum</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-plum.png"><img alt="doric-plum theme sample" src="https://protesilaos.com/assets/images/doric/doric-plum.png" /></a></p>

<h3>doric-water</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-water.png"><img alt="doric-water theme sample" src="https://protesilaos.com/assets/images/doric/doric-water.png" /></a></p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: live package maintenance (denote, doric-themes, etc.) today 2025-05-21 at 11:00 Europe/Athens time</title>
      <description>I am doing a live stream today where I will be maintaining some of my packages for Emacs.</description>
      <pubDate>Wed, 21 May 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-05-21-emacs-live-denote-doric-themes/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-05-21-emacs-live-denote-doric-themes/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=JCgI54VxuK0">https://www.youtube.com/watch?v=JCgI54VxuK0</a></p>
         
         <p>At 11:00 AM Europe/Athens, I will start streaming my work on some of
the Emacs packages I have authored and maintain. I will engage with
the chat, if there are any comments, but my focus will be on the code.</p>

<p>The packages I plan to cover are denote, denote-org, denote-sequence,
doric-themes. Depending on how it goes, I will work on more of my
packages.</p>

<p><strong>The video will be recorded and can be watched later.</strong></p>

<p>All my Emacs-related work: <a href="https://protesilaos.com/emacs">https://protesilaos.com/emacs</a>.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: my new Doric themes</title>
      <description>Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate).</description>
      <pubDate>Tue, 13 May 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-05-13-emacs-doric-themes/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-05-13-emacs-doric-themes/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <code class="language-plaintext highlighter-rouge">doric-themes</code> is my new in-development package for Emacs. It is a set of themes that conform with a minimalist aesthetic: they use few colours and appear monochromatic in many contexts. Below are the screen shots.</p>

<p>In terms of my overall theme work for Emacs, the <code class="language-plaintext highlighter-rouge">doric-themes</code> are the most minimalist, <code class="language-plaintext highlighter-rouge">ef-themes</code> the most maximalist, and the <code class="language-plaintext highlighter-rouge">modus-themes</code> remain what I consider the best “default theme” style. All of them are designed to be highly legible.</p>

<p>I plan to add <code class="language-plaintext highlighter-rouge">doric-themes</code> to GNU ELPA within the next days. For the time being, they are only available from source code: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a>.</p>

<p>Finally, the backronym for “Doric” is “Doric Only Really Intensifies Conservatively”.</p>

<p>Enjoy your new theme!</p>

<h2>Samples</h2>

<h3>doric-light</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-light.png"><img alt="doric-light theme sample" src="https://protesilaos.com/assets/images/doric/doric-light.png" /></a></p>

<h3>doric-marble</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-marble.png"><img alt="doric-marble theme sample" src="https://protesilaos.com/assets/images/doric/doric-marble.png" /></a></p>

<h3>doric-earth</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-earth.png"><img alt="doric-earth theme sample" src="https://protesilaos.com/assets/images/doric/doric-earth.png" /></a></p>

<h3>doric-wind</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-wind.png"><img alt="doric-wind theme sample" src="https://protesilaos.com/assets/images/doric/doric-wind.png" /></a></p>

<h3>doric-dark</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-dark.png"><img alt="doric-dark theme sample" src="https://protesilaos.com/assets/images/doric/doric-dark.png" /></a></p>

<h3>doric-obsidian</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-obsidian.png"><img alt="doric-obsidian theme sample" src="https://protesilaos.com/assets/images/doric/doric-obsidian.png" /></a></p>

<h3>doric-fire</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-fire.png"><img alt="doric-fire theme sample" src="https://protesilaos.com/assets/images/doric/doric-fire.png" /></a></p>

<h3>doric-water</h3>

<p><a href="https://protesilaos.com/assets/images/doric/doric-water.png"><img alt="doric-water theme sample" src="https://protesilaos.com/assets/images/doric/doric-water.png" /></a></p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Live @ 2025-05-11, 14:00 Europe/Athens: ‘Ask Me Anything’ about Emacs, Linux, and Life in general</title>
      <description>I will do a live stream where I answer all questions from the people in the chat. The event will be recorded.</description>
      <pubDate>Fri, 09 May 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-05-09-live-stream-emacs-linux-life/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-05-09-live-stream-emacs-linux-life/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=0N7vshEYOok">https://www.youtube.com/watch?v=0N7vshEYOok</a></p>
         
         <p>On Sunday, the 11th of May 2025, at 14:00 o’clock of time zone
Europe/Athens, I will do a live stream where I will answer every
question posted in the chat. The idea is to cover any of the topics I
already write/talk about on my website, including Emacs, my recently
published “Emacs Lisp Elements” free book, libre software, politics,
philosophy, and everyday affairs.</p>

<p>I will answer every question from top to bottom to the best of my
abilities and will not give any of those formulaic non-answers. No
tricks; no gimmicks!</p>

<p>The plan is to do a minimum of two hours, but may extend it for at
least one or two more hours depending on the participation in the
chat.</p>

<p>The event will be recorded: no worries if you cannot make it live.</p>

<p>Talk to all of you soon!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: ef-themes version 1.10.0</title>
      <description>Information about the latest version of my colourful-yet-legible themes for GNU Emacs.</description>
      <pubDate>Tue, 29 Apr 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-04-29-emacs-ef-themes-1-10-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-04-29-emacs-ef-themes-1-10-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The <code class="language-plaintext highlighter-rouge">ef-themes</code> are a collection of light and dark themes for GNU
Emacs that provide colourful (“pretty”) yet legible options for users
who want something with a bit more flair than the <code class="language-plaintext highlighter-rouge">modus-themes</code> (also
designed by me).</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">ef-themes</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/ef-themes">https://protesilaos.com/emacs/ef-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/ef-themes-changelog">https://protesilaos.com/emacs/ef-themes-changelog</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/ef-themes-pictures">https://protesilaos.com/emacs/ef-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/ef-themes">https://github.com/protesilaos/ef-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/ef-themes">https://gitlab.com/protesilaos/ef-themes</a></li>
    </ul>
  </li>
  <li>Backronym: Eclectic Fashion in Themes Hides Exaggerated Markings,
Embellishments, and Sparkles.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 1.10.0 on 2025-04-29</h2>

<p>This version introduces minor refinements to an already stable
package.</p>

<h3>The palette preview uses a tabulated interface</h3>

<p>The commands <code class="language-plaintext highlighter-rouge">ef-themes-preview-colors</code> and <code class="language-plaintext highlighter-rouge">ef-themes-preview-colors-current</code>
produce a preview of the given theme’s palette. In the past, we were
using a bespoke buffer for this task, just how the built-in command
<code class="language-plaintext highlighter-rouge">list-colors-display</code> does it.</p>

<p>Now we rely on the built-in <code class="language-plaintext highlighter-rouge">tabulated-list-mode</code> to get a cleaner
tabulated view. Plus, users can sort by column.</p>

<h3>Support for more faces or face groups</h3>

<ul>
  <li>
    <p>Added support for my <code class="language-plaintext highlighter-rouge">tmr</code> package. This will be especially
noticeable in its tabulated view (used to show timers, with the
command <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code> (alias <code class="language-plaintext highlighter-rouge">tmr-list-timers</code>)).</p>
  </li>
  <li>
    <p>Added explicit support for my <code class="language-plaintext highlighter-rouge">spacious-padding</code> package.
Specifically, this is for the faces <code class="language-plaintext highlighter-rouge">spacious-padding-subtle-mode-line-active</code>
and <code class="language-plaintext highlighter-rouge">spacious-padding-subtle-mode-line-inactive</code>. Those can be
configured as part of the user option <code class="language-plaintext highlighter-rouge">spacious-padding-subtle-mode-line</code>.</p>

    <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">spacious-padding-subtle-mode-line</span>
      <span class="o">'</span><span class="p">(</span> <span class="ss">:mode-line-active</span> <span class="nv">spacious-padding-subtle-mode-line-active</span>
         <span class="ss">:mode-line-inactive</span> <span class="nv">spacious-padding-subtle-mode-line-inactive</span><span class="p">))</span>
</code></pre></div>    </div>
  </li>
  <li>
    <p>Made the <code class="language-plaintext highlighter-rouge">helpful</code> headings use whatever the style of level 1
headings is, as defined by the user option <code class="language-plaintext highlighter-rouge">ef-themes-heading</code>.
Thanks to John Haman for applying the relevant code we have for the
<code class="language-plaintext highlighter-rouge">modus-themes</code>. The change is small (and comes from my <code class="language-plaintext highlighter-rouge">modus-themes</code>,
anyway), meaning that John does not need to assign copyright to the
Free Software Foundation.</p>
  </li>
  <li>
    <p>Added support for the <code class="language-plaintext highlighter-rouge">howm</code> package.</p>
  </li>
  <li>
    <p>Extended support for the <code class="language-plaintext highlighter-rouge">auto-dim-other-buffers</code> package to include
its <code class="language-plaintext highlighter-rouge">auto-dim-other-buffers-hide-face</code>.</p>
  </li>
  <li>
    <p>Made sure that all new <code class="language-plaintext highlighter-rouge">transient</code> faces conform with the design
priorities of the themes. Concretely, this means that they do not
support any colour-coding: all keys look the same, regardless of
whether they mean “continue”, “exit”, or anything else.
Colour-coding with a full spectrum of colours cannot be accessible
(and I do not believe colour-coding alone even works because the
colours have nothing else to be associated with, like how a red line
in a diff buffer also goes together with the minus sign).</p>

    <p>Thanks to Kevin Fleming for including the <code class="language-plaintext highlighter-rouge">transient-key-stack</code> face
that I had originally missed. This was done in pull request 54:
<a href="https://github.com/protesilaos/ef-themes/pull/54">https://github.com/protesilaos/ef-themes/pull/54</a>. The change is
small, meaning that Kevin does not need to assign copyright to the
Free Software Foundation</p>
  </li>
  <li>
    <p>Extended support for <code class="language-plaintext highlighter-rouge">adoc-mode</code> courtesy of Leilei332. This was
done in pull request 52: <a href="https://github.com/protesilaos/ef-themes/pull/52">https://github.com/protesilaos/ef-themes/pull/52</a>.</p>

    <p>The change is within the ~15-line limit, meaning that its author does
not need to assign copyright to the Free Software Foundation.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Aporetic fonts version 1.2.0</title>
      <description>Release notes for the latest version of my custom 'Aporetic' fonts.</description>
      <pubDate>Sun, 27 Apr 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-04-27-aporetic-fonts-version-1-2-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-04-27-aporetic-fonts-version-1-2-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Customised build of the Iosevka typeface, with a consistent rounded
style and overrides for almost all individual glyphs in both upright
(roman) and slanted (italic) variants. This is the successor to my
now-discontinued “Iosevka Comfy” fonts.</p>

<ul>
  <li>Git repository: <a href="https://github.com/protesilaos/aporetic">https://github.com/protesilaos/aporetic</a>.</li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/aporetic-fonts-pictures">https://protesilaos.com/emacs/aporetic-fonts-pictures</a></li>
  <li>Backronym: Aporetic’s Predecessor Objects’ Reserved Eponym Truly Included “Comfy”.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<p>The major change for this release is that Aporetic Sans Mono and
Aporetic Serif Mono are rendered in a strictly monospaced width. This
means that characters such as the em dash (<code class="language-plaintext highlighter-rouge">—</code>) occupy the same space
as the regular dash.</p>

<p>Before, Aporetic Sans Mono and Aporetic Serif Mono had some characters
that were proportionately spaced. This would upset the expectations of
terminal emulators and thus break the display, sometimes with
characters overlapping when they should not.</p>

<p>Other changes are more subtle. They pertain to the style of individual
characters, namely:</p>

<ul>
  <li>
    <p>The Greek lower case lambda (<code class="language-plaintext highlighter-rouge">λ</code>) has a flat top instead of a straight
one. The legs remain straight. This makes it consistent with the
design of the Greek lower case delta (<code class="language-plaintext highlighter-rouge">δ</code>), among others.</p>
  </li>
  <li>
    <p>The Greek lower case mee (<code class="language-plaintext highlighter-rouge">μ</code>) has a rounder right corner, which is
in line with a whole range of characters.</p>
  </li>
  <li>
    <p>The micro sign is the same design as the Greek lower case mee, even
though these are technically two distinct code points.</p>
  </li>
  <li>
    <p>The at sign (<code class="language-plaintext highlighter-rouge">@</code>) of Aporetic Sans and Aporetic Serif (i.e. the
 proportionately spaced fonts I provide) is a bit taller than it was
 before. This makes it look more related to its monospaced
 counterpart, which is also relatively tall.</p>
  </li>
</ul>

<p>I also added support for some more Greek characters, as well as the
Latin eth (<code class="language-plaintext highlighter-rouge">ð</code>), thorn (<code class="language-plaintext highlighter-rouge">þ</code>), and thorn capital (<code class="language-plaintext highlighter-rouge">Þ</code>).</p>

<p>All other changes are done to retain the aesthetic of the fonts while
dealing with the breaking changes introduced by the upstream Iosevka
project.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: show-font version 0.3.0</title>
      <description>Information about the latest version of my show-font package for GNU Emacs.</description>
      <pubDate>Sat, 26 Apr 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-04-26-emacs-show-font-0-3-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-04-26-emacs-show-font-0-3-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This package lets you preview a font inside of Emacs. It does so in
three ways:</p>

<ul>
  <li>Prompt for a font on the system and display it in a buffer.</li>
  <li>List all known fonts in a buffer, with a short preview for each.</li>
  <li>Provide a major mode to preview a font whose file is among the
installed ones.</li>
</ul>

<p>Sources:</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">show-font</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/show-font">https://protesilaos.com/emacs/show-font</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/show-font-changelog">https://protesilaos.com/emacs/show-font-changelog</a></li>
  <li>Git repository: <a href="https://github.com/protesilaos/show-font">https://github.com/protesilaos/show-font</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/codelog/2024-09-10-emacs-show-font-0-1-0/">https://protesilaos.com/codelog/2024-09-10-emacs-show-font-0-1-0/</a></li>
  <li>Backronym: Should Highlight Only With the Family Of the Named Typeface.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 0.3.0 on 2025-04-26</h2>

<p>This version adds some refinements to an already stable package.</p>

<h3>The command <code class="language-plaintext highlighter-rouge">show-font-list</code> is an alias for <code class="language-plaintext highlighter-rouge">show-font-tabulated</code></h3>

<p>The <code class="language-plaintext highlighter-rouge">show-font-list</code> command was using a custom buffer that listed
font families and their corresponding short preview. It did not have
any other feature.</p>

<p>I made changes under the hood to rely on the built-in
<code class="language-plaintext highlighter-rouge">tabulated-list-mode</code> which is a standard and gives us the option to
sort by column. The <code class="language-plaintext highlighter-rouge">show-font-list</code> is thus an alias for the new
command <code class="language-plaintext highlighter-rouge">show-font-tabulated</code>. Right now the sorting facility only
applies to reversing the name-based order. In the future we may have
more columns, such as if we describe a font as “Latin”, “Greek”, etc.</p>

<h3>The tabulated list marks fonts that cannot be previewed</h3>

<p>In the past, the font listing would include families that could not
display the <code class="language-plaintext highlighter-rouge">show-font-pangram</code> or, indeed, any Latin character. Those
would be rendered as empty boxes.</p>

<p>I have now introduced a simple heuristic to test that the given family
supports Latin characters. If it does not, then (i) it is highlighted
with a different colour, (ii) it shows “No preview” instead of the
pangram, and (iii) it displays the information in the Emacs default
font family. Some families do not play nice with this approach though,
as they pass the test but still do not display any Latin characters.
This happens with icon fonts.</p>

<p>The long-term goal is to support different scripts and show the
appropriate text for each of them.</p>

<h3>The <code class="language-plaintext highlighter-rouge">show-font-sentences-sample</code> adds more to the <code class="language-plaintext highlighter-rouge">show-font-select-preview</code></h3>

<p>The new user option <code class="language-plaintext highlighter-rouge">show-font-sentences-sample</code> is a list of strings
that can be used to exhibit common patterns and letter combinations.
The default value is carefully designed to show if a font family is
stylistically consistent, such as with how it draws <code class="language-plaintext highlighter-rouge">i</code>, <code class="language-plaintext highlighter-rouge">l</code>, <code class="language-plaintext highlighter-rouge">t</code>, or
<code class="language-plaintext highlighter-rouge">h</code>, <code class="language-plaintext highlighter-rouge">n</code>, <code class="language-plaintext highlighter-rouge">m</code>, and so on. Plus, it teaches you some obscure words like
“scholarch”, “antipode”, and “heteroclite”: use them with your Greek
friends—and if they do not know those words, then they must buy you
a café frappé!</p>

<h3>Miscellaneous</h3>

<ul>
  <li>The face <code class="language-plaintext highlighter-rouge">show-font-title-small</code> is an obsolete alias for the more
appropriately named <code class="language-plaintext highlighter-rouge">show-font-title-in-listing</code>.</li>
  <li>The prompt used by the command <code class="language-plaintext highlighter-rouge">show-font-select-preview</code> now
correctly uses its own history and default value.</li>
  <li>The default value of the user option <code class="language-plaintext highlighter-rouge">show-font-character-sample</code>
includes some more patterns to better test the adequacy of a font
family. This sample is displayed in the buffer produced by the
command <code class="language-plaintext highlighter-rouge">show-font-select-preview</code>.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: tmr version 1.1.0</title>
      <description>Information about the latest version of my TMR package for GNU Emacs.</description>
      <pubDate>Fri, 18 Apr 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-04-18-emacs-tmr-1-1-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-04-18-emacs-tmr-1-1-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>TMR provides facilities for setting timers using a convenient
notation. Lots of commands are available to operate on timers, while
there also exists a tabulated view to display all timers in a nice
grid.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">tmr</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/tmr">https://protesilaos.com/emacs/tmr</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/tmr-changelog">https://protesilaos.com/emacs/tmr-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/tmr">https://github.com/protesilaos/tmr</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/tmr">https://gitlab.com/protesilaos/tmr</a></li>
    </ul>
  </li>
  <li>Backronym: TMR May Ring; Timer Must Run.</li>
</ul>

<p>Below are the release notes.</p>

<hr />

<h2>Version 1.1.0 on 2025-04-18</h2>

<p>This version makes small refinements to an already stable package.</p>

<h3>All of <code class="language-plaintext highlighter-rouge">tmr-tabulated.el</code>  is part of <code class="language-plaintext highlighter-rouge">tmr.el</code></h3>

<p>The command <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code>, which produces a grid with
timers+descriptions, used to be in a separate file. It now is part of
the singular <code class="language-plaintext highlighter-rouge">tmr.el</code> to keep things simple. Users who were using
<code class="language-plaintext highlighter-rouge">(require 'tmr-tabulated)</code> or similar will now get a warning. Simply
load <code class="language-plaintext highlighter-rouge">tmr</code> instead.</p>

<h3>Refined the behaviour of the <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code> command</h3>

<p>When the command <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code> (alias <code class="language-plaintext highlighter-rouge">tmr-list-timers</code>) is
called interactively, it uses the <code class="language-plaintext highlighter-rouge">*tmr-tabulated-view*</code> buffer just
as it did before. Though it also evaluates the new user option
<code class="language-plaintext highlighter-rouge">tmr-list-timers-action-alist</code>: it is a variable that controls where
the buffer is displayed. The default value displays the buffer at the
bottom of the Emacs frame and makes some other tweaks for usability.</p>

<p>Watch my video on the <code class="language-plaintext highlighter-rouge">display-buffer-alist</code> for further details on
how to control the display of buffers: <a href="https://protesilaos.com/codelog/2024-02-08-emacs-window-rules-display-buffer-alist/">https://protesilaos.com/codelog/2024-02-08-emacs-window-rules-display-buffer-alist/</a>.</p>

<p>The <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code> command is further revised to make it
callable from a program. One scenario where we do this is to interrupt
the termination of Emacs if there are running timers (more below).</p>

<h3>TMR interrupts the termination of Emacs if it must</h3>

<p>In the past, we did not have anything to prevent the termination of
Emacs if timers were running: Emacs would simply shut down. Now we
define the <code class="language-plaintext highlighter-rouge">tmr-kill-emacs-query-function</code>, which is added to the
standard <code class="language-plaintext highlighter-rouge">kill-emacs-query-functions</code>: if there are running timers, it
asks for confirmation before closing Emacs. To make it easier for
users to decide how to proceed, it also pops up the list with all the
timers (i.e. it uses <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code> from Lisp, as noted above).</p>

<h3>The list view is easier to follow</h3>

<p>The buffer produced by <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code> now uses more colours to
make it easier to track the data it presents. These are all the faces
it applies:</p>

<ul>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">tmr-tabulated-start-time</code>:</strong> The time when the timer was started.</p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">tmr-tabulated-end-time</code>:</strong> The time when the timer is set to end.</p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">tmr-tabulated-remaining-time</code>:</strong> The remaining time.</p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">tmr-tabulated-acknowledgement</code>:</strong> Whether the timer needs to be
“acknowledged” after it ends (if it is marked as “acknowledged”,
then it will not go away until the user confirms they have seen it).</p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">tmr-tabulated-description</code>:</strong> The text describing what the timer is
about.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: modus-themes version 4.7.0</title>
      <description>Information about the latest version of my highly accessible themes for GNU Emacs.</description>
      <pubDate>Thu, 17 Apr 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-04-17-emacs-modus-themes-4-7-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-04-17-emacs-modus-themes-4-7-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just published the latest stable release of <a href="https://protesilaos.com/emacs/modus-themes">the Modus
themes</a>. The change log
entry is reproduced further below. For any questions, you are welcome
to <a href="https://protesilaos.com/contact/">contact me</a>. I will now work to
apply these same changes to emacs.git, so please wait a little longer
for the updates to trickle down to you.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">modus-themes</code> (also built into Emacs 28+)</li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/modus-themes-changelog">https://protesilaos.com/emacs/modus-themes-changelog</a></li>
  <li>Colour palette: <a href="https://protesilaos.com/emacs/modus-themes-colors">https://protesilaos.com/emacs/modus-themes-colors</a></li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/modus-themes-pictures">https://protesilaos.com/emacs/modus-themes-pictures</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/modus-themes">https://github.com/protesilaos/modus-themes</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/modus-themes">https://gitlab.com/protesilaos/modus-themes</a></li>
    </ul>
  </li>
  <li>Backronym: My Old Display Unexpectedly Sharpened … themes.</li>
</ul>

<hr />

<h2>4.7.0 on 2025-04-17</h2>

<p>This release introduces many subtle stylistic tweaks to the “tinted”,
“deuteranopia”, and “tritanopia” theme variants.</p>

<h3>The <code class="language-plaintext highlighter-rouge">modus-themes-list-colors</code> command uses a tabulated list</h3>

<p>This command and its <code class="language-plaintext highlighter-rouge">modus-themes-list-colors-current</code> variant help
users see the colour values and semantic palette mappings defined by
the given theme. In the past, their buffer was designed in the same
spirit as that of the command <code class="language-plaintext highlighter-rouge">list-faces-display</code>, whereas now it is
like the buffer of the command <code class="language-plaintext highlighter-rouge">list-packages</code>. Concretely, users may
now sort by column. Do <code class="language-plaintext highlighter-rouge">M-x describe-mode</code> while in that buffer to
learn about the available commands and their respective key bindings.</p>

<h3>The “tinted” themes have slightly different colours</h3>

<p>The overall feel of the <code class="language-plaintext highlighter-rouge">modus-operandi-tinted</code> and <code class="language-plaintext highlighter-rouge">modus-vivendi-tinted</code>
themes is the same as before. Though in a side-by-side comparison between the
old and new versions reveals lots of subtle differences. The general
idea is to make the themes a bit more consistent by tweaking the
foreground values to be more harmonious in combination with their
background.</p>

<h3>The “deuteranopia” themes are more consistently blue and yellow</h3>

<p>These are the <code class="language-plaintext highlighter-rouge">modus-operandi-deuteranopia</code> and <code class="language-plaintext highlighter-rouge">modus-vivendi-deuteranopia</code>,
which are optimised for users with red-green colour deficiency. In the
past, these themes used blue and yellow hues wherever a concept of
“success” versus “failure” had to be established. This approach is
more generalised now, to include programming syntax highlighting and
many other contexts. In short, the themes are more blue+yellow, while
retaining their original feel.</p>

<h3>The “tritanopia” themes are more consistently red and cyan</h3>

<p>As above, the <code class="language-plaintext highlighter-rouge">modus-operandi-tritanopia</code> and <code class="language-plaintext highlighter-rouge">modus-vivendi-tritanopia</code>
themes, which are optimised for users with blue-yellow colour deficiency,
use a red+cyan palette in more places. Overall, they feel like they
did before, only they are more consistent.</p>

<h3>Miscellaneous</h3>

<ul>
  <li>
    <p>Extended support for the <code class="language-plaintext highlighter-rouge">icomplete</code> faces that are coming in Emacs
version 31.</p>
  </li>
  <li>
    <p>Added support for <code class="language-plaintext highlighter-rouge">treemacs</code> faces, courtesy of Rahul Juliato in
pull request 121: <a href="https://github.com/protesilaos/modus-themes/pull/121">https://github.com/protesilaos/modus-themes/pull/121</a>.
Rahul has assigned copyright to the Free Software Foundation.</p>
  </li>
  <li>
    <p>Added support for the <code class="language-plaintext highlighter-rouge">tldr</code> package.</p>
  </li>
  <li>
    <p>Extended support for <code class="language-plaintext highlighter-rouge">adoc-mode</code>. Thanks to Leilei332 for the
contribution in pull request 137: <a href="https://github.com/protesilaos/modus-themes/pull/137">https://github.com/protesilaos/modus-themes/pull/137</a>.
The change is within the ~15-line limit, meaning that the author
does not need to assign copyright to the Free Software Foundation.</p>
  </li>
  <li>
    <p>Added support for my <code class="language-plaintext highlighter-rouge">spacious-padding</code> package, specifically the
faces it can use when the <code class="language-plaintext highlighter-rouge">spacious-padding-subtle-mode-line</code> user
option is enabled.</p>
  </li>
  <li>
    <p>Added support for the <code class="language-plaintext highlighter-rouge">howm</code> package.</p>
  </li>
  <li>
    <p>Extended support to the new faces of the <code class="language-plaintext highlighter-rouge">transient</code> package. More
specifically, all those faces use the same colour for key bindings
because the idea of colour coding keys (e.g. light yellow means
something different than dark blue) does not work in practice when
considering accessibility. Such semantics should not be limited to
differences in colour: they should also have distinct indicators,
such as ASCII or Unicode characters.</p>
  </li>
  <li>
    <p>Revised the <code class="language-plaintext highlighter-rouge">avy</code> package’s faces to only use one coloured
background. The multiple coloured backgrounds have been a perennial
problem for our accessibility requirements and have made the themes
needlessly more complex just to support an edge case. With this
simplified style, <code class="language-plaintext highlighter-rouge">avy</code> continues to work fine: it simply is less
flamboyant. Other interfaces with <code class="language-plaintext highlighter-rouge">avy</code>-like model of interaction,
such as optional extensions to the <code class="language-plaintext highlighter-rouge">vertico</code> and <code class="language-plaintext highlighter-rouge">corfu</code> packages,
have these same changes, in the interest of consistency.</p>
  </li>
  <li>
    <p>Update the <code class="language-plaintext highlighter-rouge">meow</code> sample configuration in the manual. This package
is not directly supported at the theme level because (i) I do not
use it and (ii) it is very hard for an outsider to it to trigger the
display of all of its faces in the right context. Without seeing how
all of them look together, I cannot come up with a reliable design.
The manual offers a “good enough” approximation.</p>
  </li>
  <li>
    <p>Broadened the support of the <code class="language-plaintext highlighter-rouge">vterm</code> faces to include the “bright”
colours, while updating those that were already covered. Thanks to
Edgar Vincent for informing me that some of the vterm faces were
changed a while ago. This was done in issue 317 on the GitLab
mirror: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/317">https://gitlab.com/protesilaos/modus-themes/-/issues/317</a>.</p>
  </li>
  <li>
    <p>Revised the <code class="language-plaintext highlighter-rouge">org-column-title</code> face to inherit the <code class="language-plaintext highlighter-rouge">fixed-pitch</code>
face if the user option <code class="language-plaintext highlighter-rouge">modus-themes-mixed-fonts</code> is non-nil. This
user option makes it possible to have a buffer with proportionately
spaced fonts (such as by enabling <code class="language-plaintext highlighter-rouge">variable-pitch-mode</code>), while
keeping spacing-sensitive elements, like tables and code blocks, in a
monospaced font.</p>

    <p>Thanks to pedro-nonfree for bringing this matter to my attention in
issue 129: <a href="https://github.com/protesilaos/modus-themes/issues/129">https://github.com/protesilaos/modus-themes/issues/129</a>.</p>
  </li>
  <li>
    <p>Simplified the helper function <code class="language-plaintext highlighter-rouge">modus-themes--retrieve-palette-value</code>
to make it more efficiently. Thanks to Basil L. Contovounesios for
the contribution in merge request 60 on the GitLab mirror:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/60">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/60</a>.</p>
  </li>
  <li>
    <p>Reworded the minibuffer prompt of the <code class="language-plaintext highlighter-rouge">modus-themes-list-colors</code>
command.</p>
  </li>
  <li>
    <p>Made Ivy and IDO subdirectories and “virtual” buffers easier to tell
apart from matching text highlights.</p>
  </li>
  <li>
    <p>Included coverage for the <code class="language-plaintext highlighter-rouge">auto-dim-other-buffers-hide-face</code> of the
package <code class="language-plaintext highlighter-rouge">auto-dim-other-buffers</code></p>
  </li>
  <li>
    <p>Covered the built-in <code class="language-plaintext highlighter-rouge">abbrev-table-name</code> face.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
  </channel>
</rss>
