<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Andrey Listopadov</title>
    <link>https://andreyor.st/tags/editor-configuration/</link>
    <image>
      <title>Andrey Listopadov</title>
      <link>https://andreyor.st/tags/editor-configuration/</link>
      <url>https://andreyor.st/tags/editor-configuration/favicon-64.png</url>
    </image>
    <description>Posts tagged 'editor-configuration' by Andrey Listopadov</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>Andrey Listopadov 2020-2026 - This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</copyright>
    <lastBuildDate>Wed, 20 Jul 2022 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://andreyor.st/tags/editor-configuration/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Limiting Horizontal Scroll In Emacs</title>
      <link>https://andreyor.st/posts/2022-07-20-limiting-horizontal-scroll-in-emacs/</link>
      <guid>https://andreyor.st/posts/2022-07-20-limiting-horizontal-scroll-in-emacs/</guid>
      <description>&lt;p&gt;I use Emacs mainly for programming, but I also write a lot of non-code in it, either for this blog, documentation for my projects, or just when I take notes.
And I do it with a git-friendly style of formatting with a single sentence per line.
And because of that, I enable line truncation, to avoid wrapping text, because when the text is written this way, the wrapped version looks like a mess, in my opinion.
This also helps with code, that has long lines - the formatting is preserved and unexpected multi-line expressions don&amp;rsquo;t mess me up.&lt;/p&gt;
&lt;p&gt;But because lines get truncated when exceeding window width, it means that I have to use horizontal scrolling.
I rarely actually use scrolling, because this is a very good indication of a very long sentence, that should be rephrased into smaller ones, but still.
However, when I do have to scroll, there&amp;rsquo;s a problem - Emacs doesn&amp;rsquo;t limit horizontal scrolling properly.&lt;/p&gt;
&lt;p&gt;If you open some other editor, like Gedit, and disable line wrapping, you&amp;rsquo;ll see that the most amount of horizontal scrolling you can get is basically such that the last character of the longest line is at the right border of the window.
In Emacs, however, it&amp;rsquo;s not limited like that, and you can scroll past the last character of the longest line, and basically overshoot.
This can be handy when you want to have some empty space to the right, for comfortable writing, but I don&amp;rsquo;t need that.
Instead, I would like to get the behavior of editors like Gedit.&lt;/p&gt;
&lt;p&gt;Turns out, if you enable &lt;code&gt;horizontal-scroll-bar-mode&lt;/code&gt;, Emacs will show the scroll-bar at the bottom, which will not allow you to over-scroll text, like in Gedit.
But if you use a touchpad, or manually call &lt;code&gt;scroll-left&lt;/code&gt; it will continue scrolling.
So let&amp;rsquo;s fix this.&lt;/p&gt;
&lt;p&gt;The first thing we&amp;rsquo;ll need is a custom predicate, that will check if any line in the buffer exceeds buffer width.
There are some corner cases to be aware of, like if the buffer&amp;rsquo;s font size is changed via &lt;code&gt;text-scale-adjust&lt;/code&gt;, or if the line numbers are displayed, so this predicate should account for that too.
I wrote such predicate like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;truncated-lines-p&lt;/span&gt; ()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Non-nil if any line is longer than &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`window-width&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; + &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`window-hscroll&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;Returns t if any line exceeds the right border of the window.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;Used for stopping scroll from going beyond the longest line.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;Based on &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`so-long-detected-long-line-p&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;save-excursion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;goto-char&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point-min&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let*&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-width&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; This computes a more accurate width rather than `window-width&amp;#39;, and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; respects `text-scale-mode&amp;#39; font width.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;/&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-body-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;t&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-font-width&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hscroll-offset&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; `window-hscroll&amp;#39; returns columns that are not affected by&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; `text-scale-mode&amp;#39;.  Because of that, we have to recompute the correct&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; `window-hscroll&amp;#39; by multiplying it with a non-scaled value and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; dividing it with a scaled width value, rounding it to the upper&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; boundary.  Since there&amp;#39;s no way to get unscaled value, we have to get&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; a width of a face that is not scaled by `text-scale-mode&amp;#39;, such as&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; `window-divider&amp;#39; face.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ceiling&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;/&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-hscroll&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-font-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;window-divider&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;float&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-font-width&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line-number-width&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; Compensate for line number width.  Add support for&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; other modes if you use any, like `linum-mode&amp;#39;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bound-and-true-p&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;display-line-numbers-mode&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;display-line-numbers-width&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              0))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;threshold&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hscroll-offset&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line-number-width&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         -2))) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;; -2 to compensate rounding during calculation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;excessive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;not&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;eobp&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;start&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;save-restriction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;narrow-to-region&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;start&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;min&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;start&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;threshold&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point-max&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;forward-line&lt;/span&gt; 1))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;unless&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bolp&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;eobp&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;=&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;point&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;start&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;threshold&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;excessive&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;t&lt;/span&gt;))))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To illustrate what it does, here&amp;rsquo;s a screenshot of the Emacs window with this blog post, as I edit it:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2022-07-20-limiting-horizontal-scroll-in-emacs/lines_exceed_window_width.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;I&amp;rsquo;ve made the frame smaller and enabled the &lt;code&gt;horizontal-scroll-bar-mode&lt;/code&gt; to better show what I mean.
In the echo area &lt;code&gt;t&lt;/code&gt; is displayed because I&amp;rsquo;ve called &lt;code&gt;truncated-lines-p&lt;/code&gt;, and it shows that some line exceeds the width of the window.
You can see that lines go beyond the right border (though there&amp;rsquo;s no arrow in the fringe, as I disabled these), and if I scroll with the scroll-bar, Emacs stops scrolling at about this position:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2022-07-20-limiting-horizontal-scroll-in-emacs/line_end_reached.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Now &lt;code&gt;nil&lt;/code&gt; is displayed in the echo area because I&amp;rsquo;ve called &lt;code&gt;truncated-lines-p&lt;/code&gt; again, which means that the predicate works, since there&amp;rsquo;s no need to scroll anymore, all lines are not truncated by the right border.
However, I can continue scrolling if I use the touchpad:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2022-07-20-limiting-horizontal-scroll-in-emacs/overscroll.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Note, that the handle in the scroll bar changed its width.
Emacs calculates the width of the handle based on the longest line currently visible in the window, meaning that it will change depending on the position in the buffer.
And perhaps scroll-bar width limited for what you&amp;rsquo;re seeing is a performance optimization.
My function does it for the whole buffer, and there is a lot of code for calculating text width with respect to the horizontal scroll.
Thus, the calculation process may not seem very optimal, but benchmarking this function seems to have decent performance on my &lt;code&gt;1603&lt;/code&gt; lines &lt;code&gt;init.el&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; some lines exceed the width&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;benchmark&lt;/span&gt; 1000 &amp;#39;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;truncated-lines-p&lt;/span&gt;)) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;; Elapsed time: 0.597171s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; no lines exceed the width&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;benchmark&lt;/span&gt; 1000 &amp;#39;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;truncated-lines-p&lt;/span&gt;)) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;; Elapsed time: 1.247346s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In practice, I never feel any slowdown from it.
The only thing left is to make &lt;code&gt;sroll-left&lt;/code&gt; to actually use it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;define-advice&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;scroll-left&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:before-while&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;amp;rest&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;prevent-overscroll&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;truncate-lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;not&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;memq&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;major-mode&lt;/span&gt; &amp;#39;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;vterm-mode&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;term-mode&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;truncated-lines-p&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I use a &lt;code&gt;before-while&lt;/code&gt; advice, which acts like a predicate on its own and doesn&amp;rsquo;t run function if the result is &lt;code&gt;nil&lt;/code&gt;.
As can be seen, it does an additional check for &lt;code&gt;truncate-lines&lt;/code&gt; to be on, since if lines are not truncated there&amp;rsquo;s no reason to ever scroll left.
I also would like to prevent this from working in certain major modes, like terminals, since these automatically wrap lines themselves.&lt;/p&gt;
&lt;p&gt;Hope this is useful for someone, and if anybody knows a more robust way to calculate text width with the respect to the zoom level feel free to suggest improvements.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Limiting Horizontal Scroll In Emacs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Wed, 20 Jul 2022 00:00:00 +0000</pubDate>
    </item><item>
      <title>Project.el enhancements</title>
      <link>https://andreyor.st/posts/2022-07-16-project-el-enhancements/</link>
      <guid>https://andreyor.st/posts/2022-07-16-project-el-enhancements/</guid>
      <description>&lt;p&gt;After publishing the last post I thought why won&amp;rsquo;t I post such things here occasionally?
