<?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 Stavrou: 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, 09 Apr 2026 05:22:24 +0000</pubDate>
    
    
    <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 try to implement a new feature for the denote-sequence package.</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>
    
    <item>
      <title>Emacs: Denote version 4.0.0</title>
      <description>Information about the latest version of my Denote package for GNU Emacs.</description>
      <pubDate>Tue, 15 Apr 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-04-15-emacs-denote-4-0-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-04-15-emacs-denote-4-0-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.0.0 on 2025-04-15</h2>

<p>This is a massive release. There is one breaking change, which should
be easy to adapt to: this pertains to the reorganisation of the
project to separate the “core” of Denote from its “extensions”. The
core is the <code class="language-plaintext highlighter-rouge">denote</code> package. Each extension now has its own package
(details below).</p>

<p>Other than that, this version includes lots of new features for
searching and linking as well as quality-of-life refinements. We have
generalised the infrastructure for performing queries in the
<code class="language-plaintext highlighter-rouge">denote-directory</code> and made the buffers with the search results more
useful.</p>

<p>Take your time to read through this publication. I am writing it for
you. Also remember that the most up-to-date resource for anything
related to Denote is its manual. You are always welcome to contact me:
<a href="https://protesilaos.com/contact">https://protesilaos.com/contact</a>. Or join the development on the Git
repository.</p>

<p>As usual, special thanks to Jean-Philippe Gagné Guay for making high
quality contributions to Denote since the beginning of the project ~3
years ago. Those will not always be headline features, but are
important improvements to the underlying code base.</p>

<p>I mention contributions from Jean-Philippe and others in its context.
Though I do not cover implementation details, otherwise this document
will be the size of a book. This does not mean that they are no
important though. Please consult the Git commit log for all the
technicalities.</p>

<h3>All the “extras” are in separate packages, including the Org dynamic blocks</h3>

<p>In previous versions of Denote, we included some optional extensions
as part of the <code class="language-plaintext highlighter-rouge">denote</code> package. These included the files
<code class="language-plaintext highlighter-rouge">denote-org-extras.el</code> (Org dynamic blocks, among others),
<code class="language-plaintext highlighter-rouge">denote-journal-extras.el</code> (streamlined for journaling),
<code class="language-plaintext highlighter-rouge">denote-silo-extras.el</code> (working with multiple Denote silos).</p>

<p>The files <code class="language-plaintext highlighter-rouge">denote-md-extras.el</code> (Markdown extras) and
<code class="language-plaintext highlighter-rouge">denote-sequence.el</code> (sequence notes, including Luhmann-style
alphanumeric sequences) were also part of the project during the last
development cycle, though they never made it into a tagged release.</p>

<p>All these are now available as standalone packages on the official GNU
ELPA archive:</p>

<ul>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">denote-org</code>:</strong> In the Emacs configuration file, replace all
instances of <code class="language-plaintext highlighter-rouge">denote-org-extras</code> with <code class="language-plaintext highlighter-rouge">denote-org</code>.</p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">denote-journal</code>:</strong> Replace <code class="language-plaintext highlighter-rouge">denote-journal-extras</code> with <code class="language-plaintext highlighter-rouge">denote-journal</code>.</p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">denote-silo</code>:</strong> Replace <code class="language-plaintext highlighter-rouge">denote-silo-extras</code> with <code class="language-plaintext highlighter-rouge">denote-silo</code>.</p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">denote-markdown</code> :</strong> Replace <code class="language-plaintext highlighter-rouge">denote-md-extras</code> with <code class="language-plaintext highlighter-rouge">denote-markdown</code>.</p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">denote-sequence</code>:</strong> No changes to any of the defined symbols.
Simply get the new package.</p>
  </li>
</ul>

<p>I will document each of these packages further below. The plan, going
forward, is to maintain all the packages and coordinate their new
versions.</p>

<h3>More things in “core”</h3>

<p>While the extras are moved out to their own code repositories, all
other features are merged into <code class="language-plaintext highlighter-rouge">denote.el</code>. Those include everything
that was in <code class="language-plaintext highlighter-rouge">denote-sort.el</code> and <code class="language-plaintext highlighter-rouge">denote-rename-buffer.el</code>.</p>

<ul>
  <li>
    <p>The “sort” mechanism is mostly for package developers. We use it
extensively in our Org dynamic blocks, which are now part of the
<code class="language-plaintext highlighter-rouge">denote-org</code> package.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-dired</code> command (alias <code class="language-plaintext highlighter-rouge">denote-sort-dired</code>) is the only
user-facing “sort” command we have always provided. It produces a
fully fledged Dired buffer showing the results of the given search
for file names. The matching files are sorted according to the
user’s expressed preference. The details are described in the
manual.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">denote-rename-buffer-mode</code> and all of its user options are
unchanged. This mode automatically renames the buffer of a given
Denote file so that it is easier to read it. Again, the manual
covers the technicalities.</p>
  </li>
</ul>

<p>Users do not need to make changes, unless they are explicitly loading
<code class="language-plaintext highlighter-rouge">denote-sort-dired</code> and <code class="language-plaintext highlighter-rouge">denote-rename-buffer</code>. In that case, they may
just remove those calls: only <code class="language-plaintext highlighter-rouge">denote</code> needs to be loaded.</p>

<h3>The <code class="language-plaintext highlighter-rouge">denote-query-mode</code></h3>

<p>Many of the features I will describe below produce search results via
the built-in Xref mechanism. Xref performs a search with a Grep or
Grep-like program, subject to the user option <code class="language-plaintext highlighter-rouge">xref-search-program</code>.
The buffer those search results are displayed in runs the
<code class="language-plaintext highlighter-rouge">denote-query-mode</code>. It supersedes <code class="language-plaintext highlighter-rouge">denote-backlinks-mode</code>.</p>

<p>The <code class="language-plaintext highlighter-rouge">denote-query-mode</code> supports the following:</p>

<ul>
  <li>Results are shown in the context, with the exact match in highlight.</li>
  <li>Matches are grouped by file. Each file is a “heading”.</li>
  <li>Headings can be folded with <code class="language-plaintext highlighter-rouge">TAB</code>, just how it is done in Org buffers.</li>
  <li>The results can be used for further queries. Type <code class="language-plaintext highlighter-rouge">C-h m</code>
(<code class="language-plaintext highlighter-rouge">describe-mode</code>) to learn about all the relevant commands.</li>
</ul>

<p>We have had support for Xref since the original version of Denote. It
now is more generalised to cover backlinks, query links, and
<code class="language-plaintext highlighter-rouge">denote-grep</code> (more below).</p>

<h3>Use query links for file contents or file names</h3>

<p>Denote has always provided the option to link directly to a file with
a given name by referencing its identifier. This can be done with the
command <code class="language-plaintext highlighter-rouge">denote-link</code>, among a few others like it (always consult the
manual of Denote).</p>

<p>In addition to these “direct links”, we also support “query links”.
Those do not point to a file but instead trigger a search. The results
are placed in a buffer that uses the appropriate major mode.</p>

<p>There are two types of query links:</p>

<ul>
  <li>
    <p><strong>Query file contents:</strong> Use the command <code class="language-plaintext highlighter-rouge">denote-query-contents-link</code>
to insert a query link at point for “file contents”. It perform a
search inside files in the <code class="language-plaintext highlighter-rouge">denote-directory</code> and put the results in
a <code class="language-plaintext highlighter-rouge">denote-query-mode</code> buffer.</p>
  </li>
  <li>
    <p><strong>Query file names:</strong> Use the <code class="language-plaintext highlighter-rouge">denote-query-filenames-link</code> to insert
a query link for “file names”. It performs the query against file
names (not contents!) and puts the results in a <code class="language-plaintext highlighter-rouge">dired</code> buffer.</p>
  </li>
</ul>

<p>The display of the buffer with the query link results is controlled by
the user option <code class="language-plaintext highlighter-rouge">denote-query-links-display-buffer-action</code>.</p>

<p>Query links are styled a little bit differently than direct links.
Compare the <code class="language-plaintext highlighter-rouge">denote-faces-link</code> with <code class="language-plaintext highlighter-rouge">denote-faces-query-link</code>. Both
should look okay with most themes.</p>

<p>Denote query links are supported as part of the <code class="language-plaintext highlighter-rouge">denote:</code> hyperlink
type. They are available in all file types we define (per the user
option <code class="language-plaintext highlighter-rouge">denote-file-type</code>) and should, in principle, work in any
custom file type (advanced users can check the variable <code class="language-plaintext highlighter-rouge">denote-file-types</code>).</p>

<h3>Backlinks now always show their context</h3>

<p>In the past, the command <code class="language-plaintext highlighter-rouge">denote-backlinks</code> would produce a bespoke
buffer showing a list of file names that included links to the current
file (any file with the Denote file-naming scheme can have backlinks,
by the way, including PDFs, videos, etc.). This buffer did not provide
any additional functionality. We used to support the option to show
results in their context via <code class="language-plaintext highlighter-rouge">denote-backlinks-show-context</code>. Those
would be rendered in a standard Xref buffer.</p>

<p>The contextual results are now the default and sole option. This is
because we have expanded the functionality of those buffers to use the
<code class="language-plaintext highlighter-rouge">denote-query-mode</code>, as explained above. Plus, it makes our code base
simpler.</p>

<p>Users will notice how backlikns look just like a query link for file
contents. This is because backlinks are the original query links since
day one of Denote.</p>

<h3>Direct links to a file with matching contents</h3>

<p>The command <code class="language-plaintext highlighter-rouge">denote-link-to-file-with-contents</code> allows users to
produce a direct link to a file whose contents (not file name!)
includes the given query.</p>

<p>Similarly, the command <code class="language-plaintext highlighter-rouge">denote-link-to-all-files-with-contents</code>
generates a typographic list (bullet list) to all files whose contents
match the given query.</p>

<p>The manual covers all linking commands in depth.</p>

<h3>The essence of <code class="language-plaintext highlighter-rouge">denote-search</code> is part of <code class="language-plaintext highlighter-rouge">denote</code></h3>

<p>The <code class="language-plaintext highlighter-rouge">denote-search</code> package by Lucas Quintana uses the infrastructure
of Denote to perform searches in file contents. We now provide its
feature set as part of core <code class="language-plaintext highlighter-rouge">denote</code>.</p>

<p>We decided to do this since query links already introduced all of the
requisite generalisations to <code class="language-plaintext highlighter-rouge">denote-query-mode</code>.</p>

<p>Users can rely on the commands <code class="language-plaintext highlighter-rouge">denote-grep</code>, <code class="language-plaintext highlighter-rouge">denote-grep-marked-dired-files</code>,
and <code class="language-plaintext highlighter-rouge">denote-grep-files-referenced-in-region</code>.</p>

<p>The placement of these buffers is subject to the user option
<code class="language-plaintext highlighter-rouge">denote-grep-display-buffer-action</code>.</p>

<p>This functionality was introduced in two pull requests by Lucas
Quintana, 571 and 573, with further changes by me:</p>

<ul>
  <li><a href="https://github.com/protesilaos/denote/pull/571">https://github.com/protesilaos/denote/pull/571</a>.</li>
  <li><a href="https://github.com/protesilaos/denote/pull/573">https://github.com/protesilaos/denote/pull/573</a>.</li>
</ul>

<p>Lucas has assigned copyright to the Free Software Foundation.</p>

<p>I think this was a much-needed addition to the core of Denote. It
complements <code class="language-plaintext highlighter-rouge">denote-dired</code> and query links.</p>

<h3>Formatting of links with <code class="language-plaintext highlighter-rouge">denote-link-description-format</code></h3>

<p>The old user option <code class="language-plaintext highlighter-rouge">denote-link-description-function</code> is deprecated
and superseded by the new <code class="language-plaintext highlighter-rouge">denote-link-description-format</code>. The new
user option still accepts a custom function as its value, so the old
behaviour should be retained.</p>

