<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.1.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2020-11-08T23:56:33+02:00</updated><id>/feed.xml</id><title type="html">Maciek Janicki’s website</title><entry><title type="html">Following science journals via RSS</title><link href="/2020/11/08/following-science-journals.html" rel="alternate" type="text/html" title="Following science journals via RSS" /><published>2020-11-08T00:00:00+02:00</published><updated>2020-11-08T00:00:00+02:00</updated><id>/2020/11/08/following-science-journals</id><content type="html" xml:base="/2020/11/08/following-science-journals.html">&lt;p&gt;Working in academia means having to follow the current state of the
research. The “usual” way to do it is downloading PDFs from websites of
conferences and journals. It is needless to say that this is terribly
inefficient: it requires us to remember when something new is expected
to appear, manually navigating through the website etc. Even worse,
recently there is a trend to increasingly rely on social media (Twitter,
ResearchGate) and bloated, proprietary, data-mining “bibliography managers”
(like Mendeley) to get suggestions on what to read. In this post, I describe
an efficient, distraction-free and privacy-protecting workflow for keeping
up with the latest research.&lt;/p&gt;

&lt;p&gt;The general idea is to use RSS feeds to track updates of the journals in a
text mode RSS reader. Furthermore, we want the link in the RSS item to send
us directly to the PDF version of the paper (opening in our favourite reader),
which usually requires a slight hack.&lt;/p&gt;

&lt;h2 id=&quot;use-rss-to-follow-updates&quot;&gt;Use RSS to follow updates&lt;/h2&gt;

&lt;p&gt;Once upon a time, there was a universal way of following updates on
any website: RSS feeds. The standard is dead-simple: each site exposes
an XML file containing a list of recent “posts”. They typically contain
a title, publication date, a short summary and a link to the full
article. There are dozens of clients, both text-based and graphical,
that you can use to subscribe to such feeds and gather all updates in
one place. Without logging in to any accounts and giving away the
information about which sources you follow and which articles you read.&lt;/p&gt;

&lt;p&gt;Here’s how I browse the journal &lt;em&gt;Journal for Data Mining &amp;amp; Digital Humanities&lt;/em&gt;
(JDMDH) in my text-based client &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newsboat&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2020/screencast-following-science-journals.gif&quot; alt=&quot;demo&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In order to get the list of articles as an RSS feeds, all you need to do is
add the feed URL (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://jdmdh.episciences.org/rss/papers&lt;/code&gt; for that
journal) to the newsboat’s list of URLs. Most sites will have such feed,
but occasionally it might be hard to find (look for “RSS” links).&lt;/p&gt;

&lt;h2 id=&quot;shorten-the-way-from-an-rss-item-to-pdf&quot;&gt;Shorten the way from an RSS item to PDF&lt;/h2&gt;

&lt;p&gt;In an ideal world, I would get the PDF on my desktop by hitting just
one keystroke in newsboat. This is sometimes possible. Where it is not,
a terminal-based web browser can minimize the pain and distraction caused
by having to pass through a website.&lt;/p&gt;

&lt;p&gt;In practice, most RSS feeds contain a link that leads not straight to
the PDF, but to a website from which a PDF can be downloaded. In the
easiest case, the URL straight to the PDF can be deduced from website
URL. For example, the “Journal of Data Mining &amp;amp; Digital Humanities”
refers to papers using an URL like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://jdmdh.episciences.org/3905&lt;/code&gt;,
while the PDF can be accessed under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://jdmdh.episciences.org/3905/pdf&lt;/code&gt;.
Thus, we always need to add a trailing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/pdf&lt;/code&gt; to the link.&lt;/p&gt;

&lt;p&gt;In order to implement this, let’s start by setting the web browser used by
newsboat (i.e. the program called when you hit the keybinding for “open”)
to a custom script. Edit the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.newsboat/config&lt;/code&gt; and add the line:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;browser ~/.newsboat/browser.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then create the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.newsboat/browser.sh&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in
&lt;/span&gt;http://jdmdh.episciences.org/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    curl &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;/pdf 2&amp;gt; /dev/null | zathura - &amp;amp;
    &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;w3m &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Right now we have one rule for the “Journal of Data Mining &amp;amp; Digital