I have a few pieces of Emacs Lisp in my configuration that I wrote for myself some time ago to fix some annoyances or improve a certain workflow.
Previously I&amp;rsquo;ve used a literate approach for my Emacs configuration which listed all these notes, but it was tedious to maintain, so I&amp;rsquo;ve opted out for a simpler &lt;code&gt;init.el&lt;/code&gt;.
But I still would like to share some pieces in a more elaborated form.
Moreover, I&amp;rsquo;ve already &lt;a href=&#34;https://andreyor.st/posts/2020-05-01-dynamic-title-for-treemacs-workspace/&#34;&gt;done&lt;/a&gt; &lt;a href=&#34;https://andreyor.st/posts/2020-05-07-making-emacs-tabs-work-like-in-atom/&#34;&gt;it&lt;/a&gt; &lt;a href=&#34;https://andreyor.st/posts/2020-05-10-making-emacs-tabs-look-like-in-atom/&#34;&gt;before&lt;/a&gt;, and now, since I don&amp;rsquo;t use these packages, it&amp;rsquo;s easier to find these in a more organized place, than search in the commit history.&lt;/p&gt;
&lt;p&gt;One such thing that I&amp;rsquo;d like to share is a configuration of the inbuilt &lt;code&gt;project.el&lt;/code&gt;, which makes it a bit more pleasant to work with.&lt;/p&gt;
&lt;h2 id=&#34;finding-project-root-based-on-specific-root-markers&#34;&gt;Finding project root based on specific root-markers&lt;/h2&gt;
&lt;p&gt;Long ago I added a function that searches for a project root a bit differently from how &lt;code&gt;project.el&lt;/code&gt; does it by default.
It does so by searching for specific files, that I&amp;rsquo;ve specified like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defcustom&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-root-markers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#39;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Cargo.toml&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;compile_commands.json&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;compile_flags.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;project.clj&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;.git&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;deps.edn&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;shadow-cljs.edn&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Files or directories that indicate the root of a project.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:type&lt;/span&gt; &amp;#39;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;repeat&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;string&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:group&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;project&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You may wonder why I&amp;rsquo;ve included &lt;code&gt;.git&lt;/code&gt; as a project marker, but I often work with submodules, and I want such submodules to be treated as separate projects.
The default &lt;code&gt;project-try-vc&lt;/code&gt; treats submodules as part of a bigger project, which is logical, I guess, but I want it to act a bit differently.
And since not all of my submodules have one of the specified markers, it&amp;rsquo;s easy to search for the git directory and be done with it.&lt;/p&gt;
&lt;p&gt;Next, we need a function that checks if a given path has any of these markers:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-root-p&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Check if the current PATH has any of the project root markers.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;found&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dolist&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;marker&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-root-markers&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;file-exists-p&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;concat&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;marker&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;found&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;marker&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nothing fancy, just a linear search for any of the markers under the current directory.
The search terminates as soon as one of the files is found.&lt;/p&gt;
&lt;p&gt;The main piece here is the &lt;code&gt;project-find-root&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-find-root&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Search up the PATH for &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`project-root-markers&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expand-file-name&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;found&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;not&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;equal&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;not&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-root-p&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;setq&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;file-name-directory&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;directory-file-name&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;found&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cons&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;transient&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt;)))))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;add-to-list&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;project-find-functions&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-find-root&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As can be seen, this function is added to the list of &lt;code&gt;project-find-functions&lt;/code&gt;, and all it does is simply look for a marker file in the current directory, and if it is not found it goes up the directory.
If file is found, it returns a &lt;code&gt;(transient . &amp;quot;path/to/root&amp;quot;)&lt;/code&gt; that &lt;code&gt;project.el&lt;/code&gt; expects.
In practice, with this function early enough in the list, &lt;code&gt;project-try-vc&lt;/code&gt; is never called, and I get very predictable project roots.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;A suggestion came from another Emacs user, that there&amp;rsquo;s a function that can search up from the current directory, called &lt;code&gt;locate-dominating-file&lt;/code&gt;.
It accepts a path as its first argument, and a file to search for as a second argument.
It may not seem useful in this use case, since we need to search for multiple files, but instead of a file, this function also can accept a predicate, that will tell if a given file exists.
Thus, the &lt;code&gt;project-find-root&lt;/code&gt; function can be rewritten as:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-find-root&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Search up the PATH for &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`project-root-markers&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;when-let&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;root&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;locate-dominating-file&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;path&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-root-p&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cons&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;transient&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expand-file-name&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;root&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is why I love Emacs!
It has a lot of functions ready to be used, and a passionate community, that suggests improvements and makes the experience even better.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;saving-only-project-buffers-before-compilation&#34;&gt;Saving only project buffers before compilation&lt;/h2&gt;
&lt;p&gt;I often use project&amp;rsquo;s commands, defined under the &lt;code&gt;project-prefix-map&lt;/code&gt;.
One of these is &lt;code&gt;project-compile&lt;/code&gt;, which I use for all sorts of things, from running tests to deploying.
However, it has an annoying habit to ask whether I want to save some buffers before I run any command.
Why yes, I want to save some buffers, but only if they belong to the current project!
So let&amp;rsquo;s fix this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-save-some-buffers&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;amp;optional&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arg&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Save some modified file-visiting buffers in the current project.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;Optional argument ARG (interactively, prefix argument) non-nil
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;means save all with no questions.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;interactive&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;P&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let*&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-buffers&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-buffers&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-current&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pred&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;lambda&lt;/span&gt; () (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;memq&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current-buffer&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-buffers&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;funcall-interactively&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;save-some-buffers&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arg&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pred&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Just a simple function that obtains the current project, queries all project buffers, and creates a custom predicate for the &lt;code&gt;save-some-buffers&lt;/code&gt; function.
I&amp;rsquo;m not sure why &lt;code&gt;project.el&lt;/code&gt; doesn&amp;rsquo;t do it by itself, but we can always advise things:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;define-advice&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-compile&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:around&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fn&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;save-project-buffers&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Only ask to save project-related buffers.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let*&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-buffers&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-buffers&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-current&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;compilation-save-buffers-predicate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;lambda&lt;/span&gt; () (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;memq&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current-buffer&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-buffers&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;funcall&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fn&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This fixes only half of the problem, however.&lt;/p&gt;
&lt;p&gt;Imagine, you&amp;rsquo;re running tests by calling &lt;code&gt;project-compile&lt;/code&gt; and one of the tests fails.
You look in the &lt;code&gt;*compilation*&lt;/code&gt; buffer why it failed and fix it.
Then you go to the &lt;code&gt;*compilation*&lt;/code&gt; buffer once again and hit the &lt;kbd&gt;g&lt;/kbd&gt; key to re-run tests.
But instead of running tests, you&amp;rsquo;re being asked if you want to save some buffers, even though you&amp;rsquo;ve saved all buffers in the project beforehand.
Turns out, that &lt;kbd&gt;g&lt;/kbd&gt; simply calls the &lt;code&gt;recompile&lt;/code&gt; function, which knows nothing about the project, and will prompt you to save buffers, that aren&amp;rsquo;t in the project and are unsaved.
This, once again, can be fixed with a piece of advice:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;define-advice&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recompile&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:around&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;amp;optional&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;edit-command&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;save-project-buffers&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Only ask to save project-related buffers if inside a project.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-current&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let*&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-buffers&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-buffers&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-current&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;compilation-save-buffers-predicate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;lambda&lt;/span&gt; () (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;memq&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current-buffer&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;project-buffers&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;funcall&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;edit-command&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;funcall&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;edit-command&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We simply check if current &lt;code&gt;*compilation*&lt;/code&gt; buffer is a part of a project, since and do the same trick, setting &lt;code&gt;compilation-save-buffers-predicate&lt;/code&gt; to our custom predicate that is aware of the project.
This, however, works best when you customize the &lt;code&gt;project-compilation-buffer-name-function&lt;/code&gt; to use &lt;code&gt;project-prefixed-buffer-name&lt;/code&gt;, so you can compile multiple projects, and it won&amp;rsquo;t be confusing when to save what buffers.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Project.el enhancements&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sat, 16 Jul 2022 12:37:00 +0300</pubDate>
    </item><item>
      <title>Automatic refreshing of package archives for Emacs</title>
      <link>https://andreyor.st/posts/2022-07-15-refresh-package-contents-automatically/</link>
      <guid>https://andreyor.st/posts/2022-07-15-refresh-package-contents-automatically/</guid>
      <description>&lt;p&gt;I was going through my git commit history in my public &lt;a href=&#34;https://gitlab.com/andreyorst/dotfiles&#34; target=&#34;_blank&#34;&gt;dotfiles repository&lt;/a&gt; and noticed that prior to using &lt;a href=&#34;https://github.com/radian-software/straight.el&#34; target=&#34;_blank&#34;&gt;straight.el&lt;/a&gt; I&amp;rsquo;ve, like many, used an inbuilt solution for managing packages, called &lt;code&gt;package.el&lt;/code&gt;.
However, there was one thing that bothered me, and one of the reasons that made me think about switching to &lt;code&gt;straight&lt;/code&gt; was the fact, that a lot of times when I wanted to update or install packages, I couldn&amp;rsquo;t, due to an outdated package cache.
So I&amp;rsquo;ve fixed this, but since I&amp;rsquo;ve moved to straight I no longer needed this piece of code, and hence I&amp;rsquo;ve deleted it.
But it might be useful for people who use &lt;code&gt;package.el&lt;/code&gt;, so I&amp;rsquo;ve decided to share it here.&lt;/p&gt;
&lt;p&gt;The first thing needed is a custom variable to store the last refresh date.
I&amp;rsquo;ve chosen Custom because it is persisted on disk, which allows me to use &lt;code&gt;customize-save-variable&lt;/code&gt; later to make the value persist across sessions, and be easily reset via the customization interface:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defcustom&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;package-last-refresh-date&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Date and time when package lists have been refreshed.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;  This variable is then used to check whether
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`package-refresh-contents&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; call is needed before calling
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`package-install&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;. The value of this variable is updated when
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`package-refresh-contents&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; is called.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;  See &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`package-refresh-hour-threshold&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; for the amount of time needed to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;  trigger a refresh.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:group&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;package&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This variable is useful on its own, but we also need another one, that will specify how much time needs to pass since the last refresh to trigger package refreshing again.
I&amp;rsquo;ve chosen to store a number of hours since you don&amp;rsquo;t need to refresh package contents really often, but it may be a personal preference.
For example, if you update or install packages once a week, it doesn&amp;rsquo;t really matter, but if you, like me often tried cool packages that people share over the internet, the refresh rate may be set a bit lower than that.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defcustom&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;package-automatic-refresh-threshold&lt;/span&gt; 24
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Amount of hours since last &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`package-refresh-contents&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; call
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;  needed to trigger automatic refresh before calling &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`package-install&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:group&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;package&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With these two helper variables we can start &amp;ldquo;patching&amp;rdquo; &lt;code&gt;package.el&lt;/code&gt; so it would use it.
We don&amp;rsquo;t need to modify code, thanks to the advanced advice system:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;define-advice&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;package-install&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:before&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;amp;rest&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;package-refresh-contents-maybe&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;null&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;package-last-refresh-date&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;/&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;float-time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;time-subtract&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;date-to-time&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format-time-string&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;%Y-%m-%dT%H:%M&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;date-to-time&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;package-last-refresh-date&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  3600)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;package-automatic-refresh-threshold&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;package-refresh-contents&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;define-advice&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;package-refresh-contents&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:after&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;amp;rest&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;update-package-refresh-date&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;customize-save-variable&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;package-last-refresh-date&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format-time-string&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;%Y-%m-%dT%H:%M&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first advice ensures that before installing a package we&amp;rsquo;ll refresh package contents if enough time has passed since the last refresh, that is.
The second one simply updates the last refresh time, and stores it in the custom file, which I, personally, changed to &lt;code&gt;custom.el&lt;/code&gt; in my Emacs directory, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;use-package&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cus-edit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:custom&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;custom-file&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expand-file-name&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;custom.el&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user-emacs-directory&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:init&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;load&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;custom-file&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:noerror&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This file is not a part of my version control system and hosts a lot of machine local configuration, so it was natural to store the last refresh date in it too.
Of course, it is possible to store it in an arbitrary file, since it&amp;rsquo;s just a string, and read it inside the &lt;code&gt;package-install&lt;/code&gt; advice, but customize makes it seamless, and worked for me quite well.&lt;/p&gt;
&lt;p&gt;Hope this was a useful tip!&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Automatic refreshing of package archives for Emacs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 15 Jul 2022 09:27:00 +0300</pubDate>
    </item><item>
      <title>Why is Paredit is so un-Emacsy?</title>
      <link>https://andreyor.st/posts/2021-09-30-why-is-paredit-is-so-un-emacsy/</link>
      <guid>https://andreyor.st/posts/2021-09-30-why-is-paredit-is-so-un-emacsy/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s a quick rant, kinda.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve become a huge fan of structural editing recently.
My structural editing journey was maybe a bit unusual, but I&amp;rsquo;ve finally settled on Smartparens for quite some time.
Originally I was introduced to structural editing by &lt;a href=&#34;https://github.com/DogLooksGood/parinfer-mode&#34; target=&#34;_blank&#34;&gt;Parinfer mode&lt;/a&gt; which had some Paredit functionality, so it got me interested.
Then I have been using &lt;a href=&#34;https://github.com/eraserhd/parinfer-rust&#34; target=&#34;_blank&#34;&gt;Parinfer-rust&lt;/a&gt; for some time, but when I got the job in Clojure, I realized that it has a major problem of generating too much noise in the Git in commits because it needs to reformat the whole buffer to work, which is way too aggressive, especially when working with multiple people.
I&amp;rsquo;ve already written a &lt;a href=&#34;https://andreyor.st/posts/2020-12-03-we-need-to-talk-about-parentheses/&#34;&gt;small article&lt;/a&gt; about parentheses, and various structural editing solutions in this blog, but I&amp;rsquo;ve actually changed my mind regarding Paredit style editing since that time.
Learning some additional shortcuts and chords was not as bad as I thought it would be.&lt;/p&gt;
&lt;p&gt;So I switched to Paredit, but it had some bugs related to Clojure, and I&amp;rsquo;ve replaced it with Smartparens with Paredit keybindings, and I was basically (mostly) satisfied ever since.
But recently I&amp;rsquo;ve read &lt;a href=&#34;https://www.masteringemacs.org/&#34; target=&#34;_blank&#34;&gt;Mastering Emacs&lt;/a&gt; (a great book) and decided to greatly simplify my Emacs config.
I was tempted to replace Smartparens with Paredit because it felt simpler and more focused, but I&amp;rsquo;ve figured out that it breaks the &lt;em&gt;tempo&lt;/em&gt;&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;.
I&amp;rsquo;ve tried to fix most shortcomings of Paredit, but it felt too clunky, and I&amp;rsquo;ve dropped the idea, since Smartparens doesn&amp;rsquo;t have such problems, so I&amp;rsquo;ve returned to it.
Funnily enough, the sole reason I wanted to replace Smartparens with Paredit was that I felt that the configuration is way too complicated, but in the end, with all these fixes, Paredit&amp;rsquo;s configuration was even longer than the one I had for Smartparens.&lt;/p&gt;
&lt;p&gt;So here are some problems with Paredit that I&amp;rsquo;ve noticed after reading Mastering Emacs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Most commands that should accept negative (or just an arbitrary prefix argument) due to being mapped on a key that &lt;strong&gt;usually&lt;/strong&gt; accepts it, completely ignore it instead.&lt;/p&gt;
&lt;p&gt;For example, &lt;code&gt;M-- M-d&lt;/code&gt; that acts as &lt;code&gt;M-backspace&lt;/code&gt; in most editing modes, just ignores the negative argument in Paredit.
I&amp;rsquo;ve managed to fix that with the following advice, but I&amp;rsquo;m not sure that every such command can be fixed this way, as there might be no counterpart command.
This aspect of modifying commands with the (negative) argument became really important to me, because I&amp;rsquo;ve started using more motion-related commands, and Paredit basically prevented me from becoming more efficient.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defvar&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst--paredit-reversable-commands&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#39;((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;paredit-forward-delete&lt;/span&gt; . &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;paredit-backward-delete&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;paredit-forward-kill-word&lt;/span&gt; . &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;paredit-backward-kill-word&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Alist of &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`paredit-mode&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; command and their backward motion equivalents.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst/paredit-support-negative-arg&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orig-fn&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;amp;rest&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;args&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Find ORIG-FN in &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`aorst--paredit-reversable-commands&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; variable,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;and apply its counterpart, when the &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`current-prefix-arg&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; is
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;negative.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;eq&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current-prefix-arg&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;-&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current-prefix-arg&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;if-let&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cdr&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;assoc&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this-command&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst--paredit-reversable-commands&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;apply&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;args&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;if-let&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;car&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rassoc&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this-command&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst--paredit-reversable-commands&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;apply&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;args&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;apply&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orig-fn&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;args&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;apply&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orig-fn&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;args&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dolist&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;flatten-list&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst--paredit-reversable-commands&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;advice-add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:around&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst/paredit-support-negative-arg&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Transient mark mode deletion feature that was added in Emacs 24 is purposely ignored by Paredit.&lt;/p&gt;
&lt;p&gt;This again can be fixed with advice, and actually works reliably enough, making me only wonder why Paredit maintainers decided to &lt;a href=&#34;https://github.com/emacsmirror/paredit/blob/8330a41e8188fe18d3fa805bb9aa529f015318e8/paredit.el#L1352-L1355&#34; target=&#34;_blank&#34;&gt;put &lt;strong&gt;censored swearing&lt;/strong&gt; in the comment&lt;/a&gt; instead of implementing the feature itself.
Paredit has everything needed to do this, and yet chose to ignore the feature.
It&amp;rsquo;s easy to fix this with advice, but again, Smartparens does respect Emacs&amp;rsquo; design decisions.
Here&amp;rsquo;s the code I&amp;rsquo;ve written to fix this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defvar&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst--paredit-delete-region-functions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#39;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;paredit-forward-delete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;paredit-backward-delete&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;List of &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`paredit-mode&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; functions that should support tmm region deletion.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defvar&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst--paredit-kill-region-functions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#39;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;paredit-forward-kill-word&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;paredit-backward-kill-word&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;List of &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;`paredit-mode&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; functions that should support tmm region killing.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst/paredit-fix-tmm&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orig-fn&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;amp;rest&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;args&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Allow deleting/killing a region if the expression is balanced.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;transient-mark-mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mark-active&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;cond&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;memq&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this-command&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst--paredit-delete-region-functions&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;paredit-delete-region&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;region-beginning&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;region-end&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;memq&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this-command&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst--paredit-kill-region-functions&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;paredit-kill-region&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;region-beginning&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;region-end&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;t&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;apply&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orig-fn&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;args&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;apply&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;orig-fn&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;args&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dolist&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;append&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst--paredit-delete-region-functions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst--paredit-kill-region-functions&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;advice-add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:around&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst/paredit-fix-tmm&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the end, after simplifying my config, I&amp;rsquo;ve completely turned off the transient mark mode, as it is really not as important as I thought.
So maybe this is why Paredit authors didn&amp;rsquo;t bother to implement this feature, but I still think it&amp;rsquo;s not an excuse not to support it, some users may rely on it.
And I still occasionally enable &lt;code&gt;tmm&lt;/code&gt; with the &lt;code&gt;C-space C-space&lt;/code&gt; shortcut, so support for this feature is still important to me.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Point position is wrong after using splice commands in inferior-lisp type REPLs and any other REPLs I&amp;rsquo;ve tried so far.&lt;/p&gt;
&lt;p&gt;This actually looks like a bug, but I&amp;rsquo;ve also noticed that not a lot of people use structural editing in the REPL (maybe because of that?).
It&amp;rsquo;s a minor inconvenience, however, I&amp;rsquo;ve had zero problems with Smartparens strict mode enabled in REPLs so far.
This is very important to me, as I often write code directly in the REPL buffer, so I&amp;rsquo;d like to have all my structural editing features.
Sadly, I wasn&amp;rsquo;t able to fix this myself.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All this may sound like I&amp;rsquo;m praising the Smartparens here, but it&amp;rsquo;s actually not true.
Smartparens has a lot of its own quirks and problems, that I had to deal with.
It is by no means a silver bullet, but in the current state it&amp;rsquo;s good enough, I guess.&lt;/p&gt;
&lt;p&gt;My dream package would be something based off &lt;a href=&#34;https://tree-sitter.github.io/tree-sitter/&#34; target=&#34;_blank&#34;&gt;Tree-sitter&lt;/a&gt; (or any other blazingly fast parser) because it actually understands the structure of the code unlike Smartparens, which uses the regex-based search for that.
Yes, regex can be used for implementing structural editing, and it works to some degree for languages other than Lisps, as shown by Smartparens, but it&amp;rsquo;s not near as accurate, as it would be with a proper parser.
I&amp;rsquo;ve tried my best at implementing an algorithm that implements a backward syntax parser for Elixir to make Smartparens better understand the &lt;code&gt;do:&lt;/code&gt; keyword, as it doesn&amp;rsquo;t require matching the &lt;code&gt;end&lt;/code&gt; keyword, which broke the parser.
It kinda works, but still breaks on some combination of symbols in the code, so it&amp;rsquo;s not nearly as good as a solution with a proper parser.&lt;/p&gt;
&lt;p&gt;However, even with its quirks, Smartparens with the Paredit compatibility layer, and respect for the Emacs editing model, make it overall a better Emacs citizen than Paredit.
Yes, it&amp;rsquo;s somewhat clunkier to configure, but in the end, you have more EMACSy structural editing than you get with Paredit itself, and I actually don&amp;rsquo;t really understand why is that, as Paredit is older, and was used by Emacs hackers for quite a long time before Smartparens appeared.
If anyone knows the story behind that, please let me know!&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested to try out Smartparens, &lt;a href=&#34;https://gitlab.com/andreyorst/dotfiles/blob/21ef6737690678a5e29d47e0563df095e25cd873/.config/emacs#smartparens&#34; target=&#34;_blank&#34;&gt;here&amp;rsquo;s my configuration&lt;/a&gt;, that makes it work similarly to Paredit in most aspects, so you don&amp;rsquo;t have to re-learn your muscle memory.
I&amp;rsquo;m suggesting you try out Smartparens for yourself, and see if these features I&amp;rsquo;ve talked about are really worth the switch.
It was for me for sure.&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;Tempo is the term from the Mastering Emacs book, which basically means that you don&amp;rsquo;t need to release Ctrl or Meta keys for some chord progressions, like when using &lt;code&gt;M-- M-d&lt;/code&gt; instead of &lt;code&gt;C-- M-d&lt;/code&gt;.&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;/ol&gt;
&lt;/div&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Why is Paredit is so un-Emacsy?&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 30 Sep 2021 23:40:00 +0300</pubDate>
    </item><item>
      <title>Programming ligatures in Emacs</title>
      <link>https://andreyor.st/posts/2020-07-21-programming-ligatures-in-emacs/</link>
      <guid>https://andreyor.st/posts/2020-07-21-programming-ligatures-in-emacs/</guid>
      <description>&lt;p&gt;For a long time, I was a fan of &lt;a href=&#34;https://sourcefoundry.org/hack/&#34; target=&#34;_blank&#34;&gt;Hack font&lt;/a&gt;.
It has really nice language support, great readability at a size of 9pt, and zero with a dot.
I &lt;strong&gt;love&lt;/strong&gt; it when &lt;strong&gt;zero&lt;/strong&gt; comes with a &lt;strong&gt;dot&lt;/strong&gt;.
Many fonts use zero with a line, to differentiate it from capital &lt;code&gt;O&lt;/code&gt;, but on small sizes, it is not great, however, a dot looks fine when both small and big.&lt;/p&gt;
&lt;p&gt;But one thing was lacking from Hack, and it is ligature support.
I always wanted to try out ligatures, but there were no other fonts that were visually close to Hack, appealing to my taste, and had good programming ligatures support.
I&amp;rsquo;ve tried &lt;a href=&#34;https://github.com/tonsky/FiraCode&#34; target=&#34;_blank&#34;&gt;Fira Code&lt;/a&gt;, but it was &lt;em&gt;too curly&lt;/em&gt; for my liking, &lt;a href=&#34;https://typeof.net/Iosevka/&#34; target=&#34;_blank&#34;&gt;Iosevka&lt;/a&gt; was a bit too narrow, and there&amp;rsquo;s also &lt;a href=&#34;https://github.com/ignatov/Haack&#34; target=&#34;_blank&#34;&gt;Hæck&lt;/a&gt;, that is based on Hack, and has ligatures, so looked like a perfect candidate.
But my eye was caught by &lt;a href=&#34;https://www.jetbrains.com/lp/mono/&#34; target=&#34;_blank&#34;&gt;JetBrains Mono&lt;/a&gt;.
While it&amp;rsquo;s not the same as Hack, it is visually similar, has great ligature support, and looks a bit nicer in Emacs!
The Hack font works for me in a terminal, where I don&amp;rsquo;t need ligatures, while in Emacs something a little thicker is preferable.
So I&amp;rsquo;ve chosen it, but the ligatures are not working out of the box.&lt;/p&gt;
&lt;h2 id=&#34;enabling-support-for-ligatures&#34;&gt;Enabling support for ligatures&lt;/h2&gt;
&lt;p&gt;There are several options for enabling ligatures in Emacs, listed at &lt;a href=&#34;https://github.com/tonsky/FiraCode/wiki/Emacs-instructions&#34; target=&#34;_blank&#34;&gt;Fira Code Wiki page&lt;/a&gt;.
There are four options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;composition mode in Emacs Mac port&lt;/li&gt;
&lt;li&gt;prettify-symbols&lt;/li&gt;
&lt;li&gt;composition char table&lt;/li&gt;
&lt;li&gt;font-lock keywords&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&amp;rsquo;re interested in the &lt;strong&gt;composition char table&lt;/strong&gt;.
The basic idea is to provide starting character, and a regular expression, that matches all ligatures starting with that character, and put it to the composition table.
Here&amp;rsquo;s the code for JetBrains Mono:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dolist&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;char/ligature-re&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         `((&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?-&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;--&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-&amp;lt;&amp;lt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-&amp;gt;&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-|&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-~&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-&amp;lt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-&amp;gt;&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?/&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;/==&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;/=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;/&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;/**&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;/*&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?*&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*/&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?&amp;lt;&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;&amp;lt;=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;&amp;lt;-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;|||&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;==&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;!--&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;=&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;||&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;|&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;-&amp;lt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                               &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;==&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;=&amp;lt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;-|&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;~&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;=|&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;~~&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;$&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;+&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;/&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                               &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;*&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;-&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;|&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;:&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;&amp;gt;&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;$&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;~&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;+&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                               &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;*&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;lt;&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?:&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;:?&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;::=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;:&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;:&amp;lt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;:?&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;:=&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?=&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;=&amp;gt;&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;==&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;=/=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;=!=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;=&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;=:=&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;=&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?!&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;!==&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;!=&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;!&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?&amp;gt;&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;gt;&amp;gt;-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;gt;&amp;gt;=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;gt;=&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;gt;]&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;gt;:&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;gt;-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;gt;=&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;gt;&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?&amp;amp;&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;amp;&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?|&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;|-&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;|||&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;||&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;|=&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;||-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;||=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;|-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;|&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                               &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;|]&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;|}&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;|=&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;|&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?.&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;.?&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;.=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;.-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;..&amp;lt;&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?+&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;+&amp;gt;&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;+&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?\[&lt;/span&gt; . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;[&amp;lt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;[|&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?\{&lt;/span&gt; . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{|&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?\?&lt;/span&gt; . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;?.&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;?=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;?:&amp;#34;&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;?&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?#&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#_(&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#[&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#{&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#!&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#:&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#_&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#?&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#(&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?\;&lt;/span&gt; . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;;&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?_&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;_|_&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;__&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?~&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;~~&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;~~&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;~&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;~-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;~@&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?$&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;$&amp;gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?^&lt;/span&gt;  . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;^=&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?\]&lt;/span&gt; . ,(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rx&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;]#&amp;#34;&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;char&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;car&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;char/ligature-re&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ligature-re&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cdr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;char/ligature-re&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set-char-table-range&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;composition-function-table&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;char&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          `([,&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ligature-re&lt;/span&gt; 0 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;font-shape-gstring&lt;/span&gt;]))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By enabling &lt;code&gt;auto-composition-mode&lt;/code&gt; we can see the ligatures in action:&lt;/p&gt;
&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-07-21-programming-ligatures-in-emacs/ligatures-off.png&#34;
         alt=&#34;Figure 1: Ligatures off&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 1: &lt;/span&gt;Ligatures off&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class=&#34;invertable&#34;&gt;&lt;img src=&#34;https://andreyor.st/2020-07-21-programming-ligatures-in-emacs/ligatures-on.png&#34;
         alt=&#34;Figure 2: Ligatures on&#34;/&gt;&lt;figcaption&gt;
            &lt;p&gt;&lt;span class=&#34;figure-number&#34;&gt;Figure 2: &lt;/span&gt;Ligatures on&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Hint&lt;/em&gt;: open images in separate tabs and toggle between those to spot the difference.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note, in order for ligatures to work, Emacs needs to have support for HarfBuzz which was added in Emacs 28.&lt;/p&gt;
&lt;p&gt;But I don&amp;rsquo;t want these ligatures to be enabled everywhere, only in programming-related modes, so here&amp;rsquo;s a config for &lt;code&gt;composite&lt;/code&gt; package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;use-package&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;composite&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:hook&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;prog-mode&lt;/span&gt; . &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;auto-composition-mode&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:init&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;global-auto-composition-mode&lt;/span&gt; -1))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This takes care of most of the errors, listed under &lt;a href=&#34;https://github.com/tonsky/FiraCode/wiki/Emacs-instructions#using-composition-char-table&#34; target=&#34;_blank&#34;&gt;composition char table section&lt;/a&gt; in Fira Code Wiki.
Also by using &lt;code&gt;rx&lt;/code&gt; macro we avoid writing complex regular expressions with backslash escape hell, and handle this task to Emacs itself.
It&amp;rsquo;s good when Emacs does boring stuff for us, isn&amp;rsquo;t it?&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Programming ligatures in Emacs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Tue, 21 Jul 2020 21:00:00 +0300</pubDate>
    </item><item>
      <title>Using a single Emacs instance to edit files</title>
      <link>https://andreyor.st/posts/2020-06-29-using-single-emacs-instance-to-edit-files/</link>
      <guid>https://andreyor.st/posts/2020-06-29-using-single-emacs-instance-to-edit-files/</guid>
      <description>&lt;p&gt;Modern text editors usually operate in one instance.
