<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Vim on Kiril Vladimirov</title>
    <link>https://vld.bg/tags/vim/</link>
    <description>Recent content in Vim on Kiril Vladimirov</description>
    <generator>Hugo -- 0.168.0</generator>
    <language>en</language>
    <lastBuildDate>Mon, 11 Mar 2024 22:18:30 +0200</lastBuildDate>
    <atom:link href="https://vld.bg/tags/vim/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>4913 &#43;= 123</title>
      <link>https://vld.bg/articles/4913_123/</link>
      <pubDate>Mon, 11 Mar 2024 22:18:30 +0200</pubDate>
      <guid>https://vld.bg/articles/4913_123/</guid>
      <description>&lt;p&gt;With merely a handful of articles, I&amp;rsquo;m still growing into my confidence as a writer.
However, I&amp;rsquo;m obviously nailing it when it comes to titles, right? It will all
make sense in a moment.&lt;/p&gt;
&lt;p&gt;As I was writing my &lt;a href=&#34;https://vld.bg/tips/inotify/&#34;&gt;tip about inotifywait(1)&lt;/a&gt;
, decided to show
how different editors behave when saving a file. &amp;ldquo;I use vim btw&amp;rdquo;™, so it didn&amp;rsquo;t
take long to try it in there.&lt;/p&gt;
&lt;p&gt;Executed &lt;code&gt;vim foo +wq&lt;/code&gt; and this is what &lt;code&gt;inotifywait(1)&lt;/code&gt; printed:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>With merely a handful of articles, I&rsquo;m still growing into my confidence as a writer.
However, I&rsquo;m obviously nailing it when it comes to titles, right? It will all
make sense in a moment.</p>
<p>As I was writing my <a href="/tips/inotify/">tip about inotifywait(1)</a>
, decided to show
how different editors behave when saving a file. &ldquo;I use vim btw&rdquo;™, so it didn&rsquo;t
take long to try it in there.</p>
<p>Executed <code>vim foo +wq</code> and this is what <code>inotifywait(1)</code> printed:</p>
<pre tabindex="0"><code>/path/to/watched/dir/ CLOSE_WRITE,CLOSE 4913
/path/to/watched/dir/ DELETE 4913
/path/to/watched/dir/ MOVED_FROM foo
/path/to/watched/dir/ CLOSE_WRITE,CLOSE foo
</code></pre><p>That&rsquo;s weird. It creates a file named 4913 and then moves it to the intended
location. Why 4913, though? Tried it several times on multiple machines - always
that same number. You know how when it comes to some vim mystery, everybody
always tells you to use <code>:help</code>? Yeah, no luck there, this time.</p>
<h3 id="git-clone-httpsgithubcomvimvimgit--rg-4913-vim"><code>git clone https://github.com/vim/vim.git &amp;&amp; rg 4913 vim</code></h3>
<p>Two meaningful results.</p>
<blockquote>
<p><strong>vim/runtime/doc/version7.txt:</strong> On MS-Windows sometimes files with number 4913 or higher are left behind.</p>
</blockquote>
<p>😅</p>
<p>Fine. <a href="https://github.com/vim/vim/blob/473952e85286eb9c6098801f1819981ba61ad153/src/bufwrite.c#L1186" target="_blank">One meaningful result</a>
:</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#999;font-style:italic">// Check if we can create a file and set the owner/group to
</span></span></span><span style="display:flex;"><span><span style="color:#999;font-style:italic">// the ones from the original file.
</span></span></span><span style="display:flex;"><span><span style="color:#999;font-style:italic">// First find a file name that doesn&#39;t exist yet (use some
</span></span></span><span style="display:flex;"><span><span style="color:#999;font-style:italic">// arbitrary numbers).
</span></span></span><span style="display:flex;"><span><span style="color:#447fcf">STRCPY</span>(IObuff, fname);
</span></span><span style="display:flex;"><span>fd = -<span style="color:#3677a9">1</span>;
</span></span><span style="display:flex; background-color:#363636"><span><span style="color:#6ab825;font-weight:bold">for</span> (i = <span style="color:#3677a9">4913</span>; ; i += <span style="color:#3677a9">123</span>)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#447fcf">sprintf</span>((<span style="color:#6ab825;font-weight:bold">char</span> *)<span style="color:#447fcf">gettail</span>(IObuff), <span style="color:#ed9d13">&#34;%d&#34;</span>, i);
</span></span><span style="display:flex;"><span>    <span style="color:#6ab825;font-weight:bold">if</span> (<span style="color:#447fcf">mch_lstat</span>((<span style="color:#6ab825;font-weight:bold">char</span> *)IObuff, &amp;st) &lt; <span style="color:#3677a9">0</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    fd = <span style="color:#447fcf">mch_open</span>((<span style="color:#6ab825;font-weight:bold">char</span> *)IObuff,
</span></span><span style="display:flex;"><span>            O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
</span></span><span style="display:flex;"><span>    <span style="color:#6ab825;font-weight:bold">if</span> (fd &lt; <span style="color:#3677a9">0</span> &amp;&amp; errno == EEXIST)
</span></span><span style="display:flex;"><span>        <span style="color:#999;font-style:italic">// If the same file name is created by another
</span></span></span><span style="display:flex;"><span>        <span style="color:#999;font-style:italic">// process between lstat() and open(), find another
</span></span></span><span style="display:flex;"><span>        <span style="color:#999;font-style:italic">// name.
</span></span></span><span style="display:flex;"><span>        <span style="color:#6ab825;font-weight:bold">continue</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#6ab825;font-weight:bold">break</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">if</span> (fd &lt; <span style="color:#3677a9">0</span>)	<span style="color:#999;font-style:italic">// can&#39;t write in directory
</span></span></span><span style="display:flex;"><span>    backup_copy = TRUE;
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">else</span> [..]
</span></span></code></pre></div><p>This is part of a (haunting) function bigger than 6000 lines called <code>int buf_write</code>. This particular block is only accessible when <code>:set backup</code> and the
user is trying to save changes in a file that already exists. So, the idea is
fairly simple: make sure to write the changes in any file whatsoever inside the
target directory in order to move it over the target file, so that the latter
will be updated atomically. No one would ever observe partial change of state.</p>
<p>But why 4913? Reminded me of a meme about that random function which always
returns 4, because it was a result of a perfectly fair dice throw. No idea, it
appeared in <a href="https://github.com/vim/vim/commit/071d4279d6ab81b7187b48f3a0fc61e587b6db6c" target="_blank">the 7th
commit</a>

since the migration to git for version 7. <strong>If anybody knows, please reach
out.</strong></p>
<p>The purpose of adding 123 until the end of time is clear, though. Pick &ldquo;a
random&rdquo; non-existent file to the target directory. Choosing 123 in particular
is there just because Bram had to write some number, probably. Doing this
indefinitely is not really a bad idea <strong>in this case</strong>. I mean, who in their
right mind will create thousands of files with names that are only numbers
starting from 4913 and then adding 123?</p>
<details>
    <summary> Well, me, apparently. (click to expand) </summary>
<p>Let&rsquo;s see how hard we can make it for vim. A single write over already existing
file does not take long even on pretty old hardware (Xeon E5-2690):</p>
<pre tabindex="0"><code>$ time vim files/foo +wq

real    0m0.035s
user    0m0.015s
sys     0m0.012s
</code></pre><p>Let&rsquo;s see what happens when 4913 exists:</p>
<pre tabindex="0"><code>$ touch files/4913 &amp;&amp; time vim files/foo +wq

real    0m0.034s
user    0m0.021s
sys     0m0.004s
</code></pre><p>Pretty much the same. What is one more <code>open(2)</code> after all. inotifywait(1) reports:</p>
<pre tabindex="0"><code>CLOSE_WRITE,CLOSE 4913
CLOSE_WRITE,CLOSE 5036
DELETE 5036
MOVED_FROM foo
CLOSE_WRITE,CLOSE foo
</code></pre><p>How about we make it work just a bit more:</p>
<pre tabindex="0"><code>$ n=4913
$ for i in {1..4096}; do n=$(($n+123)); touch files/$n; done
$ time vim files/foo +wq

real    0m0.041s
user    0m0.021s
sys     0m0.011s
</code></pre><p>Still far quicker than anybody would notice in already insane scenario. And
yet&hellip;</p>
<pre tabindex="0"><code>$ for i in {1..50000}; do n=$(($n+123)); touch files/$n; done
$ time vim files/foo +wq

real    0m0.134s
user    0m0.020s
sys     0m0.098s
</code></pre><p>Now, we&rsquo;re talking. I even saw the terminal flickering in order to draw the
window, before being able to finish with the <code>:wq</code> command. Testing with
anything more than that is way above any even remotely possible scenario.</p>
</details>
<p>Having thousands files in a single directory is something you never want in the
real world anyways. There are filesystems with a hard limit by design. While
modern filesystems don&rsquo;t, you will surely experience performance issues when
working with such a directory.</p>
<h2 id="y-tho">Y tho?</h2>
<p>Why am I telling you all this? Because I like digging deeper into such quirky
details. The next time you stumble upon something peculiar, remember: there
might just be an amusing or enlightening story waiting to be uncovered. Or
maybe not, but you&rsquo;ll learn something anyway.</p>
]]></content:encoded>
    </item>
    <item>
      <title>ttymouse_sgr</title>
      <link>https://vld.bg/articles/ttymouse-sgr/</link>
      <pubDate>Fri, 11 Aug 2023 23:52:50 +0200</pubDate>
      <guid>https://vld.bg/articles/ttymouse-sgr/</guid>
      <description>&lt;p&gt;Recently I bought myself a new &amp;ldquo;ultra-wide&amp;rdquo; monitor - LG 35WN75C. Quite nice if