Humanities” and a default rule at the end, which opens everything else using
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w3m&lt;/code&gt;. The rule for JDMDH executes the following command:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &quot;$1&quot;/pdf 2&amp;gt; /dev/null | zathura - &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;which:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;appends &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/pdf&lt;/code&gt; to the URL referenced in the RSS item,&lt;/li&gt;
  &lt;li&gt;downloads the PDF file and prints it to standard input,&lt;/li&gt;
  &lt;li&gt;launches &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zathura&lt;/code&gt; that reads the PDF from stdin (option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now pressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt; on an item in newsboat should pull up the PDF in zathura.&lt;/p&gt;

&lt;p&gt;A little annoyance of this method is that you need to implement a separate
rule for almost every source, because each of them might have a different
way of changing the webpage URL to the one of the PDF - you need to figure
out the rule by comparing those every time. Here’s one for arXiv:&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://arxiv.org/abs/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;PDFURL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s|^http://|https://|; s|/abs/|/pdf/|; s|$|.pdf|'&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
    curl &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PDFURL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; 2&amp;gt;/dev/null | zathura - &amp;amp;
    &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;setup-w3m-to-directly-open-pdfs&quot;&gt;Setup w3m to directly open PDFs&lt;/h2&gt;

&lt;p&gt;For sime sites, the relation between the URLs might be unpredictable or
downloading with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wget&lt;/code&gt; might not work for some reason. Our default
rule opens the site in w3m then. If there’s a “Download PDF” link somewhere, 
you can setup w3m to open the file directly in zathura by adding the
following line:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;application/pdf; zathura %s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;to either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.mailcap&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.w3m/mailcap&lt;/code&gt;. Then all you need to do is to
navigate the site to find the PDF link - if you open it in w3m, you can
at least avoid looking at the ads and flashy webdesign.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The above workflow gives me a standard and minimum-distraction way to follow
the newly appearing articles. Especially a look at arXiv, which has almost
daily updates, allows me to keep up with the field. All sources are accessible
with the same text-based interface, thanks to which I can better focus on
the text. As in the other solutions that I present, it allows me to flexibly
and seamlessly combine the most suitable applications for the job: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newsboat&lt;/code&gt;
for RSS, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w3m&lt;/code&gt; for quick Web browsing without really looking at the site,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zathura&lt;/code&gt; for reading PDFs. The fresh research is delivered straight to
my desk.&lt;/p&gt;</content><author><name></name></author><category term="science" /><category term="workflow" /><summary type="html">Working in academia means having to follow the current state of the research. The “usual” way to do it is downloading PDFs from websites of conferences and journals. It is needless to say that this is terribly inefficient: it requires us to remember when something new is expected to appear, manually navigating through the website etc. Even worse, recently there is a trend to increasingly rely on social media (Twitter, ResearchGate) and bloated, proprietary, data-mining “bibliography managers” (like Mendeley) to get suggestions on what to read. In this post, I describe an efficient, distraction-free and privacy-protecting workflow for keeping up with the latest research.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/images/thumbnails/following-science-journals.png" /><media:content medium="image" url="/assets/images/thumbnails/following-science-journals.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Executing code chunks from Vim</title><link href="/2020/09/26/executing-code-chunks-from-vim.html" rel="alternate" type="text/html" title="Executing code chunks from Vim" /><published>2020-09-26T00:00:00+03:00</published><updated>2020-09-26T00:00:00+03:00</updated><id>/2020/09/26/executing-code-chunks-from-vim</id><content type="html" xml:base="/2020/09/26/executing-code-chunks-from-vim.html">&lt;p&gt;Recently “notebook” applications like Jupyter and RStudio have become a popular
way of teaching and practicing programming. Their advantage is making
programming interactive: you write several lines of code, then execute it and
look what happens. You can tinker with your complex data structures and try
unfamiliar functions out without the need to rerun the whole script each time.
However, this also comes with the massive disadvantage: you are locked down to
a GUI application and cannot edit the code with a decent text editor. In this
tutorial, I show how to achieve the same effect using Vim, the standard REPL
console, and tmux to connect them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; &lt;strong&gt;tmux&lt;/strong&gt; or “terminal multiplexer” is a program that allows you to
manage multiple terminal emulators inside one text terminal or window. In
the tutorial below, I assume that you are familiar with the basic concepts
of tmux, like &lt;em&gt;sessions&lt;/em&gt;, &lt;em&gt;windows&lt;/em&gt; and &lt;em&gt;panes&lt;/em&gt;. If not, I strongly recommend
to check out this amazing piece of software.&lt;/p&gt;

&lt;p&gt;Before we get started, here’s a short demo of what we’re aiming at:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2020/screencast-executing-code-chunks.gif&quot; alt=&quot;Demo of executing chunks of R code.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can see that the first time I hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+E&lt;/code&gt; inside Vim, a new tmux window
pops up, showing a session named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;repl-R&lt;/code&gt; and running the R interpreter. Then I
can select chunks of code and press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+E&lt;/code&gt; again, which sends the selected
code to the interpreter. Inside a tiling window manager (mine is
&lt;a href=&quot;https://dwm.suckless.org/&quot;&gt;dwm&lt;/a&gt;), it looks almost like an RStudio session,
except that I’m using my favourite terminal-based tools. Furthermore, it be
done exactly the same way for different text editors (e.g. Emacs or
&lt;a href=&quot;https://github.com/martanne/vis&quot;&gt;vis&lt;/a&gt;) and different interpreters (Python,
Haskell, what have you). Let’s get down to implementing it.&lt;/p&gt;

&lt;h2 id=&quot;step-1-sending-keys-to-a-tmux-pane-from-outside&quot;&gt;Step 1. Sending keys to a tmux pane from outside&lt;/h2&gt;

&lt;p&gt;In the first step, we’re going to learn how to control an application running
in a tmux pane by running shell commands from outside that pane.&lt;/p&gt;

&lt;p&gt;Execute the following steps:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Start a new tmux session called “test” by running
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tmux new -s test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;in a terminal emulator. This will create the session and a new window with
ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; inside it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Open a completely new terminal window (even without running tmux inside,
doesn’t matter) and execute the following command:
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tmux send-keys -t test:0 ls Enter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Go back to the window running the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; session. You should see that the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt; command has been run in window 0!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As the name suggests, the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;send-keys&lt;/code&gt; sends keypress events to the tmux
pane indicated by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; parameter. This way we can control any application
that’s running there from outside.&lt;/p&gt;

&lt;p&gt;Now let’s modify those steps slightly to get closer to the goal. In step one,
instead run:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tmux new -s test R
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This will open the R interpreter in the newly created window. In step two, run:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tmux send-keys -t test:0 'data(iris)' Enter 'hist(Sepal.Width)' Enter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You should see a nice histogram pop up!&lt;/p&gt;

&lt;h2 id=&quot;step-2-sending-the-vim-selection&quot;&gt;Step 2. Sending the Vim selection&lt;/h2&gt;

&lt;p&gt;We now know how to send keys to an application running inside a tmux pane with
a shell command. Now we will learn how to run this command from Vim and pass
the currently selected text as parameter.&lt;/p&gt;

&lt;p&gt;Vim allows you to run an external command and pass the currently selected lines
to its standard input using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:write&lt;/code&gt; command. You simply pass the command
preceded with a bang sign (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt;) instead of a filename. Try it by selecting some
text in Vim (in visual mode) and running:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:write !tr a b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;A new dialog window should pop up, in which you will see the same text with all
a’s replaced with b’s. This is the output of the command.&lt;/p&gt;

&lt;p&gt;Our goal is to call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux send-keys ...&lt;/code&gt; command on the selected block of
code (say, R code for this example). However, we need to preprocess the code a
little bit to ensure that:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;each line is followed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enter&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;the whitespaces, quotes and other special characters are passed correctly,
instead of breaking the shell command.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is the function that does the whole work. You can first add it to your
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.vimrc&lt;/code&gt; and test it a little bit. Then we will discuss it in detail:&lt;/p&gt;

&lt;div class=&quot;language-vimscript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; SendToREPL&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;silent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'''&amp;lt;,'&lt;/span&gt;'&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;write&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;      \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;sed &lt;span class=&quot;s2&quot;&gt;&quot;s/.*/\0\nEnter/&quot;&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;      \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;\n&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;\0&quot;&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;      \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; xargs &lt;span class=&quot;m&quot;&gt;-0&lt;/span&gt; tmux send&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;' . b:repl_session . '&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;'
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In order to test it, you need to set the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b:repl_session&lt;/code&gt; to the name
of the tmux session, in which our R interpreter is running:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:let b:repl_session=&quot;test&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then you can call the function by selecting some R code in visual mode and
running:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:call SendToREPL()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Note that when you press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt; in visual mode, the prompt that appears looks like
this: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:'&amp;lt;,'&amp;gt;&lt;/code&gt; - i.e. it contains the selected range. You need to remove those
extra characters (up to the colon) to achieve the proper behaviour. We will
automatize this in Step 3.&lt;/p&gt;

&lt;p&gt;Let’s have a closer look at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SendToREPL()&lt;/code&gt;. The first line: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;silent! execute
'''&amp;lt;''&amp;gt;write&lt;/code&gt; just executes Vim’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt; command on the currently selected
range. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;silent!&lt;/code&gt; means that we don’t want the dialog window with the output to
pop up (because we’re not expecting any output) and the whole command is
enclosed in single quotes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'&lt;/code&gt;), with quotes inside the command being escaped
by doubling them.&lt;/p&gt;

&lt;p&gt;The three subsequent lines contain the shell command that is passed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt;.
It’s actually a pipeline of three commands:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed &quot;s/.*/\0\nEnter/&quot;&lt;/code&gt; adds after each line a line consisting of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enter&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tr &quot;\n&quot; &quot;\0&quot;&lt;/code&gt; changes all line breaks to the NUL character - this is
important for the next command,&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xargs -0 tmux send-keys -t ' . b:repl_session .':0.0'&lt;/code&gt; calls the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux
send-keys&lt;/code&gt; command while passing the lines from its stdin as arguments. The
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-0&lt;/code&gt; parameter means that the input lines are separated by NUL characters
instead of newlines - this way they are passed literally, no matter what
whitespace and special characters they contain. As the target tmux pane, we
set the pane 0 of window 0 of the session, the name of which is written in
the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b:repl_session&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;step-3-ensuring-that-the-interpreter-is-running&quot;&gt;Step 3. Ensuring that the interpreter is running&lt;/h2&gt;

&lt;p&gt;The missing part is now the first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+E&lt;/code&gt; press, which starts the tmux session
running the interpreter. In order to simplify this process, we will set some
variables based on the file type:&lt;/p&gt;

&lt;div class=&quot;language-vimscript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;FileType&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;rmd &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:repl_cmd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;R&quot;&lt;/span&gt;
autocmd &lt;span class=&quot;nb&quot;&gt;FileType&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:repl_cmd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;python3&quot;&lt;/span&gt;
autocmd &lt;span class=&quot;nb&quot;&gt;FileType&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;rmd&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:repl_session&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;repl-&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:repl_cmd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b:&lt;/code&gt; prefix means that the variables are local to the buffer. We set two
variables: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b:repl_cmd&lt;/code&gt; is the command to run the appropriate interpreter,
while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b:repl_session&lt;/code&gt; is the name of the tmux session where it’s supposed to
be running.&lt;/p&gt;

&lt;p&gt;Now we define the following function which starts the interpreter if it’s not
already running:&lt;/p&gt;

&lt;div class=&quot;language-vimscript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; EnsureREPL&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;b:repl_cmd&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;tmux has-session -t &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:repl_session&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; 
&lt;span class=&quot;se&quot;&gt;                    \&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; || ( st -e tmux new-session -s &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;                    \&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:repl_session&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b:repl_cmd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; ) &amp;amp;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux has-session&lt;/code&gt; command checks whether the session is already running.
If not, we start it in a new terminal window - remember to replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;st&lt;/code&gt; in line
4 with your terminal emulator of choice.&lt;/p&gt;

&lt;p&gt;Finally, we set the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+E&lt;/code&gt; keybinding for both normal and visual mode:&lt;/p&gt;

&lt;div class=&quot;language-vimscript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;autocmd &lt;span class=&quot;nb&quot;&gt;FileType&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;rmd&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;python&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;  \&lt;/span&gt; nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;silent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; EnsureREPL&lt;span class=&quot;p&quot;&gt;()&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
autocmd &lt;span class=&quot;nb&quot;&gt;FileType&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;rmd&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;python&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;  \&lt;/span&gt; vnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&amp;lt;&lt;/span&gt;C&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;silent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; SendToREPL&lt;span class=&quot;p&quot;&gt;()&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;final-remarks&quot;&gt;Final remarks&lt;/h2&gt;

&lt;p&gt;As I’ve noted at the beginning, the workflow is not Vim-specific and can be
implemented in any text editor that allows selecting a chunk of text and piping
it to an external shell command. The essential part here is tmux and this is
one example for how powerful this application is when it comes to managing text
terminals.&lt;/p&gt;

&lt;p&gt;Some might say that there are editors that allow you to run a terminal inside
an editor buffer, like neovim. I find this solution somehow inelegant - you
typically run a text editor inside a terminal, so you shouldn’t be running
another terminal inside the editor. Here we use the editor for editing text and
delegate everything else to external applications.&lt;/p&gt;

&lt;p&gt;Using this solution for R, I completely eliminated RStudio from my workflow.
I don’t miss its constant crashes at all!&lt;/p&gt;</content><author><name></name></author><category term="programming" /><category term="vim" /><category term="tmux" /><summary type="html">Recently “notebook” applications like Jupyter and RStudio have become a popular way of teaching and practicing programming. Their advantage is making programming interactive: you write several lines of code, then execute it and look what happens. You can tinker with your complex data structures and try unfamiliar functions out without the need to rerun the whole script each time. However, this also comes with the massive disadvantage: you are locked down to a GUI application and cannot edit the code with a decent text editor. In this tutorial, I show how to achieve the same effect using Vim, the standard REPL console, and tmux to connect them.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/images/thumbnails/2020-08-24-executing-code-chunks-from-vim.png" /><media:content medium="image" url="/assets/images/thumbnails/2020-08-24-executing-code-chunks-from-vim.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Having all PDFs just a few keystrokes away</title><link href="/2020/09/20/dmenu-documents.html" rel="alternate" type="text/html" title="Having all PDFs just a few keystrokes away" /><published>2020-09-20T00:00:00+03:00</published><updated>2020-09-20T00:00:00+03:00</updated><id>/2020/09/20/dmenu-documents</id><content type="html" xml:base="/2020/09/20/dmenu-documents.html">&lt;p&gt;I tend to have a lot of PDF files on my computer: books, science papers,
presentations… I often need to quickly open one of them: check a theoretical
detail in a book related to what I’m doing or a reference in a paper I’m
reading. With the help of dmenu and a short shellscript, I have found a way to
make this process as quick and unintrusive as possible.&lt;/p&gt;

&lt;h2 id=&quot;dmenu-a-quick-introduction&quot;&gt;dmenu: a quick introduction&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://tools.suckless.org/dmenu/&quot;&gt;dmenu&lt;/a&gt; is a fantastic program that serves
only the purpose of “choosing one option out of a list of possibilities”. It is
very similar to &lt;a href=&quot;/tag/fzf&quot;&gt;fzf&lt;/a&gt; that I’ve mentioned before, but operating in a
graphical window manager instead of the text terminal. Here’s a minimal
example:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;apples&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;bananas&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;grapes&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;oranges&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;pears&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;pineapple&quot;&lt;/span&gt; | dmenu
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will show the following menu on the top of the screen:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2020/dmenu.gif&quot; alt=&quot;dmenu&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once you start typing, the selection will be narrowed down to the entries
containing the typed string. The chosen item will be printed on standard
output.&lt;/p&gt;

&lt;h2 id=&quot;the-basic-solution&quot;&gt;The basic solution&lt;/h2&gt;

&lt;p&gt;In our case, the entries in the list are going to be paths of PDF files on the
system. I store all my documents in the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Documents&lt;/code&gt;, so I can
obtain a list of all of them with the following command:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;find ~/Documents &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'*.pdf'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s combine this with dmenu to be able to choose one file from the list:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;find ~/Documents &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'*.pdf'&lt;/span&gt; | dmenu &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; 20
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i&lt;/code&gt; makes dmenu match case-insensitively and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-l 20&lt;/code&gt; displays
one entry per line in 20 lines (instead of displaying all entries in one line
as in the example).&lt;/p&gt;

&lt;p&gt;The output of the command is the chosen file. The only missing part now is to
pass the filename to your PDF reader of choice. Mine is
&lt;a href=&quot;https://pwmt.org/projects/zathura/&quot;&gt;zathura&lt;/a&gt;, so I do the following:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;find ~/Documents &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'*.pdf'&lt;/span&gt; | dmenu &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; 20&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;zathura &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILENAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And here’s the result:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2020/dmenu-pdfs.gif&quot; alt=&quot;dmenu&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Just save it to a shellscript file, bind it to a key in your window manager and
there you go!&lt;/p&gt;

&lt;h2 id=&quot;except&quot;&gt;…except…&lt;/h2&gt;

&lt;p&gt;If you’re a purist like me, you may be disturbed be the need to call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find&lt;/code&gt;
command every time this script is executed. If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Documents&lt;/code&gt; directory is
large, it might be quite slow and involve a lot of unnecessary disk reads. A
reasonable solution would be to keep the list of all files in a text file (say,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.txt&lt;/code&gt;) and only update it if the content of the directory changes. That’s
why we’ll change the script to the following:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ~/Documents/index.txt &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; ~/Documents &lt;span class=&quot;nt&quot;&gt;-nt&lt;/span&gt; ~/Documents/index.txt &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;find ~/Documents &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'*.pdf'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ~/Documents/index.txt
&lt;span class=&quot;k&quot;&gt;fi
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;dmenu &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; 20 &amp;lt; ~/Documents/index.txt&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;zathura &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILENAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The condition in the first line makes use of two tests: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;! -f&lt;/code&gt; is true
when the file does not exist, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nt&lt;/code&gt; checks whether the argument on the
left is “&lt;strong&gt;n&lt;/strong&gt;ewer &lt;strong&gt;t&lt;/strong&gt;han” the one on the right (in the sense of the “last
modified” filesystem entry). Every time you make some modification to the
documents directory (like add a new file), its “last modified” date will be
updated and this condition will be fulfilled on the next check. In this case,
we update the index. This way we can use the index file as input to dmenu and
avoid calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find&lt;/code&gt; unnecessarily.&lt;/p&gt;

&lt;p&gt;It is easy to generalize this script to handle different directories, file
extensions and opening programs (movies, images, what have you). This will be
left as an exercise for the reader.&lt;/p&gt;</content><author><name></name></author><category term="desktop" /><category term="dmenu" /><category term="shell" /><summary type="html">I tend to have a lot of PDF files on my computer: books, science papers, presentations… I often need to quickly open one of them: check a theoretical detail in a book related to what I’m doing or a reference in a paper I’m reading. With the help of dmenu and a short shellscript, I have found a way to make this process as quick and unintrusive as possible.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/images/thumbnails/2020-09-20-dmenu-documents.png" /><media:content medium="image" url="/assets/images/thumbnails/2020-09-20-dmenu-documents.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Announcing chesstools</title><link href="/2020/05/03/announcing-chesstools.html" rel="alternate" type="text/html" title="Announcing chesstools" /><published>2020-05-03T00:00:00+03:00</published><updated>2020-05-03T00:00:00+03:00</updated><id>/2020/05/03/announcing-chesstools</id><content type="html" xml:base="/2020/05/03/announcing-chesstools.html">&lt;p&gt;The long weekend has been very fruitful for me: after some hours of coding, I
can proudly announce version 0.1 of chesstools - a suite of minimalist tools
for chess study following the UNIX philosophy. The main component of the
package is &lt;strong&gt;pgnvi&lt;/strong&gt; - a vi-like editor and browser for PGN files.
It comes with a simple graphical application for
drawing the chess board and a few other tools.  You can get the package from my
&lt;a href=&quot;https://gitlab.com/mmj/chesstools&quot;&gt;Gitlab&lt;/a&gt; or
&lt;a href=&quot;https://github.com/maciejjan/chesstools&quot;&gt;Github&lt;/a&gt; pages.&lt;/p&gt;

&lt;p&gt;Recently I was trying to get better in chess, but I’ve always found the
educational materials hard to use. Replaying games on the board while reading a
book is slow and clumsy, while computer programs for browsing PGN files
typically come with terrible bloated GUIs (couldn’t find any counterexample). I
noticed that I would need something simple and keyboard-driven, ideally with Vi
keybindings, which would integrate well into the terminal-based workflow. It’s
just reading text files and drawing a simple picture, shouldn’t be that
complicated, right? So I ended up writing it.&lt;/p&gt;

&lt;p&gt;Originally I wanted to make a single TUI application, in which the position
would be drawn using Unicode symbols for chess pieces (yes, there are such!).
It turned out to be an impractical idea, because the resulting board is very
small and barely readable. And if you enlarge the terminal font, all the other
text in the window becomes too huge.&lt;/p&gt;

&lt;p&gt;Then I had this awesome idea: why not delegate the drawing to a separate
program that does &lt;em&gt;only&lt;/em&gt; this? Simply read the position in FEN notation from
stdin (it’s even a single line) and draw it! A text-based PGN browser could
then call this program as a subprocess and write positions to its stdin. That’s
how &lt;strong&gt;drawboard&lt;/strong&gt; came about on one evening after work.&lt;/p&gt;

&lt;p&gt;The main component of the package is &lt;strong&gt;pgnvi&lt;/strong&gt; - a text mode browser and editor
for PGN files. It features a tree view that you can use as an opening explorer
with large databases. This is how &lt;strong&gt;pgnvi&lt;/strong&gt;’s tree view and &lt;strong&gt;drawboard&lt;/strong&gt; look
together in action:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2020/pgnvi-tree-view.png&quot; alt=&quot;pgnvi tree view&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Of course you can also use &lt;strong&gt;pgnvi&lt;/strong&gt; to watch and edit games - all using the vi
keybindings:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2020/pgnvi-game-view.png&quot; alt=&quot;pgnvi tree view&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Instead of an “insert mode”, &lt;strong&gt;pgnvi&lt;/strong&gt; features an “append mode”, in which you
can append the moves at the end of the game or delete the moves from a certain
position onwards. This is enough for editing - why would you change a chess
game in the middle? As the validity of moves and positions is constantly
checked, this would quickly result in an invalid state.&lt;/p&gt;

&lt;p&gt;The append mode features another interesting functionality. The three main
rows of the keyboard (those with letters) are completely remapped to the
following layout:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|  1  |  2  |  3  |  4  |  +  | O-O |  5  |  6  |  7  |  8  |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 |  a  |  b  |  c  |  d  |     |     |  e  |  f  |  g  |  h  |
 +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  |  R  |  N  |  B  |  Q  |     |  x  |  K  |  B  |  N  |  R  |
  +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note how the 8 ranks and 8 files used in chess ideally match the 8 fingers that
we use for typing (not counting thumbs). The layout corresponds visually to the
chessboard and makes the frequently used combinations easily reachable. It will
surely have a somewhat steep learning curve, but I’m pretty sure that once
mastered, it will make entering moves enormously efficient.&lt;/p&gt;

&lt;p&gt;But, I didn’t spend the whole long weekend programming. It’s nice to breathe
some fresh air in between. Taking a break between long hours of coding, I did a
20km hike in Finnish woods.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2020/may-woods.jpg&quot; alt=&quot;me in the woods&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Chesstools is still at an early alpha stage: plagued with bugs, missing
important functionality (especially comments and variants!) and exhibiting an
ugly and impoverished user interface. But I’ve already used it to transcribe a
couple of games - both my own and from books - and to browse a couple of game
collections. And it clearly is &lt;em&gt;the&lt;/em&gt; chess toolkit that I need. I hope it will
be useful for others, too.&lt;/p&gt;

&lt;p&gt;And when it achieves maturity, maybe I can finally focus on chess.&lt;/p&gt;</content><author><name></name></author><category term="own-projects" /><category term="chess" /><summary type="html">The long weekend has been very fruitful for me: after some hours of coding, I can proudly announce version 0.1 of chesstools - a suite of minimalist tools for chess study following the UNIX philosophy. The main component of the package is pgnvi - a vi-like editor and browser for PGN files. It comes with a simple graphical application for drawing the chess board and a few other tools. You can get the package from my Gitlab or Github pages.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/images/thumbnails/2020-05-03-announcing-chesstools.png" /><media:content medium="image" url="/assets/images/thumbnails/2020-05-03-announcing-chesstools.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Happy new decade!</title><link href="/2020/01/25/happy-new-decade.html" rel="alternate" type="text/html" title="Happy new decade!" /><published>2020-01-25T00:00:00+02:00</published><updated>2020-01-25T00:00:00+02:00</updated><id>/2020/01/25/happy-new-decade</id><content type="html" xml:base="/2020/01/25/happy-new-decade.html">&lt;p&gt;It’s been a while since the last post and for me it was a time of big changes.
After having received my PhD, I moved from Leipzig to Helsinki to work as a
postdoc at the university here. Of course the relocation, getting used to a new
country and starting a new job meant a lot of work and effort, which is why I
was too busy to update this site for a while. But everything went more than
fine and I’m doing well here up north. As for the site, I have a lot of notes
and unfinished articles lying around, so now that I’ve settled in the new
place, I might share Linux tips more often. Well, I’m not promising anything,
we’ll see.&lt;/p&gt;</content><author><name></name></author><category term="blog" /><summary type="html">It’s been a while since the last post and for me it was a time of big changes. After having received my PhD, I moved from Leipzig to Helsinki to work as a postdoc at the university here. Of course the relocation, getting used to a new country and starting a new job meant a lot of work and effort, which is why I was too busy to update this site for a while. But everything went more than fine and I’m doing well here up north. As for the site, I have a lot of notes and unfinished articles lying around, so now that I’ve settled in the new place, I might share Linux tips more often. Well, I’m not promising anything, we’ll see.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/images/thumbnails/2020-01-25-happy-new-decade.png" /><media:content medium="image" url="/assets/images/thumbnails/2020-01-25-happy-new-decade.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">PhD thesis defended successfully</title><link href="/2019/09/04/phd-thesis-defended.html" rel="alternate" type="text/html" title="PhD thesis defended successfully" /><published>2019-09-04T00:00:00+03:00</published><updated>2019-09-04T00:00:00+03:00</updated><id>/2019/09/04/phd-thesis-defended</id><content type="html" xml:base="/2019/09/04/phd-thesis-defended.html">&lt;p&gt;Last month I had my PhD defense at the University of Leipzig and I obtained my
PhD title with magna cum laude. In near future, I will be probably moving to
another university and widening my research interests, as I am no longer bound
to a single, focused long-term goal. If you are interested in my thesis, you
can download it &lt;a href=&quot;/science.html&quot;&gt;here&lt;/a&gt; and the code is available on
&lt;a href=&quot;http://gitlab.com/mmj/morle&quot;&gt;Gitlab&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="blog" /><summary type="html">Last month I had my PhD defense at the University of Leipzig and I obtained my PhD title with magna cum laude. In near future, I will be probably moving to another university and widening my research interests, as I am no longer bound to a single, focused long-term goal. If you are interested in my thesis, you can download it here and the code is available on Gitlab.</summary></entry><entry><title type="html">Change to another shell’s working directory</title><link href="/2019/07/27/change-to-another-shells-cwd.html" rel="alternate" type="text/html" title="Change to another shell’s working directory" /><published>2019-07-27T00:00:00+03:00</published><updated>2019-07-27T00:00:00+03:00</updated><id>/2019/07/27/change-to-another-shells-cwd</id><content type="html" xml:base="/2019/07/27/change-to-another-shells-cwd.html">&lt;p&gt;Today I’m going to share another trick for changing a shell’s working directory
involving the fuzzy finder. Let us assume that you are doing something in a
terminal and then need suddenly need another window for working in the same
directory. There is an easy way to do this. It involves defining a function,
which shows the current directories of all running shells in fzf, so that we
can quickly choose one of them and navigate to it.&lt;/p&gt;

&lt;p&gt;I’ll start by showing the full code of the function. Then, I’ll discuss it
command by command.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;choose_from_cwds&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;PROCID &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;pgrep &lt;span class=&quot;s2&quot;&gt;&quot;^&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SHELL&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
		&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;readlink&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; /proc/&lt;span class=&quot;nv&quot;&gt;$PROCID&lt;/span&gt;/cwd
	&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	| &lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	| fzf &lt;span class=&quot;nt&quot;&gt;--height&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Of course, I refer to the function presented here by a handy alias:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;chd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cd &quot;$(choose_from_cwds)&quot; &amp;amp;&amp;amp; pwd'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Similarly to the function defined in the previous post, also the alias &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chd&lt;/code&gt;
presents me with a fuzzy finder containing a list of directories. When I choose
one of them, it navigates to it and displays the directory we’ve end up in.&lt;/p&gt;

&lt;p&gt;So now let’s have a look at the commands used in the function.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pgrep &lt;span class=&quot;s2&quot;&gt;&quot;^&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SHELL&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;$&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This gives us a list of PIDs of all running shell processes. The environment
variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$SHELL&lt;/code&gt; contains the location of the binary running as shell (e.g.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/bin/bash&lt;/code&gt;). We extract the name of the binary (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt;) using the command
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;basename&lt;/code&gt;. Be sure to enclose the name in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^$&lt;/code&gt;, so that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pgrep&lt;/code&gt; does not match
other processes whose commands accidentally contain this string.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;readlink&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; /proc/&lt;span class=&quot;nv&quot;&gt;$PROCID&lt;/span&gt;/cwd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is the most important line of the function: we use the PID of a shell’s
process to find out its current working directory. Under Linux, this is very
simple: the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/proc/$PID&lt;/code&gt; contains various useful information about
the process in question, which are served by the operating system as “files”.
One of them is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cwd&lt;/code&gt;, which is… simply a symbolic link to the process’s
current directory! I can’t think of a simpler and more elegant way to expose
such information - the beauty of Unix shows here.&lt;/p&gt;

&lt;p&gt;We follow the link using the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readlink -e&lt;/code&gt;, which returns the path of
the referred directory (and also ensures that it exists).&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Of course we may have multiple shells running with the same current directory.
In this case, we don’t want to have multiple identical entries on our list,
hence unique sort.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fzf &lt;span class=&quot;nt&quot;&gt;--height&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, we pipe the list of directories to the fuzzy finder, which presents us
with a neat chooser.&lt;/p&gt;</content><author><name></name></author><category term="shell" /><category term="fzf" /><summary type="html">Today I’m going to share another trick for changing a shell’s working directory involving the fuzzy finder. Let us assume that you are doing something in a terminal and then need suddenly need another window for working in the same directory. There is an easy way to do this. It involves defining a function, which shows the current directories of all running shells in fzf, so that we can quickly choose one of them and navigate to it.</summary></entry><entry><title type="html">Navigate through filesystem quickly with fzf</title><link href="/2019/06/06/navigate-filesystem-fzf.html" rel="alternate" type="text/html" title="Navigate through filesystem quickly with fzf" /><published>2019-06-06T00:00:00+03:00</published><updated>2019-06-06T00:00:00+03:00</updated><id>/2019/06/06/navigate-filesystem-fzf</id><content type="html" xml:base="/2019/06/06/navigate-filesystem-fzf.html">&lt;p&gt;Navigating to the right directory is one of the most unnecessarily
time-consuming tasks while working in the shell. Have you ever found yourself
typing long paths by hand and repeatedly pressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tab&lt;/code&gt; because you forgot the
name of some directory?  Personally, I use a couple of tricks to avoid typing
paths. Here’s the most important one.&lt;/p&gt;

&lt;h2 id=&quot;the-goal&quot;&gt;The goal&lt;/h2&gt;

&lt;p&gt;Let’s say I want to work on the post that you’re currently reading. Normally, I
would have to type something like this into my terminal:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/projects/website/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;_posts
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vim navigate-filesystem-fzf.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s quite a bit of typing! And of course, if I misspell anything, I have to
try again. On the other hand, using some tricks, I can get to the right file
in just a few keystrokes and I don’t even have to hit exactly the right keys.
It looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2019/navigate-filesystem-fzf.gif&quot; alt=&quot;Navigating through the filesystem with fzf.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Of course, the animation is slowed down a great deal. In my normal workflow, it
takes less than 3 seconds. There are a couple of different tricks here, but the
most important one is using the program called &lt;strong&gt;fzf&lt;/strong&gt;. Let’s have a closer
look.&lt;/p&gt;

&lt;h2 id=&quot;fzf-a-quick-introduction&quot;&gt;fzf: a quick introduction&lt;/h2&gt;

&lt;p&gt;The program you see in action in the above screencast is
&lt;a href=&quot;https://github.com/junegunn/fzf&quot;&gt;fzf&lt;/a&gt;, which is an abbreviation for “fuzzy
finder”. It basically serves one purpose: choosing an item from a list by
typing parts of its name. The “item” and the “list” can be whatever, which
opens nearly endless possibilities for our creativity.&lt;/p&gt;

&lt;p&gt;If you run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fzf&lt;/code&gt; without any arguments, it serves as a file chooser: it
recursively searches all subdirectories of the current directory for files and
lets you choose one file. It is worth noting that the recursive search is
blazingly fast.&lt;/p&gt;

&lt;p&gt;However, the real greatness of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fzf&lt;/code&gt; comes from its flexibility: if you pass
something on standard input, it is interpreted as a list, one item per line.
Then, it lets you pick an item from this list, instead of a file. The chosen
line is printed on standard output. Try the following:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;apples&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;bananas&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;grapes&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;oranges&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;pears&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;pineapple&quot;&lt;/span&gt; | fzf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At first, you see the complete list. You can simply navigate it with either
Emacs-style (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-N/P&lt;/code&gt;) or Vi-style (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-J/K&lt;/code&gt;) hotkeys. If you start typing,
the choice is narrowed to the entries matching what you’ve typed. The matching
is - as the program’s name says - “fuzzy”, i.e. not exact. Even if you type
non-consecutive letters, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rg&lt;/code&gt;, it will still match &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oranges&lt;/code&gt;. It is also
tolerant for slight misspellings: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apl&lt;/code&gt; still selects &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apples&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pineapple&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;navigating-through-the-filesystem&quot;&gt;Navigating through the filesystem&lt;/h2&gt;

&lt;p&gt;In order to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fzf&lt;/code&gt; for navigating, I want to call it in a loop. Every time,
it should list the contents of the current directory and let me choose one item
from this list. If it is a directory, it should go to this directory and repeat
the same. If I’ve chosen a file, it should open the file and terminate. To
achieve this behavior, I have written the following function:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fuzzy_open&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILENAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-maxdepth&lt;/span&gt; 1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/.bookmarks&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
                     | fzf &lt;span class=&quot;nt&quot;&gt;--height&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
        if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILENAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
            &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILENAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else
            &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;break
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi
    done
    if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILENAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        return &lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
    ~/.scripts/open &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILENAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At its heart lies the following line, which decides which input is piped to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fzf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-maxdepth&lt;/span&gt; 1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/.bookmarks&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is a concatenation of two different sources. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find . -maxdepth 1&lt;/code&gt; lists the
contents of the current directory. In the second part, I additionally pass
entries from a file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bookmarks&lt;/code&gt; in my home directory.&lt;/p&gt;

&lt;p&gt;The bookmark file is actually a very important element of the whole thing. It
stores paths that I use all the time, like the ones associated with the
projects that I’m currently working on. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/projects/website&lt;/code&gt;,
which contains my website sources, is listed in the bookmarks, as is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Documents/bibliography&lt;/code&gt;, where I store all scientific papers.&lt;/p&gt;

&lt;p&gt;Every time I find myself in a directory where I’m probably going to return, I
simply run:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bookmarks
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And I have this directory available in a few keystrokes from anywhere. Note
that it’s important not to type a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; or bye bye all your bookmarks.
It’s probably better to create an alias for this command.&lt;/p&gt;

&lt;p&gt;Turning back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fuzzy_open()&lt;/code&gt;, once the file name is chosen, there are three
possible cases:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;It is a name of the directory - change to this directory and repeat.&lt;/li&gt;
  &lt;li&gt;It is empty - exit with exit code &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;. Note that we still end up in the
directory we’ve chosen in the previous iteration.&lt;/li&gt;
  &lt;li&gt;It is a name of a file - open this file. I’ll leave my generic file opening
script (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.scripts/open&lt;/code&gt;) for another post, but you can guess what it does.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, in order to be able to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fuzzy_open&lt;/code&gt; quickly, I set up a
convenient alias:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'fuzzy_open'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s it! I hope you’ve learned something useful and the next time you need to
get to the right directory in the shell, you’ll save yourself some time,
keystrokes and nerves.&lt;/p&gt;</content><author><name></name></author><category term="shell" /><category term="fzf" /><summary type="html">Navigating to the right directory is one of the most unnecessarily time-consuming tasks while working in the shell. Have you ever found yourself typing long paths by hand and repeatedly pressing Tab because you forgot the name of some directory? Personally, I use a couple of tricks to avoid typing paths. Here’s the most important one.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/images/thumbnails/2019-06-06-navigate-filesystem-fzf.png" /><media:content medium="image" url="/assets/images/thumbnails/2019-06-06-navigate-filesystem-fzf.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Making your keyboard layout more ergonomic</title><link href="/2019/05/24/keyboard-ergonomy.html" rel="alternate" type="text/html" title="Making your keyboard layout more ergonomic" /><published>2019-05-24T00:00:00+03:00</published><updated>2019-05-24T00:00:00+03:00</updated><id>/2019/05/24/keyboard-ergonomy</id><content type="html" xml:base="/2019/05/24/keyboard-ergonomy.html">&lt;p&gt;There is no doubt that the keyboard is the most efficient input device to
interact with your computer. I use the keyboard for pretty much everything,
including web browsing, switching between windows and arranging them, writing
e-mails etc. However, many programs require combinations with a modifier key
(especially &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt;) to trigger some functionality. Because of the placement of
the modifier keys on the keyboard, repeated pressing of such combinations can
be inconvenient and require weird twists and stretches. In this post, I show
how to remap certain keys to a much more ergonomic placement.&lt;/p&gt;

&lt;h2 id=&quot;the-home-row-and-the-placement-of-modifier-keys&quot;&gt;The home row and the placement of modifier keys&lt;/h2&gt;

&lt;p&gt;As I live in Germany, I normally use German keyboards with the so-called ISO
layout, meaning an extra key between Z and left Shift. However, I use the
Polish keyboard layout, which is basically the same as the US layout.
Thus, a typical keyboard I work on looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2019/keyboard-1.png&quot; alt=&quot;The home row and other easily reachable keys&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The keys marked in green are the so-called “home row” - the position in which
your fingers should normally rest. They are obviously the easiest keys to
reach, as you don’t have to move your fingers at all in order to reach them.
Additionally, the keys marked in orange are also quite easy to reach - they
require only a slight finger movement.&lt;/p&gt;

&lt;p&gt;Now, I mentioned the combinations involving the modifier keys. Let’s have a
look on where they are placed:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2019/keyboard-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt&lt;/code&gt; keys are not that bad. They are placed right next to the space
bar, so you can press them with your thumbs and the position of the other
fingers is almost unaffected. But the other ones, especially the frequently
needed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt;, are a catastrophe. They are apparently supposed to be pressed by
the little finger, which is the weakest of all. Moreover, doing this requires
either twisting the wrist outwards, or crooking the little finger, or most
often both. This introduces a tension in your hand, requires you to use more
strength, and the bend of the wrist changes the position of other fingers,
making the letter keys harder to reach. You may laugh, but if you have to do
this non-stop for 10 hours a day or longer, it &lt;em&gt;is&lt;/em&gt; a serious problem. This is
the reason why some people find programs that make extensive use of such
combinations, like especially Emacs, unusable.&lt;/p&gt;

&lt;p&gt;(I myself don’t use Emacs, but mostly for other reasons. I’ve found that the
modkey combinations are not as awful as they seem, if you follow the advice in
this post.)&lt;/p&gt;

&lt;h2 id=&quot;a-simple-solution&quot;&gt;A simple solution&lt;/h2&gt;

&lt;p&gt;A simple solution to this problem is to place the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; keys near to the home
row, so that they are reachable without leaving the natural position:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2019/keyboard-3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;On the left, pretty much all keyboard have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CapsLock&lt;/code&gt; in this position. This
key is large, wonderfully reachable and completely useless. Remapping it to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; is thus a commonly found advice and I strongly recommend it.&lt;/p&gt;

&lt;p&gt;However, I also need an equally convenient right &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; key. The key that
occupies the right position is the backslash/pipe (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\|&lt;/code&gt;). It is not used very
often, so it doesn’t harm to remap it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; and find another place for the
backslash. On my keyboard, the perfect place for that is the ISO key (marked in
blue), which is useless in the Polish/US layout, because its characters -
greater/less sign - are also found elsewhere.&lt;/p&gt;

&lt;p&gt;That’s it! This slight remapping will make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt;-combinations ergonomic. A
further idea would be to remap &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tab&lt;/code&gt; to a modifier key (for example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Super&lt;/code&gt;),
but it didn’t work well for me. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tab&lt;/code&gt; is slightly smaller than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CapsLock&lt;/code&gt;, so
it is not as easy to reach as it seems, and we have a muscle memory for
pressing it in some contexts. Moreover, I don’t really need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Super&lt;/code&gt;, since my
window manager (DWM) uses the left &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt&lt;/code&gt; as a modifier key.&lt;/p&gt;

&lt;p&gt;Some Vim users map &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tab&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Esc&lt;/code&gt;, but for Vim I have a better idea, which I’ll
save for another post.&lt;/p&gt;

&lt;p&gt;There is also another type of keyboard, called ANSI, on which the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Return&lt;/code&gt; key
is bar-shaped and the backslash is placed above it. I don’t use this type
currently and I’m not sure whether remapping backslash to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; would be a
good idea there.&lt;/p&gt;

&lt;h2 id=&quot;xmodmap&quot;&gt;xmodmap&lt;/h2&gt;

&lt;p&gt;On the X window system, such key remapping is ridiculously easy to achieve
using the program &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xmodmap&lt;/code&gt;. You describe the desired mappings in a text file,
typically called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.xmodmaprc&lt;/code&gt;, and then simply call:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ xmodmap ~/.xmodmaprc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is good to have this command auto-run on system start, for example by
putting it into your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.xinitrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.xmodmaprc&lt;/code&gt;, which does the remapping described above, looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;clear Lock
keycode 66 = Control_L
keycode 51 = Control_R
add Control = Control_L Control_R
keycode 94 = backslash bar backslash bar dead_grave dead_breve
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each physical key on the keyboard is identified by a &lt;em&gt;number&lt;/em&gt; (called
&lt;em&gt;keycode&lt;/em&gt;). Using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keycode&lt;/code&gt; command, you can reassign those codes to the
“meanings” (&lt;em&gt;keysyms&lt;/em&gt;) recognized by X. Remapping &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CapsLock&lt;/code&gt; is a bit tricky,
because you have to deactivate the “lock” that it triggers. This is what the
first line does. The fourth line adds (or re-adds) the concept of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Control&lt;/code&gt;
modifier, which consists of pressing the left or right &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt;. I am not sure
why it has to be explicitly stated as it should be set up by default, but
without this line the “new” &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; keys didn’t work.&lt;/p&gt;

&lt;p&gt;The last line maps the ISO key to what the backslash key (51) previously was.
As you see, you can assign multiple keysyms to a key. The first one is the key
pressed without any modifiers, the second one with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shift&lt;/code&gt;. The third and
fourth one seems to be with some weird modifier key that nobody uses (and
with/without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shift&lt;/code&gt;), so it is virtually always mapped to the same as the
first and second. Finally, the fifth/sixth pair is achieved by additionally
pressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AltGr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Needless to say, the manpage for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xmodmap&lt;/code&gt; explains all the available commands.
It is not a lot in this case.&lt;/p&gt;

&lt;p&gt;There are different ways of finding out what the keycode of a key is. Firstly,
you can use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xev&lt;/code&gt; program. It opens a window and reports all the events for
this window (among others, keypresses) to the terminal. If you press a key with
this window focused, you will get some information about the pressed key,
including its keycode.&lt;/p&gt;

&lt;p&gt;Another method is to call:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ xmodmap -pk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;which prints out the table of current mappings.&lt;/p&gt;

&lt;h2 id=&quot;one-final-advice&quot;&gt;One final advice&lt;/h2&gt;

&lt;p&gt;There is a reason why I insisted on having both a left and a right &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; in a
convenient place. People sometimes tend to use only one of them - typically the
left one - and press combinations like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+S&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+C&lt;/code&gt; with one hand. I
think it is a bad habit. I recommend to always press the modifier key with the
opposite hand as the letter key. This allows you to use less strength and move
your hands less - especially stay in the home row. The same applies to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shift&lt;/code&gt;.&lt;/p&gt;</content><author><name></name></author><category term="x11" /><category term="ergonomy" /><summary type="html">There is no doubt that the keyboard is the most efficient input device to interact with your computer. I use the keyboard for pretty much everything, including web browsing, switching between windows and arranging them, writing e-mails etc. However, many programs require combinations with a modifier key (especially Ctrl) to trigger some functionality. Because of the placement of the modifier keys on the keyboard, repeated pressing of such combinations can be inconvenient and require weird twists and stretches. In this post, I show how to remap certain keys to a much more ergonomic placement.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/images/thumbnails/2019-05-24-keyboard-ergonomy.png" /><media:content medium="image" url="/assets/images/thumbnails/2019-05-24-keyboard-ergonomy.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Site design finished</title><link href="/2019/05/15/site-design-finished.html" rel="alternate" type="text/html" title="Site design finished" /><published>2019-05-15T00:00:00+03:00</published><updated>2019-05-15T00:00:00+03:00</updated><id>/2019/05/15/site-design-finished</id><content type="html" xml:base="/2019/05/15/site-design-finished.html">&lt;p&gt;I’ve been quite busy since the last post, but yesterday and today I finally
found time to finish the site. With the nice index of posts by year and by tag
on the right (made with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll-archive&lt;/code&gt;), it is now more or less complete.
There is still some content missing on the “Books” and “Software” pages, but I
will fill it incrementally.  I also already have multiple posts in preparation -
I prefer to work on them in parallel, rather than post them one by one. So,
real content is going to appear here very soon!&lt;/p&gt;</content><author><name></name></author><category term="blog" /><summary type="html">I’ve been quite busy since the last post, but yesterday and today I finally found time to finish the site. With the nice index of posts by year and by tag on the right (made with jekyll-archive), it is now more or less complete. There is still some content missing on the “Books” and “Software” pages, but I will fill it incrementally. I also already have multiple posts in preparation - I prefer to work on them in parallel, rather than post them one by one. So, real content is going to appear here very soon!</summary></entry></feed>