When I select some advanced text editor as my preferred editor in the system, I expect this to happen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I click on some files in the file manager;&lt;/li&gt;
&lt;li&gt;If there&amp;rsquo;s no editor instance opened, a new instance opens with the file ready to edit;&lt;/li&gt;
&lt;li&gt;If there is an instance of an editor opened somewhere, a file is being opened in it, and the editor is brought to me via some focus event.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is what happens when you associate most of your files to be opened in VSCode for example.
But this is not the case for Emacs, which is unfortunate.
But, this is Emacs, of course, we can change it!&lt;/p&gt;
&lt;p&gt;Usually, we don&amp;rsquo;t think about it much, but Emacs comes in two parts.
The first one is the Emacs server, and the other one is the Emacs client.
However, every time when someone mentions the Emacs server, it happens in the context of a startup time issue solution &amp;ndash; e.g. launch Emacs once, then only connect to the process.
And mostly the solution is to run Emacs when the system starts, and only restart it if you&amp;rsquo;ve updated the configuration in a way when Emacs has to be restarted.&lt;/p&gt;
&lt;p&gt;This is not what I want, since I don&amp;rsquo;t have startup speed issues &amp;ndash; my Emacs configuration starts under 1.4 seconds on my machine.
However, I want Emacs to use one instance unless I explicitly request an additional one.
I did a bit of searching for a solution but unfortunately didn&amp;rsquo;t find any that would satisfy my needs.&lt;/p&gt;
&lt;h2 id=&#34;configuring-server-mode&#34;&gt;Configuring &lt;code&gt;server-mode&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To achieve our goal we need to configure &lt;code&gt;server-mode&lt;/code&gt; in Emacs.
Surprisingly there&amp;rsquo;s not so much of a configuration needed.
I&amp;rsquo;m using &lt;code&gt;use-package&lt;/code&gt; so I&amp;rsquo;ve added this into my &lt;code&gt;init.el&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;use-package&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:straight&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;unless&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;server-running-p&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;server-start&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can see, that we&amp;rsquo;re starting the server only when there is no other server running.
This is important for us, so we still could use multiple sessions without confusion.&lt;/p&gt;
&lt;p&gt;Unfortunately, other sessions will not use their own servers, but I personally don&amp;rsquo;t care.
I&amp;rsquo;ve thought about maintaining a persistent variable that holds server &lt;code&gt;PID&lt;/code&gt; but dropped the idea since I&amp;rsquo;ve never actually used two different sessions of Emacs where I would want to connect sessions to different servers.
This is definitively the point that can be improved, but it works fine for my needs in its current form, but if someone has an idea, feel free to open an issue or pull a request at my &lt;a href=&#34;https://gitlab.com/andreyorst/dotfiles&#34; target=&#34;_blank&#34;&gt;dotfiles&lt;/a&gt; repository so we could discuss it.&lt;/p&gt;
&lt;p&gt;Although the server part is not the only configuration we need to perform, otherwise this would not really be enough to make a post :)&lt;/p&gt;
&lt;h2 id=&#34;system-configurations&#34;&gt;System configurations&lt;/h2&gt;
&lt;p&gt;Another big part is the desktop file, which we will be using to launch Emacs from the desktop environment menus, as well as the function for when we&amp;rsquo;re launching from the shell.&lt;/p&gt;
&lt;p&gt;First is the shell function, as it is not so convoluted:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;emacs() { emacsclient -a &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;emacs&amp;#39;&lt;/span&gt; -n &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;$@&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null || &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;command&lt;/span&gt; emacs; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you add this function to your &lt;code&gt;.bashrc&lt;/code&gt; it will replace &lt;code&gt;emacs&lt;/code&gt; command in your shell session.
What this command does, is tries to open &lt;code&gt;emacsclient&lt;/code&gt;, and connect to the server.
We may fail, because there&amp;rsquo;s no server running yet, and in this case, we fall back to &lt;code&gt;command emacs&lt;/code&gt; which will launch Emacs, which in turn will start the missing server.&lt;/p&gt;
&lt;p&gt;In case the server is already running, &lt;code&gt;emacsclient&lt;/code&gt; will be able to connect to it, but it will not spawn another window, instead it will use a running instance and a file will be opened in it.
Sweet!&lt;/p&gt;
&lt;p&gt;This pretty much defines the behavior I want, but I&amp;rsquo;m not launching Emacs from shell very often, so I want this behavior to happen when I click on files in my file manager, or when I&amp;rsquo;ve downloaded something in a web browser.
For this, we will need a very similar thing as our shell function, except it will be the &lt;code&gt;.desktop&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;XDG specification allows us to create &lt;code&gt;emacs.desktop&lt;/code&gt; under &lt;code&gt;~/.local/share/applications/&lt;/code&gt; with these contents:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[Desktop Entry]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Name=Emacs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GenericName=Text Editor
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Comment=Edit text
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MimeType=text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;english&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;plain&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-makefile&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-c&lt;span style=&#34;&#34;&gt;++&lt;/span&gt;hdr&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-c&lt;span style=&#34;&#34;&gt;++&lt;/span&gt;src&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-chdr&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-csrc&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-java&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-moc&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-pascal&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-tcl&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-tex&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;application&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-shellscript&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-c&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;text&lt;span style=&#34;&#34;&gt;/&lt;/span&gt;x-c&lt;span style=&#34;&#34;&gt;++;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Exec=sh -c &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;emacsclient -a emacs -n \&amp;#34;\$@\&amp;#34; || command emacs&amp;#34;&lt;/span&gt; dummy &lt;span style=&#34;&#34;&gt;%&lt;/span&gt;F
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Icon=emacs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Type=Application
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Terminal=&lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Categories=Development&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;TextEditor&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;Utility&lt;span style=&#34;&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;StartupWMClass=Emacs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Note, you&amp;rsquo;ll also need &lt;code&gt;emacs.png&lt;/code&gt; icon under &lt;code&gt;~/.local/share/icons/&lt;/code&gt;, so this &lt;code&gt;.desktop&lt;/code&gt; file could be displayed with it in the menus.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can see that we&amp;rsquo;re using exactly the same function, as in the shell, except we pass the &lt;code&gt;dummy&lt;/code&gt; argument because that&amp;rsquo;s how it works for some reason.
And we have all this other noise around, to correctly display menu entries.&lt;/p&gt;
&lt;p&gt;Now we can associate files we want to be opened with Emacs with this &lt;code&gt;.desktop&lt;/code&gt; file, and just as with the shell function, Emacs will be opened if no instance is running, and the existing instance will be used if you click on another file without spawning new windows.
With &lt;a href=&#34;https://andreyor.st/posts/2020-05-10-making-emacs-tabs-look-like-in-atom/&#34;&gt;tabs&lt;/a&gt; this is really handy and works exactly how I would expect from an advanced text editor.&lt;/p&gt;
&lt;p&gt;I think the same trick should be possible to do on other operating systems, but I don&amp;rsquo;t know their equivalent of &lt;code&gt;.desktop&lt;/code&gt; files, so I&amp;rsquo;ll lave this part for those who would want to try ;)&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Using a single Emacs instance to edit files&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Mon, 29 Jun 2020 22:45:00 +0300</pubDate>
    </item><item>
      <title>Managing background processes from Kakoune</title>
      <link>https://andreyor.st/posts/2020-06-05-managing-background-processes-from-kakoune/</link>
      <guid>https://andreyor.st/posts/2020-06-05-managing-background-processes-from-kakoune/</guid>
      <description>&lt;p&gt;While working on my previous post I was mainly using Emacs, because it has the best support for Lisp languages.