<p>What the new <code class="language-plaintext highlighter-rouge">denote-link-description-format</code> supports is an easier
way to customise the description of a link by using format specifiers
for common options. For example, users who only want to see the title
of the linked file can do this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(setq denote-link-description-format "%t")
</code></pre></div></div>

<p>The documentation of this user option covers all the format specifiers
and further details.</p>

<h3>Miscellaneous changes for all users</h3>

<ul>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">denote-add-front-matter</code> is superseded by
<code class="language-plaintext highlighter-rouge">denote-rename-file</code> and related. Those renaming commands will add
missing front matter or rewrite the modified lines of existing front
matter. This is due to refinements made by Jean-Philippe Gagné Guay
to the file renaming mechanism. We discussed this deprecation in
issue 498: <a href="https://github.com/protesilaos/denote/issues/498">https://github.com/protesilaos/denote/issues/498</a>. Also
thanks to Samuel Flint for reporting an earlier problem with file
name signatures: <a href="https://github.com/protesilaos/denote/issues/492">https://github.com/protesilaos/denote/issues/492</a>.</p>
  </li>
  <li>
    <p>The user option <code class="language-plaintext highlighter-rouge">denote-open-link-function</code> specifies the function
used by Denote to open the file of a direct link.</p>
  </li>
  <li>
    <p>The user option <code class="language-plaintext highlighter-rouge">denote-org-store-link-to-heading</code> can now be set to
form generic context links without a <code class="language-plaintext highlighter-rouge">PROPERTIES</code> drawer and
corresponding <code class="language-plaintext highlighter-rouge">CUSTOM_ID</code>. Set the value of this variable to
<code class="language-plaintext highlighter-rouge">'context</code>. Read its documentation for further details.</p>
  </li>
  <li>
    <p>Also about <code class="language-plaintext highlighter-rouge">denote-org-store-link-to-heading</code>, we have changed its
default value to <code class="language-plaintext highlighter-rouge">nil</code>, which is what we were doing for most of
Denote’s history. This means that, by default, <code class="language-plaintext highlighter-rouge">org-store-link</code> and
anything building on top of it will create a link only to the
current Denote file, like <code class="language-plaintext highlighter-rouge">denote:IDENTIFIER</code>, but not to the
current heading within that file. To create links to the
file+heading, set the value of this variable to <code class="language-plaintext highlighter-rouge">'id</code>.</p>
  </li>
  <li>
    <p>The command <code class="language-plaintext highlighter-rouge">denote-dired-link-marked-notes</code> is an alias for
<code class="language-plaintext highlighter-rouge">denote-link-dired-marked-notes</code>.</p>
  </li>
  <li>
    <p>The user option <code class="language-plaintext highlighter-rouge">denote-sort-dired-extra-prompts</code> control what
<code class="language-plaintext highlighter-rouge">denote-dired</code> (alias <code class="language-plaintext highlighter-rouge">denote-sort-dired</code>) prompts for. It accepts
either a nil value or a list of symbols among <code class="language-plaintext highlighter-rouge">sort-by-component</code>,
<code class="language-plaintext highlighter-rouge">reverse-sort</code>, and <code class="language-plaintext highlighter-rouge">exclude-regexp</code>. The order those symbols appear
in the list is significant, with the leftmost coming first.</p>
  </li>
  <li>
    <p>There is a new <code class="language-plaintext highlighter-rouge">denote-sort-identifier-comparison-function</code> variable
which determines how identifier-based sorting should be done by
default. It complements the existing <code class="language-plaintext highlighter-rouge">denote-sort-title-comparison-function</code>,
<code class="language-plaintext highlighter-rouge">denote-sort-keywords-comparison-function</code>, <code class="language-plaintext highlighter-rouge">denote-sort-signature-comparison-function</code>.
Thanks to Maikol Solís for the contribution in pull request 517:
<a href="https://github.com/protesilaos/denote/pull/517">https://github.com/protesilaos/denote/pull/517</a>. The change is
small, meaning that Maikol does not need to assign copyright to the
Free Software Foundation (though I believe the paperwork is done, anyway).</p>
  </li>
  <li>
    <p>Lots of refinements to the doc strings of individual variables
and/or functions as well as the manual.</p>
  </li>
  <li>
    <p>Lots of other contributions to discussions and questions on the Git
repository. Granted, these are not “changes” per se but are part of
the development effort nonetheless.</p>
  </li>
  <li>
    <p>Made <code class="language-plaintext highlighter-rouge">denote-get-path-by-id</code> use <code class="language-plaintext highlighter-rouge">denote-get-file-extension-sans-encryption</code>
instead of <code class="language-plaintext highlighter-rouge">denote-get-file-extension</code>. This fixes a bug where the
extension is duplicated if it has an encryption component. Thanks to
eum3l for the patch in pull request 562: <a href="https://github.com/protesilaos/denote/pull/562">https://github.com/protesilaos/denote/pull/562</a>.
The change is small, meaning that the author does not need to assign
copyright to the Free Software Foundation.</p>
  </li>
  <li>
    <p>Same as above for <code class="language-plaintext highlighter-rouge">denote--rename-file</code>, which was done in pull
request 557: <a href="https://github.com/protesilaos/denote/pull/557">https://github.com/protesilaos/denote/pull/557</a>.</p>
  </li>
</ul>

<h3>For developers or advanced users</h3>

<p>The following have been added or modified.</p>

<ul>
  <li>
    <p><strong>NEW Function <code class="language-plaintext highlighter-rouge">denote-file-has-denoted-filename-p</code>:</strong> Return non-nil
if <code class="language-plaintext highlighter-rouge">FILE</code> respects the file-naming scheme of Denote. This tests the
rules of Denote’s file-naming scheme. Sluggification is ignored. It
is done by removing all file name components and validating what
remains. Thanks to Jean-Philippe Gagné Guay for the pull request
515: <a href="https://github.com/protesilaos/denote/pull/515">https://github.com/protesilaos/denote/pull/515</a>.</p>
  </li>
  <li>
    <p><strong>NEW Functions <code class="language-plaintext highlighter-rouge">denote-infer-keywords-from-files</code>:</strong> Return list of
keywords in <code class="language-plaintext highlighter-rouge">denote-directory-files</code>. With optional
<code class="language-plaintext highlighter-rouge">FILES-MATCHING-REGEXP</code>, only extract keywords from the matching
files. Otherwise, do it for all files. Keep any duplicates. Users
who do not want duplicates should refer to the functions
<code class="language-plaintext highlighter-rouge">denote-keywords</code>.</p>
  </li>
  <li>
    <p><strong>MODIFIED Function <code class="language-plaintext highlighter-rouge">denote-keywords</code>:</strong> Returns an appropriate list
of keyword candidates, while accounting for the value of the user
option <code class="language-plaintext highlighter-rouge">denote-infer-keywords</code>. It now also accepts the optional
<code class="language-plaintext highlighter-rouge">FILES-MATCHING-REGEXP</code> parameter.</p>
  </li>
  <li>
    <p><strong>MODIFIED Function <code class="language-plaintext highlighter-rouge">denote-directory-files</code>:</strong> Returns a list of
absolute file paths in variable <code class="language-plaintext highlighter-rouge">denote-directory</code>. It now accepts
the optional <code class="language-plaintext highlighter-rouge">EXCLUDE-REGEXP</code> parameter.</p>
  </li>
  <li>
    <p><strong>MODIFIED Function <code class="language-plaintext highlighter-rouge">denote-format-file-name</code>:</strong> Formats a file name.
The way it treats its <code class="language-plaintext highlighter-rouge">ID</code> parameter has changed. Please read its
doc string. Thanks to Jean-Philippe Gagné Guay for the pull request
496: <a href="https://github.com/protesilaos/denote/pull/496">https://github.com/protesilaos/denote/pull/496</a>.</p>
  </li>
  <li>
    <p><strong>ALIAS Function <code class="language-plaintext highlighter-rouge">denote-retrieve-filename-keywords-as-list</code>:</strong> This
is a name that is easier to discover than <code class="language-plaintext highlighter-rouge">denote-extract-keywords-from-path</code>,
because of the many other functions with the <code class="language-plaintext highlighter-rouge">denote-retrieve-*</code> prefix.</p>
  </li>
  <li>
    <p><strong>MODIFIED Function <code class="language-plaintext highlighter-rouge">denote-retrieve-filename-identifier</code>:</strong> Extracts
the identifier from <code class="language-plaintext highlighter-rouge">FILE</code> name, if present, else returns nil. To
create a new one from a date, refer to the <code class="language-plaintext highlighter-rouge">denote-get-identifier</code>
function. Thanks to Jean-Philippe Gagné Guay for the pull request
476: <a href="https://github.com/protesilaos/denote/pull/476">https://github.com/protesilaos/denote/pull/476</a>.</p>
  </li>
  <li>
    <p><strong>MODIFIED Function <code class="language-plaintext highlighter-rouge">denote-get-identifier</code>:</strong> Converts <code class="language-plaintext highlighter-rouge">DATE</code> into a
Denote identifier using <code class="language-plaintext highlighter-rouge">denote-id-format</code>. If <code class="language-plaintext highlighter-rouge">DATE</code> is nil, it
returns an empty string as the identifier. Also by Jean-Philippe in
pull request 476 mentioned right above.</p>
  </li>
  <li>
    <p><strong>MODIFIED Function <code class="language-plaintext highlighter-rouge">denote-date-prompt</code>:</strong> Prompts for a date,
expecting <code class="language-plaintext highlighter-rouge">YYYY-MM-DD</code> or that plus <code class="language-plaintext highlighter-rouge">HH:MM</code> (or even <code class="language-plaintext highlighter-rouge">HH:MM:SS</code>).
Can also use Org’s more advanced date selection utility if the user
option <code class="language-plaintext highlighter-rouge">denote-date-prompt-use-org-read-date</code> is non-nil. It now has
the optional parameters <code class="language-plaintext highlighter-rouge">INITIAL-DATE</code> and <code class="language-plaintext highlighter-rouge">PROMPT-TEXT</code>. Thanks to
Jean-Philippe Gagné Guay for the pull request 576:
<a href="https://github.com/protesilaos/denote/pull/576">https://github.com/protesilaos/denote/pull/576</a>.</p>
  </li>
  <li>
    <p><strong>NEW Function <code class="language-plaintext highlighter-rouge">denote-retrieve-groups-xref-query</code>:</strong> Accesses the
location of xrefs for <code class="language-plaintext highlighter-rouge">QUERY</code> and group them per file. Limit the
search to text files.</p>
  </li>
  <li>
    <p><strong>NEW Function <code class="language-plaintext highlighter-rouge">denote-retrieve-files-xref-query</code>:</strong> Returns sorted,
deduplicated file names with matches for <code class="language-plaintext highlighter-rouge">QUERY</code> in their contents.
Limits the search to text files.</p>
  </li>
  <li>
    <p><strong>NEW Function <code class="language-plaintext highlighter-rouge">denote-retrieve-xref-alist</code>:</strong> Returns xref alist of
files with the location of matches for <code class="language-plaintext highlighter-rouge">QUERY</code>. With optional
<code class="language-plaintext highlighter-rouge">FILES-MATCHING-REGEXP</code>, it limits the list of files accordingly
(per <code class="language-plaintext highlighter-rouge">denote-directory-files</code>). At all times, it limits the search
to text files.</p>
  </li>
  <li>
    <p><strong>NEW Function <code class="language-plaintext highlighter-rouge">denote-prepend-front-matter</code>:</strong> Prepend front matter
