<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title><![CDATA[Magnus web site - emacs]]></title>
<description><![CDATA[Magnus web site - emacs]]></description>
<link>https://magnus.therning.org//tag-emacs.html</link>
<lastBuildDate>Wed, 18 Feb 2026 00:09:50 +0100</lastBuildDate>
<item>
  <title><![CDATA[Switching to project.el]]></title>
  <description><![CDATA[
<p>
I've used <a href="https://github.com/bbatsov/projectile">projectile</a> ever since I created my own Emacs config. I have a vague
memory choosing it because some other package only supported it. (It might have
been <a href="https://emacs-lsp.github.io/lsp-mode/">lsp-mode</a>, but I'm not sure.) Anyway, now that <a href="https://magnus.therning.org/2026-01-19-trying-eglot,-again.html">I'm trying out eglot</a>, <a href="https://magnus.therning.org/2026-01-25-more-on-the-switch-to-eglot.html">again</a>,
I thought I might as well see if I can switch to <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Projects.html">project.el</a>, which is included
in Emacs nowadays.
</p>
<div id="outline-container-org80f0ee9" class="outline-2">
<h2 id="org80f0ee9">A non-VC project marker</h2>
<div class="outline-text-2" id="text-org80f0ee9">
<p>
Projectile allows using a file, <code>.projectile</code>, in the root of a project. This
makes it possible to turn a folder into a project without having to use version
control. It's possible to configure project.el to respect more VC markers than
what's built-in. This can be used to define a non-VC marker.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">setopt</span> project-vc-extra-root-markers '<span class="org-rainbow-delimiters-depth-2">(</span><span class="org-string">".projectile"</span> <span class="org-string">".git"</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
Since I've set <code>vc-handled-backends</code> to <code>nil</code> (the default made VC interfere
with magit, so I turned it off completely) I had to add <code>".git"</code> to make git
repos be recognised as projects too.
</p>
</div>
</div>
<div id="outline-container-org511d0e2" class="outline-2">
<h2 id="org511d0e2">Xref history</h2>
<div class="outline-text-2" id="text-org511d0e2">
<p>
The first thing to solve was that the <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html">xref</a> stack wasn't per project. Somewhat
disappointingly there only seems to be two options for <code>xref-history-storage</code>
shipped with Emacs
</p>

<dl class="org-dl">
<dt><code>xref-global-history</code></dt><dd>a single global history (the default)</dd>
<dt><code>xref-window-local-history</code></dt><dd>a history per window</dd>
</dl>

<p>
I had the same issue with projectile, and ended up writing my own package for
it. For project.el I settled on using <a href="https://codeberg.org/imarko/xref-project-history.git">xref-project-history</a>.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">use-package</span> xref-project-history
  <span class="org-builtin">:ensure</span> <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-builtin">:type</span> git
           <span class="org-builtin">:repo</span> <span class="org-string">"https://codeberg.org/imarko/xref-project-history.git"</span>
           <span class="org-builtin">:branch</span> <span class="org-string">"master"</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-builtin">:custom</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>xref-history-storage #'xref-project-history<span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>
</div>
</div>
<div id="outline-container-orgbaa0d4d" class="outline-2">
<h2 id="orgbaa0d4d">Jumping between implementation and test</h2>
<div class="outline-text-2" id="text-orgbaa0d4d">
<p>
Projectile has a function for jumping between implementation and test. Not too
surprisingly it's called <code>projectile-toggle-between-implementation-and-test</code>. I
found some old emails in an archive suggesting that project.el might have had
something similar in the past, but if that's the case it's been removed by now.
When searching for a package I came across <a href="https://lists.gnu.org/archive/html/emacs-devel/2022-09/msg00300.html">this email comparing tools for
finding related files</a>. The author mentions two that are included with Emacs
</p>

<dl class="org-dl">
<dt><code>ff-find-other-file</code></dt><dd>part of find-file.el, which a few other functions and
a rather impressive set of settings to customise its behaviour.</dd>
<dt><code>find-sibling-file</code></dt><dd>a newer command, I believe, that also can be
customised.</dd>
</dl>

<p>
So, there are options, but neither of them are made to work nicely with
project.el out of the box. My most complicated use case seems to be in Haskell
projects where modules for implementation and test live in separate (mirrored)
folder hierarchies, e.g.
</p>

<pre class="example" id="org712aefd">
src
└── Sider
    └── Data
        ├── Command.hs
        ├── Pipeline.hs
        └── Resp.hs
test
└── Sider
    └── Data
        ├── CommandSpec.hs
        ├── PipelineSpec.hs
        └── RespSpec.hs

</pre>

<p>
I'm not really sure how I'd configure <code>find-sibling-rules</code>, which are regular
expressions, to deal with folder hierarchies like this. To be honest, I didn't
really see a way of configuring <code>ff-find-other-file</code> at first either. Then I
happened on a post about <a href="https://dev.to/fredericlepied/emacs-how-to-switch-from-modulepy-to-testmodulepy-67k">switching between a module and its tests in Python</a>.
With its help I came up with the following
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">defun</span> <span class="org-function-name">mes/setup-hs-ff</span> <span class="org-rainbow-delimiters-depth-2">()</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">when-let*</span> <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-rainbow-delimiters-depth-4">(</span>proj-root <span class="org-rainbow-delimiters-depth-5">(</span>project-root <span class="org-rainbow-delimiters-depth-6">(</span>project-current<span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span>
              <span class="org-rainbow-delimiters-depth-4">(</span>rel-proj-root <span class="org-rainbow-delimiters-depth-5">(</span><span class="org-keyword">-some--&gt;</span> <span class="org-rainbow-delimiters-depth-6">(</span>buffer-file-name<span class="org-rainbow-delimiters-depth-6">)</span>
                               <span class="org-rainbow-delimiters-depth-6">(</span>file-name-directory it<span class="org-rainbow-delimiters-depth-6">)</span>
                               <span class="org-rainbow-delimiters-depth-6">(</span>f-relative proj-root it<span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span>
              <span class="org-rainbow-delimiters-depth-4">(</span>sub-tree <span class="org-rainbow-delimiters-depth-5">(</span>car <span class="org-rainbow-delimiters-depth-6">(</span>f-split <span class="org-rainbow-delimiters-depth-7">(</span>f-relative <span class="org-rainbow-delimiters-depth-8">(</span>buffer-file-name<span class="org-rainbow-delimiters-depth-8">)</span> proj-root<span class="org-rainbow-delimiters-depth-7">)</span><span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span>
              <span class="org-rainbow-delimiters-depth-4">(</span>search-dirs <span class="org-rainbow-delimiters-depth-5">(</span><span class="org-keyword">--&gt;</span> '<span class="org-rainbow-delimiters-depth-6">(</span><span class="org-string">"src"</span> <span class="org-string">"test"</span><span class="org-rainbow-delimiters-depth-6">)</span>
                                <span class="org-rainbow-delimiters-depth-6">(</span>remove sub-tree it<span class="org-rainbow-delimiters-depth-6">)</span>
                                <span class="org-rainbow-delimiters-depth-6">(</span>-map <span class="org-rainbow-delimiters-depth-7">(</span><span class="org-keyword">lambda</span> <span class="org-rainbow-delimiters-depth-8">(</span>p<span class="org-rainbow-delimiters-depth-8">)</span> <span class="org-rainbow-delimiters-depth-8">(</span>f-join proj-root p<span class="org-rainbow-delimiters-depth-8">)</span><span class="org-rainbow-delimiters-depth-7">)</span> it<span class="org-rainbow-delimiters-depth-6">)</span>
                                <span class="org-rainbow-delimiters-depth-6">(</span>-select #'f-directory? it<span class="org-rainbow-delimiters-depth-6">)</span>
                                <span class="org-rainbow-delimiters-depth-6">(</span>-mapcat <span class="org-rainbow-delimiters-depth-7">(</span><span class="org-keyword">lambda</span> <span class="org-rainbow-delimiters-depth-8">(</span>p<span class="org-rainbow-delimiters-depth-8">)</span> <span class="org-rainbow-delimiters-depth-8">(</span>f-directories p nil t<span class="org-rainbow-delimiters-depth-8">)</span><span class="org-rainbow-delimiters-depth-7">)</span> it<span class="org-rainbow-delimiters-depth-6">)</span>
                                <span class="org-rainbow-delimiters-depth-6">(</span>-map <span class="org-rainbow-delimiters-depth-7">(</span><span class="org-keyword">lambda</span> <span class="org-rainbow-delimiters-depth-8">(</span>p<span class="org-rainbow-delimiters-depth-8">)</span> <span class="org-rainbow-delimiters-depth-8">(</span>f-relative p proj-root<span class="org-rainbow-delimiters-depth-8">)</span><span class="org-rainbow-delimiters-depth-7">)</span> it<span class="org-rainbow-delimiters-depth-6">)</span>
                                <span class="org-rainbow-delimiters-depth-6">(</span>-map <span class="org-rainbow-delimiters-depth-7">(</span><span class="org-keyword">lambda</span> <span class="org-rainbow-delimiters-depth-8">(</span>p<span class="org-rainbow-delimiters-depth-8">)</span> <span class="org-rainbow-delimiters-depth-8">(</span>f-join rel-proj-root p<span class="org-rainbow-delimiters-depth-8">)</span><span class="org-rainbow-delimiters-depth-7">)</span> it<span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span>
    <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-keyword">setq-local</span> ff-search-directories search-dirs
                ff-other-file-alist '<span class="org-rainbow-delimiters-depth-4">(</span><span class="org-rainbow-delimiters-depth-5">(</span><span class="org-string">"Spec\\.hs$"</span> <span class="org-rainbow-delimiters-depth-6">(</span><span class="org-string">".hs"</span><span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span>
                                      <span class="org-rainbow-delimiters-depth-5">(</span><span class="org-string">"\\.hs$"</span> <span class="org-rainbow-delimiters-depth-6">(</span><span class="org-string">"Spec.hs"</span><span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
A few things to note
</p>

<ol class="org-ol">
<li>The order of rules in <code>ff-other-file-alist</code> is important, the first match is
chosen.</li>
<li><code>(buffer-file-name)</code> can, and really does, return <code>nil</code> at times, and
<code>file-name-directory</code> doesn't deal with anything but strings.</li>
<li>The entries in <code>ff-search-directories</code> have to be relative to the file in the
current buffer, hence the rather involved <code>varlist</code> in the <code>when-let*</code>
expression.</li>
</ol>

<p>
With this in place I get the following values for <code>ff-search-directories</code>
</p>

<dl class="org-dl">
<dt><code>src/Sider/Data/Command.hs</code></dt><dd><code>("../../../test/Sider" "../../../test/Sider/Data")</code></dd>
<dt><code>test/Sider/Data/CommandSpec.hs</code></dt><dd><code>("../../../src/Sider" "../../../src/Sider/Data")</code></dd>
</dl>

<p>
And <code>ff-find-other-file</code> works beautifully.
</p>
</div>
</div>
<div id="outline-container-orgb8cf766" class="outline-2">
<h2 id="orgb8cf766">Conclusion</h2>
<div class="outline-text-2" id="text-orgb8cf766">
<p>
My setup with project.el now covers everything I used from projectile so I'm
fairly confident I'll be happy keeping it.
</p>
</div>
</div>
<div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-emacs.html">emacs</a> <a href="https://magnus.therning.org/tag-project-el.html">project-el</a> </div>
]]></description>
  <category><![CDATA[emacs]]></category>
  <category><![CDATA[project-el]]></category>
  <link>https://magnus.therning.org/2026-02-18-switching-to-project.el.html</link>
  <guid>https://magnus.therning.org/2026-02-18-switching-to-project.el.html</guid>
  <pubDate>Wed, 18 Feb 2026 00:09:00 +0100</pubDate>
</item>
<item>
  <title><![CDATA[Using advice to limit lsp-ui-doc nuisance]]></title>
  <description><![CDATA[
<p>
I've switched back to <a href="https://emacs-lsp.github.io/lsp-mode/">lsp-mode</a> temporarily until I've had time to fix a few
things with my <code>eglot</code> setup. Returning prompted me to finally address an
irritating behaviour with <a href="https://emacs-lsp.github.io/lsp-ui/#lsp-ui-doc">lsp-ui-doc</a>.
</p>

<p>
No matter what I set <code>lsp-ui-doc-position</code> to it ends up covering information
that I want to see. While waiting for a <a href="https://github.com/emacs-lsp/lsp-ui/issues/793">fix</a> I decided to work around it. It
seems to me that this is exactly what <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Functions.html">advice</a> is for.
</p>

<p>
I came up with the following to make sure the frame appears on the half of the
buffer where <code>point</code> isn't.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">defun</span> <span class="org-function-name">my-lsp-ui-doc-wrapper</span> <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-type">&amp;rest</span> _<span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">let*</span> <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-rainbow-delimiters-depth-4">(</span>pos-line <span class="org-rainbow-delimiters-depth-5">(</span>- <span class="org-rainbow-delimiters-depth-6">(</span>line-number-at-pos <span class="org-rainbow-delimiters-depth-7">(</span>point<span class="org-rainbow-delimiters-depth-7">)</span><span class="org-rainbow-delimiters-depth-6">)</span>
                      <span class="org-rainbow-delimiters-depth-6">(</span>line-number-at-pos <span class="org-rainbow-delimiters-depth-7">(</span>window-start<span class="org-rainbow-delimiters-depth-7">)</span><span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span>
         <span class="org-rainbow-delimiters-depth-4">(</span>pos <span class="org-rainbow-delimiters-depth-5">(</span><span class="org-keyword">if</span> <span class="org-rainbow-delimiters-depth-6">(</span>&lt;= pos-line <span class="org-rainbow-delimiters-depth-7">(</span>/ <span class="org-rainbow-delimiters-depth-8">(</span>window-body-height<span class="org-rainbow-delimiters-depth-8">)</span> 2<span class="org-rainbow-delimiters-depth-7">)</span><span class="org-rainbow-delimiters-depth-6">)</span>
                  'bottom
                'top<span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span>
    <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-keyword">setopt</span> lsp-ui-doc-position pos<span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>

<span class="org-rainbow-delimiters-depth-1">(</span>advice-add 'lsp-ui-doc--move-frame <span class="org-builtin">:before</span> #'my-lsp-ui-doc-wrapper<span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>
<div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-emacs.html">emacs</a> <a href="https://magnus.therning.org/tag-lsp-mode.html">lsp-mode</a> </div>
]]></description>
  <category><![CDATA[emacs]]></category>
  <category><![CDATA[lsp-mode]]></category>
  <link>https://magnus.therning.org/2026-02-16-using-advice-to-limit-lsp-ui-doc-nuisance.html</link>
  <guid>https://magnus.therning.org/2026-02-16-using-advice-to-limit-lsp-ui-doc-nuisance.html</guid>
  <pubDate>Mon, 16 Feb 2026 20:10:00 +0100</pubDate>
</item>
<item>
  <title><![CDATA[More on the switch to eglot]]></title>
  <description><![CDATA[
<p>
Since the <a href="https://magnus.therning.org/2026-01-19-trying-eglot,-again.html">switching to eglot</a> I've ended up making a few related changes.
</p>
<div id="outline-container-org8cdfce1" class="outline-2">
<h2 id="org8cdfce1">Replacing flycheck with flymake</h2>
<div class="outline-text-2" id="text-org8cdfce1">
<p>
Since <code>eglot</code> it's written to work with other packages in core, which means it
integrates with <a href="https://www.gnu.org/software/emacs/manual/html_mono/flymake.html"><code>flymake</code></a>. The switch comprised
</p>

<ul class="org-ul">
<li>Use <code>:ensure nil</code> to make sure <code>elpaca</code> knows there's nothing to download.</li>
<li>Add a call to <code>flymake-mode</code> to <code>prog-mode-hook</code>.</li>
<li>Define two functions to toggle showing a list of diagnostics for the current
buffer and the project.</li>
<li></li>

<li>Redefine the relevant keybindings.</li>
</ul>

<p>
The two functions for toggling showing diagnostics look like this
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">defun</span> <span class="org-function-name">mes/toggle-flymake-buffer-diagnostics</span> <span class="org-rainbow-delimiters-depth-2">()</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">interactive</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">if-let*</span> <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-rainbow-delimiters-depth-4">(</span>window <span class="org-rainbow-delimiters-depth-5">(</span>get-buffer-window <span class="org-rainbow-delimiters-depth-6">(</span>flymake--diagnostics-buffer-name<span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span>
      <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-keyword">save-selected-window</span> <span class="org-rainbow-delimiters-depth-4">(</span>quit-window nil window<span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span>
    <span class="org-rainbow-delimiters-depth-3">(</span>flymake-show-buffer-diagnostics<span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>

<span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">defun</span> <span class="org-function-name">mes/toggle-flymake-project-diagnostics</span> <span class="org-rainbow-delimiters-depth-2">()</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">interactive</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">if-let*</span> <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-rainbow-delimiters-depth-4">(</span>window <span class="org-rainbow-delimiters-depth-5">(</span>get-buffer-window <span class="org-rainbow-delimiters-depth-6">(</span>flymake--project-diagnostics-buffer <span class="org-rainbow-delimiters-depth-7">(</span>projectile-project-root<span class="org-rainbow-delimiters-depth-7">)</span><span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span>
      <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-keyword">save-selected-window</span> <span class="org-rainbow-delimiters-depth-4">(</span>quit-window nil window<span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span>
    <span class="org-rainbow-delimiters-depth-3">(</span>flymake-show-project-diagnostics<span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
And the changed keybindings are
</p>

<table>


<colgroup>
<col  class="org-left">

<col  class="org-left">
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">flycheck</th>
<th scope="col" class="org-left">flymake</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">flycheck-next-error</td>
<td class="org-left">flymake-goto-next-error</td>
</tr>

<tr>
<td class="org-left">flycheck-previous-error</td>
<td class="org-left">flymake-goto-prev-error</td>
</tr>

<tr>
<td class="org-left">mes/toggle-flycheck-error-list</td>
<td class="org-left">mes/toggle-flymake-buffer-diagnostics</td>
</tr>

<tr>
<td class="org-left">mes/toggle-flycheck-projectile-error-list</td>
<td class="org-left">mes/toggle-flymake-project-diagnostics</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="outline-container-orgadc4f2e" class="outline-2">
<h2 id="orgadc4f2e">Using <code>with-eval-after-load</code> instead of <code>:after eglot</code></h2>
<div class="outline-text-2" id="text-orgadc4f2e">
<p>
When it comes to <code>use-package</code> I keep on being surprised, and after the switch
to <code>elpaca</code> I've found some new surprises. One of them was that using <code>:after
eglot</code> like this
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">use-package</span> haskell-ng-mode
  <span class="org-builtin">:afer</span> eglot
  <span class="org-builtin">:ensure</span> <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-builtin">:type</span> git
           <span class="org-builtin">:repo</span> <span class="org-string">"git@gitlab.com:magus/haskell-ng-mode.git"</span>
           <span class="org-builtin">:branch</span> <span class="org-string">"main"</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-builtin">:init</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>add-to-list 'major-mode-remap-alist '<span class="org-rainbow-delimiters-depth-3">(</span>haskell-mode . haskell-ng-mode<span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>add-to-list 'eglot-server-programs '<span class="org-rainbow-delimiters-depth-3">(</span>haskell-ng-mode <span class="org-string">"haskell-language-server-wrapper"</span> <span class="org-string">"--lsp"</span><span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">setq-default</span> eglot-workspace-configuration
                <span class="org-rainbow-delimiters-depth-3">(</span>plist-put eglot-workspace-configuration
                           <span class="org-builtin">:haskell</span>
                           '<span class="org-rainbow-delimiters-depth-4">(</span><span class="org-builtin">:formattingProvider</span> <span class="org-string">"fourmolu"</span>
                             <span class="org-builtin">:plugin</span> <span class="org-rainbow-delimiters-depth-5">(</span><span class="org-builtin">:stan</span> <span class="org-rainbow-delimiters-depth-6">(</span><span class="org-builtin">:global-on</span> <span class="org-builtin">:json-false</span><span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span>
  ...
  <span class="org-builtin">:hook</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>haskell-ng-mode . eglot-ensure<span class="org-rainbow-delimiters-depth-2">)</span>
  ...<span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
would delay initialisation until after <code>eglot</code> had been loaded. However, it
turned out that nothing in <code>:init ...</code> seemed to run and upon opening a haskell file
no mode was loaded.
</p>

<p>
After a bit of thinking and tinkering I got it working by removing <code>:after
eglot</code> and using <code>with-eval-after-load</code>
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">use-package</span> haskell-ng-mode
  <span class="org-builtin">:ensure</span> <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-builtin">:type</span> git
           <span class="org-builtin">:repo</span> <span class="org-string">"git@gitlab.com:magus/haskell-ng-mode.git"</span>
           <span class="org-builtin">:branch</span> <span class="org-string">"main"</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-builtin">:init</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>add-to-list 'major-mode-remap-alist '<span class="org-rainbow-delimiters-depth-3">(</span>haskell-mode . haskell-ng-mode<span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">with-eval-after-load</span> 'eglot
    <span class="org-rainbow-delimiters-depth-3">(</span>add-to-list 'eglot-server-programs '<span class="org-rainbow-delimiters-depth-4">(</span>haskell-ng-mode <span class="org-string">"haskell-language-server-wrapper"</span> <span class="org-string">"--lsp"</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span>
    <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-keyword">setq-default</span> eglot-workspace-configuration
                  <span class="org-rainbow-delimiters-depth-4">(</span>plist-put eglot-workspace-configuration
                             <span class="org-builtin">:haskell</span>
                             '<span class="org-rainbow-delimiters-depth-5">(</span><span class="org-builtin">:formattingProvider</span> <span class="org-string">"fourmolu"</span>
                               <span class="org-builtin">:plugin</span> <span class="org-rainbow-delimiters-depth-6">(</span><span class="org-builtin">:stan</span> <span class="org-rainbow-delimiters-depth-7">(</span><span class="org-builtin">:global-on</span> <span class="org-builtin">:json-false</span><span class="org-rainbow-delimiters-depth-7">)</span><span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span>
  ...
  <span class="org-builtin">:hook</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>haskell-ng-mode . eglot-ensure<span class="org-rainbow-delimiters-depth-2">)</span>
  ...<span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
That change worked for haskell, and it seemed to work for python too, but after
a little while I realised that python needed a bit more attention.
</p>
</div>
</div>
<div id="outline-container-orgc610d55" class="outline-2">
<h2 id="orgc610d55">Getting the configuration for Python to work properly</h2>
<div class="outline-text-2" id="text-orgc610d55">
<p>
The python setup looked like this
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">use-package</span> python
  <span class="org-builtin">:init</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>add-to-list 'major-mode-remap-alist '<span class="org-rainbow-delimiters-depth-3">(</span>python-mode . python-ts-mode<span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">with-eval-after-load</span> 'eglot
    <span class="org-rainbow-delimiters-depth-3">(</span>assoc-delete-all '<span class="org-rainbow-delimiters-depth-4">(</span>python-mode python-ts-mode<span class="org-rainbow-delimiters-depth-4">)</span> eglot-server-programs<span class="org-rainbow-delimiters-depth-3">)</span>
    <span class="org-rainbow-delimiters-depth-3">(</span>add-to-list 'eglot-server-programs
                 `<span class="org-rainbow-delimiters-depth-4">(</span><span class="org-rainbow-delimiters-depth-5">(</span>python-mode python-ts-mode<span class="org-rainbow-delimiters-depth-5">)</span> . ,<span class="org-rainbow-delimiters-depth-5">(</span>eglot-alternatives
                                                    '<span class="org-rainbow-delimiters-depth-6">(</span><span class="org-rainbow-delimiters-depth-7">(</span><span class="org-string">"rass"</span> <span class="org-string">"python"</span><span class="org-rainbow-delimiters-depth-7">)</span> <span class="org-string">"pylsp"</span><span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span>
  ...
  <span class="org-builtin">:hook</span> <span class="org-rainbow-delimiters-depth-2">(</span>python-ts-mode . eglot-ensure<span class="org-rainbow-delimiters-depth-2">)</span>
  ...<span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
and it worked all right, but then I visited the package (using <code>elpaca-visit</code>)
and realised that the downloaded package was all of emacs. That's a bit of
overkill, I'd say.
</p>

<p>
However, adding <code>:ensure nil</code> didn't have the expected effect of just using the
version that's in core. Instead the whole configuration seemed to never take
effect and again I was back to the situation where I had to jump to
<code>python-ts-mode</code> manually.
</p>

<p>
The documentation for <code>use-package</code> says that <code>:init</code> is for
</p>

<blockquote>
<p>
Code to run before PACKAGE-NAME has been loaded.
</p>
</blockquote>

<p>
but I'm guessing "before" isn't quite before enough. Then I noticed <code>:preface</code>
with the description
</p>

<blockquote>
<p>
Code to be run before everything except <code>:disabled</code>; this can be used to define
functions for use in <code>:if</code>, or that should be seen by the byte-compiler.
</p>
</blockquote>

<p>
and yes, "before everything" is early enough. The final python configuration
looks like this
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">use-package</span> python
  <span class="org-builtin">:ensure</span> nil
  <span class="org-builtin">:preface</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>add-to-list 'major-mode-remap-alist '<span class="org-rainbow-delimiters-depth-3">(</span>python-mode . python-ts-mode<span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-builtin">:init</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">with-eval-after-load</span> 'eglot
    <span class="org-rainbow-delimiters-depth-3">(</span>assoc-delete-all '<span class="org-rainbow-delimiters-depth-4">(</span>python-mode python-ts-mode<span class="org-rainbow-delimiters-depth-4">)</span> eglot-server-programs<span class="org-rainbow-delimiters-depth-3">)</span>
    <span class="org-rainbow-delimiters-depth-3">(</span>add-to-list 'eglot-server-programs
                 `<span class="org-rainbow-delimiters-depth-4">(</span><span class="org-rainbow-delimiters-depth-5">(</span>python-mode python-ts-mode<span class="org-rainbow-delimiters-depth-5">)</span> . ,<span class="org-rainbow-delimiters-depth-5">(</span>eglot-alternatives
                                                    '<span class="org-rainbow-delimiters-depth-6">(</span><span class="org-rainbow-delimiters-depth-7">(</span><span class="org-string">"rass"</span> <span class="org-string">"python"</span><span class="org-rainbow-delimiters-depth-7">)</span> <span class="org-string">"pylsp"</span><span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span>
  ...
  <span class="org-builtin">:hook</span> <span class="org-rainbow-delimiters-depth-2">(</span>python-ts-mode . eglot-ensure<span class="org-rainbow-delimiters-depth-2">)</span>
  ...<span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>
</div>
</div>
<div id="outline-container-orgc2d0d13" class="outline-2">
<h2 id="orgc2d0d13">Closing remark</h2>
<div class="outline-text-2" id="text-orgc2d0d13">
<p>
I'm still not sure I have the correct intuition about how to use <code>use-package</code>,
but hopefully it's <i>more</i> correct now than before. I have a growing suspicion
that <code>use-package</code> changes behaviour based on the package manager I use. Or
maybe it's just that some package managers make <code>use-package</code> more forgiving of
bad use.
</p>
</div>
</div>
<div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-eglot.html">eglot</a> <a href="https://magnus.therning.org/tag-emacs.html">emacs</a> </div>
]]></description>
  <category><![CDATA[eglot]]></category>
  <category><![CDATA[emacs]]></category>
  <link>https://magnus.therning.org/2026-01-25-more-on-the-switch-to-eglot.html</link>
  <guid>https://magnus.therning.org/2026-01-25-more-on-the-switch-to-eglot.html</guid>
  <pubDate>Sun, 25 Jan 2026 14:18:00 +0100</pubDate>
</item>
<item>
  <title><![CDATA[Trying eglot, again]]></title>
  <description><![CDATA[
<p>
I've been using <a href="https://emacs-lsp.github.io/lsp-mode/">lsp-mode</a> since I switched to Emacs several years ago. When <a href="https://github.com/joaotavora/eglot">eglot</a>
made into Emacs core I used it very briefly but quickly switched back. Mainly I
found eglot a bit too bare-bones; I liked some of the bells and whistles of
<code>lsp-ui</code>. Fast-forward a few years and I've grown a bit tired of those bells and
whistles. Specifically that it's difficult to make <code>lsp-ui-sideline</code> and
<code>lsp-ui-doc</code> work well together. <code>lsp-ui-sidedline</code> is shown on the right side,
which is good, but combining it with <code>lsp-ui-doc</code> leads to situations where the
popup covers the sideline. What I've done so far is centre the line to bring the
sideline text out. I was playing a little bit with making the setting of
<code>lsp-ui-doc-position</code> change depending on the location of the current position.
It didn't work that well though so I decided to try to find a simpler setup.
Instead of simplifying the setup of <code>lsp-config</code> I thought I'd give <code>eglot</code>
another shot.
</p>
<div id="outline-container-orgb1f7433" class="outline-2">
<h2 id="orgb1f7433">Basic setup</h2>
<div class="outline-text-2" id="text-orgb1f7433">
<p>
I removed the statements pulling in <code>lsp-mode</code>, <code>lsp-ui</code>, and all
language-specific packages like <code>lsp-haskell</code>. Then I added this to configure
<code>eglot</code>
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">use-package</span> eglot
  <span class="org-builtin">:ensure</span> nil
  <span class="org-builtin">:custom</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>eglot-autoshutdown t<span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>eglot-confirm-server-edits '<span class="org-rainbow-delimiters-depth-3">(</span><span class="org-rainbow-delimiters-depth-4">(</span>eglot-rename . nil<span class="org-rainbow-delimiters-depth-4">)</span>
                                <span class="org-rainbow-delimiters-depth-4">(</span>t . diff<span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
The rest was mainly just switching <code>lsp-mode</code> functions for <code>eglot</code> functions.
</p>

<table>


<colgroup>
<col  class="org-left">

<col  class="org-left">
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">lsp-mode function</th>
<th scope="col" class="org-left">eglot function</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left"><code>lsp-deferred</code></td>
<td class="org-left"><code>eglot-ensure</code></td>
</tr>

<tr>
<td class="org-left"><code>lsp-describe-thing-at-point</code></td>
<td class="org-left"><code>eldoc</code></td>
</tr>

<tr>
<td class="org-left"><code>lsp-execute-code-action</code></td>
<td class="org-left"><code>eglot-code-actions</code></td>
</tr>

<tr>
<td class="org-left"><code>lsp-find-type-definition</code></td>
<td class="org-left"><code>eglot-find-typeDefinition</code></td>
</tr>

<tr>
<td class="org-left"><code>lsp-format-buffer</code></td>
<td class="org-left"><code>eglot-format-buffer</code></td>
</tr>

<tr>
<td class="org-left"><code>lsp-format-region</code></td>
<td class="org-left"><code>eglot-format</code></td>
</tr>

<tr>
<td class="org-left"><code>lsp-organize-imports</code></td>
<td class="org-left"><code>eglot-code-action-organize-imports</code></td>
</tr>

<tr>
<td class="org-left"><code>lsp-rename</code></td>
<td class="org-left"><code>eglot-rename</code></td>
</tr>

<tr>
<td class="org-left"><code>lsp-workspace-restart</code></td>
<td class="org-left"><code>eglot-reconnect</code></td>
</tr>

<tr>
<td class="org-left"><code>lsp-workspace-shutdown</code></td>
<td class="org-left"><code>eglot-shutdown</code></td>
</tr>
</tbody>
</table>

<p>
I haven't verified that the list is fully correct yet, but it looks good so far.
</p>

<p>
The one thing I might miss is lenses, and using <code>lsp-avy-lens</code>. However,
everything that I use lenses for can be done using actions, and to be honest I
don't think I'll miss the huge lens texts from missing type annotations in
Haskell.
</p>
</div>
</div>
<div id="outline-container-orgd8ac829" class="outline-2">
<h2 id="orgd8ac829">Configuration</h2>
<div class="outline-text-2" id="text-orgd8ac829">
<p>
One good thing about <code>lsp-mode</code>'s use of language-specific packages is that
configuration of the various servers is performed through functions. This makes
it easy to discover what options are available, though it also means not all
options may be available. In <code>eglot</code> configuration is less organised, I have to
know about the options for each language server and put the options into
<code>eglot-workspace-configuration</code> myself. It's not always easy to track down what
options are available, and I've found no easy way to verify the settings. For
instance, with <code>lsp-mode</code> I configures <a href="https://github.com/haskell/haskell-language-server">HLS</a> like this
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span>lsp-haskell-formatting-provider <span class="org-string">"fourmolu"</span><span class="org-rainbow-delimiters-depth-1">)</span>
<span class="org-rainbow-delimiters-depth-1">(</span>lsp-haskell-plugin-stan-global-on nil<span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
which translates to this for <code>eglot</code>
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">setq-default</span> eglot-workspace-configuration
              <span class="org-rainbow-delimiters-depth-2">(</span>plist-put eglot-workspace-configuration
                         <span class="org-builtin">:haskell</span>
                         '<span class="org-rainbow-delimiters-depth-3">(</span><span class="org-builtin">:formattingProvider</span> <span class="org-string">"fourmolu"</span>
                           <span class="org-builtin">:plugin</span> <span class="org-rainbow-delimiters-depth-4">(</span><span class="org-builtin">:stan</span> <span class="org-rainbow-delimiters-depth-5">(</span><span class="org-builtin">:global-on</span> <span class="org-builtin">:json-false</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
and I can verify that this configuration has taken effect because I know enough
about the Haskell tools.
</p>

<p>
I do some development in Python and I used to configure <a href="https://pypi.org/project/python-lsp-server/">pylsp</a> like this
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span>lsp-pylsp-plugins-mypy-enabled t<span class="org-rainbow-delimiters-depth-1">)</span>
<span class="org-rainbow-delimiters-depth-1">(</span>lsp-pylsp-plugins-ruff-enabled t<span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
which I <i>think</i> translates to this for <code>eglot</code>
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">setq-default</span> eglot-workspace-configuration
              <span class="org-rainbow-delimiters-depth-2">(</span>plist-put eglot-workspace-configuration
                         <span class="org-builtin">:pylsp</span>
                         '<span class="org-rainbow-delimiters-depth-3">(</span><span class="org-builtin">:plugins</span> <span class="org-rainbow-delimiters-depth-4">(</span><span class="org-builtin">:ruff</span> <span class="org-rainbow-delimiters-depth-5">(</span><span class="org-builtin">:enabled</span> t<span class="org-rainbow-delimiters-depth-5">)</span>
                                     <span class="org-builtin">:mypy</span> <span class="org-rainbow-delimiters-depth-5">(</span><span class="org-builtin">:enabled</span> t<span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
but I don't know any convenient way of verifying these settings. I'm simply not
familiar enough with the Python tools. I can check the value of
<code>eglot-workspace-configuration</code> by inspecting it or calling
<code>eglot-show-workspace-configuration</code> but is there really no way of asking the
language server for its active configuration?
</p>
</div>
</div>
<div id="outline-container-org3d20108" class="outline-2">
<h2 id="org3d20108">Closing remark</h2>
<div class="outline-text-2" id="text-org3d20108">
<p>
The last time I gave up on <code>eglot</code> very quickly, probably too quickly to be
honest. I made these changes to my configuration over the weekend, so the real
test of <code>eglot</code> starts when I'm back in the office. I have a feeling I'll stick
to it longer this time.
</p>
</div>
</div>
<div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-eglot.html">eglot</a> <a href="https://magnus.therning.org/tag-emacs.html">emacs</a> <a href="https://magnus.therning.org/tag-lsp-mode.html">lsp-mode</a> </div>
]]></description>
  <category><![CDATA[eglot]]></category>
  <category><![CDATA[emacs]]></category>
  <category><![CDATA[lsp-mode]]></category>
  <link>https://magnus.therning.org/2026-01-19-trying-eglot,-again.html</link>
  <guid>https://magnus.therning.org/2026-01-19-trying-eglot,-again.html</guid>
  <pubDate>Mon, 19 Jan 2026 08:00:00 +0100</pubDate>
</item>
<item>
  <title><![CDATA[Making a theme based on modus]]></title>
  <description><![CDATA[
<p>
In <code>modus-theme</code> 5.0.0 Prot introduced a structured way to build a theme based
on modus. Just a few days ago he released version 5.1.0 with some improvements
in this area.
</p>

<p>
The official documentation of how to <a href="https://protesilaos.com/emacs/modus-themes#h:86eb375b-9be4-43ce-879a-0686a524a63b">build on top of the Modus themes</a> is very
good. It's focused on how to make sure your theme fits in with the rest of the
"modus universe". However, after reading it I still didn't have a good idea of
how to get started with my own theme. In case others feel the same way I thought
I'd write down how I ended up getting started.
</p>

<p>
The resulting theme, <code>modus-catppuccin</code>, can be found <a href="https://gitlab.com/magus/modus-catppuccin">here</a>.
</p>
<div id="outline-container-org4839f2f" class="outline-2">
<h2 id="org4839f2f">A little background</h2>
<div class="outline-text-2" id="text-org4839f2f">
<p>
I read about how to <a href="https://www.rahuljuliato.com/posts/modus-catppuccin">create a catppuccin-mocha theme using modus-vivendi</a> through
modus' mechanism of overrides. On Reddit someone pointed out that Prot had been
working on basing themes on modus and when I checked the state of it he'd just
released version 5.0.0. Since I'm using catppuccin themes for pretty much all
software with a GUI I thought it could be interesting to see if I could make a
modus-based catppuccin theme to replace my use of <a href="https://github.com/catppuccin/emacs"><code>catppuccin-theme</code></a>.
</p>

<p>
I'm writing the rest as if it was a straight and easy journey. It wasn't! I made
a few false starts, each time realising something new about the structure and
starting over with a better idea.
</p>
</div>
</div>
<div id="outline-container-org61bc0bd" class="outline-2">
<h2 id="org61bc0bd">Finding a starting point</h2>
<div class="outline-text-2" id="text-org61bc0bd">
<p>
When reading what Prot had written about <code>modus-themes</code> in general, and about
how to create themes based on it, in particular, I found that he's ported both
<a href="https://github.com/protesilaos/standard-themes"><code>standard-themes</code></a> and <a href="https://github.com/protesilaos/ef-themes"><code>ef-themes</code></a> so they now are based on modus. Instead of
just using them for inspiration I decided that since <code>standard-themes</code> is so
small I might as well use it as my starting point.
</p>
</div>
</div>
<div id="outline-container-org8f0c803" class="outline-2">
<h2 id="org8f0c803">Starting</h2>
<div class="outline-text-2" id="text-org8f0c803">
<p>
I copied all files of <code>standard-themes</code> to an empty git repository, then I
</p>

<ul class="org-ul">
<li>deleted all but one of the theme file</li>
<li>copied the remaining theme file so I had four in total (one for each of the
<a href="https://catppuccin.com/palette/">catppuccin flavours</a>)</li>
<li>renamed constants, variables, and functions so they would match the
theme and its flavours</li>
<li>put the colours into each <code>catppuccin-&lt;flavour&gt;-palette</code></li>
<li>emptied the common palette, <code>modus-catppuccin-common-palette-mappings</code></li>
<li>made sure that my use of <code>modus-themes-theme</code> was reasonable, in particular
the base palette (I based the light flavour on <code>modus-operandi</code> and the three
dark flavours on <code>modus-vivendi</code>)</li>
</ul>

<p>
The result can be seen <a href="https://gitlab.com/magus/modus-catppuccin/-/tree/c86e17d29e0fc8f0d4a6a2e94a475f32037d2851">here</a>.
</p>

<p>
At this point the three theme flavours contained no relevant mappings of their
own, so what I had was in practice <code>modus-operandi</code> under a new name and
<code>modus-vivendi</code> under three new names.
</p>
</div>
</div>
<div id="outline-container-org28309d9" class="outline-2">
<h2 id="org28309d9">Adding mappings for catppuccin</h2>
<div class="outline-text-2" id="text-org28309d9">
<p>
By organising the theme flavours the way outlined above I only need to add
mappings to <code>modus-catppuccin-common-palette-mappings</code> because
</p>

<ol class="org-ol">
<li>each flavour-specific mapping adds its colour palette using the same name
(that's how catppuccin organises its colors too, <a href="https://catppuccin.com/palette/">as seen here</a>)</li>
<li>each flavour-specific mapping is combined with the common one</li>
<li>any missing mapping is picked up by the underlying theme, <code>modus-operandi</code> or
<code>modus-vivendi</code>, so there will be (somewhat) nice colours for everything</li>
</ol>

<p>
I started out with the mappings in the <a href="https://github.com/protesilaos/standard-themes/blob/main/standard-dark-theme.el">dark standard theme</a> but then I realised
that's not the complete list of available mappings and I started looking at the
themes in <code>modus-themes</code> itself.
</p>
</div>
</div>
<div id="outline-container-orgeb19297" class="outline-2">
<h2 id="orgeb19297">Current state of <code>modus-catppuccin</code></h2>
<div class="outline-text-2" id="text-orgeb19297">
<p>
I've so far defined enough mappings to make it look enough like catppuccin for
my use. There are a lot of possible mappings so my plan is to add them over time
and use <a href="https://github.com/catppuccin/emacs"><code>catppuccin-theme</code></a> for inspiration.
</p>
</div>
</div>
<div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-emacs.html">emacs</a> </div>
]]></description>
  <category><![CDATA[emacs]]></category>
  <link>https://magnus.therning.org/2025-11-08-making-a-theme-based-on-modus.html</link>
  <guid>https://magnus.therning.org/2025-11-08-making-a-theme-based-on-modus.html</guid>
  <pubDate>Sat, 08 Nov 2025 09:45:00 +0100</pubDate>
</item>
<item>
  <title><![CDATA[Listing buffers by tab using consult and bufferlo]]></title>
  <description><![CDATA[
<p>
I've gotten into the habit of using tabs, via <code>tab-bar</code>, to organise my buffers
when I have multiple projects open at once. Each project has its own tab.
There's nothing fancy here (yet), I simply open a new tab manually before
opening a new project.
</p>

<p>
A while ago I added <a href="https://github.com/florommel/bufferlo">bufferlo</a> to my config to help with getting <code>consult-buffer</code>
to organise buffers (somewhat) by tab. I copied the configuration from <a href="https://github.com/florommel/bufferlo?tab=readme-ov-file#consult">the
bufferlo README</a> and started using it. It took me a little while to notice that
the behaviour wasn't quite what I wanted. It seemed like one buffer "leaked"
from another tab.
</p>


<figure id="org1786323">
<img src="static/2025-09-16-buffer-leakage.png" alt="2025-09-16-buffer-leakage.png">

<figcaption><span class="figure-number">Figure 1: </span>Example of buffer leakage</figcaption>
</figure>

<p>
In the image above all files in <code>~/.emacs.d</code> should be listed under <i>Other
Buffers</i>, but one has been brought over into the tab for the Sider project.
</p>

<p>
After a bit of experimenting I realised that
</p>

<ol class="org-ol">
<li>the buffer that leaks is the one I'm in when creating the new tab, and</li>
<li>my function for creating a new tab doesn't work the way I thought.</li>
</ol>

<p>
My function for creating a new tab looked like this
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">lambda</span> <span class="org-rainbow-delimiters-depth-2">()</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">interactive</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>tab-new<span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>dashboard-open<span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
and it turns out that <code>tab-new</code> shows the current buffer in the new tab which in
turn caused bufferlo to associate it to the wrong tab. From what I can see
there's no way to tell <code>tab-new</code> to open a specific buffer in the newly created
tab. I tried the following
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">lambda</span> <span class="org-rainbow-delimiters-depth-2">()</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">interactive</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">with-current-buffer</span> dashboard-buffer-name
    <span class="org-rainbow-delimiters-depth-3">(</span>tab-new<span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
hoping that the dashboard would open in the new tab. It didn't, it was still the
active buffer that popped up in the new tab.
</p>

<p>
In the end I resorted to use <code>bufferlo-remove</code> to simply remove the current
buffer from the new tab.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">lambda</span> <span class="org-rainbow-delimiters-depth-2">()</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">interactive</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>tab-new<span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>bufferlo-remove <span class="org-rainbow-delimiters-depth-3">(</span>current-buffer<span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span>dashboard-open<span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</code></pre>
</div>

<p>
No more leakage and <code>consult-buffer</code> works like I wanted it to.
</p>
<div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-emacs.html">emacs</a> </div>
]]></description>
  <category><![CDATA[emacs]]></category>
  <link>https://magnus.therning.org/2025-09-16-listing-buffers-by-tab-using-consult-and-bufferlo.html</link>
  <guid>https://magnus.therning.org/2025-09-16-listing-buffers-by-tab-using-consult-and-bufferlo.html</guid>
  <pubDate>Tue, 16 Sep 2025 08:29:00 +0200</pubDate>
</item>
<item>
  <title><![CDATA[Reviewing GitHub PRs in Emacs]]></title>
  <description><![CDATA[
<p>
My Emacs config's todo-list has long had an item about finding some way to
review GitHub PRs without having to leave Emacs and when the <a href="https://github.com/magit/forge/issues/75">forge issue</a> that I
subscribe to came alive again I thought it was time to see if I can improve my
config.
</p>

<p>
I found three packages for doing reviews
</p>

<ul class="org-ul">
<li><a href="https://github.com/wandersoncferreira/code-review">code-review</a></li>
<li><a href="https://github.com/charignon/github-review">github-review</a></li>
<li><a href="https://github.com/blahgeek/emacs-pr-review">emacs-pr-review</a></li>
</ul>

<p>
I've tried the first one before but at the time it didn't seem to work at all.
Apparently that's improved somewhat, though there's a PR with a change that's
necessary to make it work.<sup><a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink">1</a></sup> The first two don't support comments on multiple
lines of a PR, there are issues/discussions for both
</p>

<ul class="org-ul">
<li><code>code-review</code>: <a href="https://github.com/wandersoncferreira/code-review/discussions/259">Code suggestion on multiple lines</a></li>
<li><code>github-review</code>: <a href="https://github.com/charignon/github-review/issues/46">Multi-line code comments</a></li>
</ul>

<p>
The last one, <code>emacs-pr-review</code> does support commenting on multiple lines, but
it lacks a nice way of opening a review from <code>magit</code>. What I can do is
</p>

<ol class="org-ol">
<li>position the cursor on a PR in the <code>magit</code> status view, then</li>
<li>copy the the PR's URL using <code>forge-copy-url-at-point-as-kill</code>, and</li>
<li>open the PR by calling <code>pr-review</code> and pasting the PR's URL.</li>
</ol>

<p>
Which I did for a few days until I got tired of it and wrote a function to cut
out they copy/paste part.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">defun</span> <span class="org-function-name">mes/pr-review-via-forge</span> <span class="org-rainbow-delimiters-depth-2">()</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">interactive</span><span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">if-let*</span> <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-rainbow-delimiters-depth-4">(</span>target <span class="org-rainbow-delimiters-depth-5">(</span>forge--browse-target<span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span>
            <span class="org-rainbow-delimiters-depth-4">(</span>url <span class="org-rainbow-delimiters-depth-5">(</span><span class="org-keyword">if</span> <span class="org-rainbow-delimiters-depth-6">(</span>stringp target<span class="org-rainbow-delimiters-depth-6">)</span> target <span class="org-rainbow-delimiters-depth-6">(</span>forge-get-url target<span class="org-rainbow-delimiters-depth-6">)</span><span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span>
            <span class="org-rainbow-delimiters-depth-4">(</span>rev-url <span class="org-rainbow-delimiters-depth-5">(</span>pr-review-url-parse url<span class="org-rainbow-delimiters-depth-5">)</span><span class="org-rainbow-delimiters-depth-4">)</span><span class="org-rainbow-delimiters-depth-3">)</span>
      <span class="org-rainbow-delimiters-depth-3">(</span>pr-review url<span class="org-rainbow-delimiters-depth-3">)</span>
    <span class="org-rainbow-delimiters-depth-3">(</span><span class="org-warning">user-error</span> <span class="org-string">"No PR to review at point"</span><span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</pre>
</div>

<p>
I've bound it to a key in <code>magit-mode-map</code> to make it easier.
</p>

<p>
I have to say I'm not completely happy with <code>emacs-pr-review</code>, so if either of
the other two sort out commenting on multiple lines I'll check them out again.
</p>

<p>
My full setup for <code>pr-review</code> is <a href="https://gitlab.com/magus/mes/-/blob/8615353ec007bd66209ee1ae3badddd26d3a3dc9/lisp/mes-dev-basics.el#L76">here</a>.
</p>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">

<div class="footdef"><sup><a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
The details can be found among the comments of the <a href="https://github.com/magit/forge/issues/75">forge issue</a>.
</p></div></div>


</div>
</div><div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-emacs.html">emacs</a> </div>
]]></description>
  <category><![CDATA[emacs]]></category>
  <link>https://magnus.therning.org/2025-01-19-reviewing-github-prs-in-emacs.html</link>
  <guid>https://magnus.therning.org/2025-01-19-reviewing-github-prs-in-emacs.html</guid>
  <pubDate>Sun, 19 Jan 2025 11:10:00 +0100</pubDate>
</item>
<item>
  <title><![CDATA[Followup on secrets in my work notes]]></title>
  <description><![CDATA[
<p>
I got the following question on my post on how I handle secrets in my work notes:
</p>

<blockquote>
<p>
Sounds like a nice approach for other secrets but how about <code>:dbconnection</code> for
Orgmode and <code>sql-connection-alist</code>?
</p>
</blockquote>

<p>
I have to admit I'd never come across the variable <code>sql-connection-alist</code>
before. I've never really used <code>sql-mode</code> for more than editing SQL queries and
setting up code blocks for running them was one of the first things I used
<a href="https://github.com/joaotavora/yasnippet">yasnippet</a> for.
</p>

<p>
I did a little reading and unfortunately it looks like <code>sql-connection-alist</code>
can only handle string values. However, there is a variable
<code>sql-password-search-wallet-function</code>, with the default value of
<code>sql-auth-source-search-wallet</code>, so using <a href="https://www.gnu.org/software/emacs/manual/html_mono/auth.html">auth-source</a> is already supported for
the password itself.
</p>

<p>
There seems to be a lack of good tutorials for setting up <code>sql-mode</code> in a secure
way &#x2013; all articles I found place the password in clear-text in the config &#x2013;
filling that gap would be a nice way to contribute to the Emacs community. I'm
sure it'd prompt me to re-evaluate incorporating <code>sql-mode</code> in my workflow.
</p>
<div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-emacs.html">emacs</a> <a href="https://magnus.therning.org/tag-org-mode.html">org-mode</a> </div>
]]></description>
  <category><![CDATA[emacs]]></category>
  <category><![CDATA[org-mode]]></category>
  <link>https://magnus.therning.org/2024-09-09-followup-on-secrets-in-my-work-notes.html</link>
  <guid>https://magnus.therning.org/2024-09-09-followup-on-secrets-in-my-work-notes.html</guid>
  <pubDate>Mon, 09 Sep 2024 22:36:00 +0200</pubDate>
</item>
<item>
  <title><![CDATA[Improving how I handle secrets in my work notes]]></title>
  <description><![CDATA[
<p>
At work I use org-mode to keep notes about useful ways to query our systems,
mostly that involves using the built-in SQL support to access DBs and <a href="https://github.com/ag91/ob-http">ob-http</a> to
send HTTP requests. In both cases I often need to provide credentials for the
systems. I'm embarrassed to admit it, but for a long time I've taken the easy
path and kept all credentials in clear text. Every time I've used one of those
code blocks I've thought I really ought to find a better way of handling these
secrets one of these days. Yesterday was that day.
</p>

<p>
I ended up with two functions that uses <a href="https://www.gnu.org/software/emacs/manual/html_mono/auth.html">auth-source</a> and its <code>~/.authinfo.gpg</code>
file.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">defun</span> <span class="org-function-name">mes/auth-get-pwd</span> <span class="org-rainbow-delimiters-depth-2">(</span>host<span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-doc">"Get the password for a host (authinfo.gpg)"</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">-&gt;</span> <span class="org-rainbow-delimiters-depth-3">(</span>auth-source-search <span class="org-builtin">:host</span> host<span class="org-rainbow-delimiters-depth-3">)</span>
      car
      <span class="org-rainbow-delimiters-depth-3">(</span>plist-get <span class="org-builtin">:secret</span><span class="org-rainbow-delimiters-depth-3">)</span>
      funcall<span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>

<span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">defun</span> <span class="org-function-name">mes/auth-get-key</span> <span class="org-rainbow-delimiters-depth-2">(</span>host key<span class="org-rainbow-delimiters-depth-2">)</span>
  <span class="org-doc">"Get a key's value for a host (authinfo.gpg)</span>

<span class="org-doc">Not usable for getting the password (:secret), use '</span><span class="org-doc"><span class="org-constant">mes/auth-get-pwd</span></span><span class="org-doc">'</span>
<span class="org-doc">for that."</span>
  <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-keyword">-&gt;</span> <span class="org-rainbow-delimiters-depth-3">(</span>auth-source-search <span class="org-builtin">:host</span> host<span class="org-rainbow-delimiters-depth-3">)</span>
      car
      <span class="org-rainbow-delimiters-depth-3">(</span>plist-get key<span class="org-rainbow-delimiters-depth-3">)</span><span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span>
</pre>
</div>

<p>
It turns out that the library can handle more keys than the documentation
suggests so for DB entries I'm using a <code>machine</code> (<code>:host</code>) that's a bit shorter
and easier to remember than the full AWS hostname. Then I keep the DB host and
name in <code>dbhost</code> (<code>:dbhost</code>) and <code>dbname</code> (<code>:dbname</code>) respectively. That makes
an entry look like this:
</p>

<div class="org-src-container">
<pre class="src src-authinfo"><span class="org-variable-name">machine</span> <span class="org-builtin">db.svc</span> <span class="org-comment-delimiter">login</span> <span class="org-keyword">user</span> <span class="org-comment-delimiter">port</span> <span class="org-type">port</span> <span class="org-comment-delimiter">password</span> <span class="org-doc">pwd</span> <span class="org-constant">dbname</span> dbname <span class="org-constant">dbhost</span> dbhost
</pre>
</div>

<p>
If I use it in a property drawer it looks like this
</p>

<div class="org-src-container">
<pre class="src src-org"><span class="org-org-drawer">:PROPERTIES:</span>
<span class="org-org-special-keyword">:header-args:sql:</span> <span class="org-org-property-value">:engine postgresql</span>
<span class="org-org-special-keyword">:header-args:sql+:</span> <span class="org-org-property-value">:dbhost (mes/auth-get-key "db.svc" :dbhost)</span>
<span class="org-org-special-keyword">:header-args:sql+:</span> <span class="org-org-property-value">:dbport (string-to-number (mes/auth-get-key "db.svc" :port))</span>
<span class="org-org-special-keyword">:header-args:sql+:</span> <span class="org-org-property-value">:dbuser (mes/auth-get-key "db.svc" :user)</span>
<span class="org-org-special-keyword">:header-args:sql+:</span> <span class="org-org-property-value">:dbpassword (mes/auth-get-pwd "db.svc")</span>
<span class="org-org-special-keyword">:header-args:sql+:</span> <span class="org-org-property-value">:database (mes/auth-get-key "db.svc" :dbname)</span>
<span class="org-org-drawer">:END:</span>
</pre>
</div>
<div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-emacs.html">emacs</a> <a href="https://magnus.therning.org/tag-org-mode.html">org-mode</a> </div>
]]></description>
  <category><![CDATA[emacs]]></category>
  <category><![CDATA[org-mode]]></category>
  <link>https://magnus.therning.org/2024-09-01-improving-how-i-handle-secrets-in-my-work-notes.html</link>
  <guid>https://magnus.therning.org/2024-09-01-improving-how-i-handle-secrets-in-my-work-notes.html</guid>
  <pubDate>Sun, 01 Sep 2024 15:03:00 +0200</pubDate>
</item>
<item>
  <title><![CDATA[Removing symlink question]]></title>
  <description><![CDATA[
<p>
I'm not sure why, but all of a sudden I started getting this question every time
emacs starts
</p>

<blockquote>
<p>
Symbolic link to Git-controlled source file; follow link?
</p>
</blockquote>

<p>
After some searching I found out that it's <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Version-Control.html">VC</a> asking. I'm guessing this comes
from <a href="https://github.com/radian-software/straight.el">straight</a>'s very liberal use of symlinks. Though I'm still a little
surprised at VC kicking in when reading the config.
</p>

<p>
Anyway, there are two variables to consider, <code>vc-follow-symlinks</code> and
<code>vc-handled-backends</code>. I opted to modify the latter one, and since I don't use
VC at all I'm turning it off completely.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-keyword">setopt</span> vc-handled-backends nil<span class="org-rainbow-delimiters-depth-1">)</span>
</pre>
</div>
<div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-emacs.html">emacs</a> </div>
]]></description>
  <category><![CDATA[emacs]]></category>
  <link>https://magnus.therning.org/2024-08-11-removing-symlink-question.html</link>
  <guid>https://magnus.therning.org/2024-08-11-removing-symlink-question.html</guid>
  <pubDate>Sun, 11 Aug 2024 08:41:00 +0200</pubDate>
</item>
</channel>
</rss>