It has great integration with the REPL, can run a server for my application in the background, and so on.
And actually, I use this a lot while working on this blog - I run &lt;code&gt;hugo&lt;/code&gt; process in the background to see how my page is looking.
This got me thinking about handling all of this in Kakoune.&lt;/p&gt;
&lt;p&gt;Kakoune has facilities to run processes in the background, and it does this for many tools like &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;make&lt;/code&gt;, &lt;code&gt;ctags&lt;/code&gt;, and other common shell tools that we use often.
Kakoune also has built-in REPL support with &lt;code&gt;repl&lt;/code&gt; and &lt;code&gt;send-text&lt;/code&gt; commands, which can be used when I work with Lisps.
However, there&amp;rsquo;s a problem.&lt;/p&gt;
&lt;p&gt;When working with Clojure, I need to run two JVM instances in the background.
This is due to the architecture of the project, and I can&amp;rsquo;t really do anything about it.
So when I&amp;rsquo;m programming in Emacs, an amazing package, named &lt;a href=&#34;https://docs.cider.mx/cider/index.html&#34; target=&#34;_blank&#34;&gt;CIDER&lt;/a&gt;&lt;sup&gt;(Clojure IDE that Rocks)&lt;/sup&gt; does this for me.
But in order to do this in Kakoune, I have to start another terminal or create a new window in Tmux, and I don&amp;rsquo;t really like this.&lt;/p&gt;
&lt;p&gt;So I&amp;rsquo;ve thought, why not start this from Kakoune itself?
The problem though is that there&amp;rsquo;s no built-in way that I can think of.
There are &lt;code&gt;!&lt;/code&gt; and &lt;code&gt;|&lt;/code&gt; commands to run a synchronous process and pipe its result into a buffer, which is not for me.
I&amp;rsquo;d also like to kill a process if I don&amp;rsquo;t need it, and see its log as if it ran in a terminal.
Turns out it isn&amp;rsquo;t a really hard task.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve created &lt;a href=&#34;https://gitlab.com/andreyorst/pmanage.kak&#34; target=&#34;_blank&#34;&gt;pmanage.kak&lt;/a&gt; plugin to test this idea.
This plugin is quite small and has these three commands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pstart &amp;lt;command&amp;gt;&lt;/code&gt;: Starts command as a background process, and creates FIFO buffer for that process named after process PID.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pstop &amp;lt;PID&amp;gt;&lt;/code&gt;: delete process buffer and send &lt;code&gt;SIGTERM&lt;/code&gt; signal to process.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pkill &amp;lt;PID&amp;gt;&lt;/code&gt;: delete process buffer and send &lt;code&gt;SIGKILL&lt;/code&gt; signal to process.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So now, I can do this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;open Kakoune in project root;&lt;/li&gt;
&lt;li&gt;call &lt;code&gt;:pstart &#39;npx shadow-cljs watch app&#39;&lt;/code&gt; to start background watching process.
&lt;ul&gt;
&lt;li&gt;A new FIFO buffer is created, and process PID is stored into a special option;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Then I can do &lt;code&gt;:repl &#39;npx shadow-cljs cljs-repl app&#39;&lt;/code&gt; and open REPL window that will be connected to that watcher process;&lt;/li&gt;
&lt;li&gt;Develop!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I am also now able to run &lt;code&gt;:pstart &#39;hugo server -D&#39;&lt;/code&gt;, and edit any Markdown files that my blog is made of.
And when I don&amp;rsquo;t need that process I simply can call &lt;code&gt;:pstop PID&lt;/code&gt; or &lt;code&gt;:delete-buffer PID&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I know about &lt;a href=&#34;https://github.com/mawww/kakoune/issues/1414&#34; target=&#34;_blank&#34;&gt;kakoune:1414&lt;/a&gt;, but I think the solution I came up with is fine for most use cases.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Managing background processes from Kakoune&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 05 Jun 2020 13:04:00 +0300</pubDate>
    </item><item>
      <title>Making Emacs tabs look like in Atom</title>
      <link>https://andreyor.st/posts/2020-05-10-making-emacs-tabs-look-like-in-atom/</link>
      <guid>https://andreyor.st/posts/2020-05-10-making-emacs-tabs-look-like-in-atom/</guid>
      <description>&lt;p&gt;This is yet another follow-up post in the Emacs configuration series, which is also about Tabs.