to <code class="language-plaintext highlighter-rouge">FILE</code>. The <code class="language-plaintext highlighter-rouge">TITLE</code>, <code class="language-plaintext highlighter-rouge">KEYWORDS</code>, <code class="language-plaintext highlighter-rouge">DATE</code>, <code class="language-plaintext highlighter-rouge">ID</code>, <code class="language-plaintext highlighter-rouge">SIGNATURE</code>, and
<code class="language-plaintext highlighter-rouge">FILE-TYPE</code> are passed from the renaming command and are used to
construct a new front matter block if appropriate.</p>
  </li>
  <li>
    <p><strong>MODIFIED Function <code class="language-plaintext highlighter-rouge">denote-rewrite-front-matter</code>:</strong> Rewrites front
matter of note after <code class="language-plaintext highlighter-rouge">denote-rename-file</code> (or related). The <code class="language-plaintext highlighter-rouge">FILE</code>,
<code class="language-plaintext highlighter-rouge">TITLE</code>, <code class="language-plaintext highlighter-rouge">KEYWORDS</code>, <code class="language-plaintext highlighter-rouge">SIGNATURE</code>, <code class="language-plaintext highlighter-rouge">DATE</code>, <code class="language-plaintext highlighter-rouge">IDENTIFIER</code>, and
<code class="language-plaintext highlighter-rouge">FILE-TYPE</code> arguments are given by the renaming command and are used
to construct new front matter values if appropriate. If
<code class="language-plaintext highlighter-rouge">denote-rename-confirmations</code> contains <code class="language-plaintext highlighter-rouge">rewrite-front-matter</code>,
prompt to confirm the rewriting of the front matter. Otherwise
produce a <code class="language-plaintext highlighter-rouge">y-or-n-p</code> prompt to that effect. Thanks to
Jean-Philippe Gagné Guay for the pull request 558:
<a href="https://github.com/protesilaos/denote/pull/558">https://github.com/protesilaos/denote/pull/558</a>.</p>
  </li>
</ul>

<h3>Denote “extensions” that are not in the <code class="language-plaintext highlighter-rouge">denote</code> package anymore</h3>

<h4><code class="language-plaintext highlighter-rouge">denote-journal</code> integrates nicely with <code class="language-plaintext highlighter-rouge">M-x calendar</code></h4>

<p>The <code class="language-plaintext highlighter-rouge">calendar</code> can now highlight days that have journal entry. It may
also be used as a date picker to view or write a journal entry for
that day.</p>

<ul>
  <li>
    <p>Thanks to Alan Schmitt for reporting an issue with the calendar
integration during development:
<a href="https://github.com/protesilaos/denote-journal/issues/8">https://github.com/protesilaos/denote-journal/issues/8</a>.</p>
  </li>
  <li>
    <p>Thanks to Vineet C. Kulkarni for tweaking the identification of the
journal keyword to be more robust:
<a href="https://github.com/protesilaos/denote-journal/pull/4">https://github.com/protesilaos/denote-journal/pull/4</a>.</p>
  </li>
  <li>
    <p>Thanks to Honza Pokorny for fixing two small issues with the path
expansion:</p>
    <ul>
      <li><a href="https://github.com/protesilaos/denote-journal/pull/5">https://github.com/protesilaos/denote-journal/pull/5</a></li>
      <li><a href="https://github.com/protesilaos/denote-journal/pull/7">https://github.com/protesilaos/denote-journal/pull/7</a></li>
    </ul>
  </li>
</ul>

<p>Other than that, the package is providing the same functionality as
the discontinued <code class="language-plaintext highlighter-rouge">denote-journal-extras.el</code>.</p>

<ul>
  <li>Manual: <a href="https://protesilaos.com/emacs/denote-journal">https://protesilaos.com/emacs/denote-journal</a>.</li>
  <li>GitHub: <a href="https://github.com/protesilaos/denote-journal">https://github.com/protesilaos/denote-journal</a>.</li>
</ul>

<h4><code class="language-plaintext highlighter-rouge">denote-org</code> is almost the same as the discontinued <code class="language-plaintext highlighter-rouge">denote-org-extras.el</code></h4>

<p>The only addition to dynamic blocks the optional <code class="language-plaintext highlighter-rouge">:not-regexp</code> parameter.
This is a regular expression that can further filter the results of a
search, such that the matching items are removed from the output.</p>

<p>The official manual of <code class="language-plaintext highlighter-rouge">denote-org</code> covers the technicalities.</p>

<ul>
  <li>Manual: <a href="https://protesilaos.com/emacs/denote-org">https://protesilaos.com/emacs/denote-org</a>.</li>
  <li>GitHub: <a href="https://github.com/protesilaos/denote-org">https://github.com/protesilaos/denote-org</a>.</li>
</ul>

<p>Also thanks to Elias Storms for fixing a small issue with the “missing
links” Org dynamic block, in pull request 486: <a href="https://github.com/protesilaos/denote/pull/486">https://github.com/protesilaos/denote/pull/486</a></p>

<h4><code class="language-plaintext highlighter-rouge">denote-silo</code> is the same as the discontinued <code class="language-plaintext highlighter-rouge">denote-silo-extras.el</code></h4>

<p>I have only made small tweaks to it, but nothing that changes the user
experience.</p>

<ul>
  <li>Manual: <a href="https://protesilaos.com/emacs/denote-silo">https://protesilaos.com/emacs/denote-silo</a></li>
  <li>GitHub: <a href="https://github.com/protesilaos/denote-silo">https://github.com/protesilaos/denote-silo</a></li>
</ul>

<h4><code class="language-plaintext highlighter-rouge">denote-markdown</code> for some Markdown-specific extras</h4>

<p>This package provides some convenience functions to better integrate
Markdown with Denote. This is mostly about converting links from one
type to another so that they can work in different applications
(because Markdown does not have a standardised way to define custom
link types). It also defines an “Obsidian” file type which does not
have any front matter but only uses a level 1 heading for the title of
the note.</p>

<p>The code of <code class="language-plaintext highlighter-rouge">denote-markdown</code> used to be bundled up with the <code class="language-plaintext highlighter-rouge">denote</code>
package before version <code class="language-plaintext highlighter-rouge">4.0.0</code> of the latter and was available in the
file <code class="language-plaintext highlighter-rouge">denote-md-extras.el</code>. Users of the old code will need to adapt
their setup to use the <code class="language-plaintext highlighter-rouge">denote-markdown</code> package. This can be done by
replacing all instances of <code class="language-plaintext highlighter-rouge">denote-md-extras</code> with <code class="language-plaintext highlighter-rouge">denote-markdown</code>
across their configuration.</p>

<ul>
  <li>Manual: <a href="https://protesilaos.com/emacs/denote-markdown">https://protesilaos.com/emacs/denote-markdown</a></li>
  <li>GitHub: <a href="https://github.com/protesilaos/denote-markdown">https://github.com/protesilaos/denote-markdown</a></li>
</ul>

<h4>Write sequence notes (or “folgezettel”) with <code class="language-plaintext highlighter-rouge">denote-sequence</code></h4>

<p>Users who want their notes to have an inherent structure can use
<code class="language-plaintext highlighter-rouge">denote-sequence</code>. The idea is to have thoughts that naturally form
sequences and are named accordingly. The sequence scheme is either
numeric or alphanumeric. The manual of the package explains all the
details.</p>

<ul>
  <li>Manual: <a href="https://protesilaos.com/emacs/denote-sequence">https://protesilaos.com/emacs/denote-sequence</a></li>
  <li>GitHub: <a href="https://github.com/protesilaos/denote-sequence">https://github.com/protesilaos/denote-sequence</a></li>
</ul>

<p>I had a lot of fun developing this comprehensive package during the
winter holidays.</p>

<p>Thanks to Claudio Migliorelli, Kierin Bell, Mirko Hernandez for
helping me fix some issues during development:</p>

<ul>
  <li><a href="https://github.com/protesilaos/denote/pull/518">https://github.com/protesilaos/denote/pull/518</a>.</li>
  <li><a href="https://github.com/protesilaos/denote/pull/528">https://github.com/protesilaos/denote/pull/528</a>.</li>
  <li><a href="https://github.com/protesilaos/denote/pull/540">https://github.com/protesilaos/denote/pull/540</a>.</li>
  <li><a href="https://github.com/protesilaos/denote/pull/541">https://github.com/protesilaos/denote/pull/541</a>.</li>
  <li><a href="https://github.com/protesilaos/denote-sequence/issues/2">https://github.com/protesilaos/denote-sequence/issues/2</a>.</li>
</ul>

<h3>The <code class="language-plaintext highlighter-rouge">consult-denote</code> also gets a small update</h3>

<p>This has always been a standalone package. I made the function
<code class="language-plaintext highlighter-rouge">consult-denote-file-prompt</code> read the special-purpose variable
<code class="language-plaintext highlighter-rouge">denote-file-prompt-use-files-matching-regexp</code>. This is related to
commit <code class="language-plaintext highlighter-rouge">e0f1d47</code> in denote.git, about issue 536 as reported by Alan
Schmitt: <a href="https://github.com/protesilaos/denote/issues/536">https://github.com/protesilaos/denote/issues/536</a>. The
variable <code class="language-plaintext highlighter-rouge">denote-file-prompt-use-files-matching-regexp</code> is meant to be
<code class="language-plaintext highlighter-rouge">let</code> bound and is for advanced users or developers.</p>

<h3>Feature freeze at least until the end of April 2025</h3>

<p>I will not develop new features or accept pull request for a couple of
weeks. The idea is to focus on fixing any bug reports. We can then
publish point releases quickly.</p>

<p>New features can be included after we are confident that the packages
we have are okay.</p>

<h3>Git commits</h3>

<p>This is just an overview of the Git commits, though remember that
there is more that goes into a project, such as the reporting of
inconsistencies, discussion of new ideas, et cetera. Thanks to
everybody involved! Plus, some commits are large while others are
tiny.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/Git/Projects/denote $ git shortlog 3.1.0..4.0.0  --summary --numbered
   470	Protesilaos Stavrou
    90	Jean-Philippe Gagné Guay
     6	Kierin Bell
     4	Alan Schmitt
     3	eum3l
     2	Claudio Migliorelli
     2	Lucas Quintana
     2	grtcdr
     1	Elias Storms
     1	Laurent Gatto
     1	Maikol Solís
     1	Octavian
     1	TomoeMami
</code></pre></div></div>

<p>The following are not accurate because they only reflect the changes
after the reorganisation I made. But we have to start from somewhere.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/Git/Projects/denote-journal $ git shortlog  --summary --numbered
    54	Protesilaos Stavrou
     2	Honza Pokorny
     1	Vineet C. Kulkarni

~/Git/Projects/denote-sequence $ git shortlog  --summary --numbered
    22	Protesilaos Stavrou

~/Git/Projects/denote-silo $ git shortlog  --summary --numbered
    17	Protesilaos Stavrou

~/Git/Projects/denote-org $ git shortlog  --summary --numbered
    15	Protesilaos Stavrou

~/Git/Projects/denote-markdown $ git shortlog  --summary --numbered
    11	Protesilaos Stavrou
</code></pre></div></div>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: My new ‘Emacs Lisp Elements’ book</title>
      <description>I wrote a book that provides a big picture view of the Emacs Lisp programming language.</description>
      <pubDate>Sat, 12 Apr 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-04-12-emacs-lisp-elements-book/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-04-12-emacs-lisp-elements-book/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just published the book “Emacs Lisp Elements”. It is available for
free and in freedom under the same terms as all documentation that
ships with GNU Emacs:</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>

<p>I provide a big picture view of the Emacs Lisp programming language by
combining prose with code. The goal is to give readers an idea of how
Elisp works by showing some of the main concepts or patterns
discernible in everyday code.</p>

<p>Some chapters are beginner-friendly, while others dive into deeper
waters. Though I think everything is still approachable, as I try to
explain basic concepts and take things one step at a time.</p>