you ask me. One of its greatest feature is that I can open 5-6 vertical splits
of code (I use vim btw) without sacrificing on readability. Soon, I&amp;rsquo;ve realized
that my mouse usage is increasing a lot. Apparently, scrolling through code and
selecting things, when out of the-zone™, is far more comfortable with the
mouse. How did I find that, you ask?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently I bought myself a new &ldquo;ultra-wide&rdquo; monitor - LG 35WN75C. Quite nice if
you ask me. One of its greatest feature is that I can open 5-6 vertical splits
of code (I use vim btw) without sacrificing on readability. Soon, I&rsquo;ve realized
that my mouse usage is increasing a lot. Apparently, scrolling through code and
selecting things, when out of the-zone™, is far more comfortable with the
mouse. How did I find that, you ask?</p>
<p>Clicking on code in the fifth split left to write, actually got registered
as a click in the third one. Started to experiment and realized that it
registered properly on the 222nd column, but any other column after that got
also registered there. Weird. Something happens on column 223?</p>
<p>This is what my vim configuration looked like, when it comes to mouse support:</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span><span style="color:#999;font-style:italic">&#34; Mouse support</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> mouse=a
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">if</span> !has(<span style="color:#ed9d13">&#39;nvim&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#6ab825;font-weight:bold">set</span> ttymouse=xterm2
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">endif</span>
</span></span></code></pre></div><p>No idea how did I ever got to that <code>ttymouse=xterm2</code>. Probably copied it from
somebody else&rsquo;s vimfiles. Anyways, apparently mouse support gets activated with
<code>set mouse=a</code>. Let&rsquo;s go into mouse&rsquo;s help and look for that magical number 223.
Open vim, call <code>:help mouse</code> and search for 223.</p>
<p>&hellip; and voilà! First result is precisely about that <code>xterm2</code> value of <code>ttymouse</code>:</p>
<blockquote>
<pre><code>     xterm        xterm-like mouse handling.  The mouse generates
                  &quot;&lt;Esc&gt;[Mscr&quot;, where &quot;scr&quot; is three bytes:
                          &quot;s&quot;  = button state
                          &quot;c&quot;  = column plus 33
                          &quot;r&quot;  = row plus 33
                  This only works up to 223 columns!  See &quot;dec&quot;,
                  &quot;urxvt&quot;, and &quot;sgr&quot; for solutions.
</code></pre>
</blockquote>
<p>So, I get to choose between dec, urxvt and sgr. After a bit of digging, it
looks like sgr is the most modern one, supported since 7.3.632. Here&rsquo;s the
patch if you&rsquo;re into this:
<a href="http://ftp.vim.org/pub/vim/patches/7.3/7.3.632" target="_blank">http://ftp.vim.org/pub/vim/patches/7.3/7.3.632</a>
</p>
<p>So, this is how my &ldquo;mouse setup&rdquo; looks like now:</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span><span style="color:#999;font-style:italic">&#34; Mouse support</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> mouse=a
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">if</span> !has(<span style="color:#ed9d13">&#39;nvim&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#6ab825;font-weight:bold">if</span> has(<span style="color:#ed9d13">&#34;mouse_sgr&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#6ab825;font-weight:bold">set</span> ttymouse=sgr
</span></span><span style="display:flex;"><span>    <span style="color:#6ab825;font-weight:bold">else</span>
</span></span><span style="display:flex;"><span>        <span style="color:#6ab825;font-weight:bold">set</span> ttymouse=xterm2
</span></span><span style="display:flex;"><span>    <span style="color:#6ab825;font-weight:bold">endif</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">endif</span>
</span></span></code></pre></div><p>The mouse support is now working <del>great</del> well enough, considering we&rsquo;re
talking about a terminal application here.</p>
<h2 id="y-tho">Y tho?</h2>
<p>Why am I telling you all this? It&rsquo;s a clear example of how one can debug and fix
an issue in vim simply by browsing <code>:help</code>. Not to mention that I had two
different ways to arrive at the same help page. Notice that <code>if !has('nvim')</code>
there? I didn&rsquo;t even bother to check if the same reproduces in neovim (spoiler
alert: it does not). Instead of going through trial and error for that magical
number 223, I could&rsquo;ve just tried in neovim and then go directly into reading
<code>:help ttymouse</code>.</p>
<p>One can learn a lot about vim, simply by wandering in there. Apparently having
a good documentation helps your users. Modern software tend to overlook that. I
tend to overlook it into the software I write and maintain. The new way is
writing tutorials and endless <code>README.md</code> pages in the project&rsquo;s root. We might
want to reconsider this.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