The previous post was about how tabs behave when you close them, and how I think the algorithm can be improved.
This post is more about visuals and horizontal space management.&lt;/p&gt;
&lt;p&gt;By default tabs in Emacs are named after their respective buffers.
This is how tabs look with my configurations and default naming:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-10-making-emacs-tabs-look-like-in-atom/emacs-default-look.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Looks fine, but there&amp;rsquo;s a catch.
Tabs with really long names take a lot of horizontal space, which can be a problem when dealing with buffers that were created by some package, like CIDER:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-10-making-emacs-tabs-look-like-in-atom/emacs-cider-buffer-name.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;With tabs of this size, no wonder we get complaints that tabs are not usable.
And on this screenshot, you can see that all tabs have different widths, which doesn&amp;rsquo;t really look good in my opinion.
Both problems can be fixed with some code, but first, let&amp;rsquo;s check how the Atom editor handles tab sizes.&lt;/p&gt;
&lt;h2 id=&#34;tabs-in-atom&#34;&gt;Tabs in Atom&lt;/h2&gt;
&lt;p&gt;This is the default look of tabs in Atom editor with One Dark theme:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-10-making-emacs-tabs-look-like-in-atom/atom-two-tabs.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;By default tabs in Atom occupy more space than is actually needed for a tab, and I think that this is beautiful.
Someone may be concerned that it wastes horizontal space, but it&amp;rsquo;s actually not - if we open more tabs, their width will shrink to make those fit in the window:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-10-making-emacs-tabs-look-like-in-atom/atom-many-tabs.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;But this not going to happen all the time, and eventually, once some minimum width is reached, tabs will no longer shrink, and we&amp;rsquo;ll have to scroll those.
We still can get the idea of what file is opened in the tab, and there are a lot of them in such a tiny window.
And if some tab has really long name that doesn&amp;rsquo;t fit into a tab, it gets truncated:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-10-making-emacs-tabs-look-like-in-atom/atom-a-lot-of-tabs.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This is the behavior we&amp;rsquo;re going to replicate in Emacs.&lt;/p&gt;
&lt;h2 id=&#34;making-emacs-tabs-resize-automatically&#34;&gt;Making Emacs tabs resize automatically&lt;/h2&gt;
&lt;p&gt;First, we will need two variables - one for minimum width, and one for maximum width.
I like to define variables that extend some built-in packages via &lt;code&gt;defcustom&lt;/code&gt; because if someone else will use my config they will be able to customize such things with the custom interface or via code.
Also Custom makes persistent configurations a bit easier as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defcustom&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-tab-min-width&lt;/span&gt; 10
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Minimum width of a tab in characters.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;integer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:group&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;tab-line&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defcustom&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-tab-max-width&lt;/span&gt; 30
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Maximum width of a tab in characters.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;integer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:group&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;tab-line&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Good.
This will later be used in a function that creates a name for the tab.
Now we need to think about the general algorithm.
Note that we&amp;rsquo;re defining size in terms of monospace characters.
This algorithm will not work for variable pitch fonts.&lt;/p&gt;
&lt;p&gt;In Atom, tabs use fixed width up until there is no more horizontal space in the window to fit full-sized tabs.
In Emacs, we can access the width of a window with the &lt;code&gt;window-width&lt;/code&gt; function.
So our first step will be to obtain such width, and check how many tabs will fit into it.
However, instead of checking the number of tabs, we will calculate the width of the tab that we will need for all tabs that we currently have:&lt;/p&gt;
&lt;img src=&#34;https://andreyor.st/ltximg/2020-05-10-making-emacs-tabs-look-like-in-atom_001cf887ecd716cf6126afdedc5ec5891109f887.svg&#34; alt=&#34;\[\text{window-tab-width}=\frac{\text{window-width}}{\text{amount-of-tabs}}\]&#34; class=&#34;org-svg&#34; /&gt;
&lt;p&gt;So, if our window is &lt;code&gt;300&lt;/code&gt; chars wide, and we have one tab, it will occupy the whole width.
If we have two tabs, each should be &lt;code&gt;150&lt;/code&gt; chars long, and so on.
This is great, but if we have 70 tabs, each would be only &lt;code&gt;4&lt;/code&gt; chars.
Given that we need at least one char to display the left padding, one char to display the close button, and one char for the right padding, we&amp;rsquo;re left with &lt;code&gt;1&lt;/code&gt; char for the name which is not good at all.
However we don&amp;rsquo;t want to use such wide or such narrow tabs, so we need to adjust their length based on these conditions:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://andreyor.st/ltximg/2020-05-10-making-emacs-tabs-look-like-in-atom_bd41ae352c2315c7e34fd5bf533b07983a71cdee.svg&#34; alt=&#34;\[
\text{tab-width}=\left(\begin{cases}
\text{tab-line-tab-max-width}&amp;amp;amp;\text{if window-tab-width}\geq\text{tab-line-tab-max-width}\\
\text{tab-line-tab-min-width}&amp;amp;amp;\text{if window-tab-width}&amp;amp;lt;\text{tab-line-tab-min-width}\\
\text{window-tab-width}&amp;amp;amp;\text{otherwise}
\end{cases}\right)-\text{close-button-width}
\]&#34; class=&#34;org-svg&#34; /&gt;&lt;/p&gt;
&lt;p&gt;This way if we have a tab width larger than our maximum width, we will use maximum width.
If we have a width that is less than our minimum width, we will use minimal width, and this will enable scrolling.
If we&amp;rsquo;re in between, we&amp;rsquo;re using the width that was calculated in the previous formula.
Note that we&amp;rsquo;re subtracting the size of the close button from our width which is represented as &lt;code&gt;×&lt;/code&gt; with spaces at the front and the end.&lt;/p&gt;
&lt;p&gt;The second thing we need is to produce a valid name for the tab, but right now we will simply &lt;code&gt;string-trim&lt;/code&gt; buffer name, and calculate its width.
This should leave us with these computations:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst/tab-line-name-buffer&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;amp;rest&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_buffers&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;with-current-buffer&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let*&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-width&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-width&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-buffer-window&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;close-button-size&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-close-button-show&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;length&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;substring-no-properties&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-close-button&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                0))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-amount&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;length&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-tabs-window-buffers&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-max-tab-width&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-amount&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-width&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;cond&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-max-tab-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-tab-max-width&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-tab-max-width&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                               ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-max-tab-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-tab-min-width&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-tab-min-width&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                               (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-max-tab-width&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;close-button-size&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer-name&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;string-trim&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer-name&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name-width&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;length&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer-name&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now, when we have all this information, we can compute the name for the tab and its paddings.
First, we need to check if the trimmed buffer name exceeds the tab width.
If it is, we truncate the name to the width of the tab minus &lt;code&gt;3&lt;/code&gt;, because we need to add single space padding before a name and add an ellipsis symbol followed by a space at the end.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name-width&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-width&lt;/span&gt; 3))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;concat&lt;/span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;truncate-string-to-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer-name&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-width&lt;/span&gt; 3)) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;… &amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If &lt;code&gt;name-width&lt;/code&gt; is less than &lt;code&gt;tab-width&lt;/code&gt; minus &lt;code&gt;3&lt;/code&gt;, we can produce left &lt;code&gt;padding&lt;/code&gt;, by computing difference between &lt;code&gt;tab-width&lt;/code&gt; and &lt;code&gt;name-width&lt;/code&gt;, and dividing it by &lt;code&gt;2&lt;/code&gt;.
Then we concatenate this padding and calculate the right padding needed for the name.
This extra calculation is needed when a name is odd or even, so we produce equally sized tabs for any buffer name:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let*&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;padding&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;make-string&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;/&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name-width&lt;/span&gt;) 2) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?\s&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer-name&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;concat&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;padding&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer-name&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name-width&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;length&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer-name&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;concat&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer-name&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;make-string&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-width&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name-width&lt;/span&gt;) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?\s&lt;/span&gt;)))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This gives us such results.
With the same window width as in Atom examples, two tabs will occupy this amount of space:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-10-making-emacs-tabs-look-like-in-atom/emacs-two-tabs.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;If we will open four tabs, the size of each tab will shrink accordingly:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-10-making-emacs-tabs-look-like-in-atom/emacs-many-tabs.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Though this is not as nice as in atom, due to the small unused space on the right side of the window.
Unfortunately, we can compute width only in terms of characters, which can&amp;rsquo;t really have variable width, unless we use variable pitch font, but as I&amp;rsquo;ve mentioned earlier, this algorithm will not work with variable-sized fonts, and perhaps such computation will be quite expensive.
Computing variable width in terms of pixels may be possible, but I couldn&amp;rsquo;t find any information on this topic.
But the character-based solution should also work fine in terminal Emacs.&lt;/p&gt;
&lt;p&gt;When we open too many tabs, we can see scroll buttons, and tabs no longer shrink in size beyond &lt;code&gt;tab-line-tab-min-width&lt;/code&gt; value.
We also can disable the close button if we want:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-10-making-emacs-tabs-look-like-in-atom/emacs-a-lot-of-tabs.png&#34;/&gt;
&lt;/figure&gt;