<p>The book is not meant to be a replacement for the built-in Emacs Lisp
Reference Manual. It simply gives you enough information to reason
about Elisp. Once you start extending Emacs, the rest will follow
naturally.</p>

<p>I hope you enjoy it and continue to have fun with Emacs.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: dired-preview version 0.5.0</title>
      <description>Information about the latest version of my dired-preview package for GNU Emacs.</description>
      <pubDate>Wed, 09 Apr 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-04-09-emacs-dired-preview-0-5-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-04-09-emacs-dired-preview-0-5-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.5.0 on 2025-04-09</h2>

<p>This version contains a few bug fixes and minor refinements that
should improve the behaviour of the package.</p>

<h3>Revised how preview windows are deleted</h3>

<p>In the past, <code class="language-plaintext highlighter-rouge">dired-preview-mode</code> could delete windows that held
another buffer, thus undoing the window layout that was present before
a preview buffer was displayed. Now <code class="language-plaintext highlighter-rouge">dired-preview-mode</code> makes sure to
only delete windows that have not had another buffer shown in them,
i.e. windows that were created just for preview purposes.</p>

<h3>Directories no longer get misunderstood as “large files”</h3>

<p>We tweaked how we test the type of the buffer-to-be-preview such that
directories are not mistaken for “large files”. This was an issue for
Mac computers that Sean Devlin brought to my attention in issue 27:
<a href="https://github.com/protesilaos/dired-preview/issues/27">https://github.com/protesilaos/dired-preview/issues/27</a>.</p>

<h3>The <code class="language-plaintext highlighter-rouge">dired-preview-delay</code> has a 0.1 second minimum to avoid instability</h3>

<p>A value of 0 could lead to a noticeably degraded experience while
navigating the Dired buffer. Thanks to Yiyu Zhou for reporting the
matter in issue 2 on the GitLab mirror:
<a href="https://gitlab.com/protesilaos/dired-preview/-/issues/2">https://gitlab.com/protesilaos/dired-preview/-/issues/2</a>.</p>

<h3>Files without an extension can also be ignored</h3>

<p>The user option <code class="language-plaintext highlighter-rouge">dired-preview-ignored-extensions-regexp</code> will now
also match files without an extension, such as the <code class="language-plaintext highlighter-rouge">.DS_Store</code> on Mac
computers.</p>

<p>Thanks to Sean Devlin for the contribution in pull request 26:
<a href="https://github.com/protesilaos/dired-preview/pull/26">https://github.com/protesilaos/dired-preview/pull/26</a>. The change is
within the ~15-line limit, meaning that Sean does not need to assign
copyright to the Free Software Foundation.</p>

<h3>The preview buffer is the “other window” for scrolling purposes</h3>

<p>The commands which scroll the other window, such as
<code class="language-plaintext highlighter-rouge">scroll-other-window</code> now operate on the preview buffer when that is
displayed. Thanks to Karthik Chikmagalur for proposing this in issue
24: <a href="https://github.com/protesilaos/dired-preview/issues/24">https://github.com/protesilaos/dired-preview/issues/24</a>.</p>

<p>This is in addition to the commands we already provided for scrolling
the preview window, namely, <code class="language-plaintext highlighter-rouge">dired-preview-page-up</code> and <code class="language-plaintext highlighter-rouge">dired-preview-page-down</code>.
Do <code class="language-plaintext highlighter-rouge">M-x describe-keymap</code> and then search for <code class="language-plaintext highlighter-rouge">dired-preview-mode-map</code>:
it is in effect when <code class="language-plaintext highlighter-rouge">dired-preview-mode</code> is enabled.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: stylistic refinements to the “tinted” Modus themes</title>
      <description>Status update on the development process of the 'modus-themes' package.</description>
      <pubDate>Sun, 06 Apr 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-04-06-emacs-modus-tinted-refinements/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-04-06-emacs-modus-tinted-refinements/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>As part of the current development target of the <code class="language-plaintext highlighter-rouge">modus-themes</code> package, I am introducing small changes to the <code class="language-plaintext highlighter-rouge">modus-operandi-tinted</code> and <code class="language-plaintext highlighter-rouge">modus-vivendi-tinted</code> themes. These concern fine details, some of which most users will probably not even notice. Though the cumulative effect of these changes is obvious once we compare the themes to their main counterparts, namely, <code class="language-plaintext highlighter-rouge">modus-operandi</code> and <code class="language-plaintext highlighter-rouge">modus-vivendi</code>. I am doing this to improve the consistency of the “tinted” themes. I think existing users will appreciate the attention to detail.</p>

<p>Below are some screen shots with the out-of-the-box design of the themes (remember that they are highly customisable). I also include pictures with <code class="language-plaintext highlighter-rouge">spacious-padding-mode</code> enabled (from my <code class="language-plaintext highlighter-rouge">spacious-padding</code> package). Notice that in this case the mode lines are just an overline, which is done by customising the user option <code class="language-plaintext highlighter-rouge">spacious-padding-subtle-mode-line</code>.</p>

<p>I plan to install those changes to emacs.git and make them available via GNU ELPA as part of <code class="language-plaintext highlighter-rouge">modus-themes</code> version <code class="language-plaintext highlighter-rouge">4.7.0</code>, which I hope to publish some time this month or in May.</p>

<h2>Modus Operandi VS Modus Operandi Tinted</h2>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-operandi-sample.png"><img alt="Sample of modus-operandi theme" src="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-operandi-sample.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-operandi-tinted-sample.png"><img alt="Sample of modus-operandi-tinted theme" src="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-operandi-tinted-sample.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-operandi-spacious-padding-sample.png"><img alt="Sample of modus-operandi theme" src="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-operandi-spacious-padding-sample.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-operandi-tinted-spacious-padding-sample.png"><img alt="Sample of modus-operandi-tinted theme" src="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-operandi-tinted-spacious-padding-sample.png" /></a></p>

<h2>Modus Vivendi VS Modus Vivendi Tinted</h2>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-vivendi-sample.png"><img alt="Sample of modus-vivendi theme" src="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-vivendi-sample.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-vivendi-tinted-sample.png"><img alt="Sample of modus-vivendi-tinted theme" src="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-vivendi-tinted-sample.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-vivendi-spacious-padding-sample.png"><img alt="Sample of modus-vivendi theme" src="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-vivendi-spacious-padding-sample.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-vivendi-tinted-spacious-padding-sample.png"><img alt="Sample of modus-vivendi-tinted theme" src="https://protesilaos.com/assets/images/attachments/2025-04-06-modus-vivendi-tinted-spacious-padding-sample.png" /></a></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 customized. 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: ‘denote-journal’ integration with ‘M-x calendar’</title>
      <description>The new version of my 'denote-journal' package will integrate with the Emacs 'calendar'.</description>
      <pubDate>Mon, 31 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-03-31-emacs-denote-journal-calendar/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-03-31-emacs-denote-journal-calendar/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I just made it possible for users of my <code class="language-plaintext highlighter-rouge">denote-journal</code> package to
interact with the <code class="language-plaintext highlighter-rouge">M-x calendar</code> as part of their journaling workflow.</p>

<h2>Highlight dates with a Denote journal entry</h2>

<p>The new minor mode <code class="language-plaintext highlighter-rouge">denote-journal-calendar-mode</code> highlights dates in
the <code class="language-plaintext highlighter-rouge">M-x calendar</code> which have a corresponding Denote journal entry.
The applied face is called <code class="language-plaintext highlighter-rouge">denote-journal-calendar</code>: I made it draw
only a box around the date, thus respecting existing colouration. Here
is a demonstration, which also includes red-coloured dates for holidays:</p>

<p><a href="https://protesilaos.com/assets/images/attachments/2025-03-31-emacs-denote-journal-calendar.png"><img alt="Generic Emacs calendar" src="https://protesilaos.com/assets/images/attachments/2025-03-31-emacs-denote-journal-calendar.png" /></a></p>

<p>The <code class="language-plaintext highlighter-rouge">denote-journal-calendar-mode</code> is buffer-local and meant to be
activated inside the <code class="language-plaintext highlighter-rouge">M-x calendar</code> buffer, thus:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'calendar-mode-hook</span> <span class="nf">#'</span><span class="nv">denote-journal-calendar-mode</span><span class="p">)</span>
</code></pre></div></div>

<h2>View the journal entry for the current date</h2>

<p>While navigating the <code class="language-plaintext highlighter-rouge">calendar</code> buffer, use the command
<code class="language-plaintext highlighter-rouge">denote-journal-calendar-find-file</code> to visit the Denote journal entry
corresponding to the date at point. If there are multiple journal
entries, the command will prompt you to select one among them.</p>

<h2>Create or view journal entry for the current date</h2>

<p>The command <code class="language-plaintext highlighter-rouge">denote-journal-calendar-new-or-existing</code> creates a new
journal entry for the date at point or visits any existing one. This is
like <code class="language-plaintext highlighter-rouge">denote-journal-new-or-existing-entry</code> but for the given <code class="language-plaintext highlighter-rouge">M-x
calendar</code> date.</p>

<h2>Part of development</h2>

<p>Remember that I have split <code class="language-plaintext highlighter-rouge">denote</code> into several packages, one of
which is <code class="language-plaintext highlighter-rouge">denote-journal</code>. I plan to coordinate the release of new
versions across all Denote-related packages, so expect the
aforementioned to be available at around the same time as <code class="language-plaintext highlighter-rouge">denote</code>
version <code class="language-plaintext highlighter-rouge">4.0.0</code> (which is going to be massive, by the way).</p>

<h3>About Denote journal</h3>

<p>The <code class="language-plaintext highlighter-rouge">denote-journal</code> package makes it easier to use Denote for
journaling. While it is possible to use the generic <code class="language-plaintext highlighter-rouge">denote</code> command
(and related) to maintain a journal, this package defines extra
functionality to streamline the journaling workflow.</p>

<p>The code of <code class="language-plaintext highlighter-rouge">denote-journal</code> used to be bundled up with the <code class="language-plaintext highlighter-rouge">denote</code>
package before version <code class="language-plaintext highlighter-rouge">4.0.0</code> of the latter and was available in the
file <code class="language-plaintext highlighter-rouge">denote-journal-extras.el</code>. Users of the old code will need to
adapt their setup to use the <code class="language-plaintext highlighter-rouge">denote-journal</code> package. This can be
done by replacing all instances of <code class="language-plaintext highlighter-rouge">denote-journal-extras</code> with
<code class="language-plaintext highlighter-rouge">denote-journal</code> across their configuration.</p>

<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>Backronym: Denote… Journaling Obviously Utilises Reasonableness
Notwithstanding Affectionate Longing.</li>
</ul>

<h3>About Denote</h3>

<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: Denote ‘query links’ (links that trigger a search)</title>
      <description>In this video demonstration, I show the new in-development functionality of Denote for 'query links'.</description>
      <pubDate>Fri, 28 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-03-28-emacs-denote-query-links/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-03-28-emacs-denote-query-links/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=zqzAFj50MhE">https://www.youtube.com/watch?v=zqzAFj50MhE</a></p>
         
         <p>In this ~16-minute video, I demonstrate the new, in-development “query
links” functionality of Denote. These are links that trigger a search
when you interact with them. There are two types of query links: (i)
search in file contents, or (ii) search in file names. When there are
matches for a given query, those are displayed in a separate buffer,
which uses the appropriate major mode. Query links complement the
“direct links” Denote has always supported. Internally, they use the
same infrastructure that Denote backlinks rely on (and we have had
backlink support since the beginning).</p>

<h2>Denote sources</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: first look at query links for Denote version 4.0.0</title>
      <description>Report of the in-progress implementation of Denote 'query links'.</description>
      <pubDate>Mon, 24 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-03-24-emacs-denote-query-links/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-03-24-emacs-denote-query-links/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>The next version of Denote is shaping up to be a huge one. One of the
