<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Nicolas Martyanoff – Brain dump</title>
    <description>Brain dump</description>
    <language>en-us</language>
    <managingEditor>nicolas@n16f.net (Nicolas Martyanoff)</managingEditor>
    <webMaster>nicolas@n16f.net (Nicolas Martyanoff)</webMaster>
    <link>https://www.n16f.net/blog/index.xml</link>
    <atom:link href="https://www.n16f.net/blog/index.xml" rel="self" type="application/rss+xml" />
    <lastBuildDate>Sat, 26 Apr 2025 00:00:00 +0000</lastBuildDate>

    
    <item xml:base="https://www.n16f.net/blog/working-with-common-lisp-pathnames/">
      <title>Working with Common Lisp pathnames</title>
      <link>https://www.n16f.net/blog/working-with-common-lisp-pathnames/</link>
      <pubDate>Sat, 26 Apr 2025 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/working-with-common-lisp-pathnames/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;Common Lisp pathnames, used to represent file paths, have the reputation of
being hard to work with. This article aims to change this unfair reputation
while highlighting the occasional quirks along the way.&lt;/p&gt;
&lt;h2 id=&#34;filenames-and-file-paths&#34;&gt;Filenames and file paths&lt;/h2&gt;
&lt;p&gt;The distinction between filename and file paths is not always obvious. On POSIX
systems, the filename is the name of the file, while a file path represents its
absolute or relative location in the file system. Which also means that all
filenames are file paths, but not the other way around.&lt;/p&gt;
&lt;p&gt;Common Lisp uses the term filename for objects which are either pathnames or
namestrings, both being representation of file paths. We will try to avoid
confusion by using the terms filenames, pathnames and namestrings when referring
to Common Lisp concepts and we will talk about file paths when referring to the
language-agnostic file system concept.&lt;/p&gt;
&lt;h2 id=&#34;pathnames&#34;&gt;Pathnames&lt;/h2&gt;
&lt;p&gt;Pathnames are an implementation-independent representation of file paths made of
six components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an &lt;em&gt;host&lt;/em&gt; identifying either the file system or a logical host;&lt;/li&gt;
&lt;li&gt;a &lt;em&gt;device&lt;/em&gt; identifying the logical of physical device containing the file;&lt;/li&gt;
&lt;li&gt;a &lt;em&gt;directory&lt;/em&gt; representing an absolute or relative list of directory
names;&lt;/li&gt;
&lt;li&gt;a &lt;em&gt;name&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;a &lt;em&gt;type&lt;/em&gt;, a value nowadays known as &lt;em&gt;file extension&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;a &lt;em&gt;version&lt;/em&gt;, because yes file systems used to support file versioning.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While this representation might seem way too complicated —it originates from a
time where the file system ecosystem was much richer— it still is suitable for
modern file systems.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;make-pathname&lt;/code&gt; function is used to create pathnames and lets you specificy
all components. For example the following call yields a pathname representing
the file path represented on POSIX systems by &lt;code&gt;/var/run/example.pid&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(make-pathname :directory &#39;(:absolute &amp;quot;var&amp;quot; &amp;quot;run&amp;quot;) :name &amp;quot;example&amp;quot; :type &amp;quot;pid&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Common Lisp functions manipulating file paths of course accept pathnames,
letting you keep the same convenient structured representation everywhere, only
converting from/to a native representation at the boundaries of your program.&lt;/p&gt;
&lt;h3 id=&#34;special-characters&#34;&gt;Special characters&lt;/h3&gt;
&lt;p&gt;What happens when you construct a pathname with components containing separation
characters, e.g. a directory name containing &lt;code&gt;/&lt;/code&gt; on a POSIX system or a type
containing &lt;code&gt;.&lt;/code&gt;? According to Common Lisp 19.2.2.1.1, the behaviour is
implementation-defined; but if the implementation accepts these component values
it must handle quoting correctly.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CLISP rejects separator characters in component values, signaling a
&lt;code&gt;SIMPLE-ERROR&lt;/code&gt; condition.&lt;/li&gt;
&lt;li&gt;CCL accepts them and quotes them when converting the pathname to a
namestring. So &lt;code&gt;(namestring (make-pathname :name &amp;quot;foo/bar&amp;quot; :type &amp;quot;a.b&amp;quot;))&lt;/code&gt;
yields &lt;code&gt;&amp;quot;foo\\/bar.a\\.b&amp;quot;&lt;/code&gt; on Linux.&lt;/li&gt;
&lt;li&gt;SBCL accepts and quotes them but does not quote &lt;code&gt;.&lt;/code&gt; in type components,
yielding &lt;code&gt;&amp;quot;foo\\/bar.a.b&amp;quot;&lt;/code&gt; for the example above.&lt;/li&gt;
&lt;li&gt;ECL accepts them but fails to quote them when converting the pathname to a
namestring.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One could wonder about which implementation, CCL or SBCL, is correct regarding
the quoting of the &lt;code&gt;.&lt;/code&gt; character in type strings on POSIX platforms. While
everyone understands that &lt;code&gt;/&lt;/code&gt; is special in file and directory names, &lt;code&gt;.&lt;/code&gt; is
debatable because POSIX does not mention the type extension in its definitions:
&lt;code&gt;foo.txt&lt;/code&gt; is the name of the file, not a combination of a name and a type. As
such, I would argue that quoting and not quoting are both correct. And as you
will realize then reading about namestrings further in this article, it is
irrelevant since namestrings are not POSIX paths.&lt;/p&gt;
&lt;p&gt;Note that whether ECL violates the standard or not is unclear since there is no
character quoting for POSIX paths. In other words, there is no such thing as a
directory named &lt;code&gt;a/b&lt;/code&gt;, because it could not be referenced in a way different
from a directory named &lt;code&gt;b&lt;/code&gt; in a directory named &lt;code&gt;a&lt;/code&gt;. This behaviour derives
directly from POSIX systems treating paths as strings and not as structured
objects.&lt;/p&gt;
&lt;h3 id=&#34;invalid-characters&#34;&gt;Invalid characters&lt;/h3&gt;
&lt;p&gt;The Common Lisp standard mentions &lt;em&gt;special&lt;/em&gt; characters but is silent on the
subject of &lt;em&gt;invalid&lt;/em&gt; characters. For example POSIX forbids null bytes in
filenames. But since it is not a separation character, implementations are free
to deal with it as they see fit.&lt;/p&gt;
&lt;p&gt;When testing implementations with a pathname containing a null byte using
&lt;code&gt;(make-pathname :name (string (code-char 0)))&lt;/code&gt;, CCL, SBCL and ECL accept it
while CLISP signals an error mentioning an illegal argument.&lt;/p&gt;
&lt;p&gt;I am not convinced by CLISP&amp;rsquo;s behaviour since null bytes are only invalid in
&lt;em&gt;POSIX paths&lt;/em&gt;, not in &lt;em&gt;Common Lisp filenames&lt;/em&gt;, meaning that the error should
occur when the pathname is internally converted to a format usable by the
operating system.&lt;/p&gt;
&lt;h3 id=&#34;pathname-component-case&#34;&gt;Pathname component case&lt;/h3&gt;
&lt;p&gt;A rarely mentioned property of pathnames is the support for case conversion.
&lt;code&gt;MAKE-PATHNAME&lt;/code&gt; and function returning pathname components (e.g.
&lt;code&gt;PATHNAME-TYPE&lt;/code&gt;) support a &lt;code&gt;:CASE&lt;/code&gt; argument, either &lt;code&gt;:COMMON&lt;/code&gt; or &lt;code&gt;:LOCAL&lt;/code&gt;
indicating how how to handle character case in strings.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;:LOCAL&lt;/code&gt; —which is the default value—, these functions assume that
component strings are already represented following the conventions of the
underlying operating system. It also dictates that if the host only supports one
character case, strings must be returned converted to this case.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;:COMMON&lt;/code&gt;, these functions will use the default (customary) case of the
host if the string is provided all uppercase, and the opposite case if the
string is provided all lowercase. Mixed case strings are not transformed.&lt;/p&gt;
&lt;p&gt;These behaviours are not intuitive and made much more sense at a time where some
file systems only supported one specific case. You should probably stay away
from component case handling unless you really know what you are doing.&lt;/p&gt;
&lt;p&gt;On a personal note, as someone running Linux and FreeBSD, I am curious about the
behaviour of various implementations on Windows and MacOS since both NTFS and
APFS are case insensitive.&lt;/p&gt;
&lt;h3 id=&#34;unspecific-components&#34;&gt;Unspecific components&lt;/h3&gt;
&lt;p&gt;While all components can be null, some of them can be &lt;code&gt;:UNSPECIFIC&lt;/code&gt; (which ones
is implementation-defined). The only real use case for &lt;code&gt;:UNSPECIFIC&lt;/code&gt; is to
affect the behaviour of &lt;code&gt;MERGE-PATHNAMES&lt;/code&gt;: if a component is null, the function
uses the value of the component in the pathname passed as the &lt;code&gt;:DEFAULTS&lt;/code&gt;
argument; if a component is &lt;code&gt;:UNSPECIFIC&lt;/code&gt;, the function uses the same value in
the resulting pathname.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(merge-pathnames (make-pathname :name &amp;quot;foo&amp;quot;)
                 (make-pathname :type &amp;quot;txt&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yields the &lt;code&gt;&amp;quot;foo.txt&amp;quot;&lt;/code&gt; namestring, but&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(merge-pathnames (make-pathname :name &amp;quot;foo&amp;quot; :type :unspecific)
                 (make-pathname :type &amp;quot;txt&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yields &lt;code&gt;&amp;quot;foo&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately the inability to rely on its support for specific component types
(since it is implementation-defined) makes it interesting more than useful.&lt;/p&gt;
&lt;h2 id=&#34;namestrings&#34;&gt;Namestrings&lt;/h2&gt;
&lt;p&gt;Namestrings are another represention for file paths. While pathnames are
structured objects, namestrings are just strings. The most important aspect of
namestrings is that unless they are logical namestrings (something we will cover
later), the way they represent paths is implementation-defined (c.f. Common Lisp
19.1.1 Namestrings as Filenames). In other words the namestring for the file
&lt;code&gt;foo&lt;/code&gt; of type &lt;code&gt;txt&lt;/code&gt; in directory &lt;code&gt;data&lt;/code&gt; could be &lt;code&gt;data/foo.txt&lt;/code&gt;. Or
&lt;code&gt;data\foo.txt&lt;/code&gt;. Or &lt;code&gt;data|foo#txt&lt;/code&gt;. Or any other non-sensical representation.
Fortunately implementations tend to act rationally and use a representation as
similar as possible to the one of their host operating system.&lt;/p&gt;
&lt;p&gt;One should always remember that even though namestrings look and feel like
paths, they are still a representation of a Common Lisp pathname, meaning that
they may or may not map to a valid native path. The most obvious example would
be a pathname whose name is the null byte, created with &lt;code&gt;(make-pathname :name (string (code-char 0)))&lt;/code&gt;, whose namestring is a one character string that has no
valid native representation on modern operating systems.&lt;/p&gt;
&lt;p&gt;Pathnames can be converted to namestrings using the &lt;code&gt;NAMESTRING&lt;/code&gt; function, while
namestrings can be parsed into pathnames with &lt;code&gt;PARSE-NAMESTRING&lt;/code&gt;. The &lt;code&gt;#P&lt;/code&gt;
reader macro uses &lt;code&gt;PARSE-NAMESTRING&lt;/code&gt; to read a pathname. As such,
&lt;code&gt;#P&amp;quot;/tmp/foo.txt&amp;quot;&lt;/code&gt; is identical to &lt;code&gt;#.(parse-namestring &#39;&amp;quot;/tmp/foo.txt&amp;quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that most functions dealing with files will accept a &lt;em&gt;pathname designator&lt;/em&gt;,
i.e. either a pathname, a namestring or a stream.&lt;/p&gt;
&lt;h3 id=&#34;native-namestrings&#34;&gt;Native namestrings&lt;/h3&gt;
&lt;p&gt;An unfortunately missing feature from Common Lisp is the ability to parse
&lt;em&gt;native namestrings&lt;/em&gt;, i.e. paths that use the representation of the underlying
operating system.&lt;/p&gt;
&lt;p&gt;To understand why it is a problem, let us take &lt;code&gt;*.txt&lt;/code&gt;, a perfectly valid
filename at least on any POSIX platform. In Common Lisp, you can construct a
pathname representing this filename with &lt;code&gt;(make-pathname :name &amp;quot;*&amp;quot; :type &amp;quot;txt&amp;quot;)&lt;/code&gt;. No problem whatsoever. However the &lt;code&gt;&amp;quot;*.txt&amp;quot;&lt;/code&gt; namestring actually
represents a pathname whose name component is &lt;code&gt;:WILD&lt;/code&gt;. There is no namestring
that will return this pathname when passed to &lt;code&gt;PARSE-NAMESTRING&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As a result, when processing filenames coming from the external world (a command
line argument, a list of paths in a document, etc.), you have no way to handle
those that contain characters used by Common Lisp for wild components.&lt;/p&gt;
&lt;p&gt;There is no standard way of solving this issue. Some implementations provide
functions to parse native namestrings, e.g. SBCL with
&lt;code&gt;SB-EXT:PARSE-NATIVE-NAMESTRING&lt;/code&gt; or CCL with &lt;code&gt;CCL:NATIVE-TO-PATHNAME&lt;/code&gt;. If you
use &lt;a href=&#34;https://asdf.common-lisp.dev&#34;&gt;ASDF&lt;/a&gt;, you can also use
&lt;code&gt;UIOP:PARSE-NATIVE-NAMESTRING&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;wildcards&#34;&gt;Wildcards&lt;/h2&gt;
&lt;p&gt;Up to now pathnames may have looked like a slightly unusual representation for
paths. But we are just getting started.&lt;/p&gt;
&lt;p&gt;Pathname can be &lt;em&gt;wild&lt;/em&gt;, meaning that they contain one or more wild components.
Wild components can match any value. All components can be made wild with the
special value &lt;code&gt;:WILD&lt;/code&gt;. Directory elements also support &lt;code&gt;:WILD-INFERIORS&lt;/code&gt; which
matches one or more directory levels.&lt;/p&gt;
&lt;p&gt;As such&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(make-pathname :directory &#39;(:absolute &amp;quot;tmp&amp;quot; :wild) :name &amp;quot;foo&amp;quot; :type :wild)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is equivalent to the &lt;code&gt;/tmp/*/foo.*&lt;/code&gt; POSIX glob pattern, while&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(make-pathname :directory &#39;(:absolute &amp;quot;tmp&amp;quot; :wild-inferiors &amp;quot;data&amp;quot; :wild)
               :name :wild :type :wild)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is equivalent to &lt;code&gt;/tmp/**/data/*/*.*&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Wild pathnames only really make sense for the &lt;code&gt;DIRECTORY&lt;/code&gt; function which returns
files matching a specific pathname.&lt;/p&gt;
&lt;h2 id=&#34;logical-pathnames&#34;&gt;Logical pathnames&lt;/h2&gt;
&lt;p&gt;We currently have talked about pathnames representing either paths to physical
files or pattern of filenames. Logical pathnames go further and let you work
with files in a location-independent way.&lt;/p&gt;
&lt;p&gt;Logical pathnames are based on &lt;em&gt;logical hosts&lt;/em&gt;, set as pathname host components.
Logical pathnames can be passed around and manipulated as any other pathnames;
when used to access files, they are translated to a &lt;em&gt;physical pathname&lt;/em&gt;, i.e. a
pathname referring to an actual file in the file system.&lt;/p&gt;
&lt;p&gt;SBCL uses logical pathnames for source file locations. While SBCL is shipped
with its source files, their actual location on disk depends on how the software
was installed. Instead of manually merging pathnames with a base directory value
everywhere, SBCL uses the &lt;code&gt;SYS&lt;/code&gt; logical host to map all pathnames whose
directory starts with &lt;code&gt;SRC&lt;/code&gt; to the actual location on disk. For example on my
machine:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(translate-logical-pathname &amp;quot;SYS:SRC;ASSEMBLY;MASTER.LISP&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yields &lt;code&gt;#P&amp;quot;/usr/share/sbcl-source/src/assembly/master.lisp&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Another example would be CCL which maps pathnames with the &lt;code&gt;HOME&lt;/code&gt; logical host
to subpaths of the home directory of the user.&lt;/p&gt;
&lt;p&gt;Note that logical hosts are global to the Common Lisp environment. While &lt;code&gt;SYS&lt;/code&gt;
is reserved for the implementation, all other hosts are free to use by anyone.
To avoid collisions, it is a good idea to name hosts after their program or
library.&lt;/p&gt;
&lt;h3 id=&#34;logical-namestrings&#34;&gt;Logical namestrings&lt;/h3&gt;
&lt;p&gt;Logical namestrings are implementation-independent, meaning that you can safely
use them in your programs without wondering about how they will be interpreted.
Their syntax, detailed in section 19.3.1 of the Common Lisp standard, is quite
different from usual POSIX paths. The host is separated from the rest of the
path by a colon character, and directory names are separated by semicolon
characters.&lt;/p&gt;
&lt;p&gt;For example &lt;code&gt;&amp;quot;SOURCE:SERVER;LISTENER.LISP&amp;quot;&lt;/code&gt; is the logical namestring equivalent
of the &lt;code&gt;/server/listener.lisp&lt;/code&gt; POSIX path for the &lt;code&gt;SOURCE&lt;/code&gt; logical host.&lt;/p&gt;
&lt;p&gt;The astute reader will notice the use of uppercase characters in logical
namestrings. It happens that the different parts of a logical namestring are
defined as using uppercase characters, but that the implementation translates
lowercase letters to uppercase letters when parsing the namestrings (c.f. Common
Lisp 19.3.1.1.7). We use the canonical uppercase representation for clarity.&lt;/p&gt;
&lt;h3 id=&#34;translation&#34;&gt;Translation&lt;/h3&gt;
&lt;p&gt;Translation is controlled by a table that maps logical hosts to a list of
pattern (wild pathnames or namestrings) and their associated wild physical
pathnames.&lt;/p&gt;
&lt;p&gt;One can obtain the list of translations for a logical host with
&lt;code&gt;LOGICAL-PATHNAME-TRANSLATIONS&lt;/code&gt; and update it with &lt;code&gt;(SETF LOGICAL-PATHNAME-TRANSLATIONS)&lt;/code&gt;. Each translation is a list where the first
element is a logical pathname or namestring (usually a wild pathname) and the
second element is a pathname or namestring to translate into.&lt;/p&gt;
&lt;p&gt;The translation process looks for the first entry that satisfies
&lt;code&gt;PATHNAME-MATCH-P&lt;/code&gt;, which is guaranteed to behave in a way consistent with
&lt;code&gt;DIRECTORY&lt;/code&gt;. When there is match, the translation processes replaces
corresponding patterns for each components.&lt;/p&gt;
&lt;p&gt;And of course if translation results in a logical pathname, it will be
recursively translated until a physical pathname is obtained.&lt;/p&gt;
&lt;p&gt;A simple example would be the use of a logical host referring to a temporary
directory. This lets a program manipulates temporary pathnames without having to
know their actual physical location, the translation process being controlled in
a single location.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setf (logical-pathname-translations &amp;quot;tmp&amp;quot;)
      (list (list &amp;quot;TMP:**;*.*.*&amp;quot;
                  (make-pathname :directory &#39;(:absolute &amp;quot;var&amp;quot; &amp;quot;tmp&amp;quot; :wild-inferiors)
                                 :name :wild :type :wild))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or if we were to use namestrings:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setf (logical-pathname-translations &amp;quot;tmp&amp;quot;)
      &#39;((&amp;quot;TMP:**;*.*.*&amp;quot; &amp;quot;/var/tmp/**/*.*&amp;quot;)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Translating pathnames or namestrings using the &lt;code&gt;TMP&lt;/code&gt; logical host yields the
expected results. For example &lt;code&gt;(translate-logical-pathname #P&amp;quot;TMP:CACHE;DATA.TXT&amp;quot;)&lt;/code&gt; yields &lt;code&gt;#P&amp;quot;/var/tmp/cache/data.txt&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;caveats&#34;&gt;Caveats&lt;/h3&gt;
&lt;p&gt;While logical pathnames are an elegant abstraction, they are plagued by multiple
issues that make them hard to use correctly and in a portable way.&lt;/p&gt;
&lt;p&gt;Logical namestring components can only contain letters, digits and hyphens (or
the &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;**&lt;/code&gt; sequences for wild namestrings). This limitation probably comes
from a need to be compatible with all existing file systems, but it can be a
showstopper if one needs to refer to files whose naming scheme is not controlled
by the program.&lt;/p&gt;
&lt;p&gt;Namestring parsing is confusing: calling &lt;code&gt;PARSE-NAMESTRING&lt;/code&gt; on an invalid
namestring (because it contains invalid characters or because the host is not a
known logical host) will not fail. Instead the string will be parsed as a
physical namestring, introducing silent bugs. The &lt;code&gt;LOGICAL-PATHNAME&lt;/code&gt; can be used
to validate logical pathnames and namestrings.&lt;/p&gt;
&lt;p&gt;The way translation converts between both pathname patterns is unclear. It is
not specified by the Common Lisp standard. Debugging patterns can quickly become
very frustrating, especially with implementations unable to produce quality
error diagnostics.&lt;/p&gt;
&lt;p&gt;Finally, the behaviour of logical pathnames with other functions is rarely
obvious, leading to frustrating debugging sessions.&lt;/p&gt;
&lt;p&gt;They nevertheless are a unique and helpful feature for very specific use cases.&lt;/p&gt;
&lt;h2 id=&#34;recipes&#34;&gt;Recipes&lt;/h2&gt;
&lt;h3 id=&#34;resolving-a-path&#34;&gt;Resolving a path&lt;/h3&gt;
&lt;p&gt;Files are accessible through multiple paths. For example, on POSIX systems,
&lt;code&gt;foo/bar/baz.txt&lt;/code&gt;, &lt;code&gt;foo/bar/../bar/baz.txt&lt;/code&gt; refer to the same file. If your
operating system and file system support symbolic links, you can refer to the
same physical file from multiple links, themselves being files.&lt;/p&gt;
&lt;p&gt;It is sometimes useful to obtain the canonical path of a file. On POSIX systems,
the &lt;code&gt;realpath&lt;/code&gt; function serves this purpose. In Common Lisp, this canonical path
is called &lt;em&gt;truename&lt;/em&gt;, and the &lt;code&gt;TRUENAME&lt;/code&gt; function returns it.&lt;/p&gt;
&lt;h3 id=&#34;transforming-paths&#34;&gt;Transforming paths&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;:DEFAULTS&lt;/code&gt; option of &lt;code&gt;MAKE-PATHNAME&lt;/code&gt; is useful to construct a pathname that
is a variation of another pathname. When a component passed to &lt;code&gt;MAKE-PATHNAME&lt;/code&gt;
is null, the value is taken from the pathname passed with &lt;code&gt;:DEFAULTS&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example to create the pathname of a file in the same directory as another
pathname:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(make-pathname :name &amp;quot;bar&amp;quot;
               :defaults (make-pathname :directory &#39;(:absolute &amp;quot;tmp&amp;quot;) :name &amp;quot;foo&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or to create a wild pathname matching the same file names but with any
extension:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(make-pathname :type :wild
               :defaults (make-pathname :name &amp;quot;foo&amp;quot; :type &amp;quot;txt&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or to obtain a pathname for the directory of a file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(make-pathname :name nil
               :defaults (make-pathname :directory &#39;(:relative &amp;quot;a&amp;quot; &amp;quot;b&amp;quot; &amp;quot;c&amp;quot;)
                                        :name &amp;quot;foo&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;joining-two-paths&#34;&gt;Joining two paths&lt;/h3&gt;
&lt;p&gt;Joining (or concatenating) two paths can be done with &lt;code&gt;MERGE-PATHNAMES&lt;/code&gt;. In
general calling &lt;code&gt;(MERGE-PATHNAMES PATH1 PATH2)&lt;/code&gt; returns a new pathname whose
components are taken either from &lt;code&gt;PATH1&lt;/code&gt; when they are not null, or from &lt;code&gt;PATH2&lt;/code&gt;
when they are. As a special case, if the directory component of &lt;code&gt;PATH1&lt;/code&gt; is
relative, the directory component of the result pathname is the concatenation of
the directory components of both paths.&lt;/p&gt;
&lt;p&gt;In other words&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(merge-pathnames (make-pathname :directory &#39;(:relative &amp;quot;x&amp;quot; &amp;quot;y&amp;quot;))
                 (make-pathname :directory &#39;(:absolute &amp;quot;a&amp;quot; &amp;quot;b&amp;quot; &amp;quot;c&amp;quot;)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yields &lt;code&gt;&amp;quot;/a/b/c/x/y/&amp;quot;&lt;/code&gt; but&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(merge-pathnames (make-pathname :directory &#39;(:absolute &amp;quot;x&amp;quot; &amp;quot;y&amp;quot;))
                 (make-pathname :directory &#39;(:absolute &amp;quot;a&amp;quot; &amp;quot;b&amp;quot; &amp;quot;c&amp;quot;)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yields &lt;code&gt;&amp;quot;/x/y/&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;finding-files&#34;&gt;Finding files&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;DIRECTORY&lt;/code&gt; function returns files matching a pathname, wild or not.&lt;/p&gt;
&lt;p&gt;If the pathname is not wild, &lt;code&gt;DIRECTORY&lt;/code&gt; returns a list of one or zero element
depending on whether a file exists at this location or not.&lt;/p&gt;
&lt;p&gt;If the pathname is wild, &lt;code&gt;DIRECTORY&lt;/code&gt; behaves similarly to POSIX globs. Due to
the way pathnames are structured, with the name and type being two different
components, a common error is to specify a wild name without a type. In this
case, &lt;code&gt;DIRECTORY&lt;/code&gt; will not return any file with an extension (since their
pathname has a non-null type). To match all files with any extension, set both
the name and the type to &lt;code&gt;:WILD&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Another interesting possibility is to only match directories. Directories are
represented by pathnames with a non-null directory component and a null name
component. Therefore to find all directories in &lt;code&gt;/tmp&lt;/code&gt; (top-level only):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(directory (make-pathname :directory &#39;(:absolute &amp;quot;tmp&amp;quot; :wild)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that &lt;code&gt;DIRECTORY&lt;/code&gt; returns &lt;em&gt;truenames&lt;/em&gt;, i.e. pathnames representing the
canonical location of the files. An unexpected consequence is that the function
will resolve symlinks. Since the Common Lisp standard explicitely allows extra
optional arguments, some implementations have a way to disable symlink
resolving, e.g. SBCL with &lt;code&gt;:RESOLVE-SYMLINKS&lt;/code&gt; or CCL with &lt;code&gt;:FOLLOW-LINKS&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;resolving-tildes-in-paths&#34;&gt;Resolving tildes in paths&lt;/h3&gt;
&lt;p&gt;It is commonly believed that tilde characters in paths is a universal feature.
It is not. Tilde prefixes are defined in POSIX in the context of the shell (cf.
POSIX 2017 2.6.1 Tilde Expansion) and are only supported in very specific
locations.&lt;/p&gt;
&lt;p&gt;To obtain the path of a file relative to the home directory of the current user,
use the &lt;code&gt;USER-HOMEDIR-PATHNAME&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(merge-pathnames (make-pathname :directory &#39;(:relative &amp;quot;.emacs.d&amp;quot;)
                                :name &amp;quot;init&amp;quot; :type &amp;quot;el&amp;quot;)
                 (user-homedir-pathname))
&lt;/code&gt;&lt;/pre&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/controlling-link-opening-in-emacs/">
      <title>Controlling link opening in Emacs</title>
      <link>https://www.n16f.net/blog/controlling-link-opening-in-emacs/</link>
      <pubDate>Sun, 11 Aug 2024 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/controlling-link-opening-in-emacs/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;Multiple Emacs modes recognize URIs so that you can follow them in a web
browser, usually with a mouse left click. In modes that do not support it, one
can still call &lt;code&gt;browse-url-at-point&lt;/code&gt; interactively with the cursor positioned on
a URI.&lt;/p&gt;
&lt;p&gt;I wanted to make link handling more convenient for some time; this is what I
ended up with.&lt;/p&gt;
&lt;h2 id=&#34;key-bindings&#34;&gt;Key bindings&lt;/h2&gt;
&lt;p&gt;There is no global Emacs concept of following links, so modes deal with them
differently. I wanted to use the same key binding everywhere; I went for &lt;code&gt;C-o&lt;/code&gt;
(&amp;ldquo;o&amp;rdquo; for &amp;ldquo;open&amp;rdquo;) since I never use &lt;code&gt;open-line&lt;/code&gt;. I also wanted the ability to use
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_mono/eww.html&#34;&gt;Eww&lt;/a&gt; —the Emacs
builtin web browser— when it is convenient. So I added a function to select the
secondary browser when the prefix is set. This way &lt;code&gt;C-o&lt;/code&gt; opens Firefox, and &lt;code&gt;C-u C-o&lt;/code&gt; opens Eww.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq browse-url-secondary-browser-function &#39;eww-browse-url)

(defun g-browse-url-at-point (arg)
  (interactive &amp;quot;P&amp;quot;)
  (let ((browse-url-browser-function
         (if arg
             browse-url-secondary-browser-function
           browse-url-browser-function)))
    (browse-url-at-point)))

(keymap-global-set &amp;quot;C-o&amp;quot; &#39;g-browse-url-at-point)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ultimately the function calls &lt;code&gt;browse-url-at-point&lt;/code&gt; which identifies the URI
under the cursor (i.e. at the current point) and calls &lt;code&gt;browse-url&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;selecting-a-web-browser&#34;&gt;Selecting a web browser&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;browse-url&lt;/code&gt; function is fully configurable; two mechanisms are used to
select a web browser for each link:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;browse-url-handlers&lt;/code&gt; and &lt;code&gt;browse-url-default-handlers&lt;/code&gt; association lists,
used to match specific URIs using predicates or regular expression;&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;browse-url-browser-function&lt;/code&gt; variable (by default
&lt;code&gt;browser-url-default-browser&lt;/code&gt;) referencing a function which looks for
available web browsers on the current machine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since I use multiple &lt;a href=&#34;https://support.mozilla.org/en-US/kb/profile-manager-create-remove-switch-firefox-profiles&#34;&gt;Firefox
profiles&lt;/a&gt;,
I needed the ability to open URIs in the right profile depending of the
context. For example links in a professional email read in Gnus should be open
in my work context.&lt;/p&gt;
&lt;p&gt;The following function returns a handler that can be used in
&lt;code&gt;browse-url-handlers&lt;/code&gt; or as value for &lt;code&gt;browse-url-browser-function&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-browse-url-firefox-function (profile)
  (lambda (uri &amp;amp;rest args)
    (let ((process-environment (browse-url-process-environment))
          (process-name (concat &amp;quot;firefox &amp;quot; uri))
          (process-args `(&amp;quot;--new-tab&amp;quot; ,uri
                          ,@(if profile (list &amp;quot;-P&amp;quot; profile)))))
      (apply #&#39;start-process process-name nil &amp;quot;firefox&amp;quot; process-args))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, &lt;code&gt;(g-browse-url-firefox-function &amp;quot;test&amp;quot;)&lt;/code&gt; returns a browse function
that will open the link in a new tab of a Firefox window associated with the
&amp;ldquo;test&amp;rdquo; profile.&lt;/p&gt;
&lt;p&gt;To change the logic deciding how to handle links in a buffer with a specific
major mode, all you have to do is to add a hook to set
&lt;code&gt;browse-url-browser-function&lt;/code&gt; in a way that only affects the current buffer.
Since this variable is not
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/elisp/Buffer_002dLocal-Variables.html&#34;&gt;buffer-local&lt;/a&gt;
by default, you have to take care to use &lt;code&gt;setq-local&lt;/code&gt; when changing it.&lt;/p&gt;
&lt;h2 id=&#34;links-in-gnus-messages&#34;&gt;Links in Gnus messages&lt;/h2&gt;
&lt;p&gt;Gnus messages are displayed using the &lt;code&gt;gnus-article-mode&lt;/code&gt; major mode.&lt;/p&gt;
&lt;p&gt;We first write a function to identify the account associated with the current
group (assuming you are using &lt;code&gt;nnimap&lt;/code&gt; for your email accounts as I do):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-current-gnus-account ()
  (let ((group gnus-newsgroup-name))
    (when (string-match &amp;quot;^nnimap\\+\\([^:]+\\):&amp;quot; group)
      (match-string 1 group))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we define the actual browse function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-gnus-browse-url (url &amp;amp;rest args)
  (let ((profile
         (pcase (g-current-gnus-account)
           (&amp;quot;my-company&amp;quot;
            &amp;quot;my-company-profile&amp;quot;)
           (&amp;quot;a-client&amp;quot;
            &amp;quot;the-client-profile&amp;quot;)
           (_
            &amp;quot;default&amp;quot;))))
    (apply (g-browse-url-firefox-function profile) url args)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the hook function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-gnus-set-browser-function ()
  (setq-local browse-url-browser-function &#39;g-gnus-browse-url))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally we update the hook:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(use-package gnus-art
  :hook
  ((gnus-article-mode-hook . g-gnus-set-browser-function)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Links in emails are now open in the right Firefox profile!&lt;/p&gt;
&lt;h2 id=&#34;links-in-the-circe-irc-client&#34;&gt;Links in the Circe IRC client&lt;/h2&gt;
&lt;p&gt;Same idea for Circe, select the right Firefox profile based on the
network and channel of the current channel buffer.&lt;/p&gt;
&lt;p&gt;We define the function to be called during the initialization of each channel
buffer:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-circe-set-browser-function ()
  (let* ((network (with-circe-server-buffer
                    circe-network))
         (channel circe-chat-target)
         (profile (cond
                   ((and (equal network &amp;quot;my-network&amp;quot;)
                         (equal channel &amp;quot;#my-channel&amp;quot;))
                    &amp;quot;the-right-profile&amp;quot;)
                   (t
                    &amp;quot;default&amp;quot;))))
    (setq-local browse-url-browser-function
                (g-browse-url-firefox-function profile))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And add it as a hook:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(use-package circe
  :hook
  ((circe-channel-mode-hook . g-circe-set-browser-function))
&lt;/code&gt;&lt;/pre&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/taking-control-of-your-go-module-paths/">
      <title>Taking control of your Go module paths</title>
      <link>https://www.n16f.net/blog/taking-control-of-your-go-module-paths/</link>
      <pubDate>Sun, 07 Jul 2024 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/taking-control-of-your-go-module-paths/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;The canonical name of a Go module is its path. For third party modules, that
means an URI. It is no secret that GitHub is currently the dominant code hosting
platform, hence the fact that most Go modules are named
&lt;code&gt;github.com/&amp;lt;account&amp;gt;/&amp;lt;repository&amp;gt;&lt;/code&gt;. While I currently use GitHub for most of my
repositories, I also want the ability to move out of it in the future.
Fortunately the Go module system allows package authors to control how the
package is accessed. One can use it to provide Go modules with their own domain
and total control on module paths. Let us see how to do that.&lt;/p&gt;
&lt;h2 id=&#34;how-packages-are-downloaded&#34;&gt;How packages are downloaded&lt;/h2&gt;
&lt;p&gt;When the Go client downloads a module (either directly with &lt;code&gt;GOPROXY=direct&lt;/code&gt; or
when a proxy does it), it fetches the module URI with an HTTP request and a
&lt;code&gt;go-get=1&lt;/code&gt; query parameter. The server includes a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; HTML element named
&lt;code&gt;go-import&lt;/code&gt; in the response, its value indicating how to actually download the
module.&lt;/p&gt;
&lt;p&gt;Let us check ourselves with my &lt;code&gt;go-uuid&lt;/code&gt; module:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl -s https://github.com/galdor/go-uuid\?go-get\=1 | grep go-import
  &amp;lt;meta name=&amp;quot;go-import&amp;quot; content=&amp;quot;github.com/galdor/go-uuid git https://github.com/galdor/go-uuid.git&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GitHub indicates that to download the &lt;code&gt;github.com/galdor/go-uuid&lt;/code&gt; module, the
client must clone the Git repository at &lt;a href=&#34;https://github.com/galdor/go-uuid.git&#34;&gt;https://github.com/galdor/go-uuid.git&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So for a module to be named &lt;code&gt;example.com/foo&lt;/code&gt;, all you need is an HTTP server
responding to requests at &lt;code&gt;https://example.com/foo?go-get=1&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;using-github-pages&#34;&gt;Using GitHub Pages&lt;/h2&gt;
&lt;p&gt;I wanted all my packages to be available at &lt;code&gt;go.n16f.net/&amp;lt;name&amp;gt;&lt;/code&gt;. It is short,
it looks good, and it opens the possibility to move the repositories out of
GitHub in the future.&lt;/p&gt;
&lt;p&gt;While I could have used my own HTTP server, I was worried about what would
happen if someone needed to download a module when the server is down. Since I
already use GitHub to host most repositories, I decided to use GitHub Pages:
after all, what I need is a way to host HTML pages with the right &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag
at the right URI.&lt;/p&gt;
&lt;h3 id=&#34;generating-repository-pages&#34;&gt;Generating repository pages&lt;/h3&gt;
&lt;p&gt;I created a &lt;a href=&#34;https://github.com/galdor/go.n16f.net&#34;&gt;GitHub repository&lt;/a&gt; for these
pages. It was tempting to use a simple shell script to generate pages but I
really did not want to use
&lt;a href=&#34;https://en.wikipedia.org/wiki/M4_(computer_language)&#34;&gt;M4&lt;/a&gt; and Ruby lets me use
&lt;a href=&#34;https://github.com/ruby/erb&#34;&gt;ERB&lt;/a&gt; templates, so Ruby it is.&lt;/p&gt;
&lt;p&gt;All my Go modules are listed in a &lt;a href=&#34;https://github.com/galdor/go.n16f.net/blob/master/modules.txt&#34;&gt;text
file&lt;/a&gt;, and a
small &lt;a href=&#34;https://github.com/galdor/go.n16f.net/blob/master/generate-pages&#34;&gt;Ruby
script&lt;/a&gt;
generates both an index (not required but why not?) and a page for each module.
The &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag of each module page indicates that &lt;code&gt;go.n16f.net/&amp;lt;name&amp;gt;&lt;/code&gt; can be
accessed by cloning the Git repository at &lt;code&gt;https://github.com/galdor/go-&amp;lt;name&amp;gt;&lt;/code&gt;.
It is that simple.&lt;/p&gt;
&lt;h3 id=&#34;configuring-the-domain&#34;&gt;Configuring the domain&lt;/h3&gt;
&lt;p&gt;Using your own domain means configuring it to point to GitHub pages.&lt;/p&gt;
&lt;p&gt;First head to your domain name registrar website and configure your domain to
point to GitHub pages. In my case, that means creating a &lt;code&gt;CNAME&lt;/code&gt; DNS record
named &lt;code&gt;go.n16f.net.&lt;/code&gt; pointing to &lt;code&gt;galdor.github.io.&lt;/code&gt;. You will notice that the
GitHub Pages address is global to your account and not specific to each
repository: GitHub takes care of routing, based on which domain is associated
with each repository.&lt;/p&gt;
&lt;p&gt;Then go to the GitHub Pages &lt;a href=&#34;https://github.com/settings/pages&#34;&gt;settings page&lt;/a&gt;
and add your domain. You will have to create a &lt;code&gt;TXT&lt;/code&gt; DNS record with a specific
name and value to prove ownership of the domain.&lt;/p&gt;
&lt;p&gt;Once done, go to the GitHub Pages settings page of the repository. Select the
&amp;ldquo;GitHub Actions&amp;rdquo; source, and add the domain to &amp;ldquo;Custom domain&amp;rdquo;. Make sure to
tick &amp;ldquo;Enforce HTTPS&amp;rdquo; while you are here.&lt;/p&gt;
&lt;h3 id=&#34;publishing-pages&#34;&gt;Publishing pages&lt;/h3&gt;
&lt;p&gt;To generate and publish pages, we use a small GitHub Actions
&lt;a href=&#34;https://github.com/galdor/go.n16f.net/blob/master/.github/workflows/generate-pages.yaml&#34;&gt;workflow&lt;/a&gt;.
When new commits are pushed to the &lt;code&gt;master&lt;/code&gt; branch, we run the script (the
&lt;code&gt;ubuntu-latest&lt;/code&gt; image already contains Ruby, so there is nothing to setup) and
use official GitHub actions to upload and deploy the pages we just generated.&lt;/p&gt;
&lt;p&gt;A quick check shows that the new URIs work as expected:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl -s https://go.n16f.net/uuid\?go-get\=1 | grep go-import
    &amp;lt;meta name=&amp;quot;go-import&amp;quot; content=&amp;quot;go.n16f.net/uuid git https://github.com/galdor/go-uuid.git&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;updating-modules&#34;&gt;Updating modules&lt;/h2&gt;
&lt;p&gt;You can now update your Go modules: update the path in the &lt;code&gt;go.mod&lt;/code&gt; file, and
all import paths in source files. Yes this is annoying, and I would love a way
to declare the path of each dependencies at project level, but
&lt;a href=&#34;https://en.wikipedia.org/wiki/Sed&#34;&gt;Sed&lt;/a&gt; makes the task trivial.&lt;/p&gt;
&lt;p&gt;Updating dependencies is a bit trickier. If your project depends on
&lt;code&gt;github.com/example/foo&lt;/code&gt; which you just renamed to &lt;code&gt;example.com/foo&lt;/code&gt;, update all
module paths in source files then run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GOPROXY=direct go get example.com/foo@latest &amp;amp;&amp;amp; go mod tidy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will force Go to fetch the module directly from its source and not from the
global proxy which may not be up-to-date yet.&lt;/p&gt;
&lt;h2 id=&#34;result&#34;&gt;Result&lt;/h2&gt;
&lt;p&gt;For a surprisingly small amount of work, I now have all my Go modules available
at a path I fully control and I can add new modules by modifying a text file and
letting the GitHub workflow handles the rest. And while the current setup is
still dependent on GitHub, I can move it somewhere else without any change to
module paths.&lt;/p&gt;
&lt;p&gt;What is your excuse for not doing the same thing?&lt;/p&gt;
</description>

      
      <category>golang</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/pagination-for-database-objects/">
      <title>Pagination for database objects</title>
      <link>https://www.n16f.net/blog/pagination-for-database-objects/</link>
      <pubDate>Sat, 08 Jun 2024 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/pagination-for-database-objects/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;So you have a server storing objects in a relational database, and an API,
nowadays probably HTTP but it does not matter. Clients can fetch objects using
the API. Obviously you do not want them loading too many objects at the same
time, that would cause all kinds of performance issues. So you need a way to let
clients request a manageable subset of all objects and iterate to finally obtain
all objects. This is pagination.&lt;/p&gt;
&lt;p&gt;I used to think it was a trivial problem. But given the number of complex and
inefficient solutions I have seen over the years, I was clearly mistaken. Let us
find out how to do it easily and efficiently.&lt;/p&gt;
&lt;h2 id=&#34;limit-and-offset&#34;&gt;Limit and offset&lt;/h2&gt;
&lt;p&gt;One of the first things you learn with SQL is how to use &lt;code&gt;LIMIT&lt;/code&gt; and &lt;code&gt;OFFSET&lt;/code&gt; to
restrict the number of rows to retrieve.&lt;/p&gt;
&lt;p&gt;Let us define a user table and load 10 users after the first 20:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;CREATE TABLE users
  (id SERIAL PRIMARY KEY,
   name VARCHAR NOT NULL);

SELECT * FROM users
  LIMIT 10 OFFSET 20;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Have your clients send a limit and offset with each query, increment the offset
to iterate. Easy, but there is a problem: the highest the offset is, the slower
the request will be. &lt;code&gt;LIMIT&lt;/code&gt; and &lt;code&gt;OFFSET&lt;/code&gt; are applied after filtering, so if you
have a million users, selecting the last 10 ones will still require processing
the 999&#39;990 before them. Not great.&lt;/p&gt;
&lt;p&gt;Worse, this method can and will provide incorrect results when retrieving pages
one after the other: adding rows to the table between each selection will make
subsequent pages either miss rows or include some which we already returned in
previous pages.&lt;/p&gt;
&lt;h2 id=&#34;sql-cursors&#34;&gt;SQL Cursors&lt;/h2&gt;
&lt;p&gt;It can be tempting to use SQL cursors. After all, they let you consume rows
iteratively without loading the whole result set in memory. But they are really
not designed for the task: you would need to keep the associated database
connection open between requests. Next idea.&lt;/p&gt;
&lt;h2 id=&#34;key-based-pagination&#34;&gt;Key-based pagination&lt;/h2&gt;
&lt;p&gt;Sometimes called &amp;ldquo;keyset&amp;rdquo; pagination, this method uses a key from the last row
of the page you just loaded to obtain the next one efficiently.&lt;/p&gt;
&lt;p&gt;Let us load the first page:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;SELECT * FROM users
  ORDER BY id
  LIMIT 10;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then for the next page, have the client provide the identifier of the last user
in the page —let us say 42— and use it to load the second page:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;SELECT * FROM users
  ORDER BY id
  WHERE id &amp;gt; 42
  LIMIT 10;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Continue the same way for subsequent pages.&lt;/p&gt;
&lt;p&gt;As long as you are filtering on an indexed expression, the database will
efficiently retrieve the rows for the page you requested. And you can use the
exact same method to order results in the other direction, just invert the
&lt;code&gt;WHERE&lt;/code&gt; expression.&lt;/p&gt;
&lt;p&gt;You will also avoid the inconsistencies of the &lt;code&gt;LIMIT&lt;/code&gt;/&lt;code&gt;OFFSET&lt;/code&gt; method: if the
table is modified between two page retrieval operations, you may still miss rows
(nothing you can do about it unless you are willing to retrieve the entire table
in one operation), but you will not see rows from previous pages reappear in
subsequent pages. Your users will thank you (or more accurately they will open
less bug reports; even better).&lt;/p&gt;
&lt;h3 id=&#34;sorting&#34;&gt;Sorting&lt;/h3&gt;
&lt;p&gt;So you started using key-based pagination and everything looks fine, but now you
need to sort results based on something else than the primary key. Your first
idea could be to create an index on the column you want to use to sort, but it
will not help: if multiple users have the same name, how will you select your
pages?&lt;/p&gt;
&lt;p&gt;We could use an index on two columns, &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt; to obtain the strict total
order we need then filter on these two columns:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;CREATE INDEX users_name_id_idx
  ON users (name, id);

SELECT * FROM users
  WHERE (name, id) &amp;gt; (&#39;bob&#39;, 42)
  ORDER BY name, id
  LIMIT 10;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this is not standard SQL and would only work with databases supporting
row-value comparisons.&lt;/p&gt;
&lt;p&gt;Fortunately SQL lets you create indices on expressions and not just columns. So
we create our own single-value keys by concatenating values. Of course we need a
separator to avoid collisions: without it &lt;code&gt;(&#39;Bob&#39;, 42)&lt;/code&gt; and &lt;code&gt;(&#39;Bob4&#39;, 2)&lt;/code&gt; would
both yield the same &lt;code&gt;&#39;Bob42&#39;&lt;/code&gt; key). The ASCII character set includes several
separator characters which are perfect for this use case since they are not
supposed to end up in your data (if they do, use another character); let us use
the unit separator &lt;code&gt;0x1f&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;CREATE INDEX users_name_pagination_idx
  ON users ((name || E&#39;\x1f&#39; || id));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Load the first page:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;SELECT * FROM users
  ORDER BY name || E&#39;\x1f&#39; || id
  LIMIT 10;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And assuming the last user of the first page had the name &lt;code&gt;Bob&lt;/code&gt; and the
identifier &lt;code&gt;42&lt;/code&gt;, Load the second page.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;SELECT * FROM users
  WHERE name || E&#39;\x1f&#39; || id &amp;gt; E&#39;Bob\x1f42&#39;
  ORDER BY name || E&#39;\x1f&#39; || id
  LIMIT 10;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Annoying to type but efficient and easy to generate. Of course you will want to
make it easy for your clients: when returning a page, compute the key for the
previous and next page and return them along the objects. The client can then
trivially fetch the previous or next page.&lt;/p&gt;
&lt;p&gt;Need to support multiple sort criteria? Just create an index for each of them.&lt;/p&gt;
&lt;p&gt;That wasn&amp;rsquo;t so hard right?&lt;/p&gt;
</description>

      
      <category>programming</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/interactive-common-lisp-development/">
      <title>Interactive Common Lisp development</title>
      <link>https://www.n16f.net/blog/interactive-common-lisp-development/</link>
      <pubDate>Sun, 19 Nov 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/interactive-common-lisp-development/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;Common Lisp programming is often presented as &amp;ldquo;interactive&amp;rdquo;. In most
languages, modifications to your program are applied by recompiling it and
restarting it. In contrast, Common Lisp lets you incrementally modify your
program while it is running.&lt;/p&gt;
&lt;p&gt;While this approach is convenient, especially for exploratory programming, it
also means that the state of your program during execution does not always
reflect the source code. You do not just define new constructs: you look them
up, inspect them, modify them or delete them. I had to learn a lot of
subtleties the hard way. This article is a compendium of information related
to the interactive nature of Common Lisp.&lt;/p&gt;
&lt;h2 id=&#34;variables&#34;&gt;Variables&lt;/h2&gt;
&lt;p&gt;In Common Lisp variables are identified by symbols. Evaluating &lt;code&gt;(SETQ A 42)&lt;/code&gt;
creates or updates a variable with the integer &lt;code&gt;42&lt;/code&gt; as value, and associates
it to the &lt;code&gt;A&lt;/code&gt; symbol. After the call to &lt;code&gt;SETQ&lt;/code&gt;, &lt;code&gt;(BOUNDP &#39;A)&lt;/code&gt; will return &lt;code&gt;T&lt;/code&gt;
and &lt;code&gt;(SYMBOL-VALUE &#39;A)&lt;/code&gt; will return &lt;code&gt;42&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You do not delete a variable: instead, you remove the association between the
symbol and the variable. You do so with &lt;code&gt;MAKUNBOUND&lt;/code&gt;. Following the previous
example, &lt;code&gt;(MAKUNBOUND &#39;A)&lt;/code&gt; will remove the association between the &lt;code&gt;A&lt;/code&gt; symbol
and the variable. And &lt;code&gt;(BOUNDP &#39;A)&lt;/code&gt; returns &lt;code&gt;NIL&lt;/code&gt; as expected. As for
&lt;code&gt;(SYMBOL-VALUE &#39;A)&lt;/code&gt;, it now signals an &lt;code&gt;UNBOUND-VARIABLE&lt;/code&gt; error as mandated by
the standard.&lt;/p&gt;
&lt;p&gt;What about &lt;code&gt;DEFVAR&lt;/code&gt; and &lt;code&gt;DEFPARAMETER&lt;/code&gt;? They are also used to declare
variables (globally defined ones), associating them with symbols. Both define
&amp;ldquo;special&amp;rdquo; variables (i.e. variables for which all bindings are dynamic; see
CLtL2 9.2). The difference is that the initial value passed to &lt;code&gt;DEFVAR&lt;/code&gt; is not
evaluated if it already has a value. &lt;code&gt;MAKUNBOUND&lt;/code&gt; will work on variables
declared with &lt;code&gt;DEFVAR&lt;/code&gt; or &lt;code&gt;DEFPARAMETER&lt;/code&gt; as expected.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;DEFCONSTANT&lt;/code&gt; is a bit more complicated. CLtL2&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; 5.3.2 states that &amp;ldquo;once a
name has been declared by defconstant to be constant, any further assignment
to or binding of that special variable is an error&amp;rdquo;, but does not clearly
define whether &lt;code&gt;MAKUNBOUND&lt;/code&gt; should or should not be able to be used on
constants. However, CLtL2 5.3.2 also states that &amp;ldquo;defconstant […] does assert
that the value of the variable name is fixed and does license the compiler to
build assumptions about the value into programs being compiled&amp;rdquo;. If the
compiler is allowed to rely on the value associated with the variable name, it
would make sense not to allow the deletion of the binding. Thus it is
recommended to only use constants for values that are guaranteed to never
change, e.g. mathematical constants. Most of the time you want &lt;code&gt;DEFPARAMETER&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that &lt;code&gt;MAKUNBOUND&lt;/code&gt; does not apply to lexical variables.&lt;/p&gt;
&lt;h2 id=&#34;functions&#34;&gt;Functions&lt;/h2&gt;
&lt;p&gt;Common Lisp is a Lisp-2, meaning that variables and functions are part of two
separate namespaces. Despite this clear separation, functions behave similarly
to variables.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;DEFUN&lt;/code&gt; will either create or update the global function associated with
a symbol. &lt;code&gt;SYMBOL-FUNCTION&lt;/code&gt; returns the globally defined function associated
with a symbol, and &lt;code&gt;FMAKUNBOUND&lt;/code&gt; deletes this association.&lt;/p&gt;
&lt;p&gt;Let us point out a common mistake when referencing functions: &lt;code&gt;(QUOTE F)&lt;/code&gt;
(abbreviated as &lt;code&gt;&#39;F&lt;/code&gt;) yields a symbol while &lt;code&gt;(FUNCTION F)&lt;/code&gt; (abbreviated as
&lt;code&gt;#&#39;F&lt;/code&gt;) yields a function. The function argument of &lt;code&gt;FUNCALL&lt;/code&gt; and &lt;code&gt;APPLY&lt;/code&gt; can
be either a symbol or a function (see CLtL2 7.3) It has two consequences:&lt;/p&gt;
&lt;p&gt;First, one can write a function referencing &lt;code&gt;F&lt;/code&gt; as &lt;code&gt;(QUOTE F)&lt;/code&gt; with the
expectation that &lt;code&gt;F&lt;/code&gt; will later be bound to a function. The following function
definition is perfectly valid even though &lt;code&gt;F&lt;/code&gt; has not been defined yet:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun foo (a b)
  (funcall &#39;f a b))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Second, redefining the &lt;code&gt;F&lt;/code&gt; function will update its association (or binding)
to the &lt;code&gt;F&lt;/code&gt; symbol, but the previous function will still be available if it has
been referenced somewhere before the update. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setf (symbol-function &#39;foo) #&#39;1+)
(let ((old-foo #&#39;foo))
  (setf (symbol-function &#39;foo) #&#39;1-)
  (funcall old-foo 42))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What about macros? Since macros are a specific kind of functions (CLtL2 5.1.4
&amp;ldquo;a macro is essentially a function from forms to forms&amp;rdquo;), it is not surprising
that they share the same namespace and can be manipulated in the same way as
functions with &lt;code&gt;FBOUNDP&lt;/code&gt;, &lt;code&gt;SYMBOL-FUNCTION&lt;/code&gt; and &lt;code&gt;FMAKUNBOUND&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;symbols-and-packages&#34;&gt;Symbols and packages&lt;/h2&gt;
&lt;p&gt;While functions and variables are familiar concepts to developers, Common Lisp
symbols and packages are a bit more peculiar.&lt;/p&gt;
&lt;p&gt;A symbol is &lt;em&gt;interned&lt;/em&gt; when it is part of a package. The most explicit way to
create an interned symbol is to use &lt;code&gt;INTERN&lt;/code&gt;, e.g. &lt;code&gt;(INTERN &amp;quot;FOO&amp;quot;)&lt;/code&gt;. &lt;code&gt;INTERN&lt;/code&gt;
interns the symbol in the current package by default, but one can pass a
package as second argument. After that, &lt;code&gt;(FIND-SYMBOL &amp;quot;FOO&amp;quot;)&lt;/code&gt; will return our
interned symbol as expected.&lt;/p&gt;
&lt;p&gt;More surprising, the reader automatically interns symbols. You can test it by
evaluating &lt;code&gt;(READ-FROM-STRING &amp;quot;BAR&amp;quot;)&lt;/code&gt;. After evaluation, &lt;code&gt;BAR&lt;/code&gt; is a symbol
interned in the current package. This also means that it is very easy to pollute
a package with symbols in ways you did not necessarily expect. To clean up,
simply use &lt;code&gt;UNINTERN&lt;/code&gt;. Remember to refer to the right symbol: to remove the
symbol &lt;code&gt;BAR&lt;/code&gt; from the package &lt;code&gt;FOO&lt;/code&gt;, use &lt;code&gt;(UNINTERN &#39;FOO::BAR &amp;quot;BAR&amp;quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A symbol is either internal or external. &lt;code&gt;EXPORT&lt;/code&gt; will make a symbol external
to its package while &lt;code&gt;UNEXPORT&lt;/code&gt; will make it internal. As for &lt;code&gt;UNINTERN&lt;/code&gt;,
confusion usually arises around which symbol is affected. &lt;code&gt;(UNEXPORT &#39;FOO:BAR &amp;quot;FOO&amp;quot;)&lt;/code&gt; correctly refers to the external symbol in the &lt;code&gt;FOO&lt;/code&gt; package and makes
it internal again. &lt;code&gt;(UNEXPORT &#39;BAR &amp;quot;FOO&amp;quot;)&lt;/code&gt; will signal an error since the
&lt;code&gt;BAR&lt;/code&gt; symbol is not part of the &lt;code&gt;FOO&lt;/code&gt; package (unless of course the current
package happens to be &lt;code&gt;FOO&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Packages themselves can be created with &lt;code&gt;MAKE-PACKAGE&lt;/code&gt; and destroyed with
&lt;code&gt;DELETE-PACKAGE&lt;/code&gt;. Developers are usually more familiar with &lt;code&gt;DEFPACKAGE&lt;/code&gt;, a
macro allowing the creation of a package and its configuration (package use
list, imported and exported symbols, etc.) in a declarative way. A surprising
and frustrating behavior is that evaluating a &lt;code&gt;DEFPACKAGE&lt;/code&gt; form for a package
that already exists will result in undefined behavior if the new declaration
&amp;ldquo;is not consistent&amp;rdquo; (CLtL2 11.7) with the current state of the package. As an
example, adding symbols to the export list is perfectly fine. Removing one
will result in undefined behavior (usually an error) due to the inconsistency
of the export list. Fortunately, Common Lisp offers all the necessary
functions to manipulate packages and their symbols: use them!&lt;/p&gt;
&lt;h2 id=&#34;classes&#34;&gt;Classes&lt;/h2&gt;
&lt;p&gt;The Common Lisp standard includes CLOS, the Common Lisp Object System.
Unsurprisingly it provides multiple ways to interact with classes and objects
dynamically.&lt;/p&gt;
&lt;p&gt;As variables or functions, classes are identified by symbols and &lt;code&gt;FIND-CLASS&lt;/code&gt;
returns the class associated with a symbol. Class names are part of a separate
namespace shared with structures and types.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;DEFCLASS&lt;/code&gt; macro is the only way to define or redefine a class. Redefining
a class means that instances created afterward with &lt;code&gt;MAKE-INSTANCE&lt;/code&gt; will use
the new definition. Existing instances are updated: newly added slots are
added (either unbound or using the value associated with &lt;code&gt;:INITFORM&lt;/code&gt;) and
slots that are not defined anymore are deleted.
&lt;code&gt;UPDATE-INSTANCE-FOR-REDEFINED-CLASS&lt;/code&gt; is particularly interesting: developers
can define methods for this generic function in order to control how instances
are updated when their class is redefined.&lt;/p&gt;
&lt;p&gt;Defining classes may imply implicitly defining methods: the &lt;code&gt;:ACCESSOR&lt;/code&gt;,
&lt;code&gt;:READER&lt;/code&gt; and &lt;code&gt;:WRITER&lt;/code&gt; slot keyword arguments will lead to the creation of
generic functions. When a class is redefined, methods associated with slots
that have been removed will live on.&lt;/p&gt;
&lt;p&gt;A limitation of CLOS is that classes cannot be deleted. &lt;code&gt;FIND-CLASS&lt;/code&gt; can be
used as a &lt;em&gt;place&lt;/em&gt;, and &lt;code&gt;(SETF (FIND-CLASS &#39;FOO) NIL)&lt;/code&gt; will remove the
association between the &lt;code&gt;FOO&lt;/code&gt; symbol and the class, but the class itself and
its instances will not disappear. While this limitation may seem strange, ask
yourself how an implementation should handle instances of a class that has
been deleted.&lt;/p&gt;
&lt;p&gt;The class of an instance can be changed with &lt;code&gt;CHANGE-CLASS&lt;/code&gt;: slots that exist
in the new class will be conserved while those that do not are deleted. New
slots are either unbound or set to the value associated with &lt;code&gt;:INITFORM&lt;/code&gt; in
the new class. In a way similar to &lt;code&gt;UPDATE-INSTANCE-FOR-REDEFINED-CLASS&lt;/code&gt;,
&lt;code&gt;UPDATE-INSTANCE-FOR-DIFFERENT-CLASS&lt;/code&gt; lets developers control precisely the
process.&lt;/p&gt;
&lt;h3 id=&#34;generics-and-methods&#34;&gt;Generics and methods&lt;/h3&gt;
&lt;p&gt;Generics are functions which can be specialized based on the class (and not
type as one could expect) of their arguments and which can have a method
combination type.&lt;/p&gt;
&lt;p&gt;Generics can be created explicitly with &lt;code&gt;DEFGENERIC&lt;/code&gt; or implicitly when
&lt;code&gt;DEFMETHOD&lt;/code&gt; is called and the list of parameter specializers and method
combination does not match any existing generic function. Since generics are
functions, &lt;code&gt;FBOUNDP&lt;/code&gt;, &lt;code&gt;SYMBOL-FUNCTION&lt;/code&gt; and &lt;code&gt;FMAKUNBOUND&lt;/code&gt; will work as
expected.&lt;/p&gt;
&lt;p&gt;Methods themselves are either defined as part of the &lt;code&gt;DEFGENERIC&lt;/code&gt; call or
separately with &lt;code&gt;DEFMETHOD&lt;/code&gt;. Discovering the different methods associated with
a generic function is a bit more complicated. There is no standard way to list
the methods associated with a generic, but it is at least possible to look up
a method with &lt;code&gt;FIND-METHOD&lt;/code&gt;. Do remember to pass a function (and not a symbol)
as the generic, and to pass classes (and not symbols naming classes) in the
list of specializers.&lt;/p&gt;
&lt;p&gt;Redefinition is not as obvious as for non-generic functions. When redefining a
generic with &lt;code&gt;DEFGENERIC&lt;/code&gt; all methods defined as part of the previous
&lt;code&gt;DEFGENERIC&lt;/code&gt; form are removed and methods defined in the redefinition are
added. However, methods defined separately with &lt;code&gt;DEFMETHOD&lt;/code&gt; are not affected.&lt;/p&gt;
&lt;p&gt;For example, in the following code, the second call to &lt;code&gt;DEFGENERIC&lt;/code&gt; will
replace the two methods specialized on &lt;code&gt;INTEGER&lt;/code&gt; and &lt;code&gt;FLOAT&lt;/code&gt; respectively by a
single one specialized on a &lt;code&gt;STREAM&lt;/code&gt;, but the method specialized on &lt;code&gt;STRING&lt;/code&gt;
will remain unaffected.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defgeneric foo (a)
  (:method ((a integer))
    (format nil &amp;quot;~A is an integer&amp;quot; a))
  (:method ((a float))
    (format nil &amp;quot;~A is a float&amp;quot; a)))

(defmethod foo ((a string))
  (format nil &amp;quot;~S is a string&amp;quot; a))

(defgeneric foo (a)
  (:method ((a stream))
    (format nil &amp;quot;~A is a stream&amp;quot; a)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that trying to redefine a generic with a different parameter lambda list
will cause the removal of all previously defined methods since none of them
can match the new parameters.&lt;/p&gt;
&lt;p&gt;Removing a method will require you to find it first using &lt;code&gt;FIND-METHOD&lt;/code&gt; and
then use &lt;code&gt;REMOVE-METHOD&lt;/code&gt;. With the previous example, removing the method
specialized on a &lt;code&gt;STRING&lt;/code&gt; argument is done with:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(remove-method #&#39;foo (find-method #&#39;foo nil (list (find-class &#39;string)) nil))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Working with methods is not always easy, and two errors are very common.&lt;/p&gt;
&lt;p&gt;First, remember that changing the combinator in a &lt;code&gt;DEFMETHOD&lt;/code&gt; will define a
new method. If you realize that your &lt;code&gt;:AFTER&lt;/code&gt; method should use &lt;code&gt;:AROUND&lt;/code&gt; and
reevaluate the &lt;code&gt;DEFMETHOD&lt;/code&gt; form, remember to delete the method with the
&lt;code&gt;:AFTER&lt;/code&gt; combinator or you will end up with two methods being called.&lt;/p&gt;
&lt;p&gt;Second, when defining a method for a generic from another package, remember to
correctly refer to the generic. If you want to define a method on the &lt;code&gt;BAR&lt;/code&gt;
generic from package &lt;code&gt;FOO&lt;/code&gt;, use &lt;code&gt;(DEFMETHOD FOO:BAR (…) …)&lt;/code&gt; and not
&lt;code&gt;(DEFMETHOD BAR (…) …)&lt;/code&gt;. In the latter case, you will define a new &lt;code&gt;BAR&lt;/code&gt;
generic in the current package.&lt;/p&gt;
&lt;h3 id=&#34;meta-object-protocol&#34;&gt;Meta Object Protocol&lt;/h3&gt;
&lt;p&gt;While CLOS is already quite powerful, various interactions are impossible. One
cannot create classes or methods programmatically, introspect classes or
instances for example to list their slots or obtain all their superclasses, or
list all the methods associated with a generic function.&lt;/p&gt;
&lt;p&gt;In addition of an example of a CLOS implementation, The Art of the Metaobject
Protocol&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; defines multiple extensions to CLOS including metaclasses,
metaobjects, dynamic class and generic creation, class introspection and much
more.&lt;/p&gt;
&lt;p&gt;Most Common Lisp implementations implement at least part of these extensions,
usually abbreviated as &amp;ldquo;MOP&amp;rdquo;, for &amp;ldquo;MetaObject Protocol&amp;rdquo;. The well-known
&lt;a href=&#34;https://github.com/pcostanza/closer-mop&#34;&gt;closer-mop&lt;/a&gt; system can be used as a
compatibility layer for multiple implementations.&lt;/p&gt;
&lt;h3 id=&#34;structures&#34;&gt;Structures&lt;/h3&gt;
&lt;p&gt;Structures are record constructs defined with &lt;code&gt;DEFSTRUCT&lt;/code&gt;. At a glance they
may seem very similar to classes, but they have a fundamental limitation:
the results of redefining a structure are undefined (CLtL2 19.2).&lt;/p&gt;
&lt;p&gt;While this property allows implementations to handle structures in a more
efficient way than classes, it makes structures unsuitable for incremental
development. As such, they should only be used as a last resort, when a
regular class has been proved to be a performance bottleneck.&lt;/p&gt;
&lt;h3 id=&#34;conditions&#34;&gt;Conditions&lt;/h3&gt;
&lt;p&gt;While conditions look very similar to classes the Common Lisp standard does
not define them as classes. This is one of the few differences between the
standard and CLtL2 which clearly states in 29.3.4 that &amp;ldquo;Common Lisp condition
types are in fact CLOS classes, and condition objects are ordinary CLOS
objects&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;This is why one uses &lt;code&gt;DEFINE-CONDITION&lt;/code&gt; instead of &lt;code&gt;DEFCLASS&lt;/code&gt; and
&lt;code&gt;MAKE-CONDITION&lt;/code&gt; instead of &lt;code&gt;MAKE-INSTANCE&lt;/code&gt;. This also means that one should
not use slot-related functions (including the very useful &lt;code&gt;WITH-SLOTS&lt;/code&gt; macro)
with conditions.&lt;/p&gt;
&lt;p&gt;In practice, most modern implementations follow CLtL2 and the
&lt;a href=&#34;https://www.lispworks.com/documentation/HyperSpec/Issues/iss049_w.htm&#34;&gt;&lt;code&gt;CLOS-CONDITIONS:INTEGRATE&lt;/code&gt; X3J13 Cleanup
Issue&lt;/a&gt;
and implement conditions as CLOS classes, meaning that conditions can be
manipulated and redefined as any other classes. And the same way as any other
classes, they cannot be deleted.&lt;/p&gt;
&lt;h2 id=&#34;types&#34;&gt;Types&lt;/h2&gt;
&lt;p&gt;Types are identified by symbols and are part of the same namespace as classes
(which should not be surprising since defining a class automatically defines a
type with the same name).&lt;/p&gt;
&lt;p&gt;Types are defined with &lt;code&gt;DEFTYPE&lt;/code&gt;, but documentation is surprisingly silent on
the effects of type redefinition. This can lead to interesting situations. On
some implementations (e.g. SBCL and CCL), if a class slot is defined as having
the type &lt;code&gt;FOO&lt;/code&gt;, redefining &lt;code&gt;FOO&lt;/code&gt; will not be taken into account and the type
checking operation (which is not mandated by the standard) will use the
previous definition of the type. Infortunatly Common Lisp does not mandate
any specific behavior on slot type mismatches (CLtL2 28.1.3.2).&lt;/p&gt;
&lt;p&gt;Thus developers should not expect any useful effect from redefining types.
Restarting the implementation after substantial type changes is probably best.&lt;/p&gt;
&lt;p&gt;In the same vein interactions with types are very limited. You cannot find a
type by its symbol or even check whether a type exists or not. Calling
&lt;code&gt;TYPE-OF&lt;/code&gt; on a value will return a type this value satisfies, but the nature
of the type is implementation-dependent (CLtL2 4.9): it could be any
supertype. In other words, &lt;code&gt;TYPE-OF&lt;/code&gt; could absolutly return &lt;code&gt;T&lt;/code&gt; for all values
but &lt;code&gt;NIL&lt;/code&gt;. At least &lt;code&gt;SUBTYPE-P&lt;/code&gt; lets you check whether a type is a subtype of
another type.&lt;/p&gt;
&lt;h2 id=&#34;going-further&#34;&gt;Going further&lt;/h2&gt;
&lt;p&gt;Common Lisp is a complex language with a lot of subtleties, way more than what
can be covered in a blog post. The curious reader will probably skip the
standard (not because you have to buy it, but because it is a &lt;a href=&#34;https://www.xach.com/naggum/articles/3210940486298743@naggum.net.html&#34;&gt;low quality
scan of a printed
document&lt;/a&gt;
and jump directly to CLtL2 or the &lt;a href=&#34;https://www.lispworks.com/documentation/lw50/CLHS/Front/index.htm&#34;&gt;Common Lisp
HyperSpec&lt;/a&gt;.
The Art of the Metaobject Protocol is of course the normative reference for
the CLOS extensions usually referred to as &amp;ldquo;MOP&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Guy L. Steele Jr. &lt;em&gt;Common Lisp the Language, 2nd edition.&lt;/em&gt; 1990.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Gregor Kiczales, Jim des Rivieres and Daniel G. Bobrow. &lt;em&gt;The Art of the
Metaobject Protocol.&lt;/em&gt; 1991.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/building-erlang-applications-the-hard-way/">
      <title>Building Erlang applications the hard way</title>
      <link>https://www.n16f.net/blog/building-erlang-applications-the-hard-way/</link>
      <pubDate>Sat, 17 Jun 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/building-erlang-applications-the-hard-way/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;&lt;em&gt;Edit (2023-06-19)&lt;/em&gt;&lt;br&gt;
Updated to mention the &lt;code&gt;+Bd&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;I was recently in a conversation involving &lt;a href=&#34;https://www.erlang.org/&#34;&gt;Erlang&lt;/a&gt;,
and it made me feel like revisiting the subject. Last time I used Erlang for a
commercial application, I remember a lot of frustration with the tooling, due
in part to the small size of the ecosystem. Today I decided to read the
documentation and see how to build an Erlang program from scratch. Forget
about &lt;a href=&#34;https://github.com/erlang/rebar3&#34;&gt;Rebar3&lt;/a&gt; and
&lt;a href=&#34;https://erlang.mk/&#34;&gt;Erlang.mk&lt;/a&gt;, we are going to do this the hard way.&lt;/p&gt;
&lt;h2 id=&#34;a-minimal-erlang-program&#34;&gt;A minimal Erlang program&lt;/h2&gt;
&lt;p&gt;Let us start with a small program. We could of course just write a traditional
Hello World printing a message and exiting, but we are using Erlang and Erlang
is all about servers. So our program is a server printing a message to the
standard output every second. We will build it according to
&lt;a href=&#34;https://www.erlang.org/doc/design_principles/des_princ.html&#34;&gt;OTP&lt;/a&gt; principles.&lt;/p&gt;
&lt;h3 id=&#34;writing-the-modules&#34;&gt;Writing the modules&lt;/h3&gt;
&lt;p&gt;We will need three modules.&lt;/p&gt;
&lt;p&gt;First the application, whose only role is to start the supervisor:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;-module(hello_app).

-behaviour(application).

-export([start/2, stop/1]).

start(_StartType, _Args) -&amp;gt;
  hello_sup:start_link().

stop(_State) -&amp;gt;
  ok.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then the supervisor, with a single child:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;-module(hello_sup).

-behaviour(supervisor).

-export([start_link/0]).
-export([init/1]).

start_link() -&amp;gt;
  supervisor:start_link(?MODULE, []).

init(_Args) -&amp;gt;
  Children = [#{id =&amp;gt; hello_server,
                start =&amp;gt; {hello_server, start_link, []}}],
  {ok, {#{}, Children}}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally the server, printing a message every second:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;-module(hello_server).

-behaviour(gen_server).

-export([start_link/0]).
-export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2]).

start_link() -&amp;gt;
  gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

init([]) -&amp;gt;
  schedule_hello(),
  {ok, undefined}.

terminate(_Reason, _State) -&amp;gt;
  ok.

handle_call(_Msg, _From, State) -&amp;gt;
  {reply, unhandled, State}.

handle_cast(_Msg, State) -&amp;gt;
  {noreply, State}.

handle_info({hello, Message}, State) -&amp;gt;
  io:format(&amp;quot;~ts~n&amp;quot;, [Message]),
  schedule_hello(),
  {noreply, State}.

schedule_hello() -&amp;gt;
  erlang:send_after(1000, self(), {hello, &amp;lt;&amp;lt;&amp;quot;Hello world!&amp;quot;&amp;gt;&amp;gt;}).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We store module files in a &lt;code&gt;src&lt;/code&gt; directory.&lt;/p&gt;
&lt;h3 id=&#34;writing-the-application-definition&#34;&gt;Writing the application definition&lt;/h3&gt;
&lt;p&gt;In OTP, an application is a component made of a set of modules working
together. Applications are defined with an application file; they contain an
Erlang expression describing the application and end with the &lt;code&gt;.app&lt;/code&gt;
extension. OTP, more precisely the application controller, will use it to know
how to start, stop and in general handle the application.&lt;/p&gt;
&lt;p&gt;Since the application file is read at runtime, we will store it in a second
directory named &lt;code&gt;ebin&lt;/code&gt;, which will also be used to store BEAM code files.&lt;/p&gt;
&lt;p&gt;Add the following content to &lt;code&gt;ebin/hello.app&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;{application, hello,
 [{description, &amp;quot;A hello world application.&amp;quot;},
  {vsn, &amp;quot;1.0.0&amp;quot;},
  {modules,
   [hello_app,
    hello_sup,
    hello_server]},
  {registered,
   [hello_sup,
    hello_server]},
  {applications,
   [kernel,
    stdlib]},
  {mod, {hello_app, []}},
  {env, []}]}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again nothing complicated. Feel free to refer to the
&lt;a href=&#34;https://www.erlang.org/doc/man/app.html&#34;&gt;documentation&lt;/a&gt; for more information.&lt;/p&gt;
&lt;h2 id=&#34;compiling-and-running-the-application&#34;&gt;Compiling and running the application&lt;/h2&gt;
&lt;p&gt;At the lowest level, we need to be able to compile modules, transforming
Erlang code into BEAM bytecode. We can do that just by calling &lt;code&gt;erlc&lt;/code&gt;. Of
course we probably do not want to call it manually for each module after each
modification, so let us write a simple Makefile:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-make&#34;&gt;ERLC_OPTIONS ?= -Wall -Werror

ERL_SRC = $(wildcard src/*.erl)
ERL_OBJ = $(patsubst src/%.erl,ebin/%.beam,$(ERL_SRC))

all: build

build: $(ERL_OBJ)

ebin/%.beam: src/%.erl
	erlc $(ERLC_OPTIONS) -o $(dir $@) $&amp;lt;

clean:
	$(RM) $(wildcard ebin/*.beam)

.PHONY: all build clean
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Careful about the &lt;code&gt;-o&lt;/code&gt; option: while most compilers use it to
provide the name of the destination file, &lt;code&gt;erlc&lt;/code&gt; expects a directory but will
not signal an error if it is a file, instead ignoring the option altogether.&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;make&lt;/code&gt; to compile your modules. We can now run our application. Start
&lt;code&gt;erl&lt;/code&gt;, using the &lt;code&gt;-pa ebin&lt;/code&gt; option to add the &lt;code&gt;ebin&lt;/code&gt; directory to the list of
paths Erlang looks for code files, and start the &lt;code&gt;hello&lt;/code&gt; application in the
shell:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;application:start(hello).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Barring any unexpected error, you should see the &lt;code&gt;Hello world!&lt;/code&gt; message
printed every second.&lt;/p&gt;
&lt;p&gt;Of course you can also run it in a non-interactive way:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;erl -noshell -pa ebin -eval &amp;quot;application:start(hello)&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;del&gt;Note that even with &lt;code&gt;-noshell&lt;/code&gt;, there does not seem to be any way to tell
the Erlang runtime to exit on &lt;code&gt;SIGINT&lt;/code&gt; instead of opening a interactive &amp;ldquo;break
handler&amp;rdquo; requiring additional input. Disappointing.&lt;/del&gt; You will notice that
using &lt;code&gt;C-c&lt;/code&gt; in a terminal, i.e. sending &lt;code&gt;SIGINT&lt;/code&gt; to the Erlang runtime, starts
the interactive break handler instead of stopping the program. You can use the
&lt;code&gt;-Bd&lt;/code&gt; option to exit on &lt;code&gt;SIGINT&lt;/code&gt; like other programs. Thanks to Asabil for
telling me about the &lt;code&gt;-B&lt;/code&gt; option on Reddit!&lt;/p&gt;
&lt;p&gt;At this point it is tempting to call it a day. After all we can define an
application, build its modules and run it. But this approach is limited: we
still need to install Erlang on the target server, ideally with the same
version as the one used for development and tests. We could also be tempted to
use code hot-swapping to upgrade the application without stopping it.&lt;/p&gt;
&lt;p&gt;Erlang supports releases, a way of packaging multiple applications and the
Erlang runtime itself into a self-contained archive. So let us build a
release!&lt;/p&gt;
&lt;h2 id=&#34;building-a-release&#34;&gt;Building a release&lt;/h2&gt;
&lt;h3 id=&#34;creating-the-release-resource-file&#34;&gt;Creating the release resource file&lt;/h3&gt;
&lt;p&gt;A release starts with a release resource file, an Erlang file describing the
release and the application it will contain.&lt;/p&gt;
&lt;p&gt;Our release is simple:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;{release, {&amp;quot;hello&amp;quot;, &amp;quot;1.0.0&amp;quot;},
 {erts, &amp;quot;13.2&amp;quot;},
 [{kernel, &amp;quot;8.5.4&amp;quot;},
  {stdlib, &amp;quot;4.3&amp;quot;},
  {hello, &amp;quot;1.0.0&amp;quot;}]}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We define a released named &lt;code&gt;hello&lt;/code&gt; with version &lt;code&gt;1.0.0&lt;/code&gt;, based on ERTS 13.2,
and we list three applications: &lt;code&gt;kernel&lt;/code&gt;, &lt;code&gt;stdlib&lt;/code&gt;, and &lt;code&gt;hello&lt;/code&gt;. Remember that
&lt;code&gt;kernel&lt;/code&gt; and &lt;code&gt;stdlib&lt;/code&gt; must always be included.&lt;/p&gt;
&lt;p&gt;You will notice that we need to provide the version for each component. This
is really frustrating because they depend on the version of Erlang installed
on your system, and you would expect &lt;code&gt;systool&lt;/code&gt; to handle it automatically, but
this is how it is. Clearly the release resource file is something to be
generated automatically. In the mean time, you will need to adapt the version
numbers of the example (those are for Erlang 25.3.2).&lt;/p&gt;
&lt;h3 id=&#34;generating-the-boot-script&#34;&gt;Generating the boot script&lt;/h3&gt;
&lt;p&gt;While the release resource file defines what is in the release, the boot
script explains how to start it. Again, it contains Erlang expressions, and it
can quickly get complicated (see the
&lt;a href=&#34;https://www.erlang.org/doc/man/script.html&#34;&gt;documentation&lt;/a&gt; for more
information). Furthermore, the Erlang release handler will not use the boot
script directly, but instead a compiled version with the &lt;code&gt;.boot&lt;/code&gt; file
extension. Fortunately we do not have to write the script ourselves:
&lt;code&gt;systools&lt;/code&gt; will handle both generation and compilation.&lt;/p&gt;
&lt;p&gt;To use &lt;code&gt;systools&lt;/code&gt;, let us write a small Erlang program named &lt;code&gt;generate-boot&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;#!/usr/bin/env escript

main([ReleaseName]) -&amp;gt;
  Options = [no_warn_sasl, {path, [&amp;quot;ebin&amp;quot;]}, silent],
  case systools:make_script(ReleaseName, Options) of
    {ok, _Module, []} -&amp;gt;
      ok;
    {ok, Module, Warnings} -&amp;gt;
      log_error(&amp;quot;warning: ~ts&amp;quot;, [Module:format_warning(Warnings)]);
    {error, Module, Errors} -&amp;gt;
      log_error(&amp;quot;error: ~ts&amp;quot;, [Module:format_error(Errors)]),
      halt(1)
  end;
main(_Args) -&amp;gt;
  log_error(&amp;quot;Usage: ~ts &amp;lt;release-name&amp;gt;~n&amp;quot;, [escript:script_name()]),
  halt(1).

log_error(Format, Args) -&amp;gt;
  io:format(standard_error, Format, Args).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We expect the script to be called with one argument being the name of the
release, and all we do is to call &lt;code&gt;systools:make_script&lt;/code&gt; to generate the
script file and compile it to a boot file.&lt;/p&gt;
&lt;p&gt;We provide three options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;no_warn_sasl&lt;/code&gt; to tell &lt;code&gt;systools&lt;/code&gt; not to print any warning because we did
not include the SASL application (unnecessary since we do not deal with
release upgrading in this article).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{path, [&amp;quot;ebin&amp;quot;]}&lt;/code&gt; to look in the &lt;code&gt;ebin&lt;/code&gt; directory for application
definition files.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;silent&lt;/code&gt; to return warnings and errors instead of printing them directly.
This is necessary because we want to log to the standard error output and
exit with status code 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We then update the Makefile to be able to build the boot file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-make&#34;&gt;RELEASE = hello

$(RELEASE).boot: $(RELEASE).rel ebin/$(RELEASE).app
	./generate-boot $(RELEASE)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;generating-a-release-package&#34;&gt;Generating a release package&lt;/h3&gt;
&lt;p&gt;The final form of a release is a tarball containing all the files required to
run our program, and again &lt;code&gt;systools&lt;/code&gt; knows how to generate it. So let us
write another Erlang program named &lt;code&gt;generate-tarball&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;#!/usr/bin/env escript

main([ReleaseName]) -&amp;gt;
  ERTSPath = code:root_dir(),
  Options = [no_warn_sasl, {path, [&amp;quot;ebin&amp;quot;]}, {erts, ERTSPath}, silent],
  case systools:make_tar(ReleaseName, Options) of
    {ok, _Module, []} -&amp;gt;
      ok;
    {ok, Module, Warnings} -&amp;gt;
      log_error(&amp;quot;warning: ~ts&amp;quot;, [Module:format_warning(Warnings)]);
    {error, Module, Errors} -&amp;gt;
      log_error(&amp;quot;error: ~ts&amp;quot;, [Module:format_error(Errors)]),
      halt(1)
  end;
main(_Args) -&amp;gt;
  log_error(&amp;quot;usage: ~ts &amp;lt;release-name&amp;gt;~n&amp;quot;, [escript:script_name()]),
  halt(1).

log_error(Format, Args) -&amp;gt;
  io:format(standard_error, Format, Args).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code is very similar to the one we wrote to generate the boot script. We
introduce a new option, &lt;code&gt;{erts, ERTSPath}&lt;/code&gt;, to tell &lt;code&gt;systools&lt;/code&gt; to add the
Erlang runtime to the release. This way, our release will be fully standalone:
we will be able to run it anywhere without having to install Erlang. This
option requires the path containing Erlang libraries, and we obtain it with
the &lt;code&gt;code:root_dir&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Then we add the new &lt;code&gt;release&lt;/code&gt; target to the Makefile:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-make&#34;&gt;release: $(RELEASE).tar.gz

$(RELEASE).tar.gz: $(ERL_OBJ) $(RELEASE).boot
	./generate-tarball $(RELEASE)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, we can simply run &lt;code&gt;make release&lt;/code&gt;, and let GNU Make create the
archive.&lt;/p&gt;
&lt;h3 id=&#34;running-the-application&#34;&gt;Running the application&lt;/h3&gt;
&lt;p&gt;Now that we have a tarball, we can extract it somewhere and start Erlang:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;mkdir /tmp/hello
tar -xf hello.tar.gz -C /tmp/hello
cd /tmp/hello
./erts-13.2/bin/erl -noshell -boot releases/1.0.0/start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the release contains Erlang itself. We start it with our boot
script, which has been stored in &lt;code&gt;releases/1.0.0/start.boot&lt;/code&gt;, and our
application starts.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We can now build an Erlang release from scratch! Obviously a real world
application would have other requirements such as handling multiple
applications (internal or added from external dependencies), tests, several
build profiles, extra data files or scripts to be added the release… And while
it can be handled with &lt;code&gt;systools&lt;/code&gt; and a few scripts, you probably want to
start looking at either Rebar3 or Erlang.mk.&lt;/p&gt;
&lt;p&gt;But you should now have a better understanding of the whole build and release
process. As usual, the best way to figure out how something works is to get
rid of the high level tools and try to do it on your own.&lt;/p&gt;
</description>

      
      <category>erlang</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/reduce-vs-fold-in-common-lisp/">
      <title>Reduce vs fold in Common Lisp</title>
      <link>https://www.n16f.net/blog/reduce-vs-fold-in-common-lisp/</link>
      <pubDate>Fri, 02 Jun 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/reduce-vs-fold-in-common-lisp/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;If you have already used functional languages, you are probably familiar with
fold, a high order function used to iterate on a collection of values to
combine them and return a result. You may be surprised that Common Lisp does
not have a fold function, but provides &lt;code&gt;REDUCE&lt;/code&gt; which works a bit differently.
Let us see how they differ.&lt;/p&gt;
&lt;h2 id=&#34;understanding-reduce&#34;&gt;Understanding &lt;code&gt;REDUCE&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In its simplest form, &lt;code&gt;REDUCE&lt;/code&gt; accepts a function and a sequence (meaning
either a list or a vector). It then applies the function to successive pairs
of sequence elements.&lt;/p&gt;
&lt;p&gt;You can easily check what happens by tracing the function:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CL-USER&amp;gt; (trace +)
CL-USER&amp;gt; (reduce #&#39;+ &#39;(1 2 3 4 5))
  0: (+ 1 2)
  0: + returned 3
  0: (+ 3 3)
  0: + returned 6
  0: (+ 6 4)
  0: + returned 10
  0: (+ 10 5)
  0: + returned 15
15
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, the call to &lt;code&gt;REDUCE&lt;/code&gt; evaluates &lt;code&gt;(+ (+ (+ (+ 1 2) 3) 4) 5)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can reverse the order using the &lt;code&gt;:from-end&lt;/code&gt; keyword argument:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CL-USER&amp;gt; (trace +)
CL-USER&amp;gt; (reduce #&#39;+ &#39;(1 2 3 4 5) :from-end t)
  0: (+ 4 5)
  0: + returned 9
  0: (+ 3 9)
  0: + returned 12
  0: (+ 2 12)
  0: + returned 14
  0: (+ 1 14)
  0: + returned 15
15
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In which case you will evaluate &lt;code&gt;(+ 1 (+ 2 (+ 3 (+ 4 5))))&lt;/code&gt;. The result is of
course the same since the &lt;code&gt;+&lt;/code&gt; function is associative.&lt;/p&gt;
&lt;p&gt;You can of course provide an initial value, in which case &lt;code&gt;REDUCE&lt;/code&gt; will behave
as if this value has been present at the beginning (or the end with
&lt;code&gt;:from-end&lt;/code&gt;) of the sequence.&lt;/p&gt;
&lt;p&gt;The surprising aspect of &lt;code&gt;REDUCE&lt;/code&gt; is its behaviour when called on a
sequence with less than two elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the sequence contains a single element:
&lt;ul&gt;
&lt;li&gt;if there is no initial value, the function is not called and the element
is returned directly;&lt;/li&gt;
&lt;li&gt;if there is one, the function is called on both the initial value and the
single element.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If the sequence is empty:
&lt;ul&gt;
&lt;li&gt;if there is no initial value, the function is called without any argument;&lt;/li&gt;
&lt;li&gt;if there is one, the function is not called and the initial value is
returned directly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a result, any function passed to &lt;code&gt;REDUCE&lt;/code&gt; must be able to handle being
called with zero, one or two arguments. Most examples found on the Internet
use &lt;code&gt;+&lt;/code&gt; or &lt;code&gt;append&lt;/code&gt;, and these functions happen to handle it (e.g. &lt;code&gt;(+)&lt;/code&gt;
returns the identity element of the addition, zero). If you write your own
functions, you will have to deal with it using the &lt;code&gt;&amp;amp;OPTIONAL&lt;/code&gt; lambda list
keyword.&lt;/p&gt;
&lt;p&gt;This can lead to unexpected behaviours. If you compute the sum of a sequence
of floats using &lt;code&gt;(reduce #&#39;+ floats)&lt;/code&gt;, you may find it logical to obtain a
float. But if &lt;code&gt;FLOATS&lt;/code&gt; is an empty sequence, you will get &lt;code&gt;0&lt;/code&gt; which is not a
float. Something to keep in mind.&lt;/p&gt;
&lt;h2 id=&#34;differences-with-fold&#34;&gt;Differences with fold&lt;/h2&gt;
&lt;p&gt;The fold function is traditionally defined as accepting three arguments: a
function, an initial value — or accumulator — and a list. The function is
called repeatedly with both the accumulator and a list element, using the
value returned by the function as next accumulator.&lt;/p&gt;
&lt;p&gt;For example in Erlang:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;lists:foldl(fun(X, Sum) -&amp;gt; Sum + X end, 0, [1, 2, 3, 4, 5]).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An interesting consequence is that fold functions are always called with the
same type of arguments (the list value and the accumulator), while &lt;code&gt;REDUCE&lt;/code&gt;
functions can be called with zero or two list values. This makes it
harder to write functions when the accumulated value has a different type from
sequence values.&lt;/p&gt;
&lt;p&gt;Fold is also simpler than &lt;code&gt;REDUCE&lt;/code&gt; since it does not have any special case,
making it easier to reason about its behaviour.&lt;/p&gt;
&lt;p&gt;It would be interesting to know why a function as fundamental as fold was not
included in the Common Lisp standard.&lt;/p&gt;
&lt;h2 id=&#34;implementing-foldl&#34;&gt;Implementing &lt;code&gt;FOLDL&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;We can of course implement a fold function in Common Lisp. We will concentrate
on the most common (and most efficient) left-to-right version. Let us start by
a simple implementation for lists:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun foldl/list (function value list)
  (declare (type (or function symbol) function)
           (type list list))
  (if list
      (foldl/list function (funcall function value (car list)) (cdr list))
      value))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As clearly visible, the recursive call to &lt;code&gt;FOLDL/LIST&lt;/code&gt; is in tail position and
SBCL will happily perform tail-call elimination.&lt;/p&gt;
&lt;p&gt;For vectors we use an iterative approach:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun foldl/vector (function value vector)
  (declare (type (or function symbol) function)
           (type vector vector))
  (do ((i 0 (1+ i))
       (accumulator value))
      ((&amp;gt;= i (length vector))
       accumulator)
    (setf accumulator (funcall function accumulator (aref vector i)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally we write the main &lt;code&gt;FOLDL&lt;/code&gt; function which operates on any sequence:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun foldl (function value sequence)
  (declare (type (or function symbol) function)
           (type sequence sequence))
  (etypecase sequence
    (list (foldl/list function value sequence))
    (vector (foldl/vector function value sequence))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the point we can already use &lt;code&gt;FOLDL&lt;/code&gt; for various operations. We could of
course improve it with the addition of the usual &lt;code&gt;:START&lt;/code&gt;, &lt;code&gt;:END&lt;/code&gt; and &lt;code&gt;:KEY&lt;/code&gt;
keyword arguments for more flexibility.&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/replacing-ngrok-with-frp/">
      <title>Replacing Ngrok with Frp</title>
      <link>https://www.n16f.net/blog/replacing-ngrok-with-frp/</link>
      <pubDate>Thu, 20 Apr 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/replacing-ngrok-with-frp/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I have been using Ngrok for almost two years in order to test webhooks during
development. It works really well, true; but even the personal plan costs $96
a year if you want a fixed URI. I recently came across
&lt;a href=&#34;https://github.com/fatedier/frp&#34;&gt;Frp&lt;/a&gt;, a reverse proxy packed with useful
features. This is how I used it to replace Ngrok entirely.&lt;/p&gt;
&lt;p&gt;Of course you will need a server running somewhere. It does not have to be
powerful, even the smallest VPS will do the work just fine. Personally I use
FreeBSD, but Frp is written in Go and should run anywhere.&lt;/p&gt;
&lt;h2 id=&#34;configuring-the-server&#34;&gt;Configuring the server&lt;/h2&gt;
&lt;h3 id=&#34;frp-server&#34;&gt;Frp server&lt;/h3&gt;
&lt;p&gt;Server configuration turned out to be more complicated than expected. In the
current state, the FreeBSD package runs Frp as the &lt;code&gt;nobody&lt;/code&gt; user, meaning that
it cannot read external files owned by root such as a TLS key. In a perfect
world, Frp would start as &lt;code&gt;root&lt;/code&gt;, would read the TLS key and certificate then
would switch to a non-privileged user. Infortunately Frp does not support that.&lt;/p&gt;
&lt;p&gt;Of course we could let Frp run as &lt;code&gt;root&lt;/code&gt;, but there is a much better solution.
Since I already use NGINX, what about simply letting it handle TLS? This way
Frp can run as a non-privileged user without any issue.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s make it happen! First we configure the Frp server; the configuration
(located at &lt;code&gt;/usr/local/etc/frps.ini&lt;/code&gt; on FreeBSD) is minimal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[common]
bind_addr = 127.0.0.1
bind_port = 6001

proxy_bind_addr = 127.0.0.1
vhost_http_port = 8042

authentication_method = token
token = 12345678
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We bind both the main interface and the proxy interface to a local address
since we are going to use NGINX as front. We also require token authentication
from any Frp client. Of course do not forget to replace &lt;code&gt;12345678&lt;/code&gt; by a proper
random password.&lt;/p&gt;
&lt;p&gt;You may also want to patch the &lt;code&gt;rc&lt;/code&gt; script at &lt;code&gt;/usr/local/etc/rc.d/frps&lt;/code&gt; to
run Frps as a dedicated user, and make sure that the configuration file is
owned by it with permissions &lt;code&gt;0600&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;nginx&#34;&gt;NGINX&lt;/h3&gt;
&lt;p&gt;For NGINX, we need a more complex configuration.&lt;/p&gt;
&lt;p&gt;We first need a block to define a HTTPS interface which will be used to access
what is running on our workstation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https {
    server {
        listen 443 ssl;
        listen [::]:443 ssl;

        server_name dev.example.com;

        ssl_certificate /etc/ssl/certs/dev.example.com.crt;
        ssl_certificate_key /etc/ssl/private/dev.example.com.key;

        access_log /var/log/nginx/access-dev.log combined;

        location / {
            proxy_pass http://localhost:8042;

            proxy_set_header Host $host;
            proxy_set_header X-Request-Id $request_id;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obviously you will have to adjust the server name and SSL certificate file
paths (my certificate comes from &lt;a href=&#34;https://letsencrypt.org/&#34;&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; and
is generated by &lt;a href=&#34;https://github.com/go-acme/lego&#34;&gt;Lego&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Then we need a TCP interface to connect to the control port of the Frps
server. NGINX can do just that with the
&lt;a href=&#34;https://nginx.org/en/docs/stream/ngx_stream_core_module.html&#34;&gt;stream&lt;/a&gt; module.
On FreeBSD it is compiled as a dynamic library, so we have to load it first.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;load_module /usr/local/libexec/nginx/ngx_stream_module.so;

stream {
    upstream frps {
        server 127.0.0.1:6001;
    }

    server {
        listen 6000 ssl;

        ssl_certificate /etc/ssl/certs/dev.example.com.crt;
        ssl_certificate_key /etc/ssl/private/dev.example.com.key;

        proxy_pass frps;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I was positively surprised by how simple it is. Again, NGINX saves the day.&lt;/p&gt;
&lt;p&gt;The resulting architecture is a bit convoluted, but it works.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./network.png&#34; alt=&#34;Network diagram&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;configuring-the-client&#34;&gt;Configuring the client&lt;/h2&gt;
&lt;p&gt;As Ngrok, Frp requires a client to run on your workstation. Fortunately it is
already available on &lt;a href=&#34;https://aur.archlinux.org/packages/frpc&#34;&gt;AUR&lt;/a&gt; for
Archlinux, so installing it was trivial:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;git clone https://aur.archlinux.org/frp.git
cd frp
makepkg
sudo pacman -U ./frpc-0.48.0-1-x86_64.pkg.tar.zst
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The default path for the configuration file is &lt;code&gt;./frpc.ini&lt;/code&gt; which is a really
bad idea. Ideally you would want a standard absolute location such as
&lt;code&gt;~/.frpc.ini&lt;/code&gt; or &lt;code&gt;~/.config/frpc.ini&lt;/code&gt;. But we work we what we have.&lt;/p&gt;
&lt;p&gt;I went with a small script to run the client, and stored it at &lt;code&gt;~/bin/frpc&lt;/code&gt;
since &lt;code&gt;~/bin/&lt;/code&gt; is my &lt;code&gt;PATH&lt;/code&gt; environment variable.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;#!/bin/sh

exec /usr/bin/frpc --config $HOME/.frpc/frpc.ini &amp;quot;$@&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This way I can run frpc without having to worry about the path to the
configuration file. And in the future, if I end up needing several
configurations, I can easily add options to the script to select the right
file.&lt;/p&gt;
&lt;p&gt;The configuration itself is quite simple:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[common]
server_addr = server.example.com
server_port = 6000

tls_enable = true
disable_custom_tls_first_byte = true

authentication_method = token
token = 12345678

[web]
type = http
local_port = 8080
custom_domains = dev.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the &lt;code&gt;common&lt;/code&gt; section, we indicate how to contact the Frp server and how to
authenticate. You will notice the strange &lt;code&gt;disable_custom_tls_first_byte&lt;/code&gt;
option. Frp uses a single byte sent by the client to identify whether the
connection is going to use TLS or not, allowing it to support both TLS and
non-TLS connections on the same port. Since we use NGINX as TLS interface, we
need to instruct the client not to send this first byte.&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;web&lt;/code&gt; section, we declare our web proxy: we will access our local
application on &lt;code&gt;dev.example.com&lt;/code&gt;, and we expect it to listen locally on
port 8080. Obviously you will have to choose a domain you control and make
sure it points to the Frp server.&lt;/p&gt;
&lt;h2 id=&#34;done&#34;&gt;Done!&lt;/h2&gt;
&lt;p&gt;At this point, the only thing left is to start the Frp client on your
workstation. It will connect to the Frp server, and you will then be able to
publicly access your local application from the domain specified.&lt;/p&gt;
&lt;p&gt;Communication between the Frp client and server is secured with TLS, and the
application is exposed using HTTPS, both thanks to NGINX. All good!&lt;/p&gt;
&lt;p&gt;You should also have a look at the &lt;a href=&#34;https://github.com/fatedier/frp&#34;&gt;Frp
readme&lt;/a&gt; because it can do much more than just
proxying HTTP traffic. OIDC authentication, builtin admin interface,
Prometheus metrics, load balancing, you probably will find something useful to
you.&lt;/p&gt;
</description>

      
      <category>ops</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/making-ielm-more-comfortable/">
      <title>Making IELM More Comfortable</title>
      <link>https://www.n16f.net/blog/making-ielm-more-comfortable/</link>
      <pubDate>Sat, 08 Apr 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/making-ielm-more-comfortable/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;IELM is the Emacs Lisp REPL. It lets you evaluate any Elisp expression, prints
the output and keeps track of previous commands. While it is a serious step-up
from the humble &lt;code&gt;eval-expression&lt;/code&gt;, it can be uncomfortable on several aspects.
Let us improve it.&lt;/p&gt;
&lt;h2 id=&#34;adding-eldoc-hints&#34;&gt;Adding Eldoc hints&lt;/h2&gt;
&lt;p&gt;Eldoc is a generic module used to display realtime documentation hints while
you type. For Emacs Lisp, it means displaying docstrings when your
cursor is over a symbol or when you start writing a function call.&lt;/p&gt;
&lt;p&gt;When calling a function, you often need a quick remainder about the arguments.
Having Eldoc means you do not have to call &lt;code&gt;C-h f&lt;/code&gt; and deal with the
documentation buffer, and can just glance at the echo area.&lt;/p&gt;
&lt;p&gt;To enable Eldoc in IELM, let us add it to the initialization hook:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(add-hook &#39;ielm-mode-hook &#39;eldoc-mode)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;using-paredit&#34;&gt;Using Paredit&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://paredit.org/&#34;&gt;Paredit&lt;/a&gt; is an essential minor mode that lets you
manipulate Lisp code as expressions and not as simple text. If you are not
using it and think that editing all these parentheses is annoying, you are
missing out. Give it a try, you will not be disappointed.&lt;/p&gt;
&lt;p&gt;To use Paredit in IELM, we add it to the initialization hook:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(add-hook &#39;ielm-mode-hook &#39;paredit-mode)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Infortunately there is a key conflict between Paredit and IELM. Paredit
overrides &lt;code&gt;return&lt;/code&gt; to execute &lt;code&gt;paredit-RET&lt;/code&gt;, meaning that the original
&lt;code&gt;ielm-return&lt;/code&gt; is not called.&lt;/p&gt;
&lt;p&gt;The simplest way to fix it is to alter the Paredit keymap:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(define-key paredit-mode-map (kbd &amp;quot;RET&amp;quot;) nil)
(define-key paredit-mode-map (kbd &amp;quot;C-j&amp;quot;) &#39;paredit-newline)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We remove the entry associated with &lt;code&gt;return&lt;/code&gt; and use &lt;code&gt;C-j&lt;/code&gt; to insert a newline
character, useful to write a multiline expression.&lt;/p&gt;
&lt;h2 id=&#34;making-the-command-history-persistent&#34;&gt;Making the command history persistent&lt;/h2&gt;
&lt;p&gt;The most annoying part of IELM is that it does not have persistent history. I
expect any interactive command system to store past entries since they can
always be useful again. ZSH has persistence, so does the
&lt;a href=&#34;https://slime.common-lisp.dev/&#34;&gt;SLIME&lt;/a&gt; Common Lisp REPL. IELM does not, even
though Comint (the mode IELM derives from) can handle it.&lt;/p&gt;
&lt;p&gt;Let us add it. First we will write a function to configure Comint and load any
entry stored in the history file if it exists:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-ielm-init-history ()
  (let ((path (expand-file-name &amp;quot;ielm/history&amp;quot; user-emacs-directory)))
    (make-directory (file-name-directory path) t)
    (setq-local comint-input-ring-file-name path))
  (setq-local comint-input-ring-size 10000)
  (setq-local comint-input-ignoredups t)
  (comint-read-input-ring))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We store the history in the &lt;code&gt;ielm/history&lt;/code&gt; file in the user Emacs directory,
mimicking the &lt;code&gt;eshell/history&lt;/code&gt; file used by Eshell.&lt;/p&gt;
&lt;p&gt;Nothing complicated: we increase the number of entries stored in the history
file, and tell Comint to drop duplicate entries. We also are careful and use
&lt;code&gt;setq-local&lt;/code&gt; to make sure Comint settings are only modified for the current
buffer and not globally, since other buffers using different Comint-based
modes could have different requirements.&lt;/p&gt;
&lt;p&gt;We want to call this function when IELM start:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(add-hook &#39;ielm-mode-hook &#39;g-ielm-init-history)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reading the history is one thing. We need a way to add all expressions we
evaluate to it. It would have been nice to have a hook called everytime an
expression is entered, but we have to do without it. We are going to use Elisp
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Functions.html&#34;&gt;advices&lt;/a&gt;
to evaluate code each time a specific function is called. We want to write
the history file when &lt;code&gt;ielm-send-input&lt;/code&gt; returns:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defun g-ielm-write-history (&amp;amp;rest _args)
  (with-file-modes #o600
    (comint-write-input-ring)))
  
(advice-add &#39;ielm-send-input :after &#39;g-ielm-write-history)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Advising functions are called with the same arguments as the advised function.
We do not care about them, so we use the &lt;code&gt;&amp;amp;rest&lt;/code&gt; keyword to match all
arguments passed to &lt;code&gt;g-ielm-write-history&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We are careful to use &lt;code&gt;with-file-modes&lt;/code&gt; to make sure the file is always
created as only readable by the user, since it may contain private
information.&lt;/p&gt;
&lt;p&gt;This was not easy, but persistent history is worth it!&lt;/p&gt;
&lt;h2 id=&#34;useful-key-bindings&#34;&gt;Useful key bindings&lt;/h2&gt;
&lt;p&gt;Finally we will bind two key combinations.&lt;/p&gt;
&lt;p&gt;First the very common &lt;code&gt;C-l&lt;/code&gt; to clear the buffer. All modes deriving from
Comint have &lt;code&gt;C-c M-o&lt;/code&gt;, but it is awkward to type and &lt;code&gt;C-l&lt;/code&gt; is very common in
various applications.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(define-key inferior-emacs-lisp-mode-map (kbd &amp;quot;C-l&amp;quot;)
            &#39;comint-clear-buffer)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we want a way to search through old expressions. Comint has
&lt;code&gt;comint-history-isearch-backward-regexp&lt;/code&gt; which is incredibly primitive. We can
get a far better experience with &lt;a href=&#34;https://github.com/emacs-helm/helm&#34;&gt;Helm&lt;/a&gt;.
The &lt;code&gt;helm-comint-input-ring&lt;/code&gt; function lets us browse among old expressions and
select one through incremental search. We bind it to &lt;code&gt;C-r&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(define-key inferior-emacs-lisp-mode-map (kbd &amp;quot;C-r&amp;quot;)
            &#39;helm-comint-input-ring)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IELM is so much more comfortable to use now!&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/golang-workspaces-at-last/">
      <title>Golang workspaces, at last!</title>
      <link>https://www.n16f.net/blog/golang-workspaces-at-last/</link>
      <pubDate>Tue, 28 Mar 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/golang-workspaces-at-last/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;Workspaces are a feature introduced in March 2022 with Go 1.18. They did not
really get a lot of publicity, and I have not had the chance to experiment
with them until recently. However I am really glad I did because they improve
a major aspect of my workflow: dealing with multiple modules.&lt;/p&gt;
&lt;h2 id=&#34;go-modules-are-not-ideal&#34;&gt;Go modules are not ideal&lt;/h2&gt;
&lt;p&gt;Go modules were a big help when they were introduced in 2018, but they were
always limited. Larger products are often split into multiple projects: one or
more applications and several libraries and tools, meaning multiple modules.&lt;/p&gt;
&lt;p&gt;While module versioning makes sure that components use the right version of
each dependency, it is also really annoying during development. If your
application &lt;code&gt;foo&lt;/code&gt; depends on the &lt;code&gt;go-bar&lt;/code&gt; library, you will often have to work
on &lt;code&gt;go-bar&lt;/code&gt; while testing the changes in &lt;code&gt;foo&lt;/code&gt;. This means updating &lt;code&gt;go-bar&lt;/code&gt;,
commiting changes, pushing them, and updating the &lt;code&gt;foo&lt;/code&gt; module with &lt;code&gt;go get&lt;/code&gt;.
Quite cumbersome.&lt;/p&gt;
&lt;p&gt;A first improvement is the module replacement system. In the example above, we
could instruct Go to use the local copy of &lt;code&gt;go-bar&lt;/code&gt; when building &lt;code&gt;foo&lt;/code&gt;.
Assuming that &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;go-bar&lt;/code&gt; are at the same level in the filesystem:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go mod edit -replace example.com/myproject/go-bar=../go-bar
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this simple change, you have made your life easier: you can work on
changes in &lt;code&gt;go-bar&lt;/code&gt;, and immediately build and run &lt;code&gt;foo&lt;/code&gt; without any
additional operations. When you are done, you can still commit and push
normally in &lt;code&gt;go-bar&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But it is still not perfect. Module replacements are stored in the &lt;code&gt;go.mod&lt;/code&gt;
file, meaning that these changes will be pushed to your central repository
circumventing dependency versioning and causing issues for other developers
and CI processes. While module replacement works fine to point a module to a
fork, it is not really a solution for our problem.&lt;/p&gt;
&lt;h2 id=&#34;using-workspaces&#34;&gt;Using workspaces&lt;/h2&gt;
&lt;p&gt;Go workspaces let you create environments where you control the source of the
modules you use, without having to modify these modules.&lt;/p&gt;
&lt;p&gt;Going back to our example, we can solve our problem by creating a workspace
for &lt;code&gt;foo&lt;/code&gt; in which &lt;code&gt;go-bar&lt;/code&gt; refers to the local copy. In the directory of &lt;code&gt;foo&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go work init
go work use .
go work use ../go-bar
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing complicated here. The &lt;code&gt;init&lt;/code&gt; subcommand creates the &lt;code&gt;go.work&lt;/code&gt; file
which will contain the configuration of the workspace. Then the &lt;code&gt;use&lt;/code&gt;
subcommand is called to add two modules to the workspace: the &lt;code&gt;foo&lt;/code&gt; module in
the current repository, i.e. &lt;code&gt;.&lt;/code&gt;, and the one in the &lt;code&gt;go-bar&lt;/code&gt; sibling directory.&lt;/p&gt;
&lt;p&gt;At this point, building &lt;code&gt;foo&lt;/code&gt; will correctly use the local copy of &lt;code&gt;go-bar&lt;/code&gt;
without having to modify any of the modules. Problem solved.&lt;/p&gt;
&lt;p&gt;Even better, you can include &lt;code&gt;replace&lt;/code&gt; declarations in the &lt;code&gt;go.work&lt;/code&gt; file the
exact same way as in &lt;code&gt;go.mod&lt;/code&gt; file. These declarations will override those in
module files, giving you total control on the environment, again without
having to alter modules.&lt;/p&gt;
&lt;h2 id=&#34;committing-the-workspace-file&#34;&gt;Committing the workspace file&lt;/h2&gt;
&lt;p&gt;Whether you commit the workspace file or not depends on your situation. When
working in a mono-repository with other developers, committing a workspace
file allows everyone to build the project the exact same way, using
dependencies in the repository. It can also be practical with multiple
repositories as long as you expect everyone to organize their local copies the
same way.&lt;/p&gt;
&lt;p&gt;But you can also keep your own workspace files without committing them. This
gives you the ability to quickly switch to a local copy for a dependency or to
replace a module by another one during development. For example this what I do
for my &lt;a href=&#34;https://github.com/galdor/go-raft/&#34;&gt;go-raft library&lt;/a&gt; project. The
program in the &lt;code&gt;cmd/kvstore&lt;/code&gt; directory is based on the &lt;a href=&#34;https://github.com/galdor/go-service&#34;&gt;go-service
library&lt;/a&gt;. During development, I
sometimes have to add code to go-service. Therefore I have a workspace file in
go-raft which references the local copy of go-service. But I do not commit it,
to avoid affecting anyone trying to build go-raft.&lt;/p&gt;
&lt;p&gt;This flexibility is really practical, and I&amp;rsquo;m quite satisfied with workspaces
at this point.&lt;/p&gt;
&lt;h2 id=&#34;what-could-be-better&#34;&gt;What could be better&lt;/h2&gt;
&lt;p&gt;There is a small issue to keep in mind. If you get used to work with
workspaces, committing your local dependencies and having your program use
them automatically, you may still have to maintain module dependencies. It is
not necessarily a problem if you commit the workspace file and always use it,
but it makes sense to keep dependencies up-to-date in your module files.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;go work&lt;/code&gt; command has a &lt;code&gt;sync&lt;/code&gt; subcommand whose description let me think
that it would update modules included in the workspace to the right dependency
versions, but it turns out not do to so when tracking
&lt;a href=&#34;https://go.dev/ref/mod#pseudo-versions&#34;&gt;pseudo-versions&lt;/a&gt; (i.e. when you are
tracking a branch and not a specific tag).&lt;/p&gt;
&lt;p&gt;Therefore I have to continue to update non-tagged dependencies with this usual
(and quite excessive) command, here for go-service:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GOPROXY=direct go get github.com/galdor/go-service@latest
go mod tidy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This way I make sure to bypass the &lt;a href=&#34;https://proxy.golang.org/&#34;&gt;Go proxy&lt;/a&gt;,
fetch the last version of the &lt;code&gt;master&lt;/code&gt; branch and clean up the dependency
list.&lt;/p&gt;
&lt;p&gt;Despite this small inconvenience, Go workspaces have made my daily work much
easier. Still a win!&lt;/p&gt;
</description>

      
      <category>golang</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/counting-lines-with-common-lisp/">
      <title>Counting lines with Common Lisp</title>
      <link>https://www.n16f.net/blog/counting-lines-with-common-lisp/</link>
      <pubDate>Fri, 17 Mar 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/counting-lines-with-common-lisp/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;A good line counting program has two features: it only counts non-empty lines
to get a fair estimate of the size of a project, and it groups line counts by
file type to help see immediately which languages are used.&lt;/p&gt;
&lt;p&gt;A long time ago I got frustrated with two well known line counters.
&lt;a href=&#34;https://dwheeler.com/sloccount/&#34;&gt;Sloccount&lt;/a&gt; spits out multiple strange Perl
warnings about locales, and most of the output is a copyright notice and some
absurd cost estimations. &lt;a href=&#34;https://github.com/AlDanial/cloc&#34;&gt;Cloc&lt;/a&gt; has fourteen
Perl packages as dependencies. Writing a simple line counter is an interesting
exercise; at the time I was discovering Common Lisp, so I wrote my own
version.&lt;/p&gt;
&lt;p&gt;I made a few changes years after years, but most of the code stayed the same.
I thought it would be interesting to revisit this program and present it part
by part as a demonstration of how you can use Common Lisp to solve a simple
problem.&lt;/p&gt;
&lt;p&gt;We are going to write the program bottom-up, starting with the smallest
building blocks and progressively building upon them.&lt;/p&gt;
&lt;h2 id=&#34;the-program&#34;&gt;The program&lt;/h2&gt;
&lt;p&gt;The program is written in Common Lisp. The most convenient way of storing and
executing it is a single executable file stored in a directory being part of
the PATH environment variable. In my case, the script will be called &lt;code&gt;locc&lt;/code&gt;,
for &amp;ldquo;line of code counter&amp;rdquo;, and will be stored in the &lt;code&gt;~/bin&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;We start the file with a
&lt;a href=&#34;https://en.wikipedia.org/wiki/Shebang_(Unix)&#34;&gt;shebang&lt;/a&gt; indicating how to
execute the file. We use the &lt;a href=&#34;http://sbcl.org/&#34;&gt;SBCL&lt;/a&gt; implementation because
it is stable and actively developed. It also makes it easy to execute a simple
file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/sbcl --script
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;finding-files&#34;&gt;Finding files&lt;/h2&gt;
&lt;p&gt;Our line counter will operate on directories, so it has to be able to list
files in them. Path handling functions are very disconcerting at first. Common
Lisp was designed a long time ago, and operating systems were different at the
time. Let us dig in!&lt;/p&gt;
&lt;p&gt;First let us write a simple function to check if a pathname object is a
directory pathname:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun directory-path-p (path)
  &amp;quot;Return T if PATH is a directory or NIL else.&amp;quot;
  (declare (type (or pathname string) path))
  (and (not (pathname-name path))
       (not (pathname-type path))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we write a function to identify hidden files and directories since we do
not want to include them:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun hidden-path-p (path)
  &amp;quot;Return T if PATH is a hidden file or directory or NIL else.&amp;quot;
  (declare (type pathname path))
  (let ((name (if (directory-path-p path)
                  (car (last (pathname-directory path)))
                  (file-namestring path))))
    (and (plusp (length name))
         (eq (char name 0) #\.))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see we use &lt;code&gt;DIRECTORY-PATH-P&lt;/code&gt; to extract the basename of the path,
then check if it starts with a full stop (only if it is not empty of course).&lt;/p&gt;
&lt;p&gt;Finally we can write the function to actually list files in a directory
recursively:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun directory-path (path)
  &amp;quot;If PATH is a directory pathname, return it as it is. If it is a file
pathname or a string, transform it into a directory pathname.&amp;quot;
  (declare (type (or pathname string) path))
  (if (directory-path-p path)
      path
      (make-pathname :directory (append (or (pathname-directory path)
                                            (list :relative))
                                        (list (file-namestring path)))
                     :name nil :type nil :defaults path)))

(defun find-files (path)
  &amp;quot;Return a list of all files contained in the directory at PATH or any of its
subdirectories.&amp;quot;
  (declare (type (or pathname string) path))
  (flet ((list-directory (path)
           (directory
            (make-pathname :defaults (directory-path path)
                           :type :wild :name :wild))))
    (let ((paths nil)
          (children (list-directory (directory-path path))))
      (dolist (child children paths)
        (unless (hidden-path-p child)
          (if (directory-path-p child)
              (setf paths (append paths (find-files child)))
              (push child paths)))))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We use the &lt;code&gt;DIRECTORY&lt;/code&gt; standard function with a path containing a wildcard
component to list the files in a directory, and do so recursively.&lt;/p&gt;
&lt;h2 id=&#34;counting-lines&#34;&gt;Counting lines&lt;/h2&gt;
&lt;p&gt;Now that we have files, we can start counting lines. Let us first write a
function to count the number of non-empty lines in a file.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun count-file-lines (path)
  &amp;quot;Count the number of non-empty lines in the file at PATH. A line is empty if
it only contains space or tabulation characters.&amp;quot;
  (declare (type pathname path))
  (with-open-file (stream path :element-type &#39;(unsigned-byte 8))
    (do ((nb-lines 0)
         (blank-line t))
        (nil)
      (let ((octet (read-byte stream nil)))
        (cond
          ((or (null octet) (eq octet #.(char-code #\Newline)))
           (unless blank-line
             (incf nb-lines))
           (when (null octet)
             (return-from count-file-lines nb-lines))
           (setf blank-line t))
          ((and (/= octet #.(char-code #\Space))
                (/= octet #.(char-code #\Tab)))
           (setf blank-line nil)))))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We open the file to obtain a steam of octets, and read it octet by octet,
keeping track of whether the current line is blank or not. Note how we make
sure to count the last line even if it does not end with a newline character.&lt;/p&gt;
&lt;p&gt;Reading a file one octet could be a disaster for performances. Fortunately
SBCL file streams are buffered, something we can easily check by running our
program with &lt;code&gt;strace -e trace=openat,read&lt;/code&gt;. We would not rely on this property
if we wanted our program to work on multiple Common Lisp implementations, but
this is a non issue here.&lt;/p&gt;
&lt;h2 id=&#34;identifying-the-file-type&#34;&gt;Identifying the file type&lt;/h2&gt;
&lt;p&gt;Counting lines is one thing, but we need to identify their content. The
simplest way is to do so based on the file extension.&lt;/p&gt;
&lt;p&gt;Obviously we will want to ignore various files which are known not to contain
text content, so we start by building a hash table containing these
extensions:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defparameter *ignored-extensions*
  (let ((extensions &#39;(&amp;quot;a&amp;quot; &amp;quot;bin&amp;quot; &amp;quot;bmp&amp;quot; &amp;quot;cab&amp;quot; &amp;quot;db&amp;quot; &amp;quot;elc&amp;quot; &amp;quot;exe&amp;quot; &amp;quot;gif&amp;quot; &amp;quot;gz&amp;quot;
                      &amp;quot;jar&amp;quot; &amp;quot;jpeg&amp;quot; &amp;quot;jpg&amp;quot; &amp;quot;o&amp;quot; &amp;quot;pcap&amp;quot; &amp;quot;pdf&amp;quot; &amp;quot;png&amp;quot; &amp;quot;ps&amp;quot; &amp;quot;rar&amp;quot;
                      &amp;quot;svg&amp;quot; &amp;quot;tar&amp;quot; &amp;quot;tgz&amp;quot; &amp;quot;tiff&amp;quot; &amp;quot;zip&amp;quot;))
        (table (make-hash-table :test &#39;equal)))
    (dolist (extension extensions table)
      (setf (gethash extension table) t)))
  &amp;quot;A hash table containing all file extensions to ignore.&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We then create another hash table to associate a type symbol to each known
file extension:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defparameter *extension-types*
  (let ((pairs &#39;((&amp;quot;asm&amp;quot; . assembly) (&amp;quot;s&amp;quot; . assembly)
                 (&amp;quot;adoc&amp;quot; . asciidoc)
                 (&amp;quot;awk&amp;quot; . awk)
                 (&amp;quot;h&amp;quot; . c) (&amp;quot;c&amp;quot; . c)
                 (&amp;quot;hpp&amp;quot; . cpp) (&amp;quot;cpp&amp;quot; . cpp) (&amp;quot;cc&amp;quot; . cpp)
                 (&amp;quot;css&amp;quot; . css)
                 (&amp;quot;el&amp;quot; . elisp)
                 (&amp;quot;erl&amp;quot; . erlang)
                 (&amp;quot;go&amp;quot; . go)
                 (&amp;quot;html&amp;quot; . html) (&amp;quot;htm&amp;quot; . html)
                 (&amp;quot;ini&amp;quot; . ini)
                 (&amp;quot;hs&amp;quot; . haskell)
                 (&amp;quot;java&amp;quot; . java)
                 (&amp;quot;js&amp;quot; . javascript)
                 (&amp;quot;json&amp;quot; . json)
                 (&amp;quot;tex&amp;quot; . latex)
                 (&amp;quot;lex&amp;quot; . lex)
                 (&amp;quot;lisp&amp;quot; . lisp)
                 (&amp;quot;mkd&amp;quot; . markdown) (&amp;quot;md&amp;quot; . markdown)
                 (&amp;quot;rb&amp;quot; . ruby)
                 (&amp;quot;pl&amp;quot; . perl) (&amp;quot;pm&amp;quot; . perl)
                 (&amp;quot;php&amp;quot; . php)
                 (&amp;quot;py&amp;quot; . python)
                 (&amp;quot;sed&amp;quot; . sed)
                 (&amp;quot;sh&amp;quot; . shell) (&amp;quot;bash&amp;quot; . shell) (&amp;quot;csh&amp;quot; . shell)
                 (&amp;quot;zsh&amp;quot; . shell) (&amp;quot;ksh&amp;quot; . shell)
                 (&amp;quot;scm&amp;quot; . scheme)
                 (&amp;quot;sgml&amp;quot; . sgml)
                 (&amp;quot;sql&amp;quot; . sql)
                 (&amp;quot;texi&amp;quot; . texinfo)
                 (&amp;quot;texinfo&amp;quot; . texinfo)
                 (&amp;quot;vim&amp;quot; . vim)
                 (&amp;quot;xml&amp;quot; . xml) (&amp;quot;dtd&amp;quot; . xml) (&amp;quot;xsd&amp;quot; . xml)
                 (&amp;quot;yaml&amp;quot; . yaml) (&amp;quot;yml&amp;quot; . yaml)
                 (&amp;quot;y&amp;quot; . yacc)))
        (table (make-hash-table :test &#39;equal)))
    (dolist (pair pairs table)
      (setf (gethash (car pair) table) (cdr pair))))
  &amp;quot;A hash table containing a symbol identifying the type of a file for
  each known file extension.&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With these hash tables, the function identifying the type of a file is
trivial:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun identify-file-type (path)
  &amp;quot;Return a symbol identifying the type of the file at PATH, or UNKNOWN if the
file extension is not known.&amp;quot;
  (declare (type pathname path))
  (let ((extension (pathname-type path)))
    (unless (gethash extension *ignored-extensions*)
      (gethash extension *extension-types* &#39;unknown))))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;collecting-file-information&#34;&gt;Collecting file information&lt;/h2&gt;
&lt;p&gt;Up to this point, we wrote several functions without connecting them. But we
now have all the building blocks we need. Let us use them to accumulate
information about the files in a list of directories.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun collect-line-counts (directory-paths)
  &amp;quot;Collect the line count of all files in the directories located at one of the
paths in DIRECTORY-PATHS and return them grouped by file type as an
association list.&amp;quot;
  (declare (type list directory-paths))
  (let ((line-counts (make-hash-table)))
    (dolist (directory-path directory-paths)
      (dolist (path (find-files directory-path))
        (handler-case
            (let ((type (identify-file-type path)))
              (when (and type (not (eq type &#39;unknown)))
                (let ((nb-lines (count-file-lines path)))
                  (incf (gethash type line-counts 0) nb-lines))))
          (error (condition)
            (format *error-output* &amp;quot;~&amp;amp;error while reading ~A: ~A~%&amp;quot;
                    path condition)))))
    (let ((line-count-list nil))
      (maphash (lambda (type nb-lines)
                 (push (cons type nb-lines) line-count-list))
               line-counts)
      line-count-list)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We get to use all previous functions. We iterate through directory paths to
find non-hidden files using &lt;code&gt;FIND-FILES&lt;/code&gt;, then we use &lt;code&gt;IDENTIFY-FILE-TYPE&lt;/code&gt; to
obtain a type symbol and &lt;code&gt;COUNT-FILE-LINES&lt;/code&gt; to count the number of non-empty
lines in each file. Results are accumulated by file type in the &lt;code&gt;LINE-COUNTS&lt;/code&gt;
hash table. During this process, we handle errors that may occur while reading
files with a message on the error output. Finally we transform the hash table
into an association list and return it.&lt;/p&gt;
&lt;h2 id=&#34;presenting-results&#34;&gt;Presenting results&lt;/h2&gt;
&lt;p&gt;Executing all these functions in the Lisp REPL is quite practical during
developement, but the default pretty printer is not really what you expect for
the final command line tool:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./repl-output.png&#34; alt=&#34;REPL output&#34;&gt;&lt;/p&gt;
&lt;p&gt;So let us write a function to format this association list:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun format-line-counts (line-counts &amp;amp;key (stream *standard-output*))
  &amp;quot;Format the line counts in the LINE-COUNTS association list to STREAM.&amp;quot;
  (declare (type list line-counts)
           (type stream stream))
  (dolist (entry (sort line-counts &#39;&amp;gt; :key &#39;cdr))
    (let ((type (car entry))
          (nb-lines (cdr entry)))
      (format stream &amp;quot;~12A  ~8@A~%&amp;quot;
              (string-downcase (symbol-name type)) nb-lines))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We print the list sorted in descending order, meaning that the file type with
the most number of lines comes first. Of course the output is padded to make
sure numbers are all aligned.&lt;/p&gt;
&lt;h2 id=&#34;finalizing-the-program&#34;&gt;Finalizing the program&lt;/h2&gt;
&lt;p&gt;The only thing left to do is the entry point of the script. This is the only
place where we need to call a non-standard function in order to access command
line arguments. If no command line argument were passed to the script, we look
for files in the current directory.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(let ((paths (or (cdr sb-ext:*posix-argv*) &#39;(&amp;quot;.&amp;quot;))))
  (format-line-counts
   (collect-line-counts paths)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;./shell-output.png&#34; alt=&#34;Shell output&#34;&gt;&lt;/p&gt;
&lt;p&gt;Much better!&lt;/p&gt;
&lt;p&gt;There does not seem to be any performance issue: on the Linux kernel source
tree, this program is almost 11 times faster than sloccount. It would be
interesting to profile the program to make sure IO is the bottleneck and
improve inefficient parts, but this code is fast enough for my needs.&lt;/p&gt;
&lt;p&gt;As you can see, it is not that hard to use Common Lisp to solve problems.&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/when-your-product-idea-has-no-market/">
      <title>When your product idea has no market</title>
      <link>https://www.n16f.net/blog/when-your-product-idea-has-no-market/</link>
      <pubDate>Mon, 13 Mar 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/when-your-product-idea-has-no-market/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;At the end of 2021 I quitted my job to create a &lt;a href=&#34;https://exograd.com&#34;&gt;company&lt;/a&gt;
with an ex-colleague. It did not work out. One year later, both the
&lt;a href=&#34;https://eventline.net&#34;&gt;first&lt;/a&gt; and the
&lt;a href=&#34;https://www.exograd.com/products/cspwatch/&#34;&gt;second&lt;/a&gt; product were a failure,
my business partner had quit to create a VC-funded startup, and I was left
to pick up the pieces. Not fun.&lt;/p&gt;
&lt;p&gt;Since then I have been trying to find a new product to build while looking for
contract work. This is a summary of my thought process around my last idea.&lt;/p&gt;
&lt;h2 id=&#34;it-all-started-with-hacker-news&#34;&gt;It all started with Hacker News&lt;/h2&gt;
&lt;p&gt;Recently &lt;a href=&#34;https://www.n16f.net/blog/common-lisp-implementations-in-2023/&#34;&gt;one of my articles&lt;/a&gt; was posted on
&lt;a href=&#34;https://news.ycombinator.com/&#34;&gt;Hacker News&lt;/a&gt;. It is a big deal: lots of tech
people read HN, and having your content featured on the first page is really
nice when you are trying to get feedback, connect with like-minded people or
simply raise awareness about your work. I do not post my own content on HN
(though I have been told by someone from a YC company that &amp;ldquo;everyone does it
all the time&amp;rdquo;), and I spotted the submission almost by accident.&lt;/p&gt;
&lt;p&gt;Last week I was thinking about it again; missing the submission would not have
been the end of the world, but it would have been useful to receive some kind
of real time notification. A simple Telegram notification would work, how hard
could it be? And it was not just Hacker News. I would love to be notified if
my content was being posted on other websites such as
&lt;a href=&#34;https://lobste.rs/&#34;&gt;Lobste.rs&lt;/a&gt;. My imagination started running wild. There
are a lot of things on the internet I watch from time to time. But I would
really prefer a real time mechanism notification. Some services support it;
most use email which is useless because I do not check my emails every 5
minutes.&lt;/p&gt;
&lt;p&gt;I suddenly remembered one of the discussions we had during a user research
interview. A consultant told us very clearly: &amp;ldquo;automation is nice and all, but
sometimes all I want is an SMS&amp;rdquo;. Could it be a viable product?&lt;/p&gt;
&lt;h2 id=&#34;pingmewhen-the-concept&#34;&gt;PingMeWhen: the concept&lt;/h2&gt;
&lt;p&gt;The core idea is a small SaaS where users can watch for various events and be
&amp;ldquo;pinged&amp;rdquo; in real time when these events occur. No code, no complex rules, just
an email, SMS, Slack message or Telegram notification with a link and maybe a
custom message. It would start with watching Hacker News of course: when a
link to your website is being posted, or when specific keywords appear in a
title or in comments. Then I would extend it to other platforms. I could then
consider more complex events: security vulnerability alerts, financial data,
anything happening anywhere really. My mind was buzzing with all the
possibilities! I always liked the idea of letting the computer do the work and
tell me when something interesting happens. This could work.&lt;/p&gt;
&lt;p&gt;I exposed the idea to a few friends; they tought it was interesting. I found a
name, PingMeWhen, and immediately bought the pingmewhen.net domain. One thing
done. The technical aspect was not too hard: regularly poll various data
sources on the Internet depending on what users want to watch, emit events
when specific things happen, and send notifications. I was confident I could
build it quickly.&lt;/p&gt;
&lt;p&gt;Seemed solid. But it was not.&lt;/p&gt;
&lt;h2 id=&#34;who-is-going-to-pay-for-that&#34;&gt;Who is going to pay for that?&lt;/h2&gt;
&lt;p&gt;Something I learned from my last two failures is that there is no point in
building a product unless you have established that someone (ideally multiple
someones) is going to pay for it. For real, not just &amp;ldquo;yeah probably&amp;rdquo; but with
the well known &amp;ldquo;take my money!&amp;rdquo; reaction. So this weekend I started to think
about the potential market. It was not great.&lt;/p&gt;
&lt;p&gt;Your product is either B2B, where you sell to other companies, or B2C where
you target simple consumers. In this case, consumers are a really tough
market: there is nothing really attractive about real time notifications, and
people really do not want to pay for anything. Even if I could manage to
somehow market the product to them (and I have no idea how), I could not hope
to have anyone pay more than a couple dollars a month. Hardly a good business
model: I am alone and have no way to gather thousands of consumers.&lt;/p&gt;
&lt;p&gt;So why would a company use this product? As some Google search showed me,
companies which really benefit from reacting quickly to what happens on the
Internet already have specialized tools for that. All of them have their
limitations of course, but they all target specific use cases (e.g. content
marketing) and are therefore much easier to sell. Specific beats generic all
the time. For more technical use cases, the situation is not really different.
&lt;a href=&#34;https://ifttt.com/&#34;&gt;IFTTT&lt;/a&gt; already lets users react to a wide range of events
with way more flexibility than a simple notification. And it is so cheap I
cannot start to think about how to compete with them. Furthermore IFTTT is
just one of them, there are dozen of similar powerful tools, including open
source ones such as &lt;a href=&#34;https://github.com/huginn/huginn&#34;&gt;Huggin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Something is really wrong: if I have trouble figuring out who is going to buy
the product, does it really make sense to build it? Probably not.&lt;/p&gt;
&lt;h2 id=&#34;going-forward&#34;&gt;Going forward&lt;/h2&gt;
&lt;p&gt;It took me three days from the first idea to the end of this article. I usually do
not mind discarding ideas, but this one frustrates me: IFTTT does not have a
recipe to let me know when one of my articles is being posted, and I really do
not want to manage a Huggin deployment, so I&amp;rsquo;m back to square one. I feel like
if have this kind of problem, others may have too. I am just not convinced
enough people would pay for it.&lt;/p&gt;
&lt;p&gt;At least I learned a good lesson: do not buy the domain name before being sure
there is something worth pursuing. 20€ for a .net domain is way more expensive
that it used to be.&lt;/p&gt;
&lt;p&gt;I imagine I will keep the idea around just in case. And I might get some
interesting feedback from readers, who knows.&lt;/p&gt;
</description>

      
      <category>business</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/gmail-backups-using-isync/">
      <title>Gmail backups using ISync</title>
      <link>https://www.n16f.net/blog/gmail-backups-using-isync/</link>
      <pubDate>Thu, 02 Mar 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/gmail-backups-using-isync/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;Like so many people, I use Gmail. There are not a lot of options, and Google
Workspace provides me additional useful services and lets me use my own domain
name. However there has been a lot of horror stories about users losing access
to their Gmail account without any recourse. It is not clear if it can happen
with Google Workspace, but the risk is too high to ignore.&lt;/p&gt;
&lt;p&gt;I already &lt;a href=&#34;https://www.n16f.net/blog/exporting-1password-data-for-backup/&#34;&gt;backup my passwords&lt;/a&gt;; now is the time to
backup my emails. While Google Workspace offers an export system, I wanted
something scriptable. I went with IMAP access since I already use it to read
emails with &lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/gnus/&#34;&gt;Gnus&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;authentication&#34;&gt;Authentication&lt;/h2&gt;
&lt;p&gt;Gmail IMAP access requires an application password. You can refer to the
&lt;a href=&#34;https://support.google.com/accounts/answer/185833?hl=en&#34;&gt;Google help center&lt;/a&gt;
for more information about how to create them.&lt;/p&gt;
&lt;p&gt;We will store credentials in the semi-standard
&lt;a href=&#34;https://everything.curl.dev/usingcurl/netrc&#34;&gt;netrc&lt;/a&gt; file. For Gmail, add the
following entry to &lt;code&gt;~/.netrc&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;machine imap.gmail.com port 993 login &amp;lt;email-address&amp;gt; &amp;lt;password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure that your netrc file is only user readable. Its permissions should
be set to &lt;code&gt;0600&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;isync&#34;&gt;ISync&lt;/h2&gt;
&lt;p&gt;We will export emails using the synchronization features of
&lt;a href=&#34;https://isync.sourceforge.io/&#34;&gt;ISync&lt;/a&gt;. Note that ISync is the name of the
project while &lt;code&gt;mbsync&lt;/code&gt; is the name of the executable.&lt;/p&gt;
&lt;p&gt;The configuration of the program is stored in &lt;code&gt;~/.mbsyncrc&lt;/code&gt; and is based on
two main concepts: stores and channels. Stores designate location containing
emails; channels describe a link between two stores: the &amp;ldquo;far&amp;rdquo; one an
the &amp;ldquo;near&amp;rdquo; one.&lt;/p&gt;
&lt;p&gt;Let us first define the store for the Gmail account:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IMAPStore gmail
Host imap.gmail.com
Port 993
SSLType IMAPS
User &amp;lt;email-address&amp;gt;
PassCmd &amp;quot;perl -ne &#39;/^machine imap\\.gmail\\.com .*?login &amp;lt;email-address&amp;gt; .*?password (\\S+)/ &amp;amp;&amp;amp; print \&amp;quot;$1\\n\&amp;quot;&#39; ~/.netrc&amp;quot;
PipelineDepth 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While you can use simple use &lt;code&gt;Pass &amp;lt;password&amp;gt;&lt;/code&gt;, we will use &lt;code&gt;PassCmd&lt;/code&gt; to
instruct &lt;code&gt;mbsync&lt;/code&gt; to extract the password from our netrc file. I first tried
to use AWK for this purpose, but it does not support regexp capture, so I went
with Perl. Note that the login, i.e. the email address for Gmail, has to be
properly escaped in the regular expression. For example, &lt;code&gt;bob@example.com&lt;/code&gt;
must be included as &lt;code&gt;bob\\@example\\.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PipelineDepth&lt;/code&gt; controls the number of IMAP commands send in a row before
reading responses. It is recommended to use &lt;code&gt;1&lt;/code&gt; due to Gmail rate limiting.&lt;/p&gt;
&lt;p&gt;We then define the local store, i.e. a
&lt;a href=&#34;https://en.wikipedia.org/wiki/Maildir&#34;&gt;Maildir&lt;/a&gt; directory on our machine:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MaildirStore local
Path ~/mail/
Inbox ~/mail/INBOX
Subfolders Verbatim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing special here, we specify the path of the directory (careful, the final
&lt;code&gt;/&lt;/code&gt; is important), and indicate that IMAP directories are stored in Maildir
directories named the same way. At this point we can create the local
directory:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir -m 700 ~/mail
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally we define the channel:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Channel backup
Far :gmail:
Near :local:
Patterns *
Create Near
Remove Near
Expunge Near
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;Patterns&lt;/code&gt; instruction is used to indicate that we want to synchronize all
IMAP directories. We also indicate that directory creation, directory removal
and mail deletion is only performed on the &lt;code&gt;local&lt;/code&gt; store.&lt;/p&gt;
&lt;p&gt;To test that everything is correct, run &lt;code&gt;mbsync -l backup&lt;/code&gt;. If everything is
correct, &lt;code&gt;mbsync&lt;/code&gt; will list all IMAP directories which will be synchronized.&lt;/p&gt;
&lt;p&gt;To actually copy all emails, run &lt;code&gt;mbsync --pull backup&lt;/code&gt;. Since I have a
gigabit optic fiber connection, I was only limited by Google servers.
Exporting more than 20 thousands messages (1.5GB) took roughly one hour and a
half.&lt;/p&gt;
&lt;h2 id=&#34;systemd-timer&#34;&gt;Systemd timer&lt;/h2&gt;
&lt;p&gt;At this point, you could simply run &lt;code&gt;mbsync&lt;/code&gt; manually, but I am way too lazy
for that. I use Archlinux, meaning that my init system is the controversial
Systemd. While not everyone likes Systemd, it makes it easy to run periodic
tasks.&lt;/p&gt;
&lt;p&gt;First write the service file at &lt;code&gt;~/.config/systemd/user/mbsync.service&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Unit]
Description=Backup emails
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/mbsync --pull backup

[Install]
WantedBy=default.target
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then the timer itself at &lt;code&gt;~/.config/systemd/user/mbsync.timer&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Unit]
Description=Backup emails

[Timer]
OnStartupSec=5min
OnUnitActiveSec=1h

[Install]
WantedBy=timers.target
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can now use &lt;code&gt;systemctl&lt;/code&gt; to enable the service and the timer and execute it
a first time:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;systemctl --user enable mbsync.service
systemctl --user enable mbsync.timer
systemctl --user start mbsync
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The local Maildir will now be updated 5 minutes after the user session
starts, and every hour after that. You can check the status of the task with
&lt;code&gt;systemctl --user status mbsync&lt;/code&gt;.&lt;/p&gt;
</description>

      
      <category>email</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/custom-font-lock-configuration-in-emacs/">
      <title>Custom Font Lock configuration in Emacs</title>
      <link>https://www.n16f.net/blog/custom-font-lock-configuration-in-emacs/</link>
      <pubDate>Fri, 24 Feb 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/custom-font-lock-configuration-in-emacs/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/elisp/Font-Lock-Mode.html&#34;&gt;Font
Lock&lt;/a&gt;
is the builtin Emacs minor mode used to highlight textual elements in buffers.
Major modes usually configure it to detect various syntaxic constructions and
attach
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/emacs/Faces.html&#34;&gt;faces&lt;/a&gt;
to them.&lt;/p&gt;
&lt;p&gt;The reason I ended up deep into Font Lock is because I was not satisfied with
the way it is configured for &lt;code&gt;lisp-mode&lt;/code&gt;, the major mode used for both Common
Lisp and Emacs Lisp code. This forced me to get acquainted with various
aspects of Font Lock in order to change its configuration. If you want to
change highlighting for your favourite major mode, you will find this article
useful.&lt;/p&gt;
&lt;h2 id=&#34;common-lisp-highlighting-done-wrong&#34;&gt;Common Lisp highlighting done wrong&lt;/h2&gt;
&lt;p&gt;The core issue of Common Lisp highlighting in Emacs is that a lot of it is
arbitrary and inconsistent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The mode highlights what it calls &amp;ldquo;definers&amp;rdquo; and &amp;ldquo;keywords&amp;rdquo;, but it does not
really make sense in Common Lisp. Why would &lt;code&gt;WITH-OUTPUT-TO-STRING&lt;/code&gt; be
listed as a keyword, but not &lt;code&gt;CLASS-OF&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SIGNAL&lt;/code&gt; uses &lt;code&gt;font-lock-warning-face&lt;/code&gt;. Why would it be a warning? Even
stranger, why would you use this warning face for &lt;code&gt;CHECK-TYPE&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Keywords and uninterned symbols are all highlighted with
&lt;code&gt;font-lock-builtin-face&lt;/code&gt;. But they are not functions or variables. They are
not even special in any way, and their syntax already indicates clearly
their nature. Having so many yellow symbols everywhere is really
distracting.&lt;/li&gt;
&lt;li&gt;All symbols starting with &lt;code&gt;&amp;amp;&lt;/code&gt; are highlighted using &lt;code&gt;font-lock-type-face&lt;/code&gt;.
But lambda list arguments are not types, and symbols starting with &lt;code&gt;&amp;amp;&lt;/code&gt; are
not always lambda list arguments.&lt;/li&gt;
&lt;li&gt;All symbols preceded by &lt;code&gt;(&lt;/code&gt; whose name starts with &lt;code&gt;DO-&lt;/code&gt; or &lt;code&gt;WITH-&lt;/code&gt; are
highlighted as keywords. There is even a comment by RMS stating that it is
too general. He is right.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Beyond these issues, the mode sadly uses default Font Lock faces instead of
defining semantically appropriate faces and mapping them to existing ones as
default values.&lt;/p&gt;
&lt;p&gt;The chances of successfully driving this kind of large and disruptive change
directly into Emacs are incredibly low. Even if it was to be accepted, the
result would not be available until the next release, which could mean months.
Fortunately, Emacs is incredibly flexible and we can change all of this
ourselves.&lt;/p&gt;
&lt;p&gt;Note that you may not agree with the list of issues above, and this is fine.
The point of this article is to show you how you can change the way Emacs
highlights content in order to match your preferences. And you can do that for
all major modes!&lt;/p&gt;
&lt;h2 id=&#34;font-lock-configuration&#34;&gt;Font Lock configuration&lt;/h2&gt;
&lt;p&gt;Font Lock always felt a bit magic and it took me some time to find the
motivation to read the documentation. As is turned out, it can be used for
very complex highlighting schemes, but basic features are not that hard to
use.&lt;/p&gt;
&lt;p&gt;The main configuration of Font Lock is stored in the &lt;code&gt;font-lock-defaults&lt;/code&gt;
buffer-local variable. It is a simple list containing the following entries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A list of symbols containing the value to use for &lt;code&gt;font-lock-keywords&lt;/code&gt; at
each
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/elisp/Levels-of-Font-Lock.html&#34;&gt;level&lt;/a&gt;,
the first symbol being the default value.&lt;/li&gt;
&lt;li&gt;The value used for &lt;code&gt;font-lock-keywords-only&lt;/code&gt;. If it is &lt;code&gt;nil&lt;/code&gt;, it enables
syntaxic highlighting (strings and comments) in addition of search-based
(keywords) highlighting.&lt;/li&gt;
&lt;li&gt;The value used for &lt;code&gt;font-lock-keywords-case-fold-search&lt;/code&gt;. If true,
highlighting is case insensitive.&lt;/li&gt;
&lt;li&gt;The value used for &lt;code&gt;font-lock-syntax-table&lt;/code&gt;, the association list
controlling syntaxic highlighting. If it is &lt;code&gt;nil&lt;/code&gt;, Font Lock uses the syntax
table configured with &lt;code&gt;set-syntax-table&lt;/code&gt;. In &lt;code&gt;lisp-mode&lt;/code&gt; this would mean
&lt;code&gt;lisp-mode-syntax-table&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;All remaining values are bindings using the form &lt;code&gt;(VARIABLE-NAME . VALUE)&lt;/code&gt;
used to set buffer-local values for other Font Lock variables.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The part we are interested about is search-based highlighting which uses
regular expressions to find specific text fragments and attach faces to them.&lt;/p&gt;
&lt;p&gt;Values used for &lt;code&gt;font-lock-keywords&lt;/code&gt; are also lists. Each element is a
construct used to specify one or more keywords to highlight. While these
constructs can have multiple forms for more complex use cases, we will only
use the two simplest ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;(REGEXP . FACE)&lt;/code&gt; tells Font Lock to use &lt;code&gt;FACE&lt;/code&gt; for text fragments which
match &lt;code&gt;REGEXP&lt;/code&gt;. For example, you could use &lt;code&gt;(&amp;quot;\\_&amp;lt;-?[0-9]+\\_&amp;gt;&amp;quot; . font-lock-constant-face)&lt;/code&gt; to highlight integers as constants (note the use
of &lt;code&gt;\_&amp;lt;&lt;/code&gt; and &lt;code&gt;\_&amp;gt;&lt;/code&gt; to match the start and end of a symbol; see the &lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/emacs/Regexp-Backslash.html&#34;&gt;regexp
documentation&lt;/a&gt;
for more information).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(REGEXP (GROUP FACE)…)&lt;/code&gt; is a bit more advanced. When &lt;code&gt;REGEXP&lt;/code&gt; matches a
subset of the buffer, Font Lock assigns faces to the capture group
identified by their number. You could use this construction to detect a
complex syntaxic element and highlight some of its parts with different
faces.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;simplified-common-lisp-highlighting&#34;&gt;Simplified Common Lisp highlighting&lt;/h2&gt;
&lt;p&gt;We are going to configure keyword highlighting for the following types of
values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Character literals, e.g. &lt;code&gt;#\Space&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Function names in the context of a function call for standard Common lisp
functions.&lt;/li&gt;
&lt;li&gt;Standard Common Lisp values such as &lt;code&gt;*STANDARD-OUTPUT*&lt;/code&gt; or &lt;code&gt;PI&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, we want to keep the default syntaxic highlighting configuration
which recognizes character strings, documentation strings and comments.&lt;/p&gt;
&lt;h3 id=&#34;faces&#34;&gt;Faces&lt;/h3&gt;
&lt;p&gt;Let us start by defining new faces for the different values we are going to
match:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defface g-cl-character-face
  &#39;((default :inherit font-lock-constant-face))
  &amp;quot;The face used to highlight Common Lisp character literals.&amp;quot;)

(defface g-cl-standard-function-face
  &#39;((default :inherit font-lock-keyword-face))
  &amp;quot;The face used to highlight standard Common Lisp function symbols.&amp;quot;)

(defface g-cl-standard-value-face
  &#39;((default :inherit font-lock-variable-name-face))
  &amp;quot;The face used to highlight standard Common Lisp value symbols.&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing complicated here, we simply inherit from default Font Lock faces. You
can then configure these faces in your color theme without affecting other
modes using Font Lock.&lt;/p&gt;
&lt;h3 id=&#34;keywords&#34;&gt;Keywords&lt;/h3&gt;
&lt;p&gt;To detect standard Common Lisp functions and values, we are going to need a
regular expression. The first step is to build a list of strings for both
functions and values. Easy to do with a bit of Common Lisp code!&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun standard-symbol-names (predicate)
  (let ((symbols nil))
    (do-external-symbols (symbol :common-lisp)
      (when (funcall predicate symbol)
        (push (string-downcase (symbol-name symbol)) symbols)))
    (sort symbols #&#39;string&amp;lt;)))
    
(standard-symbol-names #&#39;fboundp)
(standard-symbol-names #&#39;boundp)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;STANDARD-SYMBOL-NAMES&lt;/code&gt; build a list of symbols exported from the
&lt;code&gt;:COMMON-LISP&lt;/code&gt; package which satisfy a predicate. The first call gives us the
name of all symbols bound to a function, and the second all which are bound to
a value.&lt;/p&gt;
&lt;p&gt;The astute reader will immediately wonder about symbols which are bound both a
function and a value. They are easy to find by calling &lt;code&gt;INTERSECTION&lt;/code&gt; on both
sets of names: &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;. It is not really a problem: we can
highlight function calls by matching function names preceded by &lt;code&gt;(&lt;/code&gt;, making
sure that these symbols will be correctly identified as either function
symbols or value symbols depending on the context.&lt;/p&gt;
&lt;p&gt;We store these lists of strings in the &lt;code&gt;g-cl-function-names&lt;/code&gt; and
&lt;code&gt;g-cl-value-names&lt;/code&gt; (the associated code is not reproduced here: these lists
are quite long; but I posted them as a
&lt;a href=&#34;https://gist.github.com/galdor/1c30c29471045d0365af72a4caf7b1f2&#34;&gt;Gist&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;With this lists, we can use the &lt;code&gt;regexp-opt&lt;/code&gt; Emacs Lisp function to build
optimized regular expressions matching them:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defvar g-cl-font-lock-keywords
  (let* ((character-re (concat &amp;quot;#\\\\&amp;quot; lisp-mode-symbol-regexp &amp;quot;\\_&amp;gt;&amp;quot;))
         (function-re (concat &amp;quot;(&amp;quot; (regexp-opt g-cl-function-names t) &amp;quot;\\_&amp;gt;&amp;quot;))
         (value-re (regexp-opt g-cl-value-names &#39;symbols)))
    `((,character-re . &#39;g-cl-character-face)
      (,function-re
       (1 &#39;g-cl-standard-function-face))
      (,value-re . &#39;g-cl-standard-value-face))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Characters literals are reasonably easy to match.&lt;/p&gt;
&lt;p&gt;Functions are a bit more complicated since we want to match the function name
when it is preceded by an opening parenthesis. We use a capture capture (see
the last argument of &lt;code&gt;regexp-opt&lt;/code&gt;) for the function name and highlight it
separately.&lt;/p&gt;
&lt;p&gt;Values are always matched as full symbols: we do not want to highlight parts
of a symbol, for example &lt;code&gt;MAP&lt;/code&gt; in a symbol named &lt;code&gt;MAPPING&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;final-configuration&#34;&gt;Final configuration&lt;/h3&gt;
&lt;p&gt;Finally we can define the variable which will be used for &lt;code&gt;font-lock-defaults&lt;/code&gt;
in the initialization hook; we copy the original value from &lt;code&gt;lisp-mode&lt;/code&gt;, and
change the keyword list for what is going to be our own configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defvar g-cl-font-lock-defaults
  &#39;((g-cl-font-lock-keywords)
    nil                                 ; enable syntaxic highlighting
    t                                   ; case insensitive highlighting
    nil                                 ; use the lisp-mode syntax table
    (font-lock-mark-block-function . mark-defun)
    (font-lock-extra-managed-props help-echo)
	(font-lock-syntactic-face-function
	 . lisp-font-lock-syntactic-face-function)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To configure &lt;code&gt;font-lock-defaults&lt;/code&gt;, we simply set it in the initialization hook
of &lt;code&gt;lisp-mode&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-init-lisp-font-lock ()
  (setq font-lock-defaults g-cl-font-lock-defaults))
  
(add-hook &#39;lisp-mode-hook &#39;g-init-lisp-font-lock)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;comparison&#34;&gt;Comparison&lt;/h2&gt;
&lt;p&gt;Let us compare highlighting for a fragment of code before and after our
changes:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./before.png&#34; alt=&#34;Before&#34;&gt;
&lt;img src=&#34;./after.png&#34; alt=&#34;After&#34;&gt;&lt;/p&gt;
&lt;p&gt;The differences are subtle but important:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All standard functions are highlighted, helping to distinguish them from
user-defined functions.&lt;/li&gt;
&lt;li&gt;Standard values such as &lt;code&gt;*ERROR-OUTPUT*&lt;/code&gt; are highlighted.&lt;/li&gt;
&lt;li&gt;Character literals are highlighted the same way as character strings.&lt;/li&gt;
&lt;li&gt;Keywords are not highlighted anymore, avoiding the confusion with function
names.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;That was not easy; but as always, the effort of going through the
documentation and experimenting with different Emacs components was very
rewarding. Font Lock does not feel like a black box anymore, opening the road
for the customization of other major modes.&lt;/p&gt;
&lt;p&gt;In the future, I will work on a custom color scheme to use more subtle colors,
with the hope of reducing the rainbow effect of so many major modes, including
&lt;code&gt;lisp-mode&lt;/code&gt;.&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/common-lisp-implementations-in-2023/">
      <title>Common Lisp implementations in 2023</title>
      <link>https://www.n16f.net/blog/common-lisp-implementations-in-2023/</link>
      <pubDate>Wed, 22 Feb 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/common-lisp-implementations-in-2023/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;Much has been written on Common Lisp; there is rarely one year without someone
proclaming the death of the language and how nobody uses it anymore. And yet
it is still here, so something must have been done right.&lt;/p&gt;
&lt;p&gt;Common Lisp is not a software, it is a language described by the ANSI INCITS
226-1994 standard; there are multiple implementations available, something
often used as argument for how alive and thriving the language is.&lt;/p&gt;
&lt;p&gt;Let us see what the 2023 situation is.&lt;/p&gt;
&lt;h2 id=&#34;general-information&#34;&gt;General information&lt;/h2&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Implementation&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;License&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Target&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Last release&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;http://sbcl.org/&#34;&gt;SBCL&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Public domain&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Native&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2023/01 (2.3.1)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://ccl.clozure.com/&#34;&gt;CCL&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Apache 2.0&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Native&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2021/05 (1.12.1)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://ecl.common-lisp.dev/&#34;&gt;ECL&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;LGPL 2.1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Native (C translation)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2021/02 (21.2.1)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://abcl.org/&#34;&gt;ABCL&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;GPL2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Java bytecode&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2023/02 (1.9.1)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://clasp-developers.github.io&#34;&gt;CLASP&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;LGPL 2.1&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Native (LLVM)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2023/01 (2.1.0)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://www.cons.org/cmucl/&#34;&gt;CMUCL&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Public domain&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Native&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2017/10 (21c)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://www.gnu.org/software/gcl/&#34;&gt;GCL&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;LGPL2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Native (C translation)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2023/01 (2.6.14)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://clisp.sourceforge.io/&#34;&gt;CLISP&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;GPL&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Bytecode&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2010/07 (2.49)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;http://www.lispworks.com/&#34;&gt;Lispworks&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Proprietary&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Native&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2022/06 (8.0.1)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://franz.com/products/allegro-common-lisp/&#34;&gt;Allegro&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Proprietary&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Native&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;2017/04 (10.1)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Note that all projects may have small parts with different licenses. This is
particularily important for CLASP which contains multiple components imported
from other projects.&lt;/p&gt;
&lt;p&gt;I was quite surprised to see so many projects with recent releases. Clearly a
good sign. Let us look at each implementation.&lt;/p&gt;
&lt;h2 id=&#34;implementations&#34;&gt;Implementations&lt;/h2&gt;
&lt;h3 id=&#34;sbcl&#34;&gt;SBCL&lt;/h3&gt;
&lt;p&gt;Steel Bank Common Lisp was forked from CMUCL in December 1999 and has since
massively grown in popularity; it is currently the most used implementation by
far. Unsurprisingly given its popularity, SBCL is supported by pretty much all
Common Lisp libraries and tools out there. It is well known for generating
fast native code compared to other implementations.&lt;/p&gt;
&lt;p&gt;The most important aspect of SBCL is that it is actively maintained: its
developers release new versions on a monthly basis, bringing each time a small
list of improvements and bug fixes. Activity has actually increased these last
years, something uncommon in the Common Lisp world.&lt;/p&gt;
&lt;h3 id=&#34;ccl&#34;&gt;CCL&lt;/h3&gt;
&lt;p&gt;Clozure Common Lisp has a long and complex
&lt;a href=&#34;https://ccl.clozure.com/history.html&#34;&gt;history&lt;/a&gt; and has been around for
decades. It is a mature implementation; it has two interesting aspects
compared to SBCL:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The compiler is much faster.&lt;/li&gt;
&lt;li&gt;Error messages tend to be clearer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is why I currently use it to test my code along SBCL. And according to
what I have heard, this is a common choice among developers.&lt;/p&gt;
&lt;p&gt;The main issue with CCL is that the project is almost completely abandonned.
&lt;a href=&#34;https://github.com/Clozure/ccl/graphs/contributors&#34;&gt;Git activity&lt;/a&gt; has slowed
down to a crawl in the last two years, and none of the original maintainers
from Clozure seem to be actively working on it. It remains nonetheless a major
implementation.&lt;/p&gt;
&lt;h3 id=&#34;ecl&#34;&gt;ECL&lt;/h3&gt;
&lt;p&gt;Embeddable Common Lisp is a small implementation which can be used both as a
library or as a standalone program. It contains a bytecode interpreter, but
can also translate Lisp code to C to be compiled to native code.&lt;/p&gt;
&lt;p&gt;While development is slow, improvements and bug fixes are still added on a
regular basis. Clearly an interesting project: I could see myself using ECL to
write plugins into an application able to call a C library.&lt;/p&gt;
&lt;h3 id=&#34;abcl&#34;&gt;ABCL&lt;/h3&gt;
&lt;p&gt;Armed Bear Common Lisp is quite different from other implementations: it
produces Java bytecode and targets the Java Virtual Machine, making it a
useful tool in Java ecosystems.&lt;/p&gt;
&lt;p&gt;While it has not found the same success as &lt;a href=&#34;https://clojure.org/&#34;&gt;Clojure&lt;/a&gt;,
ABCL is still a fully featured Common Lisp implementation which passes almost
the entire ANSI Common Lisp test suite.&lt;/p&gt;
&lt;p&gt;Developement is slow nowadays but there are still new releases with lots of
bug fixes. Also note that two of the developers are able to provide paid
support.&lt;/p&gt;
&lt;h3 id=&#34;clasp&#34;&gt;CLASP&lt;/h3&gt;
&lt;p&gt;CLASP is a newcomer in the Common Lisp world (new meaning it is less than a
decade old). Developed by Christian Schafmeister for his research work, this
implementation has been used as an exemple of how alive and kicking Common
Lisp, mainly due to two
&lt;a href=&#34;https://www.youtube.com/watch?v=8X69_42Mj-g&#34;&gt;excellent&lt;/a&gt;
&lt;a href=&#34;https://www.youtube.com/watch?v=mbdXeRBbgDM&#34;&gt;presentations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While very promising, CLASP suffers from its young age: trying to run the last
release on my code resulted in a brutal error with no details and no
backtrace. However I have no doubt that CLASP will get a lot better: it is
actively maintained and used in production, two of the necessary ingredients
for a software to stay relevant.&lt;/p&gt;
&lt;h3 id=&#34;gcl&#34;&gt;GCL&lt;/h3&gt;
&lt;p&gt;GNU Common Lisp is described as the official Common Lisp implementation for
the GNU project. While it clearly does not have the popularity of other
implementations, it is still a maintained project.&lt;/p&gt;
&lt;p&gt;Trying to use it, I quickly realized it is not fully compliant with the
standard. For example it will fail when evaluating a call to &lt;code&gt;COMPILE-FILE&lt;/code&gt;
with the &lt;code&gt;:VERBOSE&lt;/code&gt; key argument.&lt;/p&gt;
&lt;p&gt;Hopefully development will continue.&lt;/p&gt;
&lt;h3 id=&#34;clisp&#34;&gt;CLISP&lt;/h3&gt;
&lt;p&gt;CLISP is almost as old as I am; it was the first implementation I used a long
time ago, and it still works. While it has all the usual features
(multithreading, FFI, MOP, etc.), there is no real reason to use it compared
to other implementations.&lt;/p&gt;
&lt;p&gt;Even if it was to have any specific feature, CLISP is almost completely
abandonned. While there are has been a semblant of activity a few years ago,
active development pretty much stopped around 2012; the last release was more
than 12 years ago.&lt;/p&gt;
&lt;h3 id=&#34;lispworks&#34;&gt;Lispworks&lt;/h3&gt;
&lt;p&gt;Moving to proprietary implementations; Lispworks has been around for more than
30 years and the company producing it still release new versions on a regular
basis.&lt;/p&gt;
&lt;p&gt;While Lispworks supports most features you would expect from a commercial
product (native compiler, multithreading, FFI, GUI library, various graphical
tools, a Prolog implementation…), it is hampered by its licensing system.&lt;/p&gt;
&lt;p&gt;The free &amp;ldquo;Personal Edition&amp;rdquo; limits the program size and the amount of time it
can run, making it pretty much useless for anything but evaluation. The
professional and enterprise licenses do not really make sense for anyone: you
will have to buy separate licenses for every single platform at more than a
thousand euros per license (with the enterprise version being 2-3 times more
expensive). Of course you will have to buy a maintenance contract on a yearly
basis… but it does not include technical support. It will have to be bought
with &amp;ldquo;incident packs&amp;rdquo; costing thousands of euros; because yes, paying for a
product and a maintenance contract does not mean they will fix bugs, and you
will have to pay for each of them.&lt;/p&gt;
&lt;p&gt;I do not have anything personal against commercial software, and I strongly
support developers being paid for their work. But this kind of licensing makes
Lispworks irrelevant to everyone but those already using their proprietary
libraries.&lt;/p&gt;
&lt;h3 id=&#34;allegro&#34;&gt;Allegro&lt;/h3&gt;
&lt;p&gt;Allegro Common Lisp is the other well known proprietary implementation.
Developped by Franz Inc., it is apparently used by multiple organizations
including the U.S. Department of Defense.&lt;/p&gt;
&lt;p&gt;Releases are uncommon, the last one being almost 6 years ago. But Allegro is a
mature implementation packed with features not easily replicated such as
&lt;a href=&#34;https://franz.com/products/allegrocache/index.lhtml&#34;&gt;AllegroCache&lt;/a&gt;,
&lt;a href=&#34;https://franz.com/products/web_tools/&#34;&gt;AllegroServe&lt;/a&gt;, libraries for multiple
protocols and data formats, analysis tools, a concurrent garbage collector and
even an OpenGL interface.&lt;/p&gt;
&lt;p&gt;Allegro suffers the same issue as Lispworks: the enterprise-style pricing
system is incredibly frustrating. The website advertises a hefty $599 starting
price (which at least includes technical support), but there is no mention of
what it contains. Interested developpers will have to contact Franz Inc. to
get other prices. A quick Google search will reveal rumours of enterprise
versions priced above 8000 dollars. No comment.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Researching Common Lisp implementations has been interesting. While it is
clear that the language is far from dead, its situation is very fragile.
Proprietary implementations are completely out of touch with the needs of most
developers, leaving us with a single open source, actively maintained, high
performance implementation: SBCL. Unless of course they are willing to deal
with the JVM to use ABCL.&lt;/p&gt;
&lt;p&gt;It might me interesting to investigate a possible solution to keep CCL somehow
alive, with patches being merged and releases being produced. I sent a patch
very recently, let us see what can be done!&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/reading-files-faster-in-common-lisp/">
      <title>Reading files faster in Common Lisp</title>
      <link>https://www.n16f.net/blog/reading-files-faster-in-common-lisp/</link>
      <pubDate>Wed, 15 Feb 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/reading-files-faster-in-common-lisp/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;While Common Lisp has functions to open, read and write files, none of them
takes care of reading and returning the entire content. This is something that
I do very regularly, so it made sense to add such a function to
&lt;a href=&#34;https://github.com/galdor/tungsten&#34;&gt;Tungsten&lt;/a&gt;. It turned out to be a bit more
complicated than expected.&lt;/p&gt;
&lt;h1 id=&#34;a-simple-but-incorrect-implementation&#34;&gt;A simple but incorrect implementation&lt;/h1&gt;
&lt;p&gt;The simplest implementation relies on the &lt;code&gt;FILE-LENGTH&lt;/code&gt; function which returns
the length of a stream (which of course only makes sense for a file stream).
The
&lt;a href=&#34;http://www.lispworks.com/documentation/HyperSpec/Body/f_file_l.htm&#34;&gt;Hyperspec&lt;/a&gt;
clearly states that &amp;ldquo;for a binary file, the length is measured in units of the
element type of the stream&amp;rdquo;. Since we are only reading binary data, everything
is fine.&lt;/p&gt;
&lt;p&gt;Let us write the function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun read-file (path)
  (declare (type (or pathname string) path))
  (with-open-file (file path :element-type &#39;core:octet)
    (let ((data (make-array (file-length file) :element-type &#39;core:octet)))
      (read-sequence data file)
      data)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that &lt;code&gt;CORE:OCTET&lt;/code&gt; is a Tungsten type for &lt;code&gt;(UNSIGNED-BYTE 8)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The function works as expected, returning the content of the file as an octet
vector. But it is not entirely correct.&lt;/p&gt;
&lt;p&gt;This implementation only works for regular files. Various files on UNIX will
report a length of zero but can still be read. Now you might protest that it
would not make sense to call &lt;code&gt;READ-FILE&lt;/code&gt; on a device such as &lt;code&gt;/dev/urandom&lt;/code&gt;,
and you would be right. But a valid example would be pseudo files such as
those part of &lt;a href=&#34;https://docs.kernel.org/filesystems/proc.html&#34;&gt;&lt;code&gt;procfs&lt;/code&gt;&lt;/a&gt;. If
you want to obtain memory stats about your process on Linux, you can simply
read &lt;code&gt;/proc/self/statm&lt;/code&gt;. But this is not a regular file and &lt;code&gt;READ-FILE&lt;/code&gt; will
return an empty octet vector.&lt;/p&gt;
&lt;h1 id=&#34;doing-it-right-and-slow&#34;&gt;Doing it right and slow&lt;/h1&gt;
&lt;p&gt;The right way to read a file is to read its content block by block until the
read operation fails because it reached the end of the file.&lt;/p&gt;
&lt;p&gt;Let us re-write &lt;code&gt;READ-FILE&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun read-file (path)
  (declare (type (or pathname string) path))
  (let ((data (make-array 0 :element-type &#39;core:octet :adjustable t))
        (block-size 4096)
        (offset 0))
    (with-open-file (file path :element-type &#39;core:octet)
      (loop
        (let* ((capacity (array-total-size data))
               (nb-left (- capacity offset)))
          (when (&amp;lt; nb-left block-size)
            (let ((new-length (+ capacity (- block-size nb-left))))
              (setf data (adjust-array data new-length)))))
        (let ((end (read-sequence data file :start offset)))
          (when (= end offset)
            (return-from read-file (adjust-array data end)))
          (setf offset end))))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This time we rely on an adjustable array; we iterate, making sure we have
enough space in the array to read an entire block each time. When the array is
too short, we use &lt;code&gt;ADJUST-ARRAY&lt;/code&gt; to extend it, relying on its ability to reuse
the underlying storage instead of systematically copying its content.&lt;/p&gt;
&lt;p&gt;Finally, once &lt;code&gt;READ-SEQUENCE&lt;/code&gt; stops returning data, we truncate the array to
the right size and return it.&lt;/p&gt;
&lt;p&gt;This function worked correctly and I started using it regularly. Recently I
started working with a file larger than usual and realized that &lt;code&gt;READ-FILE&lt;/code&gt;
was way too slow. With a NVMe drive, I would expect to be able to read a 10+MB
file almost instantaneously, but it took several seconds.&lt;/p&gt;
&lt;p&gt;After inspecting the code to find what could be so slow, I started to wonder
about &lt;code&gt;ADJUST-ARRAY&lt;/code&gt;; while I thought SBCL would internally extend the
underlying memory in large blocks to minimize allocations, behaving similarly
to &lt;code&gt;realloc()&lt;/code&gt; in C, it turned out not to be the case. While reading the code
behind &lt;code&gt;ADJUST-ARRAY&lt;/code&gt;, I learned that it precisely allocates the required
size. As a result, this implementation of &lt;code&gt;READ-FILE&lt;/code&gt; performs one memory
allocation for each 4kB block. Not a problem for small files, slow for larger
ones.&lt;/p&gt;
&lt;h1 id=&#34;a-final-version-correct-and-fast&#34;&gt;A final version, correct and fast&lt;/h1&gt;
&lt;p&gt;Since I understood what the problem was, fixing it was trivial. When there is
not enough space to read a block, we extend the array by at least 50% of its
current size. Of course this is a balancing act: for example doubling the size
at each allocation would reduce even more the number of allocations, but would
increase the total amount of memory allocated. The choice is up to you.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun read-file (path)
  (declare (type (or pathname string) path))
  (let ((data (make-array 0 :element-type &#39;core:octet :adjustable t))
        (block-size 4096)
        (offset 0))
    (with-open-file (file path :element-type &#39;core:octet)
      (loop
        (let* ((capacity (array-total-size data))
               (nb-left (- capacity offset)))
          (when (&amp;lt; nb-left block-size)
            (let ((new-length (max (+ capacity (- block-size nb-left))
                                   (floor (* capacity 3) 2))))
              (setf data (adjust-array data new-length)))))
        (let ((end (read-sequence data file :start offset)))
          (when (= end offset)
            (return-from read-file (adjust-array data end)))
          (setf offset end))))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This last version reads a 250MB file in a quarter of a second, while the
original version took almost two minutes. Much better!&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/templating-in-emacs-with-tempo/">
      <title>Templating in Emacs with Tempo</title>
      <link>https://www.n16f.net/blog/templating-in-emacs-with-tempo/</link>
      <pubDate>Sun, 12 Feb 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/templating-in-emacs-with-tempo/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I have used text editors for more than 20 years; in all that time, I have
never used a templating system to generate content because copy pasting and
replacing always felt good enough. I recently decided to give it a try.&lt;/p&gt;
&lt;p&gt;In Emacs it is hard to talk about templating without mentionning
&lt;a href=&#34;https://github.com/joaotavora/yasnippet&#34;&gt;YASnippet&lt;/a&gt;. Developped by the
prolific João Távora, who also developped
&lt;a href=&#34;https://github.com/joaotavora/eglot&#34;&gt;Eglot&lt;/a&gt;, YASnippet lets you write
templates as text documents.&lt;/p&gt;
&lt;p&gt;But while I was researching the subject, I found out that Emacs already had
two builtin templating modules:
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/autotype/Skeleton-Language.html&#34;&gt;Skeleton&lt;/a&gt;
and
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/autotype/Tempo.html&#34;&gt;Tempo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Tempo looked simpler, so I decided to give it a chance.&lt;/p&gt;
&lt;h2 id=&#34;using-tempo&#34;&gt;Using Tempo&lt;/h2&gt;
&lt;p&gt;Tempo templates are functions defined with &lt;code&gt;tempo-define-template&lt;/code&gt;. The
content to be inserted is a S-expression containing various kinds of elements
which control the insertion process.&lt;/p&gt;
&lt;p&gt;As an example, let us define a template to insert a HTML figure.&lt;/p&gt;
&lt;p&gt;First we define a variable to store a list of templates. When using
&lt;code&gt;html-mode&lt;/code&gt;, we instruct Tempo to use it.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defvar g-html-tempo-tags nil)

(defun g-init-html-tempo-templates ()
  (tempo-use-tag-list &#39;g-html-tempo-tags))

(add-hook &#39;html-mode-hook &#39;g-init-html-tempo-templates)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we define the template itself:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(tempo-define-template
 &amp;quot;g-html-figure&amp;quot;
 &#39;(&amp;quot;&amp;lt;figure&amp;gt;&amp;quot; n
   &amp;gt; &amp;quot;&amp;lt;img src=\&amp;quot;&amp;quot; (p &amp;quot;URI: &amp;quot;) &amp;quot;\&amp;quot;&amp;gt;&amp;quot; n
   &amp;gt; &amp;quot;&amp;lt;figcaption&amp;gt;&amp;quot; (p &amp;quot;Caption: &amp;quot;) &amp;quot;&amp;lt;/figcaption&amp;gt;&amp;quot; n
   &amp;quot;&amp;lt;/figure&amp;gt;&amp;quot;)
 &amp;quot;figure&amp;quot;
 &amp;quot;a figure containing an image and caption&amp;quot;
 &#39;g-html-tempo-tags)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This form creates a function named &lt;code&gt;tempo-template-g-html-figure&lt;/code&gt;. When it is
called, Tempo processes elements of the template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Strings are inserted in the buffer.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;n&lt;/code&gt; symbol causes the insertion of a new line character&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;&amp;gt;&lt;/code&gt; symbol tells Emacs to indent the current line according to the rules
of the major mode of the buffer.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;p&lt;/code&gt; forms cause Tempo to ask the user for values to insert. Note that
you need to set &lt;code&gt;tempo-interative&lt;/code&gt; to &lt;code&gt;t&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that Tempo supports more elements; refer to the documentation string of
&lt;code&gt;tempo-define-template&lt;/code&gt; for more information.&lt;/p&gt;
&lt;p&gt;The template is associated to the &lt;code&gt;figure&lt;/code&gt; text tag which will be used for
completion. We also add a description, and finally add the template to the
&lt;code&gt;g-html-tempo-tags&lt;/code&gt; list. Note that these three last arguments are optional.&lt;/p&gt;
&lt;h2 id=&#34;tag-matching&#34;&gt;Tag matching&lt;/h2&gt;
&lt;p&gt;Of course we do not have to call the template manually. When we call
&lt;code&gt;tempo-complete-tag&lt;/code&gt;, Tempo uses the string before the cursor to decide which
template to insert. Open a HTML buffer, type &lt;code&gt;figure&lt;/code&gt; and execute
&lt;code&gt;tempo-complete-tag&lt;/code&gt; (I bind it to &lt;code&gt;M-S-&amp;lt;tab&amp;gt;&lt;/code&gt;): Tempo will automatically
insert our template.&lt;/p&gt;
&lt;p&gt;Tempo will handle the case where there is partial match for multiple
templates and will spawn a completion buffer.&lt;/p&gt;
&lt;p&gt;Now it would make sense to use &lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt; as tag. To do so, update the
&lt;code&gt;g-init-html-tempo-templates&lt;/code&gt; function to set the local variable that Tempo
uses to detect a tag:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq tempo-match-finder &amp;quot;\\(&amp;lt;[a-z]+&amp;gt;\\)\\=&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Doing so will use HTML tags as Tempo tags. We can then alter the call to
&lt;code&gt;tempo-define-template&lt;/code&gt; to use &lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt; as tag, and from now on use it for
template insertion.&lt;/p&gt;
&lt;p&gt;Of course this means we can customize it to allow different formats of Tempo
tags depending on the major mode we are in. Handy.&lt;/p&gt;
&lt;h2 id=&#34;writing-a-template-selector&#34;&gt;Writing a template selector&lt;/h2&gt;
&lt;p&gt;Calling template functions manually is unpractical and tag completion requires
remembering which tags have been defined. My interface of choice would be a
simple key spawning an incremental completion buffer
(&lt;a href=&#34;https://github.com/emacs-helm/helm&#34;&gt;Helm&lt;/a&gt; in my case) to let me select a
template to insert.&lt;/p&gt;
&lt;p&gt;As it turns out, it is not that hard:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-insert-tempo-template ()
  (interactive)
  (let* ((tags-data
          (mapcar (lambda (entry)
                    (let ((function (cdr entry)))
                      (list function (documentation function))))
                  (tempo-build-collection)))
         (completion-extra-properties
          `(:annotation-function
            (lambda (string)
              (let* ((data (alist-get string minibuffer-completion-table
                                      nil nil #&#39;string=))
                     (description (car data)))
                (format &amp;quot;  %s&amp;quot; description)))))
         (function-name (completing-read &amp;quot;Template: &amp;quot; tags-data))
         (function (intern function-name)))
    (funcall function)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we have already seen in &lt;a href=&#34;posts/2023-01-12-switching-between-implementations-with-slime&#34;&gt;a previous
post&lt;/a&gt;,
&lt;code&gt;completing-read&lt;/code&gt; is quite limited in terms of presentation. I will probably
spend some time switching from Helm to a mix of
&lt;a href=&#34;https://github.com/minad/vertico&#34;&gt;Vertico&lt;/a&gt; and
&lt;a href=&#34;https://github.com/minad/marginalia&#34;&gt;Marginalia&lt;/a&gt; which apparently offers more
options.&lt;/p&gt;
&lt;p&gt;This will do the job in the mean time.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Tempo is reasonably satisfying. While it is a very simple module, it lets me
define templates as Emacs Lisp expressions, associate them to tags and store
them in tag lists which can be used in the major modes of my choice.&lt;/p&gt;
&lt;p&gt;I do not expect to start using dozens of tiny templates for the simplest
constructions, but Tempo is going to help with recurrent complex constructions
such as &lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/elisp/Simple-Packages.html&#34;&gt;Emacs module
skeletons&lt;/a&gt;
or Common Lisp &lt;a href=&#34;https://asdf.common-lisp.dev/asdf/The-defsystem-form.html&#34;&gt;system
definitions&lt;/a&gt;.&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/decluttering-dired-for-peace-of-mind/">
      <title>Decluttering Dired for peace of mind</title>
      <link>https://www.n16f.net/blog/decluttering-dired-for-peace-of-mind/</link>
      <pubDate>Fri, 03 Feb 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/decluttering-dired-for-peace-of-mind/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html&#34;&gt;Dired&lt;/a&gt;
is an Emacs mode providing an interactive interface to navigate and manipulate
files. It took me a while to start using it, but it is so efficient that I now
spend more time in it than in my usual shell.&lt;/p&gt;
&lt;p&gt;However I am no fond of the way files are listed. Dired displays a lot of
information which is — at least for me — rarely used. As a result the
important content (the name of the file) is flushed to the right of the
window, often leading to unpractical line wrapping.&lt;/p&gt;
&lt;p&gt;It is hard to find what you are searching for in this kind of interface:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./dired-default-view.png&#34; alt=&#34;Dired default view&#34;&gt;&lt;/p&gt;
&lt;p&gt;So I decided to spend some time improving my Dired experience.&lt;/p&gt;
&lt;h2 id=&#34;configuring-a-simpler-view&#34;&gt;Configuring a simpler view&lt;/h2&gt;
&lt;p&gt;Dired comes with the &lt;code&gt;dired-hide-details-mode&lt;/code&gt; minor mode which hides extra
information. By default it is activated with the &lt;code&gt;(&lt;/code&gt; key.&lt;/p&gt;
&lt;p&gt;It has two drawbacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First it also hides the display of symbolic link target while still showing
the &lt;code&gt;-&amp;gt;&lt;/code&gt; marker after the link. This behaviour can be changed by setting the
&lt;code&gt;dired-hide-details-hide-symlink-targets&lt;/code&gt; variable to &lt;code&gt;nil&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Second, Dired disables this minor mode each time you move to a different
directory, which is really annoying&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We create a &lt;code&gt;g-dired-minimal-view&lt;/code&gt; variable to store the current state. When
then write two functions: one to either enable or disable the minor mode
depending on the state, called by the &lt;code&gt;dired-mode-hook&lt;/code&gt;, and one to switch
between simple and extended view bound to the more accessible &lt;code&gt;&amp;lt;tab&amp;gt;&lt;/code&gt; key.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq g-dired-minimal-view t)

(defun g-dired-setup-view ()
  (dired-hide-details-mode (if g-dired-minimal-view 1 -1)))

(defun g-dired-switch-view ()
  (interactive)
  (setq g-dired-minimal-view (not g-dired-minimal-view))
  (g-dired-setup-view))

(use-package dired
  :config
  (setq dired-hide-details-hide-symlink-targets nil)

  :hook
  ((dired-mode-hook . g-dired-setup-view))

  :bind
  (:map dired-mode-map
        (&amp;quot;&amp;lt;tab&amp;gt;&amp;quot; . g-dired-switch-view)))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;a-better-extended-view&#34;&gt;A better extended view&lt;/h2&gt;
&lt;p&gt;While I prefer the simple view by default, the extended view still has its
use; but I find it hard to read:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The traditional representations of permissions takes a lot of horizontal
space, the 4 digit octal value would be shorter.&lt;/li&gt;
&lt;li&gt;The number of links is not really useful.&lt;/li&gt;
&lt;li&gt;The size of the file would be more convenient in a human readable format.&lt;/li&gt;
&lt;li&gt;The date and time uses an irregular US-style format which is either &amp;ldquo;month
day year&amp;rdquo; or &amp;ldquo;month day hour:minute&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To list files, Dired call the &lt;code&gt;ls&lt;/code&gt; program with a list of options (defined by
the &lt;code&gt;dired-listing-switches&lt;/code&gt; variable), insert the output in the buffer and
rely on regular expressions to extract information. This means that we have
very little control on formatting. We can change the options passed to &lt;code&gt;ls&lt;/code&gt;,
but we have to be careful not to break Dired features. For example, Dired can
highlight files with specific permissions, but rely on a regular expression
based on the format used by &lt;code&gt;ls&lt;/code&gt;, so we cannot change the permission column.&lt;/p&gt;
&lt;p&gt;First we use &lt;code&gt;dired-listing-switches&lt;/code&gt; to add the &lt;code&gt;-h&lt;/code&gt; (for human-readable
sizes) and &lt;code&gt;--time-style=long-iso&lt;/code&gt; option. Since these options are only
available for the GNU version of &lt;code&gt;ls&lt;/code&gt;, I will have to add platform detection
for FreeBSD support in a way that works when Dired is running with
&lt;a href=&#34;https://www.gnu.org/software/tramp/&#34;&gt;TRAMP&lt;/a&gt;. Something for another day.&lt;/p&gt;
&lt;p&gt;Then we add a &lt;code&gt;dired-after-readin-hook&lt;/code&gt; hook which is called by Dired after
the output of &lt;code&gt;ls&lt;/code&gt; has been collected and inserted in the buffer. In this
hook, we iterate on lines and process them. We highlight metadata with the
&lt;code&gt;shadow&lt;/code&gt; face to keep them visually distinct from the filename, and we hide
the link count column using the &lt;code&gt;invisible&lt;/code&gt; text property so that the text
stays in the buffer, making sure not to break Dired features.&lt;/p&gt;
&lt;p&gt;Finally we disable wrapping with a hook.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-dired-postprocess-ls-output ()
  &amp;quot;Postprocess the list of files printed by the ls program when
executed by Dired.&amp;quot;
  (save-excursion
    (goto-char (point-min))
    (while (not (eobp))
      ;; Go to the beginning of the next line representing a file
      (while (null (dired-get-filename nil t))
        (dired-next-line 1))
      (beginning-of-line)
      ;; Narrow to the line and process it
      (let ((start (line-beginning-position))
            (end (line-end-position)))
        (save-restriction
          (narrow-to-region start end)
          (setq inhibit-read-only t)
          (unwind-protect
              (g-dired-postprocess-ls-line)
            (setq inhibit-read-only nil))))
      ;; Next line
      (dired-next-line 1))))

(defun g-dired-disable-line-wrapping ()
  (setq truncate-lines t))

(defun g-dired-postprocess-ls-line ()
  &amp;quot;Postprocess a single line in the ls output, i.e. the information
about a single file. This function is called with the buffer
narrowed to the line.&amp;quot;
  ;; Highlight everything but the filename
  (when (re-search-forward directory-listing-before-filename-regexp nil t 1)
    (add-text-properties (point-min) (match-end 0) &#39;(font-lock-face shadow)))
  ;; Hide the link count
  (beginning-of-line)
  (when (re-search-forward &amp;quot; +[0-9]+&amp;quot; nil t 1)
    (add-text-properties (match-beginning 0) (match-end 0) &#39;(invisible t))))

(use-package dired
  :config
  (setq dired-listing-switches &amp;quot;-alh --time-style=long-iso&amp;quot;)

  :hook
  ((dired-mode-hook . g-dired-disable-line-wrapping)
   (dired-after-readin-hook . g-dired-postprocess-ls-output)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Much better now!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./dired-extended-view.png&#34; alt=&#34;Dired extended view&#34;&gt;&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/using-units-in-emacs-calc/">
      <title>Using units in Emacs Calc</title>
      <link>https://www.n16f.net/blog/using-units-in-emacs-calc/</link>
      <pubDate>Sat, 28 Jan 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/using-units-in-emacs-calc/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I was recently reminded of the ability of &lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_mono/calc.html&#34;&gt;Emacs
Calc&lt;/a&gt; to
perform computations on values with units. Like so many Emacs features, it was
on the list of the things I wanted to explore. Today is the day to do so!&lt;/p&gt;
&lt;h2 id=&#34;basic-operations-with-units&#34;&gt;Basic operations with units&lt;/h2&gt;
&lt;p&gt;The Emacs Calc manual presents a lot of features but makes it hard to
understand how to start. You cannot just enter an expression such as &amp;ldquo;25mm&amp;rdquo; in
&lt;code&gt;calc-mode&lt;/code&gt;: 25 will be correctly interpreted as a number, but &amp;ldquo;mm&amp;rdquo; will be
used to trigger the &lt;code&gt;m m&lt;/code&gt; key binding which executes &lt;code&gt;calc-save-modes&lt;/code&gt;. Not
what you had in mind.&lt;/p&gt;
&lt;p&gt;To enter a value with a unit, use the &lt;code&gt;&#39;&lt;/code&gt; (apostrophe) key to enter an
algebraic expression and hit &lt;code&gt;return&lt;/code&gt; to push it on the stack. You can now use
this value for your computations.&lt;/p&gt;
&lt;p&gt;Note that after hitting &lt;code&gt;&#39;&lt;/code&gt;, you can use it a second time to recall the
expression on the stack and edit it.&lt;/p&gt;
&lt;p&gt;To remove the unit associated with a value. Simply hit &lt;code&gt;u r&lt;/code&gt;, for &amp;ldquo;&lt;strong&gt;u&lt;/strong&gt;nit
&lt;strong&gt;r&lt;/strong&gt;emove&amp;rdquo;.&lt;/p&gt;
&lt;h3 id=&#34;simplifying-expressions&#34;&gt;Simplifying expressions&lt;/h3&gt;
&lt;p&gt;Expressions containing multiple units can be simplified. For example, enter
two values, &lt;code&gt;2m&lt;/code&gt; and &lt;code&gt;50cm&lt;/code&gt; and add them with &lt;code&gt;+&lt;/code&gt;. The resulting expression is
&lt;code&gt;2 m + 50 cm&lt;/code&gt;. Hit &lt;code&gt;u s&lt;/code&gt;, for &amp;ldquo;&lt;strong&gt;u&lt;/strong&gt;nit &lt;strong&gt;s&lt;/strong&gt;implify&amp;rdquo;, to have Calc simplify
it to &lt;code&gt;2.5 m&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;converting-units&#34;&gt;Converting units&lt;/h3&gt;
&lt;p&gt;Unit conversion is of course possible. Use &lt;code&gt;u c&lt;/code&gt;, for &amp;ldquo;&lt;strong&gt;u&lt;/strong&gt;nit &lt;strong&gt;c&lt;/strong&gt;onvert&amp;rdquo;,
at any moment: Calc will ask for a unit and will try to convert the value at
the top of the stack into this unit. For example, entering &lt;code&gt;1.5mi&lt;/code&gt; (&lt;code&gt;mi&lt;/code&gt; being
the unit for miles) and typing &lt;code&gt;u c km &amp;lt;return&amp;gt;&lt;/code&gt; will correctly yield
&lt;code&gt;2.414016 km&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You will quickly discover that Calc tries way too hard to convert units and
will produce really strange results when types are not compatible. For
example, trying to convert &lt;code&gt;250mA&lt;/code&gt; into kilometers will produce &lt;code&gt;0.25A&lt;/code&gt; which
is clearly incorrect. I have no idea what causes this behaviour. Fortunately
you can use &lt;code&gt;u n&lt;/code&gt;, bound to &lt;code&gt;calc-convert-exact-units&lt;/code&gt;, which will check that
the unit you required is compatible with the unit of the expression on the
stack. To minimize the risk of producing incorrect results by mistake, I
replace the &lt;code&gt;calc-convert-units&lt;/code&gt; function by &lt;code&gt;calc-convert-exact-units&lt;/code&gt;. I
would prefer to remap &lt;code&gt;u c&lt;/code&gt;, but Calc has a strange way to handle key bindings
that prevent doing this kind of remapping.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(use-package calc
  :config
  (require &#39;calc-units)

  (setf (symbol-function &#39;calc-convert-units)
        (symbol-function &#39;calc-convert-exact-units)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As a shortcut, &lt;code&gt;u b&lt;/code&gt;, where &lt;code&gt;b&lt;/code&gt; stands for &amp;ldquo;&lt;strong&gt;b&lt;/strong&gt;ase&amp;rdquo;, will convert the value
to its base unit. For example, it will automatically convert &lt;code&gt;250mA&lt;/code&gt; to
&lt;code&gt;0.25A&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;defining-custom-units&#34;&gt;Defining custom units&lt;/h2&gt;
&lt;p&gt;Calc comes by default with more than 170 units (type &lt;code&gt;u v&lt;/code&gt; to list them all),
but none of them are about standard data size units. This is disappointing
given that Emacs is a software primarily used for programming. But we can add
new units, so it is not that much of a problem.&lt;/p&gt;
&lt;p&gt;New units can be defined with the &lt;code&gt;math-additional-units&lt;/code&gt; variable. Its format
is the same as &lt;code&gt;math-standard-units&lt;/code&gt;: each entry is a list of three elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A symbol identifying the unit.&lt;/li&gt;
&lt;li&gt;An expression indicating the value of the unit, or &lt;code&gt;nil&lt;/code&gt; for fundamental
units.&lt;/li&gt;
&lt;li&gt;A textual description.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let us add data sizes. We need two units, bits and bytes, with bytes being
defined as 8 bits. Note that using the &lt;code&gt;b&lt;/code&gt; symbol for the bit unit will
override the internal &amp;ldquo;Barn&amp;rdquo; unit; not a problem to me, I do not expect to use
it any time soon. Feel free to use &lt;code&gt;bit&lt;/code&gt; instead.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq math-additional-units
      &#39;((b nil &amp;quot;Bit&amp;quot;)
        (B &amp;quot;8 * b&amp;quot; &amp;quot;Byte&amp;quot;)))

(setq math-units-table nil)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to set &lt;code&gt;math-units-table&lt;/code&gt; to &lt;code&gt;nil&lt;/code&gt; after defining new units to force
Calc to recompute its internal table.&lt;/p&gt;
&lt;p&gt;These new units can of course be used with standard SI prefixes defined in
Calc. For example, &lt;code&gt;25kB&lt;/code&gt; will correctly be converted to &lt;code&gt;25000 B&lt;/code&gt;. And asking
for a convertion to the base unit will yield &lt;code&gt;200000 b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A limitation of Calc is its inability to handle unit prefixes of more than one
character, so we cannot define &lt;code&gt;ki&lt;/code&gt; as being a prefix with a multiplicative
value of 1024, which would for example allow us to manipulate kibibytes.&lt;/p&gt;
&lt;p&gt;A workaround is to define these power-of-two binary units with the prefix
included:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq math-additional-units
      &#39;((b nil &amp;quot;Bit&amp;quot;)
        (B &amp;quot;8 * b&amp;quot; &amp;quot;Byte&amp;quot;)

        (kiB &amp;quot;2^10 * B&amp;quot; &amp;quot;Kibibyte&amp;quot;)
        (MiB &amp;quot;2^20 * B&amp;quot; &amp;quot;Mebibyte&amp;quot;)
        (GiB &amp;quot;2^30 * B&amp;quot; &amp;quot;Gibibyte&amp;quot;)
        (TiB &amp;quot;2^40 * B&amp;quot; &amp;quot;Tebibyte&amp;quot;)
        (PiB &amp;quot;2^50 * B&amp;quot; &amp;quot;Pebibyte&amp;quot;)
        (EiB &amp;quot;2^60 * B&amp;quot; &amp;quot;Exbibyte&amp;quot;)))

(setq math-units-table nil)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Very helpful for data size conversion.&lt;/p&gt;
&lt;h2 id=&#34;going-farther-with-calc&#34;&gt;Going farther with Calc&lt;/h2&gt;
&lt;p&gt;Writing this post has been an interesting experience: it forced me to read
various parts of the Calc manual and some of its source files. It made me
realize that this package is full of useful features. I hope to find the time
to experiment with Calc features in the future.&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/custom-common-lisp-indentation-in-emacs/">
      <title>Custom Common Lisp indentation in Emacs</title>
      <link>https://www.n16f.net/blog/custom-common-lisp-indentation-in-emacs/</link>
      <pubDate>Mon, 23 Jan 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/custom-common-lisp-indentation-in-emacs/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;While &lt;a href=&#34;https://slime.common-lisp.dev/&#34;&gt;SLIME&lt;/a&gt; is most of the time able to
indent Common Lisp correctly, it will sometimes trip on custom forms. Let us
see how we can customize indentation.&lt;/p&gt;
&lt;p&gt;In the process of writing my PostgreSQL client in Common Lisp, I wrote a
&lt;code&gt;READ-MESSAGE-CASE&lt;/code&gt; macro which reads a message from a stream and execute code
depending on the type of the message:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defmacro read-message-case ((message stream) &amp;amp;rest forms)
  `(let ((,message (read-message ,stream)))
     (case (car ,message)
       (:error-response
        (backend-error (cdr ,message)))
       (:notice-response
        nil)
       ,@forms
       (t
        (error &#39;unexpected-message :message ,message)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This macro is quite useful: all message loops can use it to automatically
handle error responses, notices, and signal unexpected messages.&lt;/p&gt;
&lt;p&gt;But SLIME does not know how to indent &lt;code&gt;READ-MESSAGE-CASE&lt;/code&gt;, so by default it
will align all message forms on the first argument:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(read-message-case (message stream)
                   (:authentication-ok
                     (return))
                   (:authentication-cleartext-password
                     (unless password
                       (error &#39;missing-password))
                     (write-password-message password stream)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While we want it aligned the same way as &lt;code&gt;HANDLER-CASE&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(read-message-case (message stream)
  (:authentication-ok
    (return))
  (:authentication-cleartext-password
    (unless password
      (error &#39;missing-password))
    (write-password-message password stream)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Good news, SLIME indentation is defined as a list of rules. Each rule
associates an indentation specification (a S-expression describing how to
indent the form) to a symbol and store it as the &lt;code&gt;common-lisp-indent-function&lt;/code&gt;
property of the symbol.&lt;/p&gt;
&lt;p&gt;You can obtain the indentation rule of a Common Lisp symbol easily. For
example, executing &lt;code&gt;(get &#39;defun &#39;common-lisp-indent-function)&lt;/code&gt; (e.g. in IELM
or with &lt;code&gt;eval-expression&lt;/code&gt;) yields &lt;code&gt;(4 &amp;amp;lambda &amp;amp;body)&lt;/code&gt;. This indicates that
&lt;code&gt;DEFUN&lt;/code&gt; forms are to be indented as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first argument of &lt;code&gt;DEFUN&lt;/code&gt; (the function name) is indented by four
spaces.&lt;/li&gt;
&lt;li&gt;The second argument (the list of function arguments) is indented as a lambda
list.&lt;/li&gt;
&lt;li&gt;The rest of the arguments are indented based on the &lt;code&gt;lisp-body-indent&lt;/code&gt;
custom variable, which controls the indentation of the body of a lambda form
(two spaces by default).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can refer to the documentation of the &lt;code&gt;common-lisp-indent-function&lt;/code&gt; Emacs
function (defined in SLIME of course) for a complete description of the
format.&lt;/p&gt;
&lt;p&gt;We want &lt;code&gt;READ-MESSAGE-CASE&lt;/code&gt; to be indented the same way as &lt;code&gt;HANDLER-CASE&lt;/code&gt;,
whose indentation specification is &lt;code&gt;(4 &amp;amp;rest (&amp;amp;whole 2 &amp;amp;lambda &amp;amp;body))&lt;/code&gt; (in
short, an argument and a list of lambda lists). Fortunately there is a way to
specify that a form must be indented the same way as another form, using &lt;code&gt;(as &amp;lt;symbol&amp;gt;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let us first define a function to set the indentation specification of a
symbol:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-common-lisp-indent (symbol indent)
  &amp;quot;Set the indentation of SYMBOL to INDENT.&amp;quot;
  (put symbol &#39;common-lisp-indent-function indent))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then use it for &lt;code&gt;READ-MESSAGE-CASE&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(g-common-lisp-indent &#39;read-message-case &#39;(as handler-case))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While it is in general best to avoid custom indentation, exceptions are
sometimes necessary for readability. And SLIME makes it easy.&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/taking-code-screenshots-in-emacs/">
      <title>Taking code screenshots in Emacs</title>
      <link>https://www.n16f.net/blog/taking-code-screenshots-in-emacs/</link>
      <pubDate>Wed, 18 Jan 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/taking-code-screenshots-in-emacs/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;My friend &lt;a href=&#34;https://twitter.com/remilouf&#34;&gt;Rémi&lt;/a&gt; found an Emacs package
developed by &lt;a href=&#34;https://github.com/tecosaur&#34;&gt;Tecosaur&lt;/a&gt; to take screenshots of
your code. I usually do it with
&lt;a href=&#34;https://github.com/resurrecting-open-source-projects/scrot&#34;&gt;scrot&lt;/a&gt;, but it
always requires spending some time cropping the result with Gimp. A bit
annoying.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Let us give it a try. The &lt;code&gt;screenshot&lt;/code&gt; package is not available on
&lt;a href=&#34;https://melpa.org/&#34;&gt;MELPA&lt;/a&gt; due to &lt;a href=&#34;https://github.com/melpa/melpa/pull/7327&#34;&gt;cosmetic
issues&lt;/a&gt;, so we have two options.&lt;/p&gt;
&lt;p&gt;The first one would be to clone the
&lt;a href=&#34;https://github.com/tecosaur/screenshot&#34;&gt;repository&lt;/a&gt;, add its location to
&lt;code&gt;load-path&lt;/code&gt;, and use &lt;code&gt;require&lt;/code&gt; to load the module. But doing so means having
to explicitely install its dependencies, &lt;code&gt;transient&lt;/code&gt; and &lt;code&gt;posframe&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The second option is to rely on
&lt;a href=&#34;https://github.com/jwiegley/use-package&#34;&gt;&lt;code&gt;use-package&lt;/code&gt;&lt;/a&gt; and
&lt;a href=&#34;https://github.com/radian-software/straight.el&#34;&gt;&lt;code&gt;straight.el&lt;/code&gt;&lt;/a&gt;. With
&lt;code&gt;straight.el&lt;/code&gt;, you can load packages from various sources, including Git
repositories.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(use-package screenshot
  :straight (:type git :host github :repo &amp;quot;tecosaur/screenshot&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Evaluate the form with &lt;code&gt;C-x C-e&lt;/code&gt;, and &lt;code&gt;straight.el&lt;/code&gt; will clone the repository
and load the &lt;code&gt;screenshot&lt;/code&gt; package.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;p&gt;Simply run &lt;code&gt;M-x screenshot&lt;/code&gt; to take a screenshot. If you are currently
selecting a region, it will screenshot this part only. If not, it will use the
entire buffer.&lt;/p&gt;
&lt;p&gt;Since Screenshot uses the
&lt;code&gt;transient&lt;/code&gt; library, it has the same well designed interface system as
&lt;a href=&#34;https://magit.vc/&#34;&gt;Magit&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./interface.png&#34; alt=&#34;Screenshot interface&#34;&gt;&lt;/p&gt;
&lt;p&gt;I really like the ability to adjust the font size just for the screenshot. By
default, the &lt;code&gt;save&lt;/code&gt; action will save the image in the same directory as the
buffer which was selected when &lt;code&gt;screenshot&lt;/code&gt; was executed.&lt;/p&gt;
&lt;h2 id=&#34;customization&#34;&gt;Customization&lt;/h2&gt;
&lt;p&gt;Screenshot lets you change the default value of each setting. This is not
obvious when reading the code, because the variables used are defined
programmatically through two layers of macros: first
&lt;code&gt;screenshot--define-infix&lt;/code&gt; then &lt;code&gt;transient-define-infix&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is too bad these values are not defined as proper settings using
&lt;code&gt;defcustom&lt;/code&gt;, but we can still set them.&lt;/p&gt;
&lt;p&gt;This is a list of available settings:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Variable&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-line-numbers-p&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Whether to display line numbers or not.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-relative-line-numbers-p&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Whether to use relative line numbers or not.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-text-only-p&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Whether to show code as simple text or not.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-truncate-lines-p&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Whether to truncate long lines instead of wrapping them.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-font-family&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The name of the font to use.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-font-size&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The size of the font to use.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-border-width&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The width of the border.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-radius&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The corner radius of the border.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-min-width&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The minimal width of the screenshot as a number of characters.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-max-width&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The maximal width of the screenshot as a number of characters.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-shadow-radius&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The corner radius of the shadow.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-shadow-intensity&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The intensity of the shadow.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-shadow-color&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The hexadecimal code of the shadow.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-shadow-offset-horizontal&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The horizontal offset of the shadow in pixels.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;screenshot-shadow-offset-vertical&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;The vertical offset of the shadow in pixels.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Another nice feature is the presence of a hook executed in the temporary
buffer used for the screenshot, allowing to execute code affecting this buffer
just before the actual screenshot is being taken.&lt;/p&gt;
&lt;p&gt;In my case, I use it to disable the &lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/emacs/Displaying-Boundaries.html&#34;&gt;fill column
indicator&lt;/a&gt;
and to remove the additional line spacing added by default by Screenshot.&lt;/p&gt;
&lt;p&gt;This is my configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-screenshot-on-buffer-creation ()
  (setq display-fill-column-indicator-column nil)
  (setq line-spacing nil))

(use-package screenshot
  :straight (:type git :host github :repo &amp;quot;tecosaur/screenshot&amp;quot;)

  :config
  (setq screenshot-line-numbers-p nil)

  (setq screenshot-min-width 80)
  (setq screenshot-max-width 80)
  (setq screenshot-truncate-lines-p nil)

  (setq screenshot-text-only-p nil)

  (setq screenshot-font-family &amp;quot;Berkeley Mono&amp;quot;)
  (setq screenshot-font-size 10)

  (setq screenshot-border-width 16)
  (setq screenshot-radius 0)

  (setq screenshot-shadow-radius 0)
  (setq screenshot-shadow-offset-horizontal 0)
  (setq screenshot-shadow-offset-vertical 0)

  :hook
  ((screenshot-buffer-creation-hook . g-screenshot-on-buffer-creation)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All in all a very useful package!&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/ansi-color-rendering-in-slime/">
      <title>ANSI color rendering in SLIME</title>
      <link>https://www.n16f.net/blog/ansi-color-rendering-in-slime/</link>
      <pubDate>Mon, 16 Jan 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/ansi-color-rendering-in-slime/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I was working on the terminal output for a Common Lisp logger, and I realized
that &lt;a href=&#34;https://slime.common-lisp.dev/&#34;&gt;SLIME&lt;/a&gt; does not interpret ANSI escape
sequences.&lt;/p&gt;
&lt;p&gt;This is not the end of the world, but having at least colors would be nice.
Fortunately there is a
&lt;a href=&#34;https://gitlab.com/augfab/slime-repl-ansi-color&#34;&gt;library&lt;/a&gt; to do just that.&lt;/p&gt;
&lt;p&gt;First let us install the package, here using
&lt;a href=&#34;https://github.com/jwiegley/use-package&#34;&gt;&lt;code&gt;use-package&lt;/code&gt;&lt;/a&gt; and
&lt;a href=&#34;https://github.com/radian-software/straight.el&#34;&gt;&lt;code&gt;straight.el&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(use-package slime-repl-ansi-color
  :straight t)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While in theory we are supposed to just add &lt;code&gt;slime-repl-ansi-color&lt;/code&gt; to
&lt;code&gt;slime-contribs&lt;/code&gt;, it did not work for me, and I add to enable the minor mode
manually.&lt;/p&gt;
&lt;p&gt;If you already have a SLIME REPL hook, simply add &lt;code&gt;(slime-repl-ansi-color-mode 1)&lt;/code&gt;. If not, write an initialization function, and add it to the SLIME REPL
initialization hook:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-init-slime-repl-mode ()
  (slime-repl-ansi-color-mode 1))
  
(add-hook &#39;slime-repl-mode-hook &#39;g-init-slime-repl-mode)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To test that it works as intended, fire up SLIME and print a simple message
using ANSI escape sequences:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(let ((escape (code-char 27)))
  (format t &amp;quot;~C[1;33mHello world!~C[0m~%&amp;quot; escape escape))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While it is tempting to use the &lt;code&gt;#\Esc&lt;/code&gt; character, it is part of the Common
Lisp standard; therefore we use &lt;code&gt;CODE-CHAR&lt;/code&gt; to obtain it from its ASCII
numeric value. We use two escape sequences, the first one to set the bold flag
and foreground color, and the second one to reset display status.&lt;/p&gt;
&lt;p&gt;If everything works well, should you see a nice bold yellow message:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./output.png&#34; alt=&#34;ANSI escape sequence rendering&#34;&gt;&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/switching-between-implementations-with-slime/">
      <title>Switching between implementations with SLIME</title>
      <link>https://www.n16f.net/blog/switching-between-implementations-with-slime/</link>
      <pubDate>Thu, 12 Jan 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/switching-between-implementations-with-slime/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;While I mostly use &lt;a href=&#34;http://sbcl.org/&#34;&gt;SBCL&lt;/a&gt; for Common Lisp development, I
regularly switch to &lt;a href=&#34;https://ccl.clozure.com/&#34;&gt;CCL&lt;/a&gt; or even
&lt;a href=&#34;https://ecl.common-lisp.dev/&#34;&gt;ECL&lt;/a&gt; to run tests.&lt;/p&gt;
&lt;p&gt;This is how I do it with &lt;a href=&#34;https://slime.common-lisp.dev/&#34;&gt;SLIME&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;starting-implementations&#34;&gt;Starting implementations&lt;/h2&gt;
&lt;p&gt;SLIME lets you configure multiple implementations using the
&lt;code&gt;slime-lisp-implementations&lt;/code&gt; setting. In my case:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq slime-lisp-implementations
   &#39;((sbcl (&amp;quot;/usr/bin/sbcl&amp;quot; &amp;quot;--dynamic-space-size&amp;quot; &amp;quot;2048&amp;quot;))
     (ccl (&amp;quot;/usr/bin/ccl&amp;quot;))
     (ecl (&amp;quot;/usr/bin/ecl&amp;quot;))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Doing so means that running &lt;code&gt;M-x slime&lt;/code&gt; will execute the first implementation,
i.e. SBCL. There are two ways to run other implementations.&lt;/p&gt;
&lt;p&gt;First you can run &lt;code&gt;C-u M-x slime&lt;/code&gt; which lets you type the path and arguments
of the implementation to execute. This is a bit annoying because the prompt
starts with the content of the &lt;code&gt;inferior-lisp-program&lt;/code&gt; variable, i.e. &lt;code&gt;&amp;quot;lisp&amp;quot;&lt;/code&gt;
by default, meaning it has to be deleted manually each time. Therefore I set
&lt;code&gt;inferior-lisp-program&lt;/code&gt; to the empty string:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq inferior-lisp-program &amp;quot;&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can run &lt;code&gt;C-- M-x slime&lt;/code&gt; (or &lt;code&gt;M-- M-x slime&lt;/code&gt; which is easier to type)
to instruct SLIME to use interactive completion (via &lt;code&gt;completing-read&lt;/code&gt;) to let
you select the implementations among those configured in
&lt;code&gt;slime-lisp-implementations&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To make my life easier, I bind &lt;code&gt;C-c C-s s&lt;/code&gt; to a function which always prompt
for the implementation to start:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-slime-start ()
  (interactive)
  (let ((current-prefix-arg &#39;-))
    (call-interactively &#39;slime)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using &lt;code&gt;C-c C-s&lt;/code&gt; as prefix for all my global SLIME key bindings helps me
remember them.&lt;/p&gt;
&lt;h2 id=&#34;switching-between-multiple-implementations&#34;&gt;Switching between multiple implementations&lt;/h2&gt;
&lt;p&gt;Running the &lt;code&gt;slime&lt;/code&gt; function several times will create multiple connections as
expected. Commands executed in Common Lisp buffers are applied to the current
connection, which is by default the most recent one.&lt;/p&gt;
&lt;p&gt;There are two ways to change the current implementation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;M-x slime-next-connection&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;M-x slime-list-connections&lt;/code&gt;, which opens a buffer listing connections,
and lets you choose the current one with the &lt;code&gt;d&lt;/code&gt; key.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I find both impractical: the first one does not let me choose the
implementation, forcing me to run potentially several times before getting the
one I want. The second one opens a buffer but does not switch to it.&lt;/p&gt;
&lt;p&gt;All I want is a prompt with completion. So I wrote one.&lt;/p&gt;
&lt;p&gt;First we define a function to select a connection among existing one:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-slime-select-connection (prompt)
  (interactive)
  (let* ((connections-data
          (mapcar (lambda (process)
                    (cons (slime-connection-name process) process))
                  slime-net-processes))
         (completion-extra-properties
          &#39;(:annotation-function
            (lambda (string)
              (let* ((process (alist-get string minibuffer-completion-table
                                         nil nil #&#39;string=))
                     (contact (process-contact process)))
                (if (consp contact)
                    (format &amp;quot;  %s:%s&amp;quot; (car contact) (cadr contact))
                  (format &amp;quot;  %S&amp;quot; contact))))))
         (connection-name (completing-read prompt connections-data)))
    (let ((connection (cl-find connection-name slime-net-processes
                               :key #&#39;slime-connection-name
                               :test #&#39;string=)))
      (or connection
          (error &amp;quot;Unknown SLIME connection %S&amp;quot; connection-name)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then use it to select a connection as the current one:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-slime-switch-connection ()
  (interactive)
  (let ((connection (g-slime-select-connection &amp;quot;Switch to connection: &amp;quot;)))
    (slime-select-connection connection)
    (message &amp;quot;Using connection %s&amp;quot; (slime-connection-name connection))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I bind this function to &lt;code&gt;C-c C-s c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In a perfect world, we could format nice columns in the prompt and highlight
the current connection, but the &lt;code&gt;completing-read&lt;/code&gt; interface is really limited,
and I did not want to use an external package such as Helm.&lt;/p&gt;
&lt;h2 id=&#34;stopping-implementations&#34;&gt;Stopping implementations&lt;/h2&gt;
&lt;p&gt;Sometimes it is necessary to stop an implementations and kill all associated
buffers. It is not something I use a lot; but when I need it, it is
frustrating to have to switch to the REPL buffer, run &lt;code&gt;slime-quit-lisp&lt;/code&gt;, then
kill the REPL buffer manually.&lt;/p&gt;
&lt;p&gt;Adding this feature is trivial with the &lt;code&gt;g-slime-select-connection&lt;/code&gt; defined
earlier:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-slime-kill-connection ()
  (interactive)
  (let* ((connection (g-slime-select-connection &amp;quot;Kill connection: &amp;quot;))
         (repl-buffer (slime-repl-buffer nil connection)))
    (when repl-buffer
      (kill-buffer repl-buffer))
    (slime-quit-lisp-internal connection &#39;slime-quit-sentinel t)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally I bind this function to &lt;code&gt;C-c C-s k&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is now much more comfortable to manage multiple implementations.&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/improving-git-diffs-for-lisp/">
      <title>Improving Git diffs for Lisp</title>
      <link>https://www.n16f.net/blog/improving-git-diffs-for-lisp/</link>
      <pubDate>Sun, 08 Jan 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/improving-git-diffs-for-lisp/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;All my code is stored in various Git repositories. When Git formats a diff
between two objects, it generates a list of hunks, or groups of changes.&lt;/p&gt;
&lt;p&gt;Each hunk can be displayed with a title which is automatically extracted. Git
ships with support for multiple languages, but Lisp dialects are not part of
it. Fortunately Git lets users configure their own extraction.&lt;/p&gt;
&lt;p&gt;The first step is to identify the language using a pattern applied to the
filename. Edit your Git attribute file at &lt;code&gt;$HOME/.gitattributes&lt;/code&gt; and add
entries for both Emacs Lisp and Common Lisp:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*.lisp diff=common-lisp
*.el diff=elisp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then edit your Git configuration file at &lt;code&gt;$HOME/.gitconfig&lt;/code&gt; and configure the
path of the Git attribute file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[core]
    attributesfile = ~/.gitattributes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, set the regular expression used to match a top-level function name:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[diff &amp;quot;common-lisp&amp;quot;]
    xfuncname=&amp;quot;^\\((def\\S+\\s+\\S+)&amp;quot;
    
[diff &amp;quot;elisp&amp;quot;]
    xfuncname=&amp;quot;^\\((((def\\S+)|use-package)\\s+\\S+)&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For Lisp dialects, we do not just identify function names: it is convenient to
identify hunks for all sorts of top-level definitions. We use a regular
expression which captures the first symbol of the form and the name that
follows.&lt;/p&gt;
&lt;p&gt;Of course you can modifiy these expressions to identify more complex top-level
forms. For example, for Emacs Lisp, I also want to identify &lt;code&gt;use-package&lt;/code&gt;
expressions.&lt;/p&gt;
&lt;p&gt;You can see the result in all tools displaying Git diffs, for example in
Magit with Common Lisp code:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./common-lisp-diff.png&#34; alt=&#34;Common Lisp diff&#34;&gt;&lt;/p&gt;
&lt;p&gt;Or for my Emacs configuration file:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./elisp-diff.png&#34; alt=&#34;Emacs Lisp diff&#34;&gt;&lt;/p&gt;
&lt;p&gt;Hunk titles, highlighted in blue, now contain the type and name of the
top-level construction the changes are associated with.&lt;/p&gt;
&lt;p&gt;A simple change, but one which really helps reading diffs.&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
      <category>emacs</category>
      
      <category>git</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/eshell-key-bindings-and-completion/">
      <title>Eshell key bindings and completion</title>
      <link>https://www.n16f.net/blog/eshell-key-bindings-and-completion/</link>
      <pubDate>Fri, 06 Jan 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/eshell-key-bindings-and-completion/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I have been having completion issues in Eshell for some time, and I decided to
fix it. Of course the &lt;a href=&#34;https://en.wiktionary.org/wiki/yak_shaving&#34;&gt;yak
shaving&lt;/a&gt; is always strong with
Emacs, so it ended up being a bit more complicated than expected.&lt;/p&gt;
&lt;h2 id=&#34;defining-keys-with-use-package&#34;&gt;Defining keys with use-package&lt;/h2&gt;
&lt;p&gt;Eshell key bindings are stored in &lt;code&gt;eshell-mode-map&lt;/code&gt;. For quite some time,
Eshell has been initializing this value to &lt;code&gt;nil&lt;/code&gt;, making it impossible to
define keys before Eshell has been started. As &lt;a href=&#34;https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-02/msg01532.html&#34;&gt;initially
reported&lt;/a&gt;,
the workaround was to call &lt;code&gt;define-key&lt;/code&gt; in a hook, &lt;code&gt;eshell-mode-hook&lt;/code&gt; to be
precise.&lt;/p&gt;
&lt;p&gt;Apparently Emacs 28.1 fixed it. However to be able to use the key binding
mechanism of &lt;code&gt;use-package&lt;/code&gt;, &lt;code&gt;eshell-mode-map&lt;/code&gt; must actually be defined. The
solution is to load the right module &lt;em&gt;before&lt;/em&gt; &lt;code&gt;use-package&lt;/code&gt; configures key
bindings, therefore using &lt;code&gt;:init&lt;/code&gt; and not &lt;code&gt;:config&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(use-package eshell
  :init
  (require &#39;esh-mode) ; eshell-mode-map

  :bind
  ((&amp;quot;C-x s&amp;quot; . g-eshell)
   :map eshell-mode-map
   ((&amp;quot;C-l&amp;quot; . &#39;g-eshell-clear)
    (&amp;quot;C-r&amp;quot; . helm-eshell-history))))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;configuring-company-for-completion&#34;&gt;Configuring Company for completion&lt;/h2&gt;
&lt;p&gt;Eshell supports the standard &lt;code&gt;completion-at-point&lt;/code&gt; completion system, the
function being bound to &lt;code&gt;&amp;lt;tab&amp;gt;&lt;/code&gt; by default. If you are using Helm, it will be
automatically used to present the list of possible completions. This is a bit
cumbersome: I want completion to be inline, not in a separate buffer in the
bottom of the screen.&lt;/p&gt;
&lt;p&gt;Since I use &lt;a href=&#34;https://company-mode.github.io/&#34;&gt;Company&lt;/a&gt;, I can instead bind
&lt;code&gt;&amp;lt;tab&amp;gt;&lt;/code&gt; to &lt;code&gt;company-complete&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(define-key eshell-mode-map (kbd &amp;quot;&amp;lt;tab&amp;gt;&amp;quot;) &#39;company-complete)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;./company-completion.png&#34; alt=&#34;Company completion&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;fixing-completion-of-commands-in-subdirectories&#34;&gt;Fixing completion of commands in subdirectories&lt;/h2&gt;
&lt;p&gt;As it turns out, completion works as intended for global commands, but fails
when calling a command in a subdirectory. For example, when completing
&lt;code&gt;./utils/create-blog-post&lt;/code&gt;, &lt;code&gt;completion-at-point&lt;/code&gt; will replace the line by
&lt;code&gt;create-blog-post&lt;/code&gt;, which is of course incorrect. This bug is also present
when completing the absolute path of an executable.&lt;/p&gt;
&lt;p&gt;After spending way too much time on Google and in the &lt;code&gt;em-cmpl&lt;/code&gt; module, which
handles completion for Eshell, it turned out to be a &lt;a href=&#34;https://debbugs.gnu.org/cgi/bugreport.cgi?bug=48995&#34;&gt;known
bug&lt;/a&gt;, introduced &lt;a href=&#34;https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=82c76e3aeb2465d1d1e66eae5db13ba53e38ed84&#34;&gt;almost
two years
ago&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The workaround is to redefine &lt;code&gt;eshell--complete-commands-list&lt;/code&gt; as it was
before the commit:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun eshell--complete-commands-list ()
  &amp;quot;Generate list of applicable, visible commands.&amp;quot;
  (let ((filename (pcomplete-arg)) glob-name)
    (if (file-name-directory filename)
        (if eshell-force-execution
            (pcomplete-dirs-or-entries nil #&#39;file-readable-p)
          (pcomplete-executables))
      (if (and (&amp;gt; (length filename) 0)
               (eq (aref filename 0) eshell-explicit-command-char))
          (setq filename (substring filename 1)
                pcomplete-stub filename
                glob-name t))
      (let* ((paths (eshell-get-path))
             (cwd (file-name-as-directory
                   (expand-file-name default-directory)))
             (path &amp;quot;&amp;quot;) (comps-in-path ())
             (file &amp;quot;&amp;quot;) (filepath &amp;quot;&amp;quot;) (completions ()))
        ;; Go thru each path in the search path, finding completions.
        (while paths
          (setq path (file-name-as-directory
                      (expand-file-name (or (car paths) &amp;quot;.&amp;quot;)))
                comps-in-path
                (and (file-accessible-directory-p path)
                     (file-name-all-completions filename path)))
          ;; Go thru each completion found, to see whether it should
          ;; be used.
          (while comps-in-path
            (setq file (car comps-in-path)
                  filepath (concat path file))
            (if (and (not (member file completions)) ;
                     (or (string-equal path cwd)
                         (not (file-directory-p filepath)))
                     (if eshell-force-execution
                         (file-readable-p filepath)
                       (file-executable-p filepath)))
                (setq completions (cons file completions)))
            (setq comps-in-path (cdr comps-in-path)))
          (setq paths (cdr paths)))
        ;; Add aliases which are currently visible, and Lisp functions.
        (pcomplete-uniquify-list
         (if glob-name
             completions
           (setq completions
                 (append (if (fboundp &#39;eshell-alias-completions)
                             (eshell-alias-completions filename))
                         (eshell-winnow-list
                          (mapcar
                           (lambda (name)
                             (substring name 7))
                           (all-completions (concat &amp;quot;eshell/&amp;quot; filename)
                                            obarray #&#39;functionp))
                          nil &#39;(eshell-find-alias-function))
                         completions))
           (append (and (or eshell-show-lisp-completions
                            (and eshell-show-lisp-alternatives
                                 (null completions)))
                        (all-completions filename obarray #&#39;functionp))
                   completions)))))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I have no idea what is wrong in the new implementation of the function, but
hopefully someone can find a fix to be merged before Emacs 29 is released.&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/org-mode-headline-tips/">
      <title>Org-mode headline tips</title>
      <link>https://www.n16f.net/blog/org-mode-headline-tips/</link>
      <pubDate>Mon, 02 Jan 2023 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/org-mode-headline-tips/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;&lt;a href=&#34;https://orgmode.org/&#34;&gt;Org-mode&lt;/a&gt; is what got me into Emacs in the first place.
I use it to take notes, keep track of what I have to do and plan projects.&lt;/p&gt;
&lt;p&gt;An Org file is a tree of elements, each one starting with a headline.
Manipulating headlines can be confusing; here are a few tips that you may find
helpful.&lt;/p&gt;
&lt;h2 id=&#34;do-not-split-lines-when-adding-headlines&#34;&gt;Do not split lines when adding headlines&lt;/h2&gt;
&lt;p&gt;At any point, you can insert a new headline below the current one using the
&lt;code&gt;C-&amp;lt;return&amp;gt;&lt;/code&gt; shortcut, which calls &lt;code&gt;org-insert-heading&lt;/code&gt;. However if the cursor
is at the middle of a line (headline or content), Org will split it and add
the end of the line to the new headline.&lt;/p&gt;
&lt;p&gt;&lt;del&gt;Quite annoying, really. Fortunately there is a function to add a headline
without splitting the currentline, &lt;code&gt;org-insert-heading-respect-content&lt;/code&gt;.
I simply bind it to &lt;code&gt;C-&amp;lt;return&amp;gt;&lt;/code&gt;:&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;del&gt;Obviously I want the same behaviour for &lt;code&gt;C-M-&amp;lt;return&amp;gt;&lt;/code&gt; which inserts a TODO
headline:&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit (2023-01-07)&lt;/em&gt;&lt;br&gt;
As it turns out, a simpler way to do that is to set
&lt;code&gt;org-insert-heading-respect-content&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq org-insert-heading-respect-content t)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No need to rebind keys.&lt;/p&gt;
&lt;h2 id=&#34;jump-quickly-to-the-right-headline&#34;&gt;Jump quickly to the right headline&lt;/h2&gt;
&lt;p&gt;Some of my Org files are quite long. For example, my main development tracking
file contains more than 700 lines.&lt;/p&gt;
&lt;p&gt;I never really thought about navigation, and usually either search for
elements by title with &lt;code&gt;C-s&lt;/code&gt; or move between folded items manually (I use
&lt;code&gt;org-startup-folded&lt;/code&gt; so that all items are folded by default).&lt;/p&gt;
&lt;p&gt;As it turns out, Org has a buitin navigation system triggered by &lt;code&gt;C-c C-j&lt;/code&gt;. At
first I could not see how it could help; but then I realized that this feature
can use native Emacs completion. This is incredibly useful when combined with
a vertical completion framework such as Helm, making it easy to jump to any
headline just by typing a couple characters.&lt;/p&gt;
&lt;p&gt;In order to do that, we enable completion with &lt;code&gt;org-goto-interface&lt;/code&gt;, disable
the multi-steps navigation system, and set the maximum depth level used to
select headlines which will be listed during completion.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq org-goto-interface &#39;outline-path-completion)
(setq org-outline-path-complete-in-steps nil)
(setq org-goto-max-level 2)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;stop-highlighting-todo-headlines&#34;&gt;Stop highlighting TODO headlines&lt;/h2&gt;
&lt;p&gt;By default, Org highlights the entire headline for TODO items, not just
the &lt;code&gt;TODO&lt;/code&gt; or &lt;code&gt;DONE&lt;/code&gt; keyword.&lt;/p&gt;
&lt;p&gt;I believe this is a mistake: headlines mark the hierarchy of items, and having
multiple red or green headlines is confusing. This behaviour can be configured
with two settings:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq org-fontify-todo-headline nil)
(setq org-fontify-done-headline nil)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This way, headlines keep their original color (defined by &lt;code&gt;org-level-*&lt;/code&gt;
faces), and keywords only are highlighted with the &lt;code&gt;org-todo&lt;/code&gt; and &lt;code&gt;org-done&lt;/code&gt;
faces.&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/configuring-slime-cross-referencing/">
      <title>Configuring SLIME cross-referencing</title>
      <link>https://www.n16f.net/blog/configuring-slime-cross-referencing/</link>
      <pubDate>Wed, 28 Dec 2022 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/configuring-slime-cross-referencing/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;The &lt;a href=&#34;https://slime.common-lisp.dev/&#34;&gt;SLIME&lt;/a&gt; Emacs package for Common Lisp
supports cross-referencing: one can list all references pointing to a symbol,
move through this list and jump to the source code of each reference.&lt;/p&gt;
&lt;h2 id=&#34;removing-automatic-reference-jumps&#34;&gt;Removing automatic reference jumps&lt;/h2&gt;
&lt;p&gt;While cross-referencing is very useful, the default configuration is
frustrating: moving through the list in the Emacs buffer triggers the jump to
the reference under the cursor. If you are interested in a reference in the
middle of the list, you will have to move to it, opening multiple buffers you
do not care about as a side effect. I finally took the time to fix it.&lt;/p&gt;
&lt;p&gt;Key bindings for &lt;code&gt;slime-ref-mode&lt;/code&gt; mode are stored in the &lt;code&gt;slime-xref-mode-map&lt;/code&gt;
keymap. After a quick look in &lt;code&gt;slime.el&lt;/code&gt;, it is easy to remove bindings for
&lt;code&gt;slime-xref-prev-line&lt;/code&gt; and &lt;code&gt;slime-xref-next-line&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(define-key slime-xref-mode-map (kbd &amp;quot;n&amp;quot;) nil)
(define-key slime-xref-mode-map [remap next-line] nil)
(define-key slime-xref-mode-map (kbd &amp;quot;p&amp;quot;) nil)
(define-key slime-xref-mode-map [remap previous-line] nil)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are using &lt;code&gt;use-package&lt;/code&gt;, it is even simpler:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(use-package slime
  (:map slime-xref-mode-map
      ((&amp;quot;n&amp;quot;)
       ([remap next-line])
       (&amp;quot;p&amp;quot;)
       ([remap previous-line]))))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;changing-the-way-references-are-used&#34;&gt;Changing the way references are used&lt;/h2&gt;
&lt;p&gt;SLIME supports two ways to jump to a reference:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;With &lt;code&gt;return&lt;/code&gt; or &lt;code&gt;space&lt;/code&gt;, it spawns a buffer containing the source file and
close the cross-referencing buffer.&lt;/li&gt;
&lt;li&gt;With &lt;code&gt;v&lt;/code&gt;, it spawns the source file buffer but keeps the cross-referencing
buffer open and keeps it current.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is not practical to me, so I made a change. The default action, triggered
by &lt;code&gt;return&lt;/code&gt;, now keeps the cross-referencing buffer open and switches to the
source file in the same window. This way, I can switch back to the
cross-referencing buffer with &lt;code&gt;C-x b&lt;/code&gt; to select another reference without
spawning buffers in other windows (I do not like having my windows hijacked by
commands).&lt;/p&gt;
&lt;p&gt;To do that, I need a new function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-slime-show-xref ()
  &amp;quot;Display the source file of the cross-reference under the point
in the same window.&amp;quot;
  (interactive)
  (let ((location (slime-xref-location-at-point)))
    (slime-goto-source-location location)
    (with-selected-window (display-buffer-same-window (current-buffer) nil)
      (goto-char (point))
      (g-recenter-window))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the use of &lt;code&gt;g-recenter-window&lt;/code&gt;, a custom function to &lt;a href=&#34;https://www.n16f.net/blog/eye-level-window-centering-in-emacs/&#34;&gt;move the current
point at eye level&lt;/a&gt;. Feel free to use
the builtin &lt;code&gt;recenter&lt;/code&gt; function instead.&lt;/p&gt;
&lt;p&gt;I then bind the function to &lt;code&gt;return&lt;/code&gt; and remove other bindings:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(define-key slime-xref-mode-map (kbd &amp;quot;RET&amp;quot;) &#39;g-slime-show-xref)
(define-key slime-xref-mode-map (kbd &amp;quot;SPC&amp;quot;) nil)
(define-key slime-xref-mode-map (kbd &amp;quot;v&amp;quot;) nil)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Much better now!&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/replacing-projectile-by-project/">
      <title>Replacing Projectile by Project</title>
      <link>https://www.n16f.net/blog/replacing-projectile-by-project/</link>
      <pubDate>Tue, 27 Dec 2022 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/replacing-projectile-by-project/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I have been using &lt;a href=&#34;https://github.com/bbatsov/projectile&#34;&gt;Projectile&lt;/a&gt; for
years, and it served me well. While Projectile is really useful, it is a third
party package made of more than 8000 lines of code. Since the built-in
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/emacs/Projects.html&#34;&gt;Project&lt;/a&gt;
module has received lots of improvements since Emacs 28.1, I decided to give
it a try and see if I could remove Projectile from my Emacs setup.&lt;/p&gt;
&lt;h2 id=&#34;key-binding&#34;&gt;Key binding&lt;/h2&gt;
&lt;p&gt;The Project keymap is bound to &lt;code&gt;C-x p&lt;/code&gt; by default, but I am used to &lt;code&gt;C-c p&lt;/code&gt;.
This is easy to change, for example with &lt;code&gt;use-package&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(use-package project
  :bind-keymap
  ((&amp;quot;C-c p&amp;quot; . project-prefix-map)))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;switching-between-projects&#34;&gt;Switching between projects&lt;/h2&gt;
&lt;p&gt;By default, the project switching command uses a prompt letting you select a
command to run for the selected project. If you always use the same command,
you can configure it, allowing to switch project without any prompt.&lt;/p&gt;
&lt;p&gt;For example, to always display the project directory with Dired:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq project-switch-commands &#39;project-dired)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;search-using-helm-and-ag&#34;&gt;Search using Helm and AG&lt;/h2&gt;
&lt;p&gt;The Projectile feature I used the most is incremental project search using
&lt;code&gt;helm-projectile&lt;/code&gt; and &lt;code&gt;helm-ag&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Adding this feature to Project is not that hard. Let us write the search
function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-project-search ()
  (interactive)
  (let ((project (project-current t)))
    (helm-do-ag (project-root project))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And bind it to &lt;code&gt;C-c p s&lt;/code&gt; (replacing &lt;code&gt;project-shell&lt;/code&gt;, a command I do not use):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(use-package project
  :bind
  (:map project-prefix-map
        ((&amp;quot;s&amp;quot; . &#39;g-project-search))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One thing to be aware of: &lt;code&gt;helm-ag&lt;/code&gt; does not take patterns returned by
&lt;code&gt;project-ignores&lt;/code&gt; into consideration when filtering results. It is not that
much of a problem to me, since &lt;code&gt;ag&lt;/code&gt; already supports &lt;code&gt;.gitignore&lt;/code&gt; files&lt;/p&gt;
&lt;p&gt;But it would be an improvement to use &lt;code&gt;project-ignores&lt;/code&gt; and pass the pattern
list to &lt;code&gt;ag&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the mean time, I can also remove the &lt;code&gt;helm-projectile&lt;/code&gt; dependency.&lt;/p&gt;
&lt;h2 id=&#34;starting-eshell&#34;&gt;Starting Eshell&lt;/h2&gt;
&lt;p&gt;While both Projectile and Project can run Eshell in the current project, I
want the ability to start it the same way whether I am in a project or not.
Therefore I have a small function looking for a current project and running
Eshell the right way. Migrating to Project is easy:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-eshell ()
  &amp;quot;Start eshell at the root of the current project, or in the
current directory if the current buffer is not part of a
project.&amp;quot;
  (interactive)
  (if (project-current)
      (project-eshell)
    (eshell)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I bind it to &lt;code&gt;C-x s&lt;/code&gt; (&amp;ldquo;s&amp;rdquo; being for &amp;ldquo;shell&amp;rdquo;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(global-set-key (kbd &amp;quot;C-x s&amp;quot;) &#39;g-eshell)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The result is quite satisfying. It may not do everything Projectile supports,
but the features I use are all implemented. As a result, my Emacs setup is
simpler and lighter, relying on one less external dependency.&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/clearing-the-eshell-buffer/">
      <title>Clearing the Eshell Buffer</title>
      <link>https://www.n16f.net/blog/clearing-the-eshell-buffer/</link>
      <pubDate>Sat, 24 Dec 2022 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/clearing-the-eshell-buffer/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I have used the &lt;code&gt;C-l&lt;/code&gt; shortcut in &lt;a href=&#34;https://www.zsh.org/&#34;&gt;ZSH&lt;/a&gt; to clear the
screen for as long as I can remember. When I started using
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/eshell/&#34;&gt;Eshell&lt;/a&gt;, one of
the first problems I encountered was the inability to clear the buffer. I like
to remove the output of previous commands to be able to focus on the current
one, so let us script Emacs once again.&lt;/p&gt;
&lt;p&gt;After a quick look to the &lt;code&gt;eshell&lt;/code&gt; module, it seems we can do that in two
steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Clear the entire buffer with &lt;code&gt;(eshell/clear t)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Recreate the prompt with &lt;code&gt;(eshell-emit-prompt)&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A non-obvious edge case is that it should be possible to hit &lt;code&gt;C-l&lt;/code&gt; while
typing a command without losing what was typed. For that, we have to keep a
copy of the input content before clearing the screen and reinsert it after.&lt;/p&gt;
&lt;p&gt;The result is the following function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-eshell-clear ()
  (interactive)
  (let ((input (eshell-get-old-input)))
    (eshell/clear t)
    (eshell-emit-prompt)
    (insert input)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We then write a hook which binds the function to &lt;code&gt;C-l&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-eshell-init-keys ()
  (define-key eshell-mode-map (kbd &amp;quot;C-l&amp;quot;) &#39;g-eshell-clear))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And register the hook:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(add-hook &#39;eshell-mode-hook &#39;g-eshell-init-keys)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that clearing the screen means removing shell history from the buffer.
Not really an issue: instead of looking in the buffer, I use
&lt;code&gt;helm-eshell-history&lt;/code&gt; which is much more convenient.&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/investigating-a-ffap-issue-in-emacs/">
      <title>Investigating a FFAP issue in Emacs</title>
      <link>https://www.n16f.net/blog/investigating-a-ffap-issue-in-emacs/</link>
      <pubDate>Thu, 22 Dec 2022 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/investigating-a-ffap-issue-in-emacs/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I just encountered the strangest behaviour in Emacs. I was editing a shell
script, hit &lt;code&gt;C-x b&lt;/code&gt; to switch to another buffer, and Emacs suddenly froze with
the following message:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Pinging &amp;lt;hostname&amp;gt; (Commercial)...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where &lt;code&gt;&amp;lt;hostname&lt;/code&gt; was the hostname of a server used in the script.&lt;/p&gt;
&lt;p&gt;I really do not like the idea of my text editor pinging random servers just
because their name appears in a buffer, so I went to the bottom of it.&lt;/p&gt;
&lt;p&gt;Since I had no idea what caused this behaviour, I simply ran grep for the
&amp;ldquo;Pinging&amp;rdquo; message in the Emacs source repository and found it in the
&lt;code&gt;ffap-machine-p&lt;/code&gt; function. To find out how it was called, I enabled tracing,
making sure to print the current backtrace for each trace:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(trace-function &#39;ffap-machine-p nil &#39;backtrace)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This yielded the following (truncated) trace:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ffap-machine-p(&amp;quot;pkg.exograd.com&amp;quot;)
ffap-machine-at-point()
ffap-guesser()
ffap-guess-file-name-at-point()
run-hook-with-args-until-success(ffap-guess-file-name-at-point)
helm-guess-filename-at-point()
helm-fuzzy-highlight-matches(…)
helm--collect-matches(…)
helm-update(nil)
helm-read-from-minibuffer(nil nil nil nil nil nil nil)
helm-internal(…)
apply(helm-internal (…))
helm((helm-source-buffers-list helm-source-buffer-not-found) …)
apply(helm ((helm-source-buffers-list helm-source-buffer-not-found) …)
helm(…)
helm-buffers-list()
funcall-interactively(helm-buffers-list)
call-interactively(helm-buffers-list nil nil)
command-execute(helm-buffers-list)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Apparently, Helm tries to guess if the cursor is pointing to a filename using
the &lt;code&gt;ffap&lt;/code&gt; (for &amp;ldquo;find file at point&amp;rdquo;) module. For some reason, it does not
just identify paths, but also URLs and machine names. And the default strategy
to check if a machine is &amp;ldquo;real&amp;rdquo; and &amp;ldquo;reachable&amp;rdquo; (as documented in
&lt;code&gt;ffap-machine-p&lt;/code&gt; is to ping it.&lt;/p&gt;
&lt;p&gt;This kind is insanity is really disappointing from Emacs: a text editor should
absolutely not use the network in such a hidden way by default.&lt;/p&gt;
&lt;p&gt;The behaviour of &lt;code&gt;ffap-machine-p&lt;/code&gt; depends on three settings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ffap-machine-p-local&lt;/code&gt;: what to do if the hostname does not have a domain.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ffap-machine-p-known&lt;/code&gt;: what to do if the hostname has a known domain.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ffap-machine-p-unknown&lt;/code&gt;: what to do if the hostname has an unknown domain.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For all these variables, the value is either &lt;code&gt;accept&lt;/code&gt;, to indicate that the
hostname is a valid hostname, &lt;code&gt;reject&lt;/code&gt; to indicate it is not, or &lt;code&gt;ping&lt;/code&gt; to
check by sending a ping message.&lt;/p&gt;
&lt;p&gt;The way to fix this mess is to accept local and known hostnames while
rejecting unknown ones:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq ffap-machine-p-local &#39;accept)
(setq ffap-machine-p-known &#39;accept)
(setq ffap-machine-p-unknown &#39;reject)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are curious, &lt;code&gt;ffap&lt;/code&gt; uses &lt;code&gt;mail-extr-all-top-level-domains&lt;/code&gt; in the
&lt;code&gt;mail-extr&lt;/code&gt; module to assess if a domain is &amp;ldquo;known&amp;rdquo;. This function will
identify most common TLDs, but has never been updated for modern TLDs.
Something to keep in mind if you want to use it.&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/fixing-unquote-splicing-behaviour-with-paredit/">
      <title>Fixing unquote-splicing behaviour with Paredit</title>
      <link>https://www.n16f.net/blog/fixing-unquote-splicing-behaviour-with-paredit/</link>
      <pubDate>Tue, 13 Dec 2022 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/fixing-unquote-splicing-behaviour-with-paredit/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;&lt;a href=&#34;http://paredit.org/&#34;&gt;Paredit&lt;/a&gt; is an Emacs package for structural editing. It
is particularly useful in Lisp languages to manipulate expressions instead of
just characters.&lt;/p&gt;
&lt;p&gt;One of the numerous little features of Paredit is the automatic insertion of a
space character before a delimiting pair. For example, if you are typing
&lt;code&gt;(length&lt;/code&gt;, typing &lt;code&gt;(&lt;/code&gt; will have Paredit automatically insert a space character
before the opening parenthesis, to produce the expected &lt;code&gt;(length (&lt;/code&gt; content.&lt;/p&gt;
&lt;p&gt;Paredit is smart enough to avoid doing so after quote, backquote or comma
characters, but not after an unquote-splicing sequence (&lt;code&gt;,@&lt;/code&gt;) which is quite
annoying in languages such as Scheme or Common Lisp. As almost always in
Emacs, this behaviour can be customized.&lt;/p&gt;
&lt;p&gt;Paredit decides whether to add a space or not using the
&lt;code&gt;paredit-space-for-delimiter-p&lt;/code&gt; function, ending up with applying a list of
predicates from &lt;code&gt;paredit-space-for-delimiter-predicates&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let us add our own. For more flexibility, we will start by defining a list of
prefixes which are not to be followed by a space:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defvar g-paredit-no-space-prefixes (list &amp;quot;,@&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We then write our predicate which simply checks if we are right after one of
these prefixes:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-paredit-space-for-delimiter (endp delimiter)
  (let ((point (point)))
    (or endp
        (seq-every-p
         (lambda (prefix)
           (and (&amp;gt; point (length prefix))
                (let ((start (- point (length prefix)))
                      (end point))
                  (not (string= (buffer-substring start end) prefix)))))
         g-paredit-no-space-prefixes))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally we add a Paredit hook to append our predicate to the list:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-init-paredit-space-for-delimiter ()
  (add-to-list &#39;paredit-space-for-delimiter-predicates
               &#39;g-paredit-space-for-delimiter))

(add-hook &#39;paredit-mode-hook &#39;g-init-paredit-space-for-delimiter)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not only does it fix the problem for unquote-slicing, but it makes it easy to
add new prefixes. For example I immediately added &lt;code&gt;#p&lt;/code&gt; (used for pathnames in
Common Lisp, e.g. &lt;code&gt;#p&amp;quot;/usr/bin/&amp;quot;&lt;/code&gt;) to the list.&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/slime-compilation-tips/">
      <title>SLIME compilation tips</title>
      <link>https://www.n16f.net/blog/slime-compilation-tips/</link>
      <pubDate>Mon, 12 Dec 2022 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/slime-compilation-tips/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I recently went back to Common Lisp to
&lt;a href=&#34;https://github.com/galdor/advent-of-code-2022&#34;&gt;solve&lt;/a&gt; the daily problems of
the &lt;a href=&#34;https://adventofcode.com/2022&#34;&gt;Advent of Code&lt;/a&gt;. Of course it started with
installing and configuring &lt;a href=&#34;https://slime.common-lisp.dev/&#34;&gt;SLIME&lt;/a&gt;, the main
major mode used for Common Lisp development in Emacs.&lt;/p&gt;
&lt;p&gt;The most useful feature of SLIME is the ability to load sections of code into
the Common Lisp implementation currently running. One can use &lt;code&gt;C-c C-c&lt;/code&gt; to
evaluate the current top-level form, and &lt;code&gt;C-c C-k&lt;/code&gt; to reload the entire file,
making incremental development incredibly convenient.&lt;/p&gt;
&lt;p&gt;However I found the default configuration frustrating. Here are a few tips
which made my life easier.&lt;/p&gt;
&lt;h2 id=&#34;removing-the-compilation-error-prompt&#34;&gt;Removing the compilation error prompt&lt;/h2&gt;
&lt;p&gt;If the Common Lisp implementation fails to compile the file, SLIME will ask
the user if they want to load the fasl file (i.e. the compiled form of the
file) anyway.&lt;/p&gt;
&lt;p&gt;I cannot find a reason why one would want to load the ouput of a file that
failed to compile, and having to decline every time is quite annoying.&lt;/p&gt;
&lt;p&gt;Disable the prompt by setting &lt;code&gt;slime-load-failed-fasl&lt;/code&gt; to &lt;code&gt;&#39;never&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq slime-load-failed-fasl &#39;never)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;removing-the-slime-compilation-buffer-on-success&#34;&gt;Removing the SLIME compilation buffer on success&lt;/h2&gt;
&lt;p&gt;When compilation fails, SLIME creates a new window containing the diagnostic
reported by the Common Lisp implementation. I use &lt;code&gt;display-buffer-alist&lt;/code&gt; to
make sure the window is displayed on the right side of my three-column split,
and fix my code in the middle column.&lt;/p&gt;
&lt;p&gt;However if the next compilation succeeds, SLIME updates the buffer to indicate
the absence of error, but keeps the window open even though it is not useful
anymore, meaning that I have to switch to it and close it with &lt;code&gt;q&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;One can look at the &lt;code&gt;slime-compilation-finished&lt;/code&gt; function to see that SLIME
calls the function referenced by the &lt;code&gt;slime-compilation-finished-hook&lt;/code&gt;
variable right after the creation or update of the compilation buffer. The
default value is &lt;code&gt;slime-maybe-show-compilation-log&lt;/code&gt; which does not open a new
window if there is no error, but does not close an existing one.&lt;/p&gt;
&lt;p&gt;Let us write our own function and use it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-slime-maybe-show-compilation-log (notes)
  (with-struct (slime-compilation-result. notes successp)
      slime-last-compilation-result
    (when successp
      (let ((name (slime-buffer-name :compilation)))
        (when (get-buffer name)
          (kill-buffer name))))
    (slime-maybe-show-compilation-log notes)))
    
(setq slime-compilation-finished-hook &#39;g-slime-maybe-show-compilation-log)`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing crazy here, we obtain the compilation status (in a very SLIME-specific
way, &lt;code&gt;with-struct&lt;/code&gt; is not a standard Emacs Lisp macro) and kill the
compilation buffer if there is one while compilation succeeded.&lt;/p&gt;
&lt;h2 id=&#34;making-compilation-less-verbose&#34;&gt;Making compilation less verbose&lt;/h2&gt;
&lt;p&gt;Common Lisp specifies two variables, &lt;code&gt;*compile-verbose*&lt;/code&gt; and &lt;code&gt;*load-verbose*&lt;/code&gt;,
which control how much information is displayed during compilation and loading
respectively.&lt;/p&gt;
&lt;p&gt;My implementation of choice, &lt;a href=&#34;http://sbcl.org/&#34;&gt;SBCL&lt;/a&gt;, is quite chatty by
default. So I always set both variables to &lt;code&gt;nil&lt;/code&gt; in my &lt;code&gt;$HOME/.sbclrc&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;However SLIME forces &lt;code&gt;*compile-verbose*&lt;/code&gt;; this is done in SWANK, the Common
Lisp part of SLIME. When compiling a file, SLIME instructs the running Common
Lisp implementation to execute &lt;code&gt;swank:compile-file-for-emacs&lt;/code&gt; which forces
&lt;code&gt;*compile-verbose*&lt;/code&gt; to &lt;code&gt;t&lt;/code&gt; around the call of a list of functions susceptible
to handle the file. The one we are interested about is
&lt;code&gt;swank::swank-compile-file*&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First, let us write some Common Lisp code to replace the function with a wrapper
which sets &lt;code&gt;*compile-verbose*&lt;/code&gt; to &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(let ((old-function #&#39;swank::swank-compile-file*))
  (setf (fdefinition &#39;swank::swank-compile-file*)
        (lambda (pathname load-p &amp;amp;rest options &amp;amp;key policy &amp;amp;allow-other-keys)
          (declare (ignore policy))
          (let ((*compile-verbose* nil))
            (apply old-function pathname load-p options)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We save it to a file in the Emacs directory.&lt;/p&gt;
&lt;p&gt;In Emacs, we use the &lt;code&gt;slime-connected-hook&lt;/code&gt; hook to load the code into the
Common Lisp implementation as soon as Slime is connected to it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun g-slime-patch-swank-compilation-function ()
  (let* ((path (expand-file-name &amp;quot;swank-patch-compilation-function.lisp&amp;quot;
                                 user-emacs-directory))
         (lisp-path (slime-to-lisp-filename path)))
    (slime-eval-async `(swank:load-file ,lisp-path))))
    
(add-hook &#39;slime-connected-hook &#39;g-slime-patch-swank-compilation-function)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Quite a hack, but it works.&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/eye-level-window-centering-in-emacs/">
      <title>Eye level window centering in Emacs</title>
      <link>https://www.n16f.net/blog/eye-level-window-centering-in-emacs/</link>
      <pubDate>Sun, 30 Oct 2022 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/eye-level-window-centering-in-emacs/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;In the default Emacs configuration, &lt;code&gt;C-l&lt;/code&gt; is bound to &lt;code&gt;recenter-top-bottom&lt;/code&gt;.
This function has an interesting behaviour: when called once, it scrolls the
current window so that the current line appears at the middle of the screen.
When called several times in a row, it cycles through three scrolling
position: middle, top and bottom.&lt;/p&gt;
&lt;p&gt;This has always bugged me because I only need one of the three behaviours, and
none of these positions are useful to me. In pratice, I want to focus on the
line I am working on, which means putting it at eye level. In my case at
roughly 20% of the top of the window.&lt;/p&gt;
&lt;p&gt;Fortunately Emacs is easy to customize. As it turns out, &lt;code&gt;recenter-top-bottom&lt;/code&gt;
is based on &lt;code&gt;recenter&lt;/code&gt; which is easy to use:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defcustom g-recenter-window-eye-level 0.2
  &amp;quot;The relative position of the line considered as eye level in the
current window, as a ratio between 0 and 1.&amp;quot;)

(defun g-recenter-window ()
  &amp;quot;Scroll the window so that the current line is at eye level.&amp;quot;
  (interactive)
  (let ((line (round (* (window-height) g-recenter-window-eye-level))))
    (recenter line)))

(global-set-key (kbd &amp;quot;C-l&amp;quot;) &#39;g-recenter-window)
&lt;/code&gt;&lt;/pre&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/exporting-1password-data-for-backup/">
      <title>Exporting 1Password data for backup</title>
      <link>https://www.n16f.net/blog/exporting-1password-data-for-backup/</link>
      <pubDate>Sun, 26 Jun 2022 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/exporting-1password-data-for-backup/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;Storing credentials and confidential data in a secure location is important,
and I have been happy with &lt;a href=&#34;https://1password.com&#34;&gt;1Password&lt;/a&gt; for years.&lt;/p&gt;
&lt;p&gt;But having all this critical information stored in a single location is
dangerous; losing access to my 1Password account would be quite annoying,
forcing me to reinitialize passwords on dozens of websites and making me lose
a lot of information.&lt;/p&gt;
&lt;p&gt;Fortunately it is possible to export all data from 1Password. It does not seem
to be doable directly from their web interface, but their &lt;a href=&#34;https://1password.com/downloads/command-line/&#34;&gt;command-line
tool&lt;/a&gt; supports it.&lt;/p&gt;
&lt;p&gt;You will need first to connect your account. For example for a personal
account:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;op account add --address my.1password.com --email YOUR_EMAIL_ADDRESS
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that you will not stay signed-in, and will have to re-enter your password
later using: &lt;code&gt;eval $(op signin)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is no command to directly export all entries, but it can be done with a
small script. If you are not familiar with GPG, feel free to refer to my
&lt;a href=&#34;https://www.n16f.net/blog/using-gnupg/&#34;&gt;GnuPG introduction&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;#!/bin/sh

set -eu
set -o pipefail

# Configuration
gpg_key_id=&amp;quot;YOUR_GPG_KEY_ID&amp;quot;

# Command line
if [ $# -lt 1 ]; then
    echo &amp;quot;usage: $0 &amp;lt;output-file&amp;gt;&amp;quot; &amp;gt;&amp;amp;2
    exit 1
fi

output_file=$1

# Keep permissions tight
umask 177

# Sign in to the 1Password account
eval $(op signin)

# Create a temporary file to store the list of item ids (this list does not
# contain any confidential data).
item_file=$(mktemp)
trap &amp;quot;rm -f $item_file&amp;quot; EXIT

# Export a list containing the identifier and vault identifier of each item
op --format json item list | jq -r &#39;.[] | .id + &amp;quot; &amp;quot; + .vault.id&#39; &amp;gt;$item_file

# Export all items, encrypt all data and store them in the output file
while read item_id vault_id; do
    op --format json item get $item_id --vault $vault_id
done &amp;lt; $item_file | gpg --encrypt --sign --recipient $gpg_key_id &amp;gt;|$output
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The resulting file can then be stored anywhere, without any specific
protection since it is encrypted.&lt;/p&gt;
</description>

      
      <category>onepassword</category>
      
      <category>gpg</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/using-gnupg/">
      <title>Using GnuPG</title>
      <link>https://www.n16f.net/blog/using-gnupg/</link>
      <pubDate>Sat, 29 Jan 2022 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/using-gnupg/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;&lt;em&gt;Edit (2023-02-07)&lt;/em&gt;&lt;br&gt;
Updated to mention subkey selection during renewal.&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I recently tried to learn more about GnuPG and it turned out to be more
difficult than expected. So here are my notes regarding various GnuPG
operations.&lt;/p&gt;
&lt;p&gt;GnuPG 2.2.32 was used for all commands.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;h3 id=&#34;gnupg&#34;&gt;GnuPG&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;gpg&lt;/code&gt; command line tool looks for &lt;code&gt;$HOME/.gnupg/gpg.conf&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Options are provided using the command line arguments used by the &lt;code&gt;gpg&lt;/code&gt;
program without the &lt;code&gt;--&lt;/code&gt; prefix. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;verbose
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;causes GnuPG to behave as if the &lt;code&gt;--verbose&lt;/code&gt; option was passed to every
command.&lt;/p&gt;
&lt;p&gt;I went with the following configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Do not print any greeting message
no-greeting

# Do not include comment or version numbers in signatures
no-comments
no-emit-version

# Display long key ids to minimize collision risks
keyid-format long

# Set preferences when signing and encrypting
# Use gpg --version to see available algorithms
personal-digest-preferences SHA256
personal-cipher-preferences AES256
personal-compress-preferences ZLIB

# Use AES256 as default cipher
cipher-algo AES256

# Use SHA256 as default digest
digest-algo SHA256
cert-digest-algo SHA256

# Use ZLIB as default compression algorithm
compress-algo ZLIB

# Always export in ASCII format by default
armor
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;password-prompts&#34;&gt;Password prompts&lt;/h3&gt;
&lt;p&gt;GnuPG uses the pinentry collection of programs to prompt for passwords. We can
configure the GPG agent to always use the terminal version of pinentry instead
of spawning a graphical prompt.&lt;/p&gt;
&lt;p&gt;The agent is configured in &lt;code&gt;$HOME/.gnupg/gpg-agent.conf&lt;/code&gt;; to use the terminal
prompt, set the following option:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pinentry-program /usr/bin/pinentry-tty
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the agent has to be restarted after any modification:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;gpgconf --reload gpg-agent
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;managing-keys&#34;&gt;Managing keys&lt;/h2&gt;
&lt;h3 id=&#34;creating-a-key&#34;&gt;Creating a key&lt;/h3&gt;
&lt;p&gt;Use the &lt;code&gt;--full-gen-key&lt;/code&gt; option to create a new key. The &lt;code&gt;--gen-key&lt;/code&gt; option
can also be used but offer less control on the process.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;--expert&lt;/code&gt; option can also be used to access more advanced features such
as ECC support.&lt;/p&gt;
&lt;p&gt;The process is interactive.&lt;/p&gt;
&lt;p&gt;Once created, the new key should be visible in the list of keys which can be
visualized with &lt;code&gt;gpg --list-keys&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;using-multiple-identities&#34;&gt;Using multiple identities&lt;/h3&gt;
&lt;p&gt;A key can contain multiple identities. Edit the key with
&lt;code&gt;gpg --edit-key &amp;lt;key-id&amp;gt;&lt;/code&gt; and use the &lt;code&gt;adduid&lt;/code&gt; command to add a new identity.
You then need to trust the new identity. Use the &lt;code&gt;uid &amp;lt;n&amp;gt;&lt;/code&gt; command to select
the new uid, and run the &lt;code&gt;trust&lt;/code&gt; command to select the trust level (probably
&lt;code&gt;ultimate&lt;/code&gt; since this is your own key). Make sure to use the &lt;code&gt;primary&lt;/code&gt; command
to select the current identity as the main one. Use the &lt;code&gt;save&lt;/code&gt; command to
write the modification and exit.&lt;/p&gt;
&lt;p&gt;Note that modifying the list of identities changes the public key. If you
published it, you will need to update it.&lt;/p&gt;
&lt;h3 id=&#34;deleting-a-key&#34;&gt;Deleting a key&lt;/h3&gt;
&lt;p&gt;Keys can be deleted using &lt;code&gt;gpg --delete-secret-keys &amp;lt;key-id&amp;gt;&lt;/code&gt; and &lt;code&gt;gpg --delete-keys &amp;lt;key-id&amp;gt;&lt;/code&gt;. Note that the secret key must be deleted before the
associated public key.&lt;/p&gt;
&lt;h3 id=&#34;using-subkeys&#34;&gt;Using subkeys&lt;/h3&gt;
&lt;p&gt;Newly created keys contain a public key, a secret key which can be used for
signing and certifying other signatures, and a secret subkey which can be used
for encryption.&lt;/p&gt;
&lt;p&gt;It is a good idea to store the signing secret key in a safe location and to
generate new signing subkeys for each device which will need to sign content.
This way, if a device is compromised, one can revoke the associated signing
subkey and generate a new one without compromising the primary identity which
is guaranteed by the primary signing key.&lt;/p&gt;
&lt;p&gt;To create a new subkey, edit the key with &lt;code&gt;gpg --edit-key &amp;lt;keyid&amp;gt;&lt;/code&gt; and use the
&lt;code&gt;addkey&lt;/code&gt; command. Again, the &lt;code&gt;--expert&lt;/code&gt; option can be passed to the
&lt;code&gt;--edit-key&lt;/code&gt; command to be able to create ECC keys. The &lt;code&gt;addkey&lt;/code&gt; command will
ask for a kind of key; to create a signing sub key, opt to &amp;ldquo;set your own
capabilities&amp;rdquo;, and select the &lt;code&gt;sign&lt;/code&gt; and &lt;code&gt;authenticate&lt;/code&gt; capabilities. Use the
&lt;code&gt;save&lt;/code&gt; command to write the modification and exit.&lt;/p&gt;
&lt;p&gt;At this point, it is possible to export both the new signing subkey and the
encryption subkey and import then on the new device. Take care too use the &lt;code&gt;!&lt;/code&gt;
suffix to only export these subkeys, as described in the next section. For
example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;gpg --export-secret-keys &amp;lt;signing-subkey-id&amp;gt;! &amp;lt;encryption-subkey-id&amp;gt;!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to remove the primary secret key from the local GnuPG directory,
first obtain its keygrip using &lt;code&gt;gpg --with-keygrip --list-secret-keys&lt;/code&gt;, then
delete the key stored in &lt;code&gt;$HOME/.gnupg/private-keys-v1.d/&amp;lt;keygrip&amp;gt;.key&lt;/code&gt;. You
can check that the primary secret key is not here anymore: when listing secret
keys, the deleted key type will have the &lt;code&gt;#&lt;/code&gt; suffix, e.g. &lt;code&gt;sec#&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;exporting-keys&#34;&gt;Exporting keys&lt;/h3&gt;
&lt;p&gt;The most obvious way to share public keys is to export them from the local
keyring. The keyring is stored in &lt;code&gt;$HOME/.gnupg/pubring.kbx&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;gpg --export &amp;lt;user-id&amp;gt;&lt;/code&gt; command outputs one or more public keys
associated with a user id. Note that there are multiple way to select a user
id. See the &lt;a href=&#34;https://www.gnupg.org/documentation/manuals/gnupg/Specify-a-User-ID.html&#34;&gt;official
documentation&lt;/a&gt;
for more information.&lt;/p&gt;
&lt;p&gt;Using the key id or the email address is the simplest way to select the public
key.&lt;/p&gt;
&lt;p&gt;Secret key exports works the same way but use the &lt;code&gt;--export-secret-key&lt;/code&gt;
command. Note that exporting a subkey will by default export the entire secret
key. Add a &lt;code&gt;!&lt;/code&gt; suffix to the key id to export a single subkey.&lt;/p&gt;
&lt;p&gt;When backing up keys, use &lt;code&gt;--export-options backup&lt;/code&gt; to include all necessary
data for later restoration.&lt;/p&gt;
&lt;h3 id=&#34;publishing-a-key&#34;&gt;Publishing a key&lt;/h3&gt;
&lt;p&gt;Public keys can be published on internet servers to make it easier for other
people to download them.&lt;/p&gt;
&lt;p&gt;Note that the presence of a key on a public server does not imply it actually
belong to the person identified by the key: anyone can generate keys using any
name or email address.&lt;/p&gt;
&lt;p&gt;Also remember that published keys can never be deleted.&lt;/p&gt;
&lt;p&gt;To publish a key, simply use &lt;code&gt;gpg --keyserver &amp;lt;address&amp;gt; --send-keys &amp;lt;key-id&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;importing-a-key&#34;&gt;Importing a key&lt;/h3&gt;
&lt;p&gt;Public and private keys can be imported in the local keyring, making them
available for verification or decryption. Simply &lt;code&gt;gpg --import &amp;lt;file&amp;gt;&lt;/code&gt;. It is
also possible to pipe the public key directly into &lt;code&gt;gpg --import&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;revoking-a-key&#34;&gt;Revoking a key&lt;/h3&gt;
&lt;p&gt;Compromised keys must be revoked to signal that someone other than the owner
of the key has access to it.&lt;/p&gt;
&lt;p&gt;Revocation uses a revocation certificate which is generated from the private
key using &lt;code&gt;gpg --gen-revoke &amp;lt;key-id&amp;gt;&lt;/code&gt;. The command is interactive and asks for
the reason of the revocation.&lt;/p&gt;
&lt;p&gt;The revocation certificate can then be imported or published like any other
public key. After importing a revocation certificate in a keyring, the key
will be marked as revoked.&lt;/p&gt;
&lt;h3 id=&#34;renewing-a-key&#34;&gt;Renewing a key&lt;/h3&gt;
&lt;p&gt;If a key has an expiration date, it may need to be renewed. This can be done
by editing the key. Start the edition shell using &lt;code&gt;gpg --edit-key &amp;lt;key-id&amp;gt;&lt;/code&gt;,
and select the subkey you want to modify using the &lt;code&gt;key &amp;lt;index&amp;gt;&lt;/code&gt; command. Then
run the &lt;code&gt;expire&lt;/code&gt; interactive command. You can then write the modification and
exit with &lt;code&gt;save&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Do not forget to backup the new version of the private key and to publish the
new version of the public key.&lt;/p&gt;
&lt;p&gt;Note that you should generate and backup a new revocation certificate.&lt;/p&gt;
&lt;h2 id=&#34;using-keys&#34;&gt;Using keys&lt;/h2&gt;
&lt;h3 id=&#34;encrypting-a-file&#34;&gt;Encrypting a file&lt;/h3&gt;
&lt;p&gt;Data are encrypted using &lt;code&gt;gpg --encrypt --recipient &amp;lt;key-id&amp;gt;&lt;/code&gt;, and decrypted
using &lt;code&gt;gpg --decrypt&lt;/code&gt;. Encrypted messages contain the key id; decrypting the
file requires the presence of the associated secret key in the local GnuPG
directory.&lt;/p&gt;
&lt;h3 id=&#34;signing-a-file&#34;&gt;Signing a file&lt;/h3&gt;
&lt;p&gt;Data are signed using &lt;code&gt;gpg --sign &amp;lt;file&amp;gt;&lt;/code&gt;. The output contains both the data
and the signature.&lt;/p&gt;
&lt;p&gt;Signed data are verified using &lt;code&gt;gpg --verify&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is also possible to generate a separate — or detached — signature using
&lt;code&gt;gpg --detach-sig&lt;/code&gt;, e.g.:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;gpg --output my-file.asc --detach-sig my-file
gpg --verify my-file.asc my-file
&lt;/code&gt;&lt;/pre&gt;
</description>

      
      <category>gpg</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/default-configuration-for-the-erlang-logger/">
      <title>Default configuration for the Erlang logger</title>
      <link>https://www.n16f.net/blog/default-configuration-for-the-erlang-logger/</link>
      <pubDate>Sun, 15 Nov 2020 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/default-configuration-for-the-erlang-logger/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;The Erlang &lt;a href=&#34;https://erlang.org/doc/man/logger.html&#34;&gt;logger application&lt;/a&gt;
introduced in OTP 21 is extremely flexible, but the default settings are not
the most practical for development purposes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The default log level is &lt;code&gt;notice&lt;/code&gt;, meaning that &lt;code&gt;info&lt;/code&gt; and &lt;code&gt;debug&lt;/code&gt; messages
will not be printed.&lt;/li&gt;
&lt;li&gt;Log messages with a domain other than &lt;code&gt;[otp]&lt;/code&gt; will not be printed.&lt;/li&gt;
&lt;li&gt;Each printed log message will start with a cumbersome banner, e.g. &lt;code&gt;=NOTICE REPORT==== 15-Nov-2020::11:20:10.421265 ===&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While it is possible to change logger settings in the system configuration
file, it means that it has to be done for each project you work
on.&lt;/p&gt;
&lt;p&gt;Fortunately, Erlang has the ability to load and execute code from a file at
&lt;code&gt;$HOME/.erlang&lt;/code&gt;. For example, I use the following code to configure the
logger:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;LogHandler = #{level =&amp;gt; debug,
               filter_default =&amp;gt; log,
               filters =&amp;gt; [{remote_group_leader,
                            {fun logger_filters:remote_gl/2, stop}},
                           {progress,
                            {fun logger_filters:progress/2, stop}},
                           {sasl,
                            {fun logger_filters:domain/2,
                             {stop, sub, [otp, sasl]}}}],
               formatter =&amp;gt; {logger_formatter,
                             #{single_line =&amp;gt; false,
                               template =&amp;gt;
                                   [domain, &amp;quot; &amp;quot;, level, &amp;quot;: &amp;quot;, msg, &amp;quot;\n&amp;quot;]}}},
application:set_env(kernel, logger,
                    [{handler, default, logger_std_h, LogHandler}]),
application:set_env(kernel, logger_level, debug),
logger:set_handler_config(default, LogHandler).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For development, I went with the following settings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All messages are logged. Debug logging can still be disabled on a
per-project basis (using a local system configuration file) for applications
which are too verbose.&lt;/li&gt;
&lt;li&gt;Remote messages and progress messages are dropped, they are usually useless
during development.&lt;/li&gt;
&lt;li&gt;SASL messages are also dropped by default, they tend to be quite redundant.&lt;/li&gt;
&lt;li&gt;We keep multi-line display, which is really useful to read stack traces.&lt;/li&gt;
&lt;li&gt;Log messages are prefixed by the domain (see &lt;a href=&#34;https://erlang.org/doc/man/logger_filters.html#domain-2&#34;&gt;the
documentation&lt;/a&gt; for
more information about domains) and the log level.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that while this setup will work with &lt;code&gt;erl&lt;/code&gt;, the &lt;a href=&#34;http://rebar3.org/docs/commands/#shell&#34;&gt;Rebar3
shell&lt;/a&gt; requires some adjustments.&lt;/p&gt;
&lt;p&gt;Rebar3 must be installed from source with a start script, because the
packaged escript-based version does not load &lt;code&gt;$HOME/.erlang&lt;/code&gt;. There is an
&lt;a href=&#34;https://github.com/erlang/rebar3/issues/2425&#34;&gt;open issue&lt;/a&gt;, but in the mean
time, you can install Rebar3 from source:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clone the &lt;a href=&#34;https://github.com/erlang/rebar3.git&#34;&gt;repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Build Rebar3: &lt;code&gt;./bootstrap&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Install it locally: &lt;code&gt;./rebar3 local install&lt;/code&gt;. Note that &lt;code&gt;./rebar3 local upgrade&lt;/code&gt; will not use the code you just built, but will always fetch a
stable release from the internet.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;$HOME/.cache/rebar3/bin&lt;/code&gt; to your &lt;code&gt;PATH&lt;/code&gt; environment variable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is also an issue with logger configuration reloading in the shell. I
created a &lt;a href=&#34;https://github.com/erlang/rebar3/pull/2428&#34;&gt;PR&lt;/a&gt;, but in the mean
time you will need to apply &lt;a href=&#34;https://github.com/galdor/rebar3/commit/89de8551f0ec1304dd6e7aec40ec4b1afcab7f83&#34;&gt;this
patch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, if you load extra system configuration files with the &lt;code&gt;--config&lt;/code&gt;
command line option, you will have to make sure that any logger modification
performed in &lt;code&gt;$HOME/.erlang&lt;/code&gt; is also applied to system configuration
(e.g. with &lt;code&gt;application:set_env/3&lt;/code&gt;), since Rebar3 will reload the logger
configuration from the environment, ignoring any live setting.&lt;/p&gt;
</description>

      
      <category>erlang</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/unknown-type-specifications-with-dialyzer/">
      <title>Unknown type specifications with Dialyzer</title>
      <link>https://www.n16f.net/blog/unknown-type-specifications-with-dialyzer/</link>
      <pubDate>Mon, 07 Sep 2020 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/unknown-type-specifications-with-dialyzer/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I use &lt;a href=&#34;https://erlang.org/doc/apps/dialyzer/dialyzer_chapter.html&#34;&gt;Dialyzer&lt;/a&gt; a
lot, and it has always been useful to expose various errors in my Erlang code.&lt;/p&gt;
&lt;p&gt;Unfortunately, I recently discovered an unexpected behaviour: by default,
Dialyzer ignores unknown types. It is very surprising and suddently makes me
doubt any piece of Erlang code I ever wrote.&lt;/p&gt;
&lt;p&gt;As it turns out, there is a Dialyzer flag to detect and report these unknown
types. With &lt;a href=&#34;https://www.rebar3.org&#34;&gt;Rebar3&lt;/a&gt;, it can be added to the
&lt;code&gt;dialyzer&lt;/code&gt; setting:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;{dialyzer, [{warnings, [unknown]}]}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Activating unknown type detection could lead to interesting Dialyzer failures,
when a type is part of an unknown module. Care should be taken to list
application dependencies in the &lt;a href=&#34;https://erlang.org/doc/man/app.html&#34;&gt;application resource
file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In some cases, it is necessary to reference a type from a module whose
application is not a dependency of the current project. In that case, the
application in question can be added to the
&lt;a href=&#34;https://erlang.org/doc/apps/dialyzer/dialyzer_chapter.html#plt&#34;&gt;PLT&lt;/a&gt; with the
&lt;code&gt;plt_extra_apps&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;{dialyzer, [{plt_extra_apps, [public_key]},
            {warnings, [unknown]}]}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Activating unknown type detection for all my Erlang projects has revealed
various issues, so it is definitely an option I will keep enabled in the
future.&lt;/p&gt;
</description>

      
      <category>erlang</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/local-clhs-access-in-emacs/">
      <title>Local CLHS access in Emacs</title>
      <link>https://www.n16f.net/blog/local-clhs-access-in-emacs/</link>
      <pubDate>Wed, 01 Jan 2020 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/local-clhs-access-in-emacs/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;The CLHS, or Common Lisp HyperSpec, is one of the most important resource for
any Common Lisp developer. It is derived from the official Common Lisp
standard, and contains documentation for every aspect of the language.&lt;/p&gt;
&lt;p&gt;While it is currently made available
&lt;a href=&#34;http://www.lispworks.com/documentation/HyperSpec/Front/index.htm&#34;&gt;online&lt;/a&gt; by
&lt;a href=&#34;http://www.lispworks.com/documentation/common-lisp.html&#34;&gt;LispWorks&lt;/a&gt;, it can
be useful to be able to access it locally, for example when you do not have
any internet connection available.&lt;/p&gt;
&lt;p&gt;For this purpose, LispWorks provides an
&lt;a href=&#34;ftp://ftp.lispworks.com/pub/software_tools/reference/HyperSpec-7-0.tar.gz&#34;&gt;archive&lt;/a&gt;
which can be downloaded and browsed offline.&lt;/p&gt;
&lt;p&gt;While the HyperSpec is valuable on its own, the
&lt;a href=&#34;https://common-lisp.net/project/slime/&#34;&gt;SLIME&lt;/a&gt; Emacs mode provides various
functions to make it even more useful.&lt;/p&gt;
&lt;p&gt;I have found the following functions particularily useful:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;slime-documentation-lookup&lt;/code&gt;, or &lt;code&gt;C-c C-d h&lt;/code&gt; to browse the
documentation associated with a symbol.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;common-lisp-hyperspec-format&lt;/code&gt;, or &lt;code&gt;C-c C-d ~&lt;/code&gt;, to lookup &lt;code&gt;format&lt;/code&gt; control
characters.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;common-lisp-hyperspec-glossary-term&lt;/code&gt;, or &lt;code&gt;C-c C-d g&lt;/code&gt;, to access terms in
the
&lt;a href=&#34;http://www.lispworks.com/documentation/lw50/CLHS/Front/index.htm&#34;&gt;glossary&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the default configuration, Emacs will use the online HyperSpec. You can
have it use a local copy by setting &lt;code&gt;common-lisp-hyperspec-root&lt;/code&gt; to a file
URI. For example, if you downloaded the content of the CLHS archive to
&lt;code&gt;~/common-lisp/&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(setq common-lisp-hyperspec-root
  (concat &amp;quot;file://&amp;quot; (expand-file-name &amp;quot;~/common-lisp/HyperSpec/&amp;quot;)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if you configure Emacs to use the
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_mono/eww.html&#34;&gt;EWW&lt;/a&gt; web
browser, you can work with the CLHS without leaving your editor.&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/asdf-in-common-lisp-scripts/">
      <title>ASDF in Common Lisp scripts</title>
      <link>https://www.n16f.net/blog/asdf-in-common-lisp-scripts/</link>
      <pubDate>Mon, 30 Dec 2019 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/asdf-in-common-lisp-scripts/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;The usual way to develop programs in Common Lisp is to use
&lt;a href=&#34;https://common-lisp.net/project/slime/&#34;&gt;SLIME&lt;/a&gt; in Emacs, which starts an
implementation and provides a REPL. When a program needs to be running in
production, one can either execute it from source or compile it to an
executable core, for example with &lt;code&gt;sb-ext:save-lisp-and-die&lt;/code&gt; in SBCL.&lt;/p&gt;
&lt;p&gt;While executable cores works well for conventional applications, they are less
suitable for small scripts which should be easy to run without having to build
anything.&lt;/p&gt;
&lt;p&gt;Writing a basic script with SBCL is easy:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;#!/bin/sh
#|
exec sbcl --script &amp;quot;$0&amp;quot; &amp;quot;$@&amp;quot;
|#

(format t &amp;quot;Hello world!~%&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since UNIX shebangs cannot be used to run commands with more than one
argument, it is impossible to call SBCL directly (it requires the &lt;code&gt;--script&lt;/code&gt;
argument, and &lt;code&gt;#!/usr/bin/env sbcl --script&lt;/code&gt; contains two arguments). However
it is possible to start as a simple shell script and just execute SBCL with
the right arguments. And since we can include any shell commands, it is
possible to support multiple Common Lisp implementations depending on the
environment.&lt;/p&gt;
&lt;p&gt;This method works. But if your script has any dependency, configuring
&lt;a href=&#34;https://common-lisp.net/project/asdf/&#34;&gt;ASDF&lt;/a&gt; can be tricky. ASDF can pick up
system directory paths from &lt;a href=&#34;https://common-lisp.net/project/asdf/asdf.html#Controlling-where-ASDF-searches-for-systems&#34;&gt;multiple
places&lt;/a&gt;,
and you do not want your program to depend on your development environment. If
you run your script in a CI environment or a production system, you will not
have access to your ASDF configuration and your systems.&lt;/p&gt;
&lt;p&gt;Fortunately, ASDF makes it possible to manually configure the source registry
at runtime using &lt;code&gt;asdf:initialize-source-registry&lt;/code&gt;, giving you total control
on the places which will be used to find systems.&lt;/p&gt;
&lt;p&gt;For example, if your Common Lisp systems happen to be stored in a &lt;code&gt;systems&lt;/code&gt;
directory at the same level as your script, you can use the &lt;code&gt;:here&lt;/code&gt;
&lt;a href=&#34;https://common-lisp.net/project/asdf/asdf.html#The-here-directive&#34;&gt;directive&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;#!/bin/sh
#|
exec sbcl --script &amp;quot;$0&amp;quot; &amp;quot;$@&amp;quot;
|#

(require &#39;asdf)

(asdf:initialize-source-registry
 `(:source-registry :ignore-inherited-configuration
                    (:tree (:here &amp;quot;systems&amp;quot;))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if you store all your systems in a Git repository, you can use
&lt;a href=&#34;https://git-scm.com/book/en/v2/Git-Tools-Submodules&#34;&gt;submodules&lt;/a&gt; to include a
&lt;code&gt;systems&lt;/code&gt; directory in every project, making it simple to manage the systems
you need and their version. Additionally, anyone with an implementation
installed, SBCL in this example, can now execute these scripts without having
to install or configure anything. This is quite useful when you work with
people who do not know Common Lisp.&lt;/p&gt;
&lt;p&gt;Of course, you can use the same method when building executables: just create
a script whose only job is to setup ASDF, load your program, and dump an
executable core. This way, you can make sure you control exactly which set of
systems is used. And it can easily be run in a CI environment.&lt;/p&gt;
</description>

      
      <category>lisp</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/persistent-history-for-the-erlang-shell/">
      <title>Persistent history for the Erlang shell</title>
      <link>https://www.n16f.net/blog/persistent-history-for-the-erlang-shell/</link>
      <pubDate>Mon, 25 Nov 2019 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/persistent-history-for-the-erlang-shell/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;While the &lt;code&gt;erl&lt;/code&gt; application is really useful to tinker with Erlang modules,
the lack of a persistent history has always been annoying. I recently
discovered via &lt;a href=&#34;https://adoptingerlang.org/docs/development/setup/&#34;&gt;Adopting
Erlang&lt;/a&gt; that the history
can be made persistent since Erlang 20 with specific flags, which can be added
to the &lt;code&gt;ERL_AFLAGS&lt;/code&gt; environment variable to have them enabled by default.&lt;/p&gt;
&lt;p&gt;Shell history is handled by the &lt;code&gt;group_history&lt;/code&gt; module; since this module is
part of the &lt;code&gt;kernel&lt;/code&gt; application, the configuration flags are provided with
the &lt;code&gt;-kernel&lt;/code&gt; command line argument (see the [erl
documentation](application:get_env(kernel, shell_history_drop)), specifically
the &lt;code&gt;-Application Par Val&lt;/code&gt; syntax. An interesting property of this
mechanism is that parameters are passed as Erlang terms. Therefore a string
should be passed in shell as &lt;code&gt;&#39;&amp;quot;foo bar&amp;quot;&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The module will simply use &lt;code&gt;application:get_env(kernel, Name)&lt;/code&gt; to read these
parameters.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;http://erlang.org/doc/man/kernel_app.html&#34;&gt;kernel_app documentation&lt;/a&gt;
presents the following parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;shell_history&lt;/code&gt;: whether to enable or disable permanent history.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shell_history_drop&lt;/code&gt;: a list of commands to be omitted from the history.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shell_history_file_bytes&lt;/code&gt;: the maximum size of the history.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shell_history_path&lt;/code&gt;: the path of the directory to write history to.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is really simple to add these flags to &lt;code&gt;ERL_AFLAGS&lt;/code&gt;, for example in
&lt;code&gt;$HOME/.zshenv&lt;/code&gt; for the zsh shell:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;ERL_AFLAGS=&amp;quot;+pc unicode&amp;quot;
ERL_AFLAGS=&amp;quot;$ERL_AFLAGS -kernel shell_history enabled&amp;quot;
ERL_AFLAGS=&amp;quot;$ERL_AFLAGS -kernel shell_history_path &#39;\&amp;quot;$HOME/.erl_history\&amp;quot;&#39;&amp;quot;

export ERL_AFLAGS
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I only found two small issues with this feature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There is a small delay between the time an entry is saved and the moment is
is actually written to disk. Therefore quitting quickly after entering a
command may result in the entry missing from the history.&lt;/li&gt;
&lt;li&gt;History searching with &lt;code&gt;C-r&lt;/code&gt; seems to work, but is far less powerful than
the readline feature. Good enough I guess.&lt;/li&gt;
&lt;/ul&gt;
</description>

      
      <category>erlang</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/reading-rfc-documents-in-emacs/">
      <title>Reading RFC documents in Emacs</title>
      <link>https://www.n16f.net/blog/reading-rfc-documents-in-emacs/</link>
      <pubDate>Sun, 02 Jun 2019 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/reading-rfc-documents-in-emacs/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I am used to read RFC documents in Emacs by opening them as simple text
files. But I was always annoyed by the impossibility to follow references to
other documents. Additionally, searching for the right RFC usually involve
going back to the web browser and Google while I would prefer staying in
Emacs.&lt;/p&gt;
&lt;p&gt;Since I enjoy &lt;a href=&#34;https://github.com/emacs-helm/helm&#34;&gt;Helm&lt;/a&gt; so much, I thought it
would be easy to parse the index of all RFC documents, and create a browser
allowing me to pick a RFC. And since I was writing some elisp, I ended up
writing a major mode to highlight parts of RFC documents, including adding
links when another RFC is mentioned.&lt;/p&gt;
&lt;p&gt;So here is &lt;a href=&#34;https://github.com/galdor/rfc-mode&#34;&gt;rfc-mode&lt;/a&gt;. It is quite simple
for the time being, and I have a few ideas for more features, but it is
already quite useful.&lt;/p&gt;
&lt;p&gt;It is also available on &lt;a href=&#34;https://melpa.org/#/rfc-mode&#34;&gt;MELPA&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./rfc-mode-browser.png&#34; alt=&#34;RFC browser&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./rfc-mode-reader.png&#34; alt=&#34;RFC reader&#34;&gt;&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/printing-non-ascii-characters-in-erlang-releases/">
      <title>Printing non-ascii characters in Erlang releases</title>
      <link>https://www.n16f.net/blog/printing-non-ascii-characters-in-erlang-releases/</link>
      <pubDate>Fri, 04 Jan 2019 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/printing-non-ascii-characters-in-erlang-releases/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I have been learning a lot about Erlang recently, and I stumbled upon a
strange behaviour: printing strings containing non-ascii characters,
e.g. &lt;code&gt;&amp;quot;μs&amp;quot;&lt;/code&gt;, using &lt;code&gt;io:format&lt;/code&gt; and the &lt;code&gt;~ts&lt;/code&gt; control sequence behaves
differently depending on the way the program is run:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In &lt;code&gt;rebar3 shell&lt;/code&gt;, &lt;code&gt;rebar3 run&lt;/code&gt;, or a release running with a console: &lt;code&gt;&amp;quot;μs&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;With a release running in foreground: &lt;code&gt;&amp;quot;\x{3BC}s&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I first checked the shell environment, but &lt;code&gt;os:getenv(&amp;quot;LANG&amp;quot;)&lt;/code&gt; correctly
returns &lt;code&gt;en_US.UTF-8&lt;/code&gt; in both cases. I then suspected the Erlang VM was
initialized with a different &lt;code&gt;+pc&lt;/code&gt; flag in console mode, but adding &lt;code&gt;+pc unicode&lt;/code&gt; to &lt;code&gt;vm.args&lt;/code&gt; did not change anything.&lt;/p&gt;
&lt;p&gt;Finally I ended up on the very detailed &lt;a href=&#34;http://erlang.org/doc/apps/stdlib/io_protocol.html&#34;&gt;IO protocol
documentation&lt;/a&gt;. Printing
the IO configuration of the standard output, obtained with &lt;code&gt;io:getopts()&lt;/code&gt;,
yields different results depending on the environment: in interactive
environments and with &lt;code&gt;rebar3 run&lt;/code&gt;, the &lt;code&gt;encoding&lt;/code&gt; parameter is set to
&lt;code&gt;unicode&lt;/code&gt;, but is set to &lt;code&gt;latin1&lt;/code&gt; in releases running in foreground.&lt;/p&gt;
&lt;p&gt;As it turns out, configuring the standard IO device to output UTF-8 encoded
strings is a simple as calling &lt;code&gt;io:setopts([{encoding, unicode}])&lt;/code&gt; when the
application starts. This is definitely something I will add to all my
applications from now on.&lt;/p&gt;
</description>

      
      <category>erlang</category>
      
    </item>
    
    <item xml:base="https://www.n16f.net/blog/buffer-ordering-with-helm/">
      <title>Buffer ordering with Helm</title>
      <link>https://www.n16f.net/blog/buffer-ordering-with-helm/</link>
      <pubDate>Sun, 21 Oct 2018 18:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://www.n16f.net/blog/buffer-ordering-with-helm/</guid>
      <author>nicolas@n16f.net (Nicolas Martyanoff)</author>

      <description>&lt;p&gt;I have been using Emacs for some time, and
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_mono/ido.html&#34;&gt;ido&lt;/a&gt; has
always been my favourite way to switch buffers.&lt;/p&gt;
&lt;p&gt;But recently I discovered and started using
&lt;a href=&#34;https://github.com/emacs-helm/helm&#34;&gt;Helm&lt;/a&gt;, a package based on incremental
completion which can provide lots of interesting features. One of them being
buffer switching.&lt;/p&gt;
&lt;p&gt;The simplest way to use Helm to switch buffers is
&lt;code&gt;helm-buffers-list&lt;/code&gt;. Personally I use &lt;code&gt;C-x b&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(global-set-key (kbd &amp;quot;C-x b&amp;quot;) &#39;helm-buffers-list)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I really like that &lt;code&gt;helm-buffer-list&lt;/code&gt; orders buffers using the last time they
were used. However as soon as I start typing something to narrow the
selection, Helm switches to a different ordering based on the length of buffer
names. A &lt;a href=&#34;https://github.com/emacs-helm/helm/issues/763&#34;&gt;bug report&lt;/a&gt; was
submitted, but apparently, this is the intended behaviour.&lt;/p&gt;
&lt;p&gt;Fortunately, it is possible to override this behaviour, as suggested in
another &lt;a href=&#34;https://github.com/emacs-helm/helm/issues/1492&#34;&gt;Github issue&lt;/a&gt;.
Ordering is done in the &lt;code&gt;helm-buffers-sort-transformer&lt;/code&gt; function; we could
replace it, but it is cleaner to
&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Functions.html&#34;&gt;advise&lt;/a&gt;
it.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun nm-around-helm-buffers-sort-transformer (candidates source)
  candidates)

(advice-add &#39;helm-buffers-sort-transformer
            :override #&#39;nm-around-helm-buffers-sort-transformer)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This way we keep the LRU-style ordering even when narrowing the selection.&lt;/p&gt;
</description>

      
      <category>emacs</category>
      
    </item>
    
  </channel>
</rss>