&lt;h2 id=&#34;rationale&#34;&gt;Rationale&lt;/h2&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-10-making-emacs-tabs-look-like-in-atom/emacs-cider-buffer-name.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;After:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-10-making-emacs-tabs-look-like-in-atom/emacs-cider-buffer-name-new.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;In the beginning, I&amp;rsquo;ve said that there are a lot of complaints that tabs unnecessarily waste horizontal space.
Even though we&amp;rsquo;ve fixed this, now you may think, that this is still impractical, because you can&amp;rsquo;t see the whole name of a file in the tab, and tabs are not usable as a concept overall.
And I can agree to a certain point.
An interactive buffer list, that we can fuzzy match through, has no issues with space because we pop it up when needed, and can show you full buffer names any time.
But I find myself using tabs very often simply as a visual indicator of what buffers are next and previous in the list, and switch between those via &lt;kbd&gt;C-x right&lt;/kbd&gt; and &lt;kbd&gt;C-x left&lt;/kbd&gt;.
You can&amp;rsquo;t really do this with a buffer list unless you display it somewhere all the time, but then it takes much more space than tabs.&lt;/p&gt;
&lt;p&gt;Tabs also help a lot when someone, who isn&amp;rsquo;t an Emacs user and is unfamiliar with the concept of buffer list, sits near me, since the concept of tabs is well known and obvious to most other people, because of tabs in browsers or other editors.&lt;/p&gt;
&lt;p&gt;&lt;del&gt;One thing that I have not yet succeeded to achieve is to automatically recalculate tab width on frame or window resize events&lt;/del&gt;.
&lt;del&gt;It seems that &lt;code&gt;force-mode-line-update&lt;/code&gt; does not initiate the process of name building, but for some reason, it happens on focus events, so I have yet to investigate this part&lt;/del&gt;.&lt;/p&gt;
&lt;p&gt;Turns out there&amp;rsquo;s a way to update tab width on resize events by clearing the cache of &lt;code&gt;tab-line&lt;/code&gt; in each window.
As a quite dirty hack, we can use this &lt;code&gt;hook&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;add-hook&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;window-configuration-change-hook&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;lambda&lt;/span&gt; ()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dolist&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-list&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set-window-parameter&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;tab-line-cache&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This makes tabs resize whenever you change window or frame width with your mouse, or when you split windows via &lt;kbd&gt;C-x 3&lt;/kbd&gt; and other windowing commands that change window layout.&lt;/p&gt;
&lt;p&gt;Though this post only mentions the naming function, I&amp;rsquo;ve set up a bit more things to make tabs look as represented on screenshots.
This configuration can be found in full form in my &lt;a href=&#34;https://gitlab.com/andreyorst/dotfiles/blob/740d346088ce5a51804724659a895d13ed574f81/.config/emacs/README.org#tabline&#34; target=&#34;_blank&#34;&gt;.dotfiles&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Making Emacs tabs look like in Atom&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 10 May 2020 22:41:00 +0300</pubDate>
    </item><item>
      <title>Making Emacs tabs work like in Atom</title>
      <link>https://andreyor.st/posts/2020-05-07-making-emacs-tabs-work-like-in-atom/</link>
      <guid>https://andreyor.st/posts/2020-05-07-making-emacs-tabs-work-like-in-atom/</guid>
      <description>&lt;p&gt;Another little piece from my Emacs config that I&amp;rsquo;ve decided to turn into a small post, following up on &lt;a href=&#34;https://andreyor.st/posts/2020-05-01-dynamic-title-for-treemacs-workspace/&#34;&gt;previous one&lt;/a&gt;.