newest features I am working on is the support for “query links”.
Those use the same <code class="language-plaintext highlighter-rouge">denote:</code> link type infrastructure but exhibit a
different behaviour than the direct links we have always had. Instead
of pointing to a file via its unique identifier, they initiate a
search through the contents of all files in the <code class="language-plaintext highlighter-rouge">denote-directory</code>.
This search uses the built-in Xref mechanism and is the same as what
we have already been doing with backlinks (basically, a <code class="language-plaintext highlighter-rouge">grep</code>).</p>

<p>In short:</p>

<ul>
  <li><strong>Direct links:</strong> Those point to a file via its unique identifier.
For example, <code class="language-plaintext highlighter-rouge">denote:20250324T074132</code> resolves to a file path.
Clicking on the link opens the corresponding file. Org export will
also take care to turn this into a file path.</li>
  <li><strong>Query links:</strong> Those do not point to any file per se. They are a
string of one or more words or regular expression which is matched
against the contents of files. For example, <code class="language-plaintext highlighter-rouge">denote:this is a test</code>
produces a buffer listing all matches for the given query. Clicking
on the matching line in that buffer opens the file at that point
(just how our backlinks work when they show context—I am
generalising this mechanism).</li>
</ul>

<p><em>Direct links</em> can point to any file, including PDFs, videos, and
pictures (assuming it is renamed to use the Denote file-naming
scheme). Whereas <em>query links</em> are limited to text files.</p>

<h2>Development discussion and screenshots</h2>

<p>This is a work-in-progress that lives on its own branch as of this
writing. I will not elaborate at length right now as the
implementation details may change. I have, nonetheless, created an
issue on the GitHub repository where interested parties can provide
their feedback. It also includes some screenshots I took:
<a href="https://github.com/protesilaos/denote/issues/561">https://github.com/protesilaos/denote/issues/561</a>. The code includes
other changes which pertain to how we handle backlinks and constitutes
a simplification of the code base.</p>

<p>The idea is to add the functionality to the <code class="language-plaintext highlighter-rouge">main</code> branch in the
coming days or weeks. Then I will do a video about it and/or explain
more.</p>

<p>That granted, do not forget that the official manual is the most
up-to-date reference and the single source of truth.</p>

<h2>Denote sources</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>[ Further down on this list I include more of my Denote-related packages. ]</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: how I build from emacs.git on Debian stable</title>
      <description>Step-by-step guide on how I build Emacs from source on Debian stable.</description>
      <pubDate>Sat, 22 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-03-22-emacs-build-source-debian/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-03-22-emacs-build-source-debian/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I have been following the <code class="language-plaintext highlighter-rouge">master</code> branch of the emacs.git repository
for many years now. It helps me test new features and make necessary
adjustments to all the packages I develop/maintain. Below I explain
how I make this happen on my computer, which is running Debian stable
(Debian 12 “Bookworm” as of this writing). If you are a regular user,
there is no reason to build from source: just use the latest stable
release and you should be fine.</p>

<h2>Configure the <code class="language-plaintext highlighter-rouge">apt</code> development sources</h2>

<p>To build Emacs from source on Debian, you first need to have the
<code class="language-plaintext highlighter-rouge">deb-src</code> package archive enabled. In your <code class="language-plaintext highlighter-rouge">/etc/apt/sources.list</code>
file you must have something like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>deb http://deb.debian.org/debian/ bookworm main
deb-src http://deb.debian.org/debian/ bookworm main
</code></pre></div></div>

<p>After modifying the sources, run the following on the command line to
fetch the index with new package names+versions:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt update
</code></pre></div></div>

<h2>Get the Emacs build dependencies</h2>

<p>Now that you have enabled the <code class="language-plaintext highlighter-rouge">deb-src</code> archive, you can install the
build dependencies of the Debian <code class="language-plaintext highlighter-rouge">emacs</code> package with the following on
the command line:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt build-dep emacs
</code></pre></div></div>

<p>With this done, you are ready to build Emacs from source.</p>

<h2>Get the Emacs source code</h2>

<p>You need the <code class="language-plaintext highlighter-rouge">git</code> program to get the source code from the emacs.git
website. So install it with this command:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install git
</code></pre></div></div>

<p>Now make a copy of the Emacs source code, using this on the command
line:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://git.savannah.gnu.org/git/emacs.git ~/path/to/my/copy-of-emacs.git
</code></pre></div></div>

<p>Replace <code class="language-plaintext highlighter-rouge">~/path/to/my/copy-of-emacs.git</code> with the actual destination
of your preference. I have a <code class="language-plaintext highlighter-rouge">~/Builds</code> directory where I store all
the projects I build from source. I thus do:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://git.savannah.gnu.org/git/emacs.git ~/Builds/emacs.git
</code></pre></div></div>

<p>If the cloning process is too slow on your end, perform a <em>shallow
clone</em> instead. For example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone --depth 1 https://git.savannah.gnu.org/git/emacs.git ~/Builds/emacs.git
</code></pre></div></div>

<p>And if the Savannah website is not responsive, then clone from the
GitHub mirror (with the <code class="language-plaintext highlighter-rouge">--depth 1</code> if necessary):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/emacs-mirror/emacs.git ~/Builds/emacs.git
</code></pre></div></div>

<h2>Switch to the Emacs directory</h2>

<p>Assuming you have the copy of emacs.git stored at <code class="language-plaintext highlighter-rouge">~/Builds/emacs.git</code>,
you switch to that directory with the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ~/Builds/emacs.git
</code></pre></div></div>

<p>Keep in mind that unless you explicitly switch to another branch, you
are on <code class="language-plaintext highlighter-rouge">master</code>, i.e. the latest development target.</p>

<p><strong>NOTE:</strong> All subsequent commands are ran from your equivalent of
<code class="language-plaintext highlighter-rouge">~/Builds/emacs.git</code>.</p>

<h2>Run the <code class="language-plaintext highlighter-rouge">autogen.sh</code> the first time</h2>

<p>This script will generate the configuration scaffold. You only really
need to do this once (and I always forget about it for this very
reason). Simply do this on the command line:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./autogen.sh
</code></pre></div></div>