This time, we&amp;rsquo;re going to make tabs work as in most graphical editors.&lt;/p&gt;
&lt;p&gt;Tabs were added with &lt;code&gt;global-tab-line-mode&lt;/code&gt; in Emacs 27, and are pretty simple tabs, that are being displayed on the top of a window, and by default, their semantics are not very useful in my opinion.
The main problem is that you get only two policies of how the closing of a tab will behave.
It is either &lt;code&gt;bury-buffer&lt;/code&gt;, which simply hides the tab, and moves the buffer to the end of the buffer list, and &lt;code&gt;kill-buffer&lt;/code&gt; which always kills the buffer, and hides the tab, and you can&amp;rsquo;t really combine those behaviors by default.&lt;/p&gt;
&lt;p&gt;This is not very useful, because you can have many windows, with the same buffers in each one, and when you want to close the window you can&amp;rsquo;t do that by closing the last tab.
For example, in Atom, if we have such configuration:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/atom-two-tabs-side-by-side.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;If we close &lt;code&gt;file-B&lt;/code&gt; tab we will be left with one window:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/atom-one-tab.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This is useful and works the same way in VSCode or Sublime Text.
Let&amp;rsquo;s try the same thing in &lt;code&gt;emacs -q&lt;/code&gt;.
First, we create two windows, with a tab in each:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/emacs-two-tabs-side-by-side.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Then we press little close button on &lt;code&gt;file-b&lt;/code&gt; tab:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/emacs-tab-closed.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;And it replaces it with the &lt;code&gt;file-A&lt;/code&gt; tab.
This happens because when we click on the close button it calls &lt;code&gt;bury-buffer&lt;/code&gt;, so the tab goes away, a new buffer is displayed, and we&amp;rsquo;re getting a new tab for it.
This is not great.
I think when we close the last tab in the window, the window should be killed as in Atom&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;.&lt;/p&gt;
&lt;p&gt;The other thing is this.
In Atom we can have two windows with the same buffers opened like this:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/atom-two-tabs-one-file.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;And if you close one of the tabs the file will not be closed until all tabs are closed, but the window will be:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/atom-one-tab.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;In Emacs, however, we can&amp;rsquo;t close the tab via the close button, because it will cycle buffers, so instead we can switch to the second policy of killing buffers instead.
But it will not work either, because it will not kill the window, and it will kill the buffer in all windows.
So how do we fix this?&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s establish some logical rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Buffer can exist without a tab, but a tab can not exist without a buffer,&lt;/li&gt;
&lt;li&gt;If the tab was closed buffer should be killed only if there are no tabs for this buffer left,&lt;/li&gt;
&lt;li&gt;If the tab was closed and there are no more tabs in the window, the window should be killed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These three rules are basically how tabs work in modern editors.
Now we need to implement this in Emacs Lisp.
Since there&amp;rsquo;s no way of configuring which function is used for closing a tab, we&amp;rsquo;re going to override it with an advice in our configuration file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;define-advice&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-close-tab&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:override&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;&amp;amp;optional&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;e&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Close the selected tab.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;If the tab is presented in another window, close the tab by using the `bury-buffer` function.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;If the tab is unique to all existing windows, kill the buffer with the `kill-buffer` function.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;Lastly, if no tabs are left in the window, it is deleted with the `delete-window` function.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;interactive&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;e&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let*&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;posnp&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;event-start&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;e&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;posn-window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;posnp&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-pos-property&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;tab&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;car&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;posn-string&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;posnp&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;with-selected-window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-list&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-tabs-window-buffers&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer-list&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;flatten-list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;seq-reduce&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;lambda&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;list&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;select-window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;t&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cons&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-line-tabs-window-buffers&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;list&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-list&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;select-window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;seq-count&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;lambda&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;eq&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer&lt;/span&gt;)) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer-list&lt;/span&gt;) 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;progn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;eq&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current-buffer&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bury-buffer&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set-window-prev-buffers&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;assq-delete-all&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-prev-buffers&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set-window-next-buffers&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;delq&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-next-buffers&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;unless&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cdr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-list&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ignore-errors&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;delete-window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;kill-buffer&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;buffer&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;unless&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cdr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tab-list&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ignore-errors&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;delete-window&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window&lt;/span&gt;)))))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;force-mode-line-update&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s break this down.
First, we&amp;rsquo;re storing our &lt;code&gt;posnp&lt;/code&gt;, &lt;code&gt;window&lt;/code&gt;, and &lt;code&gt;buffer&lt;/code&gt;, then with our selected &lt;code&gt;window&lt;/code&gt;, we get a list of tabs via a call to &lt;code&gt;tab-line-tabs-window-buffers&lt;/code&gt;, which effectively returns a list of buffers that have tabs associated with those.
Then we get a full list of buffers in all windows and store it to &lt;code&gt;buffer-list&lt;/code&gt; variable, which we will need later.&lt;/p&gt;
&lt;p&gt;Next, we select the &lt;code&gt;window&lt;/code&gt; and count how many times we find buffers in our list of buffers from all windows.
If it is more than 1, then we can we&amp;rsquo;re going to bury that buffer.
If it is 1 we&amp;rsquo;re going to kill it since it is the last tab of that buffer.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s another check in there, that checks if the tab is last in the list of tabs for that window, and if it is, e.g. if &lt;code&gt;(cdr tab-list)&lt;/code&gt; returned &lt;code&gt;nil&lt;/code&gt; we&amp;rsquo;ve just closed the last tab in the window, so we can kill it as well.&lt;/p&gt;
&lt;p&gt;In the end, we force a mode-line update because it updates the tab line as well.
So now, with this function (and the rest of my config) let&amp;rsquo;s try previous examples in Emacs:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/emacs-new-two-tabs-side-by-side.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Now we close &lt;code&gt;file-B&lt;/code&gt;:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/emacs-new-one-tab.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Buffer &lt;code&gt;file-B&lt;/code&gt; and its respective window both were killed.
Now we create windows with the same buffer:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/emacs-new-two-tabs-one-file.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;And if we close the right tab, we see that window is deleted, but the buffer is not affected:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/emacs-new-one-tab.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;And if we had tab &lt;code&gt;file-A&lt;/code&gt; in first window and two tabs for &lt;code&gt;file-A&lt;/code&gt; and &lt;code&gt;file-B&lt;/code&gt; in second, closing &lt;code&gt;file-A&lt;/code&gt; in second window will not kill &lt;code&gt;file-A&lt;/code&gt; buffer, and will not kill the window, because tab for &lt;code&gt;file-B&lt;/code&gt; is still there:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/emacs-new-three-tabs.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Closing &lt;code&gt;file-A&lt;/code&gt; tab doesn&amp;rsquo;t kill &lt;code&gt;file-A&lt;/code&gt; buffer or window:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/emacs-new-two-tabs-side-by-side.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Closing &lt;code&gt;file-B&lt;/code&gt; tab kills its buffer and window:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-07-making-emacs-tabs-work-like-in-atom/emacs-new-one-tab.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;This makes tabs in Emacs behave as in Atom or VSCode.&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;Atom actually has a setting for it, so when you close the last tab it can display an empty window, in which you can later drag and drop new tabs, but in Emacs, there is no such thing as empty windows, so it makes sense to always kill the window if there are no tabs left.&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;/ol&gt;
&lt;/div&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Making Emacs tabs work like in Atom&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 07 May 2020 20:41:00 +0300</pubDate>
    </item><item>
      <title>Dynamic title for Treemacs workspace</title>
      <link>https://andreyor.st/posts/2020-05-01-dynamic-title-for-treemacs-workspace/</link>
      <guid>https://andreyor.st/posts/2020-05-01-dynamic-title-for-treemacs-workspace/</guid>
      <description>&lt;p&gt;Thought that I can share snippets of my Emacs config from time to time here, just like &lt;a href=&#34;https://github.com/clemera&#34; target=&#34;_blank&#34;&gt;@clemera&lt;/a&gt; does on &lt;a href=&#34;https://with-emacs.com&#34; target=&#34;_blank&#34;&gt;with-emacs.com&lt;/a&gt;.
I highly recommend you to check it out, there are many great recipes and articles.&lt;/p&gt;
&lt;p&gt;A while ago I&amp;rsquo;ve added static &lt;code&gt;Treemacs&lt;/code&gt; title to &lt;a href=&#34;https://github.com/Alexander-Miller/treemacs&#34; target=&#34;_blank&#34;&gt;Treemacs&lt;/a&gt; buffer for aesthetic purposes - it adds good alignment with tabs in other windows.
But recently I&amp;rsquo;ve thought that it could also be useful, and indicate the workspace that I&amp;rsquo;m currently in.
I have many workspaces, so this is good info to have.
Here&amp;rsquo;s my little piece of code that creates a dynamic title for the package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;aorst/treemacs-setup-title&lt;/span&gt; ()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bg&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;face-attribute&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;default&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:background&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fg&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;face-attribute&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;default&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:foreground&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;face-remap-add-relative&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;header-line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                             &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:background&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bg&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:foreground&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                             &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:box&lt;/span&gt; `(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:line-width&lt;/span&gt; ,(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;/&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line-pixel-height&lt;/span&gt;) 2) &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:color&lt;/span&gt; ,&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bg&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;setq&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;header-line-format&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#39;((&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;:eval&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let*&lt;/span&gt; ((&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;text&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;treemacs-workspace-&amp;gt;name&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;treemacs-current-workspace&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extra-align&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;/&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;length&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;text&lt;/span&gt;) 2) 1))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;/&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;window-width&lt;/span&gt;) 2) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extra-align&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;concat&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;make-string&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;width&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;?\s&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;text&lt;/span&gt;))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we need to &lt;code&gt;hook&lt;/code&gt; this function to &lt;code&gt;treemacs-mode-hook&lt;/code&gt;, so it is called when Treemacs sets its mode in the buffer.&lt;/p&gt;
&lt;p&gt;What this function essentially does is, it creates &lt;code&gt;header-line&lt;/code&gt; for Treemacs buffer, adds nice &lt;code&gt;box&lt;/code&gt; for it with the width half the size of line height, and set&amp;rsquo;s its background and foreground based on your theme.
After that, it gets the Treemacs workspace name, calculates its length, and the needed amount of spaces in order to center text in the window.
The ending result is like this:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-01-dynamic-title-for-treemacs-workspace/result.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Or with Emacs default theme:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://andreyor.st/2020-05-01-dynamic-title-for-treemacs-workspace/no-theme.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;Full Treemacs configuration can be found in my &lt;a href=&#34;https://gitlab.com/andreyorst/dotfiles/blob/02af73a8ec43789a16226a90a8a5bfc940eaeb25/.config/emacs/README.org#treemacs&#34; target=&#34;_blank&#34;&gt;.dotfiles&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Dynamic title for Treemacs workspace&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 01 May 2020 16:44:00 +0300</pubDate>
    </item>
  </channel>
</rss>