<p>It checks that you have all you need to get started and prints output
like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Checking whether you have the necessary tools...
(Read INSTALL.REPO for more details on building Emacs)
Checking for autoconf (need at least version 2.65) ... ok
Your system has the required tools.
Building aclocal.m4 ...
Running 'autoreconf -fi -I m4' ...
Building 'aclocal.m4' in exec ...
Running 'autoreconf -fi' in exec ...
Configuring local git repository...
'.git/config' -&gt; '.git/config.~1~'
git config transfer.fsckObjects 'true'
git config diff.cpp.xfuncname '!^[ 	]*[A-Za-z_][A-Za-z_0-9]*:[[:space:]]*($|/[/*])
^((::[[:space:]]*)?[A-Za-z_][A-Za-z_0-9]*[[:space:]]*\(.*)$
^((#define[[:space:]]|DEFUN).*)$'
git config diff.elisp.xfuncname '^\([^[:space:]]*def[^[:space:]]+[[:space:]]+([^()[:space:]]+)'
git config diff.m4.xfuncname '^((m4_)?define|A._DEFUN(_ONCE)?)\([^),]*'
git config diff.make.xfuncname '^([$.[:alnum:]_].*:|[[:alnum:]_]+[[:space:]]*([*:+]?[:?]?|!?)=|define .*)'
git config diff.shell.xfuncname '^([[:space:]]*[[:alpha:]_][[:alnum:]_]*[[:space:]]*\(\)|[[:alpha:]_][[:alnum:]_]*=)'
git config diff.texinfo.xfuncname '^@node[[:space:]]+([^,[:space:]][^,]+)'
Installing git hooks...
'build-aux/git-hooks/commit-msg' -&gt; '.git/hooks/commit-msg'
'build-aux/git-hooks/pre-commit' -&gt; '.git/hooks/pre-commit'
'build-aux/git-hooks/prepare-commit-msg' -&gt; '.git/hooks/prepare-commit-msg'
'build-aux/git-hooks/post-commit' -&gt; '.git/hooks/post-commit'
'build-aux/git-hooks/pre-push' -&gt; '.git/hooks/pre-push'
'build-aux/git-hooks/commit-msg-files.awk' -&gt; '.git/hooks/commit-msg-files.awk'
'.git/hooks/applypatch-msg.sample' -&gt; '.git/hooks/applypatch-msg'
'.git/hooks/pre-applypatch.sample' -&gt; '.git/hooks/pre-applypatch'
You can now run './configure'.
</code></pre></div></div>

<p>Do not be intimidated by it. Focus on the final line instead, which
directs you to the <code class="language-plaintext highlighter-rouge">configure</code> directive.</p>

<h2>Explore the build flags</h2>

<p>How exactly you build Emacs depends on your preferences and
system-specific requirements. At the end of this post, I copy my
current configuration, though <strong>I advise against</strong> copying it without
understanding what it does.</p>

<p>If you have no specific preferences, just use the defaults by running
this on the command line:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./configure
</code></pre></div></div>

<p>It will set up the build environment for you. If, however, you wish
to explore your options and customise the <code class="language-plaintext highlighter-rouge">emacs</code> program you will
get, then issue the following command and carefully read its output:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./configure --help
</code></pre></div></div>

<p>The <strong>minimum I recommend</strong> is to specify where the build artefacts
are stored. I use this, which has not caused me any issues over the
years:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./configure --prefix=/usr/local
</code></pre></div></div>

<h2>Configure the build environment with your preferred flags</h2>

<p>Once you have understood the available options, go ahead and run
<code class="language-plaintext highlighter-rouge">configure</code>. For example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./configure --prefix=/usr/local --with-x-toolkit=gtk3
</code></pre></div></div>

<p>Whenever you need to rebuild Emacs with some new flags, run the
<code class="language-plaintext highlighter-rouge">configure</code> command again, passing it the relevant flags. If you wish
to keep the same options for a new build, then simply do not run
<code class="language-plaintext highlighter-rouge">configure</code> again.</p>

<h2>Make the program</h2>

<p>Once <code class="language-plaintext highlighter-rouge">configure</code> finishes its work, it is time to run the <code class="language-plaintext highlighter-rouge">make</code>
program. For new builds, this is as simple as:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make
</code></pre></div></div>

<p>Sometimes you have old build artefacts that conflict with changes
upstream. When that happens, the build process will fail. You may then
need to use:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make bootstrap
</code></pre></div></div>

<p>In general, <code class="language-plaintext highlighter-rouge">make</code> is enough. It will be slow the first time, but will
be faster on subsequent runs as it reuses what is already there. A
<code class="language-plaintext highlighter-rouge">make bootstrap</code> will always be slow though, as it generates
everything anew.</p>

<h2>Install the program that was made</h2>

<p>After <code class="language-plaintext highlighter-rouge">make</code> is done, you are ready to install Emacs:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo make install
</code></pre></div></div>

<p>You will not need escalated privileges (i.e. <code class="language-plaintext highlighter-rouge">sudo</code>) is you specified
a <code class="language-plaintext highlighter-rouge">--prefix</code> with a user directory during the <code class="language-plaintext highlighter-rouge">configure</code> step. How
you go about it is up to you.</p>

<h2>Keeping Emacs up-to-date</h2>

<p>Whenever you wish to update from source, go to where your copy of
emacs.git is (e.g. <code class="language-plaintext highlighter-rouge">~/Builds/emacs.git</code>) and pull the latest changes
using the <code class="language-plaintext highlighter-rouge">git</code> program:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git pull
</code></pre></div></div>

<p>Then repeat <code class="language-plaintext highlighter-rouge">make</code> and <code class="language-plaintext highlighter-rouge">make install</code>. Remember that you do not need
to re-run <code class="language-plaintext highlighter-rouge">configure</code> unless you specifically want to modify your
build (and if you do that, you probably need to <code class="language-plaintext highlighter-rouge">make bootstrap</code>).</p>

<h2>Learn about the latest <code class="language-plaintext highlighter-rouge">NEWS</code></h2>

<p>Emacs users can at all times learn about changes introduced in their
current version of Emacs with <code class="language-plaintext highlighter-rouge">M-x view-emacs-news</code>. It is bound to
the key <code class="language-plaintext highlighter-rouge">C-h n</code> by default. This command opens the current <code class="language-plaintext highlighter-rouge">NEWS</code>
file. With a numeric prefix argument, you get the <code class="language-plaintext highlighter-rouge">NEWS</code> of the given
Emacs version. For example, <code class="language-plaintext highlighter-rouge">C-u 27 C-h n</code> shows you what Emacs
version 27 introduced.</p>

<h2>Compare your <code class="language-plaintext highlighter-rouge">NEWS</code> to those of emacs.git</h2>

<p>With the help of the built-in Emacs <code class="language-plaintext highlighter-rouge">ediff</code> package, you can compare
your latest <code class="language-plaintext highlighter-rouge">NEWS</code> to those coming from emacs.git. I always do this
after pulling the latest changes from source (with <code class="language-plaintext highlighter-rouge">git pull</code>).</p>

<p>From the root directory of your copye of emacs.git (e.g.
<code class="language-plaintext highlighter-rouge">~/Builds/emacs.git</code>), and while using Emacs, you can do <code class="language-plaintext highlighter-rouge">M-x
project-find-file</code> (<code class="language-plaintext highlighter-rouge">C-x p f</code>) to search the Emacs “project” for a
file called <code class="language-plaintext highlighter-rouge">etc/NEWS</code>. This is where the latest user-facing changes
are recorded.</p>

<p>If you are not sure where you are on the filesystem while inside
Emacs, do <code class="language-plaintext highlighter-rouge">M-x cd</code> (or <code class="language-plaintext highlighter-rouge">M-x dired</code> or <code class="language-plaintext highlighter-rouge">M-x find-file</code>), select the
root directory of your emacs.git, hit <code class="language-plaintext highlighter-rouge">RET</code>, and then do <code class="language-plaintext highlighter-rouge">M-x
project-find-file</code>.</p>

<p>Now that you have <code class="language-plaintext highlighter-rouge">emacs.git/etc/NEWS</code> in a buffer, also load your
copy of <code class="language-plaintext highlighter-rouge">NEWS</code> with <code class="language-plaintext highlighter-rouge">M-x view-emacs-news</code> (<code class="language-plaintext highlighter-rouge">C-h n</code>).</p>

<p>Then do <code class="language-plaintext highlighter-rouge">M-x ediff-buffers</code>, which will prompt for two buffers to
compare. First select your version of <code class="language-plaintext highlighter-rouge">NEWS</code> and then that of emacs.git.</p>

<p><strong>NOTE:</strong> I think the default Ediff interface is problematic. Put the
following in your configuration to make it work in a single frame:</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">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>
</code></pre></div></div>

<p>Also watch my video with the Ediff basics: <a href="https://protesilaos.com/codelog/2023-11-17-emacs-ediff-basics/">https://protesilaos.com/codelog/2023-11-17-emacs-ediff-basics/</a>.</p>

<p>This is it. You are now in the flow of building Emacs from source.
Good luck with everything!</p>

<h2>My current build options</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>--prefix=/usr/local --without-xinput2 --without-compress-install --without-gpm --without-selinux --with-native-compilation=yes --with-sound=no --without-gif --without-tiff --with-cairo --with-harfbuzz --with-tree-sitter=ifavailable --with-json --without-gsettings --without-gconf --with-x-toolkit=no --without-toolkit-scroll-bars --without-xft --without-xaw3d
</code></pre></div></div>

<p>I am not updating old publications, unless otherwise noted. The most
up-to-date recode of my Emacs build is documented in my dotemacs:
<a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a>.</p>

<p>Inspect the value of the Emacs variable <code class="language-plaintext highlighter-rouge">system-configuration-options</code>
to find out how your Emacs is built.</p>

<p>Have fun!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: Denote is becoming many packages</title>
      <description>I am almost done splitting the 'denote' Emacs package into 'core' and 'extensions'. Here is what users need to know.</description>
      <pubDate>Fri, 14 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-03-14-emacs-denote-many-packages/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-03-14-emacs-denote-many-packages/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>In February I announced the plan to reorganise the Denote project into
“core” and “extensions”: <a href="https://protesilaos.com/codelog/2025-02-11-emacs-splitting-denote-many-packages/">https://protesilaos.com/codelog/2025-02-11-emacs-splitting-denote-many-packages/</a>.
In essence, Denote is a file-naming scheme: you create new files
and/or rename existing ones (of any file type). Having that naming
scheme empowers you to retrieve stuff more easily without the need for
advanced tooling.</p>

<p>Though it turns out we can do a lot of useful things on top of this
simple-yet-powerful idea: custom Dired listings, Org dynamic blocks,
sequence notes, journaling, and many more. Having a clear separation
between core and extensions makes it easier for us to implement all
the features we want without worrying that the main package is
becoming bloated.</p>

<p>Concretely, much of the functionality that was part of the <code class="language-plaintext highlighter-rouge">denote</code>
package will now be provided by other packages. To this end, I just
made a change to the official elpa.git repository:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>commit f23ff49fb8df22390fe139b432f763860a354175
Author: Protesilaos Stavrou &lt;info@protesilaos.com&gt;
Date:   Fri Mar 14 07:14:55 2025 +0200

  * elpa-packages (denote-journal, denote-markdown, denote-org, denote-sequence, denote-silo): Add new packages

 elpa-packages | 10 ++++++++++
 1 file changed, 10 insertions(+)
</code></pre></div></div>

<h2>Finalising the reorganisation of Denote</h2>

<p>What remains to be done is for me to merge the <code class="language-plaintext highlighter-rouge">reorganise-denote</code>
branch of denote.git into <code class="language-plaintext highlighter-rouge">main</code>. I will do this as soon as the new
packages are indexed on GNU ELPA (maybe later today or tomorrow).</p>

<p>Users of the GNU ELPA package will not be affected immediately. Those
who build from source will, however, have to take action.</p>

<h2>Expect breaking changes</h2>

<p>Users will experience breaking changes when they update to the new
<code class="language-plaintext highlighter-rouge">denote</code> package: functionality will be missing. In principle, all
those should be easy to fix: install the appropriate new package and
rename the functions/variables in your configuration accordingly. In
detail:</p>

<ul>
  <li>The file <code class="language-plaintext highlighter-rouge">denote-journal-extras.el</code> becomes the package
<code class="language-plaintext highlighter-rouge">denote-journal</code>. In your configuration replace
<code class="language-plaintext highlighter-rouge">denote-journal-extras</code> with <code class="language-plaintext highlighter-rouge">denote-journal</code>.</li>
  <li>The file <code class="language-plaintext highlighter-rouge">denote-org-extras.el</code> (Org dynamic blocks and related)
becomes the package <code class="language-plaintext highlighter-rouge">denote-org</code>. In your configuration replace
<code class="language-plaintext highlighter-rouge">denote-org-extras</code> with <code class="language-plaintext highlighter-rouge">denote-org</code>.</li>
  <li>The file <code class="language-plaintext highlighter-rouge">denote-silo-extras.el</code> becomes the package <code class="language-plaintext highlighter-rouge">denote-silo</code>.
In your configuration replace <code class="language-plaintext highlighter-rouge">denote-silo-extras</code> with
<code class="language-plaintext highlighter-rouge">denote-silo</code>.</li>
</ul>

<p>Additionally, the files that were in development but never made it as
part of a formal release, namely, <code class="language-plaintext highlighter-rouge">denote-md-extras.el</code> and
<code class="language-plaintext highlighter-rouge">denote-sequence.el</code>, will debut as their own packages:
<code class="language-plaintext highlighter-rouge">denote-markdown</code> and <code class="language-plaintext highlighter-rouge">denote-sequence</code>, respectively.</p>

<h2>You are welcome to ask me any questions</h2>

<p>I am reluctant to introduce breaking changes, though this has to be
done for the long-term wellness of the project. If you have any
questions, please contact me directly or open an issue on the GitHub
repository. I am happy to help you.</p>

<h2>A concerted release cadence</h2>

<p>All new packages are marked as version <code class="language-plaintext highlighter-rouge">0.0.0</code>, which means that only
those who track GNU-devel ELPA (or build from source) will notice
them. The formal release will coincide with the new version of
<code class="language-plaintext highlighter-rouge">denote</code> (<code class="language-plaintext highlighter-rouge">4.0.0</code>), which I expect to publish some time in April or
May 2025.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Live @ 2025-03-15, 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>Sat, 08 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-03-08-live-stream-emacs-linux-life/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-03-08-live-stream-emacs-linux-life/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=p5VPxbr-2ds">https://www.youtube.com/watch?v=p5VPxbr-2ds</a></p>
         
         <p>On Saturday, the 15th of March 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, free
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.</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. My electricity should be okay because the weather forecast shows
a clear day with fairly warm temperatures (finally!).</p>

<p>The event will be recorded, so no worries if you cannot make it live.</p>

<p>Talk to all of you soon!</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: fontaine version 3.0.0</title>
      <description>Information about the latest version of my fontaine package for GNU Emacs.</description>
      <pubDate>Thu, 20 Feb 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-02-20-emacs-fontaine-3-0-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-02-20-emacs-fontaine-3-0-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Fontaine allows the user to define detailed font configurations and set
them on demand.  For example, one can have a <code class="language-plaintext highlighter-rouge">regular-editing</code> preset
and another for <code class="language-plaintext highlighter-rouge">presentation-mode</code> (these are arbitrary, user-defined
symbols): the former uses small fonts which are optimised for writing,
while the latter applies typefaces that are pleasant to read at
comfortable point sizes.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">fontaine</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/fontaine">https://protesilaos.com/emacs/fontaine</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/fontaine-changelog">https://protesilaos.com/emacs/fontaine-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/fontaine">https://github.com/protesilaos/fontaine</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/fontaine">https://gitlab.com/protesilaos/fontaine</a></li>
    </ul>
  </li>
  <li>Backronym: Fonts, Ornaments, and Neat Typography Are Irrelevant in Non-graphical Emacs.</li>
</ul>

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

<hr />

<h2>Version 3.0.0 on 2025-02-20</h2>

<p>This version changes the underlying implementation of Fontaine’s font
configuration presets. In principle, this should not have any effect
on how users experience the package, though there are some important
details that are different.</p>

<h3>Fontaine is now a “theme”</h3>

<p>Fontaine has always modified typography-related faces, such as
<code class="language-plaintext highlighter-rouge">default</code>, <code class="language-plaintext highlighter-rouge">fixed-pitch</code>, and <code class="language-plaintext highlighter-rouge">variable-pitch</code>, to apply the font
family, height, and weight specified by the user. In the past, this
was done in a way that could get overridden under certain conditions,
such as by loading a theme after setting a Fontaine preset configuration.</p>

<p>By making Fontaine a theme, we guarantee that its settings are not
undone. In practice, this means that users do not have to re-apply the
current preset after loading a theme. The function <code class="language-plaintext highlighter-rouge">fontaine-apply-current-preset</code>
is thus obsolete.</p>

<p>In Emacs, a “theme” is a bundle of configurations. Those typically
cover colours (such as with my <code class="language-plaintext highlighter-rouge">modus-themes</code>), but a theme can focus
on other settings as well. For example, the popular <code class="language-plaintext highlighter-rouge">use-package</code> is
internally done as a theme (check the value of <code class="language-plaintext highlighter-rouge">custom-known-themes</code>).</p>

<p>Fontaine is a theme in the same way <code class="language-plaintext highlighter-rouge">use-package</code> is, meaning that it
will (i) persist its effects, (ii) not show up in the
<code class="language-plaintext highlighter-rouge">custom-enabled-themes</code> and so not be affected by something like
<code class="language-plaintext highlighter-rouge">(mapc #'disable-theme custom-enabled-themes)</code>,
and (iii) not be an option among those presented by <code class="language-plaintext highlighter-rouge">load-theme</code>.</p>

<p>There are no known bugs, though please contact me if you encounter a
scenario where Fontaine does not do the right thing. Thanks, in this
regard, to Haruko and Emily Hyland for reporting a couple of bugs:</p>

<ul>
  <li><a href="https://github.com/protesilaos/fontaine/issues/14">https://github.com/protesilaos/fontaine/issues/14</a>.</li>
  <li><a href="https://github.com/protesilaos/fontaine/issues/15">https://github.com/protesilaos/fontaine/issues/15</a>.</li>
</ul>

<h3>Fontaine no longer has frame-specific effects</h3>

<p>In the past, users could apply a Fontaine preset to the current frame
without affecting other frames. While this could be useful in certain
situations, it was ultimately making the code more complex for
marginal gains. As part of the transition to a theme, which is anyway
global, I am removing everything related to frame-specific functionality.</p>

<h3>Quality-of-life refinements</h3>

<ul>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">fontaine-generic-face-families</code> are used when necessary to
guard against <code class="language-plaintext highlighter-rouge">nil</code> values. Those font families are symbolic
references to whatever the operating system is configured to use
(e.g. on Linux this is handled by fontconfig).</p>
  </li>
  <li>
    <p>If Fontaine is instructed to load an invalid preset, it displays a
warning and does nothing else. Before, it would produce an error,
which could prevent Emacs from starting up normally if this were to
happen at startup. A warning is enough to inform the user of what is
happening.</p>
  </li>
  <li>
    <p>Same principle as above when Emacs is not ran in a graphical
interface. In text terminals, Fontaine cannot work because it is not
possible to have different font families, styles, and heights, than
those of the terminal (hence the backronym of FONTAINE “Fonts,
Ornaments, and Neat Typography Are Irrelevant in Non-graphical
Emacs”). Thanks to Jorge Gomez for the patch in pull request 13:
<a href="https://github.com/protesilaos/fontaine/pull/13">https://github.com/protesilaos/fontaine/pull/13</a>. Further tweaks by
me.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">fontaine-toggle-preset</code> command will produce an error if it
cannot find the preset it is supposed to switch to. The toggle is
between the last two loaded presets, as done by the command
<code class="language-plaintext highlighter-rouge">fontaine-set-preset</code> (the <code class="language-plaintext highlighter-rouge">fontaine-mode</code> takes care to persist the
relevant history).</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: dired-preview version 0.4.0</title>
      <description>Information about the latest version of my dired-preview package for GNU Emacs.</description>
      <pubDate>Tue, 18 Feb 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-02-18-emacs-dired-preview-0-4-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-02-18-emacs-dired-preview-0-4-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.4.0 on 2025-02-18</h2>

<p>This version contains several refinements and bug fixes.</p>

<h3>Preview buffers have a mode line indicator</h3>

<p>Preview buffers have a prefix to their name to make them stand out.
This is controlled by the user option <code class="language-plaintext highlighter-rouge">dired-preview-buffer-name-indicator</code>,
which is a string that defaults to <code class="language-plaintext highlighter-rouge">[P]</code>.</p>

<h3>Control how preview buffers are cleaned up</h3>

<p>The way <code class="language-plaintext highlighter-rouge">dired-preview</code> works is to display a buffer and then keep a
list of preview buffers to economise on redisplaying it again. This
list of buffers is relevant for as long as we are in the Dired buffer,
otherwise all buffers therein are killed (buffers that were alive
before being previewed are not touched).</p>

<p>By default we delete from oldest to newest the accumulated buffers
when they exceed <code class="language-plaintext highlighter-rouge">10</code> in total. Though users can modify this behaviour
by editing the value of the new user option <code class="language-plaintext highlighter-rouge">dired-preview-kill-buffers-method</code>
(its doc string explains the technicalities).</p>

<p>Thanks to artelse for discussing this with me in issue 20:
<a href="https://github.com/protesilaos/dired-preview/issues/20">https://github.com/protesilaos/dired-preview/issues/20</a>.</p>

<h3>The <code class="language-plaintext highlighter-rouge">dired-preview-display-action-alist</code> has a new optional function</h3>

<p>The <code class="language-plaintext highlighter-rouge">dired-preview-display-action-alist</code> is the user option which
controls where the preview window is displayed. Its value can either
be the symbol of a function or a <code class="language-plaintext highlighter-rouge">display-buffer-alist</code> entry.</p>

<p>By default, we have a “do-what-I-mean” function that tries to find a
good placement for the window. The new <code class="language-plaintext highlighter-rouge">dired-preview-display-action-alist-below</code>
function has a straightforward behaviour: it always shows the preview
below the current window and it always makes the preview window 0.3
times the height of the Emacs frame.</p>

<h3>Encypted files are no longer previewed</h3>

<p>This is to ensure that potentially sensitive contents are not
displayed by accident, such as during a video call.</p>

<h3>We no longer preview the “self” directory</h3>

<p>We should not trigger a preview when the cursor is over the implicit
<code class="language-plaintext highlighter-rouge">.</code> directory, as that causes a recursion that breaks things. Thanks
to Inkbottle007 for reporting the bug in issue 23:
<a href="https://github.com/protesilaos/dired-preview/issues/23">https://github.com/protesilaos/dired-preview/issues/23</a>.</p>

<h3>Miscellaneous</h3>

<ul>
  <li>
    <p>Fixed a scenario where we would try to delete the last available
window on the current frame. This should never happen. Thanks to
artelse for reporting a relevant bug in the discussion of issue 22:
<a href="https://github.com/protesilaos/dired-preview/issues/22">https://github.com/protesilaos/dired-preview/issues/22</a>.</p>
  </li>
  <li>
    <p>Fixed a case when <code class="language-plaintext highlighter-rouge">hexl-follow-ascii</code> could fail to find an overlay
under certain conditions. This did not create any noticeable
problems, though having an error there would interfere with any
workflow that would rely on <code class="language-plaintext highlighter-rouge">toggle-debug-on-error</code>.</p>
  </li>
  <li>
    <p>The preview window will automatically be closed if the user switches
outside the given Dired buffer. We now do not consider a change to
the minibuffer as being “outside” this context. This way, a quick
<code class="language-plaintext highlighter-rouge">M-x</code> to, say, enable a minor mode does not have any effect on the
window layout.</p>
  </li>
  <li>
    <p>Suppressed the messaging facility of the underlying tracking of
preview buffers. Otherwise, Dired would notify us that the directory
has changed whenever we would preview a new one, which is
superfluous.</p>
  </li>
  <li>
    <p>The body of the <code class="language-plaintext highlighter-rouge">dired-preview-trigger</code> function, which determines
whether a preview will be displayed, is encapsulated in a <code class="language-plaintext highlighter-rouge">condition-case</code>.
This helps capture errors and thus have a more predictable behaviour.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">dired-preview-display-action-alist</code> has a more accurate
declaration which allows for its correct customisation inside the
Custom UI interface. In particular, it will behave the same way as
the <code class="language-plaintext highlighter-rouge">display-buffer-alist</code>, where relevant.</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Aporetic fonts version 1.1.0</title>
      <description>Release notes for the latest version of my custom 'Aporetic' fonts.</description>
      <pubDate>Wed, 12 Feb 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-02-12-aporetic-fonts-version-1-1-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-02-12-aporetic-fonts-version-1-1-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>This release includes two stylistic corrections that pertain to
Aporetic Serif and Aporetic Serif Mono.</p>

<ul>
  <li>
    <p>The first change is to the slanted (italic) form of the letter <code class="language-plaintext highlighter-rouge">t</code>.
Before, it was mistakenly set to have a curved, upward-facing bottom
stroke, which would clash with the flat bottom of <code class="language-plaintext highlighter-rouge">i</code> and <code class="language-plaintext highlighter-rouge">l</code>. Now
the slanted <code class="language-plaintext highlighter-rouge">t</code> has a flat bottom as intended. The upright (roman)
variants are always flat in this regard.</p>
  </li>
  <li>
    <p>The second change is to the letter <code class="language-plaintext highlighter-rouge">m</code> in both upright and slanted
forms. Before, the <code class="language-plaintext highlighter-rouge">m</code> would have a top left serif, as intended, but
not a bottom right tail. The tail is a feature of other glyphs that
need to have such a style, like <code class="language-plaintext highlighter-rouge">a</code>, <code class="language-plaintext highlighter-rouge">h</code>, <code class="language-plaintext highlighter-rouge">n</code>, <code class="language-plaintext highlighter-rouge">u</code>: it imposes a
proper rhythm together with the rest of the serif details. Now the <code class="language-plaintext highlighter-rouge">m</code>
has its missing bottom right tail, making everything consistent.</p>

    <p>[ The <code class="language-plaintext highlighter-rouge">m</code> has a shorter middle leg in all the “mono” families” to
  improve readability, especially at small point sizes. The
  proportionately spaced fonts use a normal middle leg, as <code class="language-plaintext highlighter-rouge">m</code> is
  naturally wider there and thus is already perfectly legible. The
  other details are the same. ]</p>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: I am in the process of splitting Denote into many packages</title>
      <description>Development note on the future of my 'denote' package for Emacs. The plan is to separate the core from its extensions.</description>
      <pubDate>Tue, 11 Feb 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-02-11-emacs-splitting-denote-many-packages/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-02-11-emacs-splitting-denote-many-packages/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I am reorganising the <code class="language-plaintext highlighter-rouge">denote</code> package to have a clear separation
between “core” and “extensions”. The idea is to decouple the two. The
<code class="language-plaintext highlighter-rouge">denote</code> package shall provide only the core functionality, while all
other features we already have will be available as standalone
packages.</p>

<p>The reason I am doing this is because the project has organically
grown over time to encompass lots of useful-yet-inessential
applications, such as Org dynamic blocks, journaling capabilities, and
sequence schemes, among others.</p>

<p>All those extras are nice to have, though they dilute the message
about what Denote is, making it seem far more complex than it actually
is. They are also held back by the minimalist outlook of the core:
they cannot be developed to their logical end, as any dependency they
incorporate becomes a dependency of the whole project, which makes no
sense (e.g. we can have a <code class="language-plaintext highlighter-rouge">transient.el</code> to interact with Denote
commands, but this is in no way essential, so why force it upon
everyone who downloads the <code class="language-plaintext highlighter-rouge">denote</code> package?).</p>

<h2>The core</h2>

<p>Denote essentially is a file-naming scheme. We create new files or
rename existing ones to have file names that are easy to retrieve with
even basic tools. This is my use-case and the reason I wrote Denote: I
name my videos, PDFs, pictures, and “notes” with the Denote
file-naming scheme, making it easy for me to find everything.</p>

<p>I think the Denote file-naming scheme is ingenious, though the real
value is in having a scheme—any scheme—to force consistency in how
you name things. Consistency begets predictability, which in turn
increases the likelihood of finding your data.</p>

<p>The other part of retrieving information is through links. Part of the
Denote file-naming scheme is the date+time, which is a unique
identifier. We can thus link to any file in the <code class="language-plaintext highlighter-rouge">denote-directory</code>
using its identifier. Once we have these “forward links”, we can
easily figure out what the “backward links” of a given file are, i.e.
which files link to the current one.</p>

<p>This is the core, plus a few other conveniences that I need not
enumerate herein.</p>

<h2>The extensions</h2>

<p>Anything that builds on the aforementioned is an “extension” and will
have its own Git repository as well as user manual. To this end, I
have already removed <code class="language-plaintext highlighter-rouge">denote-sequence.el</code> from the <code class="language-plaintext highlighter-rouge">denote</code> core and
made it its own entity:</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">denote-sequence</code> (⚠️ Not available yet)</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>The plan is to do the same with the “Org extras”, such as with all the
Org dynamic blocks, the “Markdown extras”, the “journal extras”, and
the “silo extras”. Once all the packages are ready for widespread use,
I will add them to GNU ELPA. Until then, everything is a WORK-IN-PROGRESS.</p>

<p>For the time being, the technical discussion is done in issue 543:
<a href="https://github.com/protesilaos/denote/issues/543">https://github.com/protesilaos/denote/issues/543</a>. The code which
will eventually be merged into the <code class="language-plaintext highlighter-rouge">main</code> branch resides in the
<code class="language-plaintext highlighter-rouge">reorganise-denote</code> branch: <a href="https://github.com/protesilaos/denote/tree/reorganise-denote">https://github.com/protesilaos/denote/tree/reorganise-denote</a>.</p>

<h2>For the longer-term benefit of the project</h2>

<p>There will be no reduction in the total set of features we provide.
This is only a matter of reorganising what we have, namely, to (i)
make it easier for new users to understand what Denote is, (ii) pick
only the extensions they require, (iii) make it possible to decentralise
the maintenance of the project should I ever need to step down (which
is not happening, but as a matter of principle).</p>

<p>Those granted, keep in mind that Denote is not a “second brain” and
will not make you smarter. It is a flexible and capable tool, truly
Emacs-y in its adaptability, that you can use as part of a workflow
that makes sense to you. Let us then decouple the core from its
extensions and continue to give users the best possible experience
with every piece of code and documentation that we write.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Iosevka Comfy is discontinued; hello ‘Aporetic’ fonts</title>
      <description>Release notes for the latest tagged release of my Aporetic fonts.</description>
      <pubDate>Tue, 04 Feb 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-02-04-aporetic-fonts-1-0-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-02-04-aporetic-fonts-1-0-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>I am discontinuing the development of the <em>Iosevka Comfy</em> fonts,
effective immediately. My new fonts are called <em>Aporetic</em> and are the
successor to my earlier project.</p>

<p>Aporetic 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>Iosevka Comfy:</p>

<ul>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/iosevka-comfy">https://github.com/protesilaos/iosevka-comfy</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/iosevka-comfy">https://gitlab.com/protesilaos/iosevka-comfy</a></li>
    </ul>
  </li>
  <li>Sample pictures: <a href="https://protesilaos.com/emacs/iosevka-comfy-pictures">https://protesilaos.com/emacs/iosevka-comfy-pictures</a></li>
  <li>Backronym: Iosevka … Could Only Modify a Font, Yes.</li>
</ul>

<h2>Legal reason for the change</h2>

<p>“Iosevka” is a reserved name. I had not realised this until I reread
the SIL Open Font License, Version 1.1, specifically:</p>

<blockquote>
  <p>3  No Modified Version of the Font Software may use the Reserved
   Font Name(s) unless explicit written permission is granted by the
   corresponding Copyright Holder. This restriction only applies to
   the primary font name as presented to the users.</p>
</blockquote>

<h2>Technical reasons for the change</h2>

<p>I wanted to change the names of the font families to make them more
intuitive. Instead of something like “Iosevka Comfy Motion Duo” I now
have “Aporetic Serif”. The full list is further below.</p>

<p>I also had to reduce the number of variants and font weights to both
(i) streamline what I am offering and (ii) make it possible to build
the fonts on my computer.</p>

<h2>Changes relative to Iosevka Comfy</h2>

<p>The fonts are these:</p>

<table>
  <thead>
    <tr>
      <th>Current name</th>
      <th>Old name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Aporetic Sans</td>
      <td>Iosevka Comfy Duo</td>
    </tr>
    <tr>
      <td>Aporetic Serif</td>
      <td>Iosevka Comfy Motion Duo</td>
    </tr>
    <tr>
      <td>Aporetic Sans Mono</td>
      <td>Iosevka Comfy</td>
    </tr>
    <tr>
      <td>Aporetic Serif Mono</td>
      <td>Iosevka Comfy Motion</td>
    </tr>
  </tbody>
</table>

<p>I no longer provide “fixed” and “wide” variants.</p>

<p>All glyphs are the same as before except for the zero (<code class="language-plaintext highlighter-rouge">0</code>), which is
now always rendered with a forward slash and a wider body. The reason
for this change is that the narrow oval shape could be mistaken for a
Greek theta (<code class="language-plaintext highlighter-rouge">θ</code>).</p>

<p>Font weights are also reduced to just <code class="language-plaintext highlighter-rouge">regular</code> and <code class="language-plaintext highlighter-rouge">bold</code>.</p>

<h2>Why “aporetic”</h2>

<p>It is a nice Greek word and no other fonts with this name exist.</p>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: aLtCaPs version 1.3.0</title>
      <description>Information about the latest version of my text-transformation package for GNU Emacs.  It helps convey sarcasm or mockery.</description>
      <pubDate>Tue, 28 Jan 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-01-28-emacs-altcaps-1-3-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-01-28-emacs-altcaps-1-3-0/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>This version does not include any user-facing changes. I made some
internal refinements and ensured everything works as expected. Just
use the sample configuration to get started:</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">altcaps</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="ss">:bind</span>
  <span class="p">(</span><span class="s">"C-x C-a"</span> <span class="o">.</span> <span class="nv">altcaps-dwim</span><span class="p">)</span>
  <span class="ss">:config</span>
  <span class="c1">;; Optionally force letter casing for certain characters (for legibility).</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">altcaps-force-character-casing</span>
      <span class="o">'</span><span class="p">((</span><span class="s">"i"</span> <span class="o">.</span> <span class="nv">downcase</span><span class="p">)</span>
        <span class="p">(</span><span class="s">"l"</span> <span class="o">.</span> <span class="nv">upcase</span><span class="p">))))</span>
</code></pre></div></div>

<h2>About <code class="language-plaintext highlighter-rouge">altcaps</code></h2>

<p>The <code class="language-plaintext highlighter-rouge">altcaps</code> package is a small, focused-in-scope tool that helps
users communicate mockery or sarcasm effectively.  It does this by
alternating the letter casing of characters in the words it affects.</p>

<ul>
  <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">altcaps</code></li>
  <li>Official manual: <a href="https://protesilaos.com/emacs/altcaps">https://protesilaos.com/emacs/altcaps</a></li>
  <li>Change log: <a href="https://protesilaos.com/emacs/altcaps-changelog">https://protesilaos.com/emacs/altcaps-changelog</a></li>
  <li>Git repositories:
    <ul>
      <li>GitHub: <a href="https://github.com/protesilaos/altcaps">https://github.com/protesilaos/altcaps</a></li>
      <li>GitLab: <a href="https://gitlab.com/protesilaos/altcaps">https://gitlab.com/protesilaos/altcaps</a></li>
    </ul>
  </li>
  <li>Backronyms: Alternating Letters Transform Casual Asides to Playful
Statements.  ALTCAPS Lets Trolls Convert Aphorisms to Proper
Shitposts.</li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: organise your init file (outline-minor-mode or Org literate config)</title>
      <description>A video demonstration of using either outline-minor-mode or Org to manage your Emacs init.el.</description>
      <pubDate>Sun, 26 Jan 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-01-26-emacs-organise-init/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-01-26-emacs-organise-init/</guid>
      <content:encoded>
        <![CDATA[
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=Dkoy3NrLN9g">https://www.youtube.com/watch?v=Dkoy3NrLN9g</a></p>
         
         <p>In this 25-minute video I show two ways to organise your Emacs init.el
file. One approach is to keep editing the code in Emacs Lisp and to
leverage the “outline”, while the other is to use a literate Org file
whose code blocks will be “tangled” to the init.el. I explain all the
technicalities and show examples. More resources:</p>

<ul>
  <li>Basic and capable Emacs configuration: <a href="https://protesilaos.com/codelog/2024-11-28-basic-emacs-configuration/">https://protesilaos.com/codelog/2024-11-28-basic-emacs-configuration/</a></li>
  <li>Modern minibuffer (Vertico, Consult, etc.): <a href="https://protesilaos.com/codelog/2024-02-17-emacs-modern-minibuffer-packages/">https://protesilaos.com/codelog/2024-02-17-emacs-modern-minibuffer-packages/</a></li>
  <li>Ediff basics: <a href="https://protesilaos.com/codelog/2023-11-17-emacs-ediff-basics/">https://protesilaos.com/codelog/2023-11-17-emacs-ediff-basics/</a></li>
  <li>My Emacs configuration:
    <ul>
      <li>Web page: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a></li>
      <li>Source: <a href="https://github.com/protesilaos/dotfiles">https://github.com/protesilaos/dotfiles</a></li>
      <li>Video explanation: <a href="https://protesilaos.com/codelog/2023-12-18-emacs-org-advanced-literate-conf/">https://protesilaos.com/codelog/2023-12-18-emacs-org-advanced-literate-conf/</a></li>
    </ul>
  </li>
</ul>
        ]]>
      </content:encoded>
    </item>
    
    <item>
      <title>Emacs: show-font version 0.2.0</title>
      <description>Information about the latest version of my show-font package for GNU Emacs.</description>
      <pubDate>Sat, 25 Jan 2025 00:00:00 +0000</pubDate>
      <link>https://protesilaos.com/codelog/2025-01-25-emacs-show-font-0-2-0/</link>
      <guid isPermaLink="true">https://protesilaos.com/codelog/2025-01-25-emacs-show-font-0-2-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.2.0 on 2025-01-25</h2>

<p>This version includes quality-of-life refinements.</p>

<h3>Show fonts in a tabulated listing</h3>

<p>The command <code class="language-plaintext highlighter-rouge">show-font-tabulated</code> will produce a listing of font
families and their preview that uses the built-in tabulated interface.
This interface is the same as the one used by <code class="language-plaintext highlighter-rouge">M-x list-packages</code>.
Users can sort fonts by font family name (move point to the given
column and type <code class="language-plaintext highlighter-rouge">S</code> or call <code class="language-plaintext highlighter-rouge">M-x tabulated-list-sort</code>).</p>

<p>When <code class="language-plaintext highlighter-rouge">show-font-tabulated</code> is called with a prefix argument (<code class="language-plaintext highlighter-rouge">C-u</code> by
default), it prompts for a string or regular expression. It then shows
only the font families matching the given input.</p>

<h3>Limit font listing using a regular expression</h3>

<p>The command <code class="language-plaintext highlighter-rouge">show-font-list</code> which we already had in version 0.1.0 is
like the <code class="language-plaintext highlighter-rouge">show-font-tabulated</code>, but uses a bespoke buffer where each
font and its preview are shown one after the other. Now it also
accepts an optional prefix argument to limit the list to only the
matching fonts.</p>

<h3>The <code class="language-plaintext highlighter-rouge">show-font-display-buffer-action-alist</code> controls buffer placement</h3>

<p>The preview buffers we use will now conform with the value of the new
user option <code class="language-plaintext highlighter-rouge">show-font-display-buffer-action-alist</code>. This is a more
advanced feature, due to how <code class="language-plaintext highlighter-rouge">display-buffer</code> works, so you may want
to check the video I did recently about controlling where buffers are
displayed: <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 default value of <code class="language-plaintext highlighter-rouge">show-font-display-buffer-action-alist</code> will show
the buffer at the bottom of the frame.</p>
        ]]>
      </content:encoded>
    </item>
    
  </channel>
</rss>
