<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>blog of axlefublr</title>
      <link>https://axlefublr.github.io</link>
      <description></description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://axlefublr.github.io/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Mon, 02 Mar 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>nirism</title>
          <pubDate>Mon, 02 Mar 2026 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/nirism/</link>
          <guid>https://axlefublr.github.io/nirism/</guid>
          <description xml:base="https://axlefublr.github.io/nirism/">&lt;p&gt;I&#x27;ve been using niri for a bit over a year now, and yet still I have a soft cap of windows I&#x27;m able to open before I&#x27;m completely lost.
Almost assuredly a skill issue on my part — I know people who have around a HUNDRED windows open at a single time, so there must be some way for me to gain the power too, right?&lt;&#x2F;p&gt;
&lt;p&gt;Recently I made some pushes on configuring my workflow to allow me to manage more windows, easier.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;overview&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#overview&quot; aria-label=&quot;Anchor link for: overview&quot;&gt;overview&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;When the overview first came out, I was excited about it but towards my &lt;strong&gt;friends&lt;&#x2F;strong&gt;, not towards myself.
It didn&#x27;t sound useful to &lt;em&gt;me&lt;&#x2F;em&gt;.
I added a hotkey for it sure, but then continued to basically never use it.
What&#x27;s the issue then?&lt;&#x2F;p&gt;
&lt;p&gt;Part of it is effort.
I open the overview and sure, I see some windows around the current one, but not &lt;em&gt;that&lt;&#x2F;em&gt; many.
It helps me find myself a bit, but with the limited value it provided it was hard to mentally argue with myself to press the separate hotkey for it.&lt;&#x2F;p&gt;
&lt;p&gt;You can, however, change the &lt;em&gt;zoom&lt;&#x2F;em&gt; level of the overview, to be able to fit more windows at once.
I thought at first that it&#x27;s not that good of an idea because then there&#x27;s less &lt;em&gt;detail&lt;&#x2F;em&gt; for me to use to discern windows, but no!
Especially thanks to another thing I&#x27;ll talk about later in this blog post, reducing the zoom level has made the overview &lt;strong&gt;much&lt;&#x2F;strong&gt; more useful to me.&lt;&#x2F;p&gt;
&lt;p&gt;I configured the zoom to fit ~2.5 workspaces both above and below.
In effect, now when I open the overview, I can see almost &lt;em&gt;all&lt;&#x2F;em&gt; of my opened windows!
Finally, the overview is doing its job — being an &lt;em&gt;overview&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;nirism&#x2F;.&#x2F;overview.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In contrast, the default zoom level looks ridiculous, in how much less useful it is.
But there&#x27;s reason for it being that way — you see, all of your window-managing hotkeys &lt;strong&gt;do&lt;&#x2F;strong&gt; work in the overview as well.
You can close, consume, expel, move windows, workspaces, and more.
Normally that can get a bit confusing, especially if you try moving workspaces (no animation for that) — but if you do it from the &lt;em&gt;overview&lt;&#x2F;em&gt;, suddenly things are a lot easier to visually track, because you have a bigger surrounding context.
Then with most people only using 1-3 workspaces, you don&#x27;t need to zoom out that much to get the benefit, so I&#x27;m guessing that&#x27;s why the default zoom is so close.&lt;&#x2F;p&gt;
&lt;p&gt;For me though? Zooming it &lt;em&gt;out&lt;&#x2F;em&gt; was the solution.&lt;&#x2F;p&gt;
&lt;p&gt;Secondly, the hotkey I chose for it at first was kind of eh.
There&#x27;s an idea I like to talk about in Hotkey™ Theory™ — “sequentiality”.
The hotkey should be pleasant and ergonomic not just in a vacuum — when thinking of the hotkeys you create, you should also consider what &lt;em&gt;other&lt;&#x2F;em&gt; hotkeys may come before and after it.&lt;&#x2F;p&gt;
&lt;p&gt;With the overview, right after opening it I might move ←↓↑→, to different windows and workspaces.
With moving bound on &lt;kbd&gt;Meta+hjkl&lt;&#x2F;kbd&gt;, and the overview being bound on &lt;kbd&gt;Meta+o&lt;&#x2F;kbd&gt;, the sequentiality is poor.
I can&#x27;t &lt;em&gt;quite&lt;&#x2F;em&gt; move to the window on the right, right after opening the overview — I must move my finger from &lt;kbd&gt;o&lt;&#x2F;kbd&gt; to &lt;kbd&gt;l&lt;&#x2F;kbd&gt; first.
There are much poorer sequentialities out there so this comparatively is not a big deal, but it was still contributing to my “eh”ness about the overview.&lt;&#x2F;p&gt;
&lt;p&gt;I rebound it on &lt;kbd&gt;Meta+Space&lt;&#x2F;kbd&gt;, and now &lt;em&gt;that&lt;&#x2F;em&gt; feels a lot better.
Normally I dislike using &lt;kbd&gt;Space&lt;&#x2F;kbd&gt; in hotkeys because of how &lt;em&gt;massive&lt;&#x2F;em&gt; it feels to press, but for the overview that actually works in its favor.
It already &lt;em&gt;feels&lt;&#x2F;em&gt; like a “large” action, so pressing a “large” key to get access to it makes sense to my fingers.
And then of course the better sequentiality.
Right after pressing &lt;kbd&gt;Meta+Space&lt;&#x2F;kbd&gt;, I can without moving any of my fingers, move ←↓↑→ to windows and workspaces, at max comfort!&lt;&#x2F;p&gt;
&lt;p&gt;After doing these two changes, I actually started seeing myself use the overview a lot more.
Really nice tool for “finding yourself” so to speak.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;workspaces&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#workspaces&quot; aria-label=&quot;Anchor link for: workspaces&quot;&gt;workspaces&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The next part that makes it easy to get lost, is how many windows I may open on a single workspace.
I start some sort of workflow; let&#x27;s say I&#x27;m working on my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;gruvbox-material-gtk-theme&quot;&gt;gtk theme&lt;&#x2F;a&gt; (probably soon discontinued).
I&#x27;ll wanna open &lt;code&gt;gtk3-widget-factory&lt;&#x2F;code&gt;, then maybe another gtk window where I&#x27;m testing something specific I can&#x27;t find in &lt;code&gt;gtk3-widget-factory&lt;&#x2F;code&gt;, a terminal for &lt;code&gt;pastel&lt;&#x2F;code&gt;, a terminal where I wanted to run some one command and forgot about, a window where I&#x27;m checking the docs on &lt;code&gt;waybar&lt;&#x2F;code&gt;, “whoops I want to check what chores I need to do today”, and so on and so forth.&lt;&#x2F;p&gt;
&lt;p&gt;A given workflow may create a bunch of windows.
A couple of them are valid, but some other ones are in the way.
The “some one command” terminal needed to exist for a second, but afterwards it remains to be clutter.
If I realize I want to run another some one command, by that point I might&#x27;ve forgotten that I already have a terminal for that, and so I&#x27;ll likely open another one.
This specific usecase I&#x27;ll talk about in a later section, but what is very of interest for now is the doc window on waybar and chore tracker.&lt;&#x2F;p&gt;
&lt;p&gt;It would be pretty nice to have auxillary windows like that to all be in the same spot, rather than riddling the workspace where I&#x27;m working on a given thing.&lt;&#x2F;p&gt;
&lt;p&gt;In niri, when a window spawns, it spawns on the current workspace.
You can make a window rule to make it open on a &lt;em&gt;different&lt;&#x2F;em&gt; workspace, as long as that workspace is &lt;strong&gt;named&lt;&#x2F;strong&gt;.
And so, I create 5 workspaces, all named: one, two, three, four, five.
Pretty much just so that I could use them in window rules.&lt;&#x2F;p&gt;
&lt;p&gt;I considered at first to then make hotkeys that activate a specific workspace, but soon gagging from the memories of awesome wm, I realized I quite dislike it.
A real nice thing about niri is its dynamicness; I want to retain that part and play into it, so my main form of navigation remains directional.&lt;&#x2F;p&gt;
&lt;p&gt;One change that I &lt;em&gt;did&lt;&#x2F;em&gt; add though, to aid moving across now more workspaces, are hotkeys to go to the first &#x2F; last workspace, and hotkeys to go to the first &#x2F; last column.
The latter ones I already noticed myself wanting many times in the past, but the workspace ones are a bit more questionable in terms of usefulness.&lt;&#x2F;p&gt;
&lt;p&gt;So, my named workspace layout is as such:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;three&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;two&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;one&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;four&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;five&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Workspace one is the middle one, the “first” (top) one is three, the last (bottom) one is five.
I still can create more workspaces if I need them — I simply create a window on the automatically created workspace beyond &lt;code&gt;three&lt;&#x2F;code&gt; or &lt;code&gt;five&lt;&#x2F;code&gt;.
Playing along niri&#x27;s dynamicness.&lt;&#x2F;p&gt;
&lt;p&gt;Workspace three will now hold a bunch of my “status” windows so to speak.
Currently on it I have open my chore tracker, calendar, a reminder thingy, a bluetooth tui, and a helix where I&#x27;m calculating my earnings.
All except the last one I window rule to &lt;em&gt;always&lt;&#x2F;em&gt; open on that workspace, so now when I suddenly decide to check what chores I have to do today while working on some project, that window will not get created in the midst of a bunch of other stuff, but instead get moved onto the workspace &lt;em&gt;specifically&lt;&#x2F;em&gt; for status windows, helping me stay more organized.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, documentation windows&lt;a href=&quot;#footnote-1&quot; id=&quot;headnote-1&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 I window rule to always appear on workspace five.
Way easier to keep track of, not get lost in, and eventually clean up.&lt;&#x2F;p&gt;
&lt;a href=&quot;#startup&quot; id=&quot;startup&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;What named workspaces also allow me to do, is create more windows on startup.
Previously I wouldn&#x27;t want to do that, because a bunch of the windows would be created on the main workspace, when I prefer to keep them on some other one.
But now I can actually express it!&lt;&#x2F;p&gt;
&lt;p&gt;On login, the reminder thingy, chore tracker, calendar is created onto workspace three.
Yazi opened in the anime directory and anki on workspace four.
Yet on the main workspace, workspace one, I still start out with my terminal window and the browser.
Less things to have to create manually! Pretty nice.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;togglies&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#togglies&quot; aria-label=&quot;Anchor link for: togglies&quot;&gt;togglies&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Windows are automatically grouped together now thanks to named workspaces, but the issue of duplicates remain.
The chore tracker is started on login, but I also have a hotkey to open it.
It&#x27;s plain easier to press that hotkey than to navigate to the existing window, and afterwards I may forget to close the new one, resulting in a duplicate that will help me get lost.&lt;&#x2F;p&gt;
&lt;p&gt;I have quite a bunch of hotkeys that create some window, actually.
And so, I decided to make their behavior a bit smarter.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;If the window doesn&#x27;t already exist, it&#x27;s created&lt;&#x2F;li&gt;
&lt;li&gt;If it does exist but isn&#x27;t focused, it&#x27;s focused&lt;&#x2F;li&gt;
&lt;li&gt;If it &lt;strong&gt;is&lt;&#x2F;strong&gt; focused, the most recent window is focused instead.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I expressed this via a fish + nu script:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #928374;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env fish&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt; -l wheres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; arg &lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;argv[..-2]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    set&lt;&#x2F;span&gt;&lt;span&gt; -a wheres &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;| where &lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;arg&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;nu&lt;&#x2F;span&gt;&lt;span&gt; --no-std-lib -nc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;    let found = niri msg -j windows&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;    | from json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;    $&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;wheres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;    if (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #928374;&quot;&gt;\$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;found | is-not-empty) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;    	if (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #928374;&quot;&gt;\$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;found | any { get is_focused }) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;    		niri msg action focus-window-previous&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;    	} else {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #928374;&quot;&gt;    		\$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;found | first | each { niri msg action focus-window --id (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #928374;&quot;&gt;\$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;in | get id) }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;    	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;    } else {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;        niri msg action spawn -- &lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;argv[-1]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How to convert it to bash + jq is left as an exercise to the reader.&lt;&#x2F;p&gt;
&lt;p&gt;The full command to give the chore tracker toggly behavior, for example, looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;find-or-make.fish&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;app_id starts-with foot&amp;quot; &amp;quot;title == loago-tracker&amp;quot; &amp;quot;footclient -NT loago-tracker fish -c loago_tracker&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First, an array of nushell &lt;code&gt;where&lt;&#x2F;code&gt; checks to identify the exact window.
And as the last argument, the command to use to create a new window.&lt;&#x2F;p&gt;
&lt;p&gt;Now whenever I want to check my chores, I press &lt;kbd&gt;h↓s&lt;&#x2F;kbd&gt; once to take a looksie, then press &lt;kbd&gt;h↓s&lt;&#x2F;kbd&gt; again to go back to what I was doing.
No new window is created if the tracker already exists, no mess is created for me to get lost in.&lt;&#x2F;p&gt;
&lt;p&gt;I used to have this kind of workflow back on &lt;em&gt;windows&lt;&#x2F;em&gt; with autohotkey actually.
Not sure why I haven&#x27;t replicated it in so long, I remember absolutely loving it.
I get to love it again 😌&lt;&#x2F;p&gt;
&lt;p&gt;A lot of my windows I can now target directly.
Most windows on workspace three, for instance.
Which makes me realize that there are only a few windows on that workspace that I&#x27;d want to focus via normal means.
So if I put all of the “other” (without a direct hotkey) windows at the start&#x2F;end of the workspace, I can use my hotkey to go to the first workspace followed by a hotkey to go to the first&#x2F;last column, and that way I can quickly jump to the “other” windows that are otherwise maybe annoying to reach.
The windows in the &lt;em&gt;middle&lt;&#x2F;em&gt; are then ones that I have direct hotkeys for, so them being more difficult to reach, compared to the first&#x2F;last windows, is not a big deal.&lt;&#x2F;p&gt;
&lt;p&gt;The first&#x2F;last column and workspace hotkeys I all have on &lt;kbd&gt;we↓&lt;&#x2F;kbd&gt;, so the sequentiality of going to the first workspace and then moving to the start of it is &lt;em&gt;fantastic&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Some windows prefer to be closed rather than stay open, though.
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pythops&#x2F;bluetui&quot;&gt;bluetui&lt;&#x2F;a&gt;, the bluetooth tui I&#x27;m using, likes to get fucked up if left unsupervised, for some reason.
So instead of just toggling away from it, I&#x27;d want to close it.&lt;&#x2F;p&gt;
&lt;p&gt;So this ↓&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;If it &lt;strong&gt;is&lt;&#x2F;strong&gt; focused, the most recent window is focused instead.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I want to also close the window afterwards.
This idea is still in the process though, I&#x27;ll either add some flag to the &lt;code&gt;find-or-make.fish&lt;&#x2F;code&gt; script above, or I&#x27;ll make a separate hotkey to express the concept of “switch to the most recent window, close the window you just switched away from”. &lt;br &#x2F;&gt;
“Doesn&#x27;t this already happen when you close a window?” you might rightfully ask — not &lt;em&gt;quite&lt;&#x2F;em&gt;!
The most recent window &lt;em&gt;on that workspace&lt;&#x2F;em&gt; is activated, rather than the global most recent window.
Reasonable behavior, mind you, but keeping recency correct has recently become significant for me, which we&#x27;ll talk about later.&lt;&#x2F;p&gt;
&lt;p&gt;The biggest usecase for &lt;code&gt;find-or-make.fish&lt;&#x2F;code&gt; is a toggle &lt;em&gt;terminal&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
All those one-off commands I might run and come back from?
I can now press &lt;kbd&gt;Meta+Enter&lt;&#x2F;kbd&gt; to activate my permanent-staying toggly terminal, then press &lt;kbd&gt;Meta+Enter&lt;&#x2F;kbd&gt; again to come back to where I was.&lt;&#x2F;p&gt;
&lt;p&gt;In the past, I had a hotkey that created a &lt;em&gt;floating&lt;&#x2F;em&gt; terminal, for a similar usecase to this.
It resolved the need somewhat, but had some downsides.
Due to it being floating, I kinda need to “handle” it immediately — if I don&#x27;t close it after I run my command, it&#x27;ll be annoyingly in the way.
That&#x27;s part of the intention yes, but there are some cases where the command I run takes some time to complete, and I don&#x27;t care to &lt;em&gt;wait&lt;&#x2F;em&gt; for it to complete — I just want to make sure I start it.
Other times, the output of the command is unbearable to view in the &lt;em&gt;small&lt;&#x2F;em&gt; floating window.
Making the floating window &lt;strong&gt;big&lt;&#x2F;strong&gt; instead makes it kind of confusing to work with.&lt;&#x2F;p&gt;
&lt;p&gt;So a normal ass terminal I toggle into is a much better approach I think 😼
As a side benefit, I get to &lt;em&gt;keep&lt;&#x2F;em&gt; old output, for me to possibly look at multiple times, rather than discarding it every time by closing the window.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;alt-tab&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#alt-tab&quot; aria-label=&quot;Anchor link for: alt-tab&quot;&gt;alt tab&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Is another niri feature I was excited for, but for my &lt;em&gt;friends&lt;&#x2F;em&gt; — not myself.
But also, I was &lt;em&gt;surprised&lt;&#x2F;em&gt; that it became part of niri upstream.
In niri, to get to windows you almost always necessarily focus multiple windows on the way, so alt-tab functionality sounds so off, right?
The small but ridiculously important caveat here is &lt;em&gt;debounce&lt;&#x2F;em&gt; — a window is not added into the most recently used list if you&#x27;ve spent less then x milliseconds focusing on it.
You can configure the x of course.&lt;&#x2F;p&gt;
&lt;p&gt;But the thing is, I don&#x27;t really think about my windows in terms of recency, I think about them in terms of geography.
&lt;em&gt;Where&lt;&#x2F;em&gt; they are, rather than what was the window I was just using.&lt;&#x2F;p&gt;
&lt;p&gt;Another skill issue of mine, I bet!
Just like many other things I trained my brain to be able to do, &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;erm&#x2F;&quot;&gt;home row mods&lt;&#x2F;a&gt; being the wackiest one, I can probably train my brain to think in the recency plane as well :3&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve tried using the feature once before in the past to no avail, but this time is a bit of a changed circumstance — now that I always have &lt;em&gt;5&lt;&#x2F;em&gt; workspaces (or more!), to move through, using the recency plane to switch between them quickly becomes a lot more juicy.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine I&#x27;m on the second workspace, open the docs for something, and want to move back.
Currently I&#x27;d need to move to the above workspace &lt;em&gt;thrice&lt;&#x2F;em&gt;, or go to the first one and move down once.
Neither are particularly pleasant!&lt;&#x2F;p&gt;
&lt;p&gt;But with alt tab, I can jump back in one fell swoop, with a nicer &lt;em&gt;semantic&lt;&#x2F;em&gt; to boot — what I want to express, after all, is “bring me back where I just was”.
When I realized that &lt;em&gt;that&#x27;s&lt;&#x2F;em&gt; what I mean, I was sure my brain would adjust to the recency plane pretty well.&lt;&#x2F;p&gt;
&lt;p&gt;But there&#x27;s some more configuring work to do on alt tab before I find it truly viable.
As I started using it, I very quickly noticed that it&#x27;s hard to &lt;em&gt;anticipate&lt;&#x2F;em&gt; the next window in it.
When you select the window on the right of your screen, you only see a small sliver of what the next window is.
Basically never enough to be able to tell ahead of time how many “next window please”s it&#x27;s going to take to get to the window that you want.
To see what the next window is, I need to “next window please”.
Then if I went too far, I need to manually go back 🙄&lt;&#x2F;p&gt;
&lt;p&gt;I realize that what I want is for the selected window to always be &lt;em&gt;centered&lt;&#x2F;em&gt; in the alt tab ui.
And that&#x27;s exactly what I did!&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;centered-mru.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;You can find the patch in my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;niri&quot;&gt;niri fork&lt;&#x2F;a&gt; or in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;discord.com&#x2F;channels&#x2F;1387519366651842574&#x2F;1476954416753147986&quot;&gt;this thread&lt;&#x2F;a&gt; on the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;discord.gg&#x2F;dxEHRDCcEC&quot;&gt;niri discord server&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now as I go through windows in the ui, my brain can preprosses how many more times I need to press my hotkey, as I can see a lot more windows ahead of time.
As opposed to pressing the hotkey, going “nope, not that one”, and pressing it again — which is an annoyingly start-stoppy workflow.&lt;&#x2F;p&gt;
&lt;p&gt;Notably, I reduce the zoom level here too, to be able to see more windows at once.
Here, losing the detail by zooming &lt;em&gt;out&lt;&#x2F;em&gt; matters reasonably more than in the overview.
To make the tradeoff worth it, I have some tips and tricks I&#x27;ll talk about in the next section.&lt;&#x2F;p&gt;
&lt;p&gt;Another feature alt tab has to try to be less annoying, is that the ui only appears after x milliseconds.
Reasonable once again, but what I found is that I&#x27;m not &lt;em&gt;that&lt;&#x2F;em&gt; annoyed about the ui popping up every time.
Yet it appearing &lt;em&gt;immediately&lt;&#x2F;em&gt; is actually really useful because I can start the brain preprocessing step earlier, helping me navigate in the recency plane better ✈️ &lt;br &#x2F;&gt;
Rather than it being &lt;em&gt;only&lt;&#x2F;em&gt; a switcher, it suddenly becomes another form of overview — but instead of geographical, it&#x27;s based on recency.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m still human though, so for the cases where I switch between only two windows over and over again, I gave myself a separate hotkey that does just that, using the &lt;code&gt;focus-window-previous&lt;&#x2F;code&gt; action that doesn&#x27;t even use the alt tab functionality (and hence ui).
This also means that it doesn&#x27;t have the crucial debounce, but should be worth it still.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;makeup&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#makeup&quot; aria-label=&quot;Anchor link for: makeup&quot;&gt;makeup&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;When all of your windows are the same size, they become hard to distinguish.
Especially when (almost) all of your windows are just terminals: text just looks like text a lot of the time.&lt;&#x2F;p&gt;
&lt;p&gt;But if they are of different &lt;em&gt;sizes&lt;&#x2F;em&gt;, they are a lot more immediately distinguishable, in alt tab, overview, and even just as you scroll through the windows naturally.
Sometimes that even results in you fitting more windows at once, as a side benefit.&lt;&#x2F;p&gt;
&lt;p&gt;I have hotkeys that change a window&#x27;s bigness by 5%, and for a while I underused them for reasons I didn&#x27;t quite get.
I use &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;erm&#x2F;&quot;&gt;home row mods&lt;&#x2F;a&gt;, and so to effectively hold some key, I need to tap it and &lt;em&gt;then&lt;&#x2F;em&gt; hold it.
Normally not a big deal, but for incremental hotkeys like 5% bigness changes, you &lt;em&gt;really&lt;&#x2F;em&gt; want to be able to hold them immediately.
With a low repeat-delay and high repeat-rate, suddenly that turns into a fantastic experience.&lt;&#x2F;p&gt;
&lt;p&gt;I rebound them on keys that &lt;em&gt;do&lt;&#x2F;em&gt; immediately get the hold behavior, rather than being tapholdies, and now I can ergonomically &lt;em&gt;whoosh&lt;&#x2F;em&gt; windows to my prefered size, followed by a few small correcting resizes.
Wonderful.&lt;&#x2F;p&gt;
&lt;p&gt;Especially (more realistically, &lt;em&gt;mostly&lt;&#x2F;em&gt;) for terminal output, I might run some command and wanna store it for later.
I run the command, resize the terminal to only as much space as it needs (maybe making it &lt;em&gt;bigger&lt;&#x2F;em&gt; instead, actually!), then maybe throw it on workspace five, to get to later.&lt;&#x2F;p&gt;
&lt;p&gt;There are a lot of windows that I want to &lt;em&gt;always&lt;&#x2F;em&gt; have the same size, though.
The reminder, chore tracker, yazi for anime, etc etc.
So! I can create window rules for those windows, sizing them some size automatically.&lt;&#x2F;p&gt;
&lt;p&gt;On the path of doing that, I also need to &lt;em&gt;name&lt;&#x2F;em&gt; those windows something specific, so that making window rules for them is straightforward.
But the incidental benefit I get from it is that now a lot of my windows are named more &lt;em&gt;usefully&lt;&#x2F;em&gt;.
When I see them in alt tab, not only does their size help me preprocess them, but also the window title I see makes things a little easier.&lt;&#x2F;p&gt;
&lt;p&gt;Taking care of your sizes and titles is the big reason why zooming out even the alt tab ui, I found to be a worthy tradeoff.&lt;&#x2F;p&gt;
&lt;a href=&quot;#henceforth&quot; id=&quot;henceforth&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;With all of these changes, I&#x27;m starting to get more comfortable managing &lt;em&gt;more&lt;&#x2F;em&gt; windows at once, and don&#x27;t feel as forced to close windows immediately.
Still trying things out, but I think this has been an awesome push to make use of moar power that niri has :3&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;footnotes&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-1&quot; id=&quot;footnote-1&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 I have hotkeys that open &lt;code&gt;man …&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;… --help&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;nu -c &#x27;… --help&#x27;&lt;&#x2F;code&gt; in a new window, either through helix or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;ov&#x2F;&quot;&gt;ov&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>rust for... scripting? pt. 2</title>
          <pubDate>Fri, 13 Feb 2026 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/rust-scripting-pt-2/</link>
          <guid>https://axlefublr.github.io/rust-scripting-pt-2/</guid>
          <description xml:base="https://axlefublr.github.io/rust-scripting-pt-2/">&lt;p&gt;In my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;rust-scripting&#x2F;&quot;&gt;previous blog post&lt;&#x2F;a&gt;, I arrived at a rust “scripting” system that I was quite satisfied with :D
But since then, I took upon a journey to learn nushell, and therefore was using it for a lot of my new needs.
For some of them, nushell isn&#x27;t even the most appropriate tool, but finding reasons to use the language so that I could &lt;em&gt;learn&lt;&#x2F;em&gt; it better is a technique I make use of all the time.&lt;&#x2F;p&gt;
&lt;p&gt;One day, I realize I want to edit a rust “script” that I already have.
Wait... how do I do this again?
There&#x27;s a workspace directory, that is symlinked to one of the directories in the cache directory, glued by a bunch of harps. Right...&lt;&#x2F;p&gt;
&lt;p&gt;When I zoom out, I realize that the system that I have created is a bit overly complicated.
Coming back to using it again, it isn&#x27;t immediately &lt;em&gt;obvious&lt;&#x2F;em&gt; what I&#x27;m supposed to do to edit existing work, and amn&#x27;t quite sure how I&#x27;m supposed to start new work.
Initially, I made the system to &lt;em&gt;ease in&lt;&#x2F;em&gt; the barrier of entry towards making a new rust program.
I succeeded in doing so somewhat, but there is still a bit of a barrier.&lt;&#x2F;p&gt;
&lt;p&gt;I can design this to be simpler, surely. And thanks to the suggestion of my friend &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;titaniumtraveler&quot;&gt;remrevo&lt;&#x2F;a&gt;, turns out I make it &lt;em&gt;better&lt;&#x2F;em&gt; too.&lt;&#x2F;p&gt;
&lt;p&gt;The core &lt;em&gt;want&lt;&#x2F;em&gt; that I want to address is that creating a new “script” contains everything it needs in a single file.
More or less.
Then, I want to &lt;em&gt;store&lt;&#x2F;em&gt; all of those scripts more or less in the same place, so that they are pleasant and easy to manage.
And, I want to &lt;em&gt;name&lt;&#x2F;em&gt; the scripts like I would be naming &lt;strong&gt;scripts&lt;&#x2F;strong&gt;, rather than how I would be naming projects.
Finally, the resulting binary should have the &lt;code&gt;.rs&lt;&#x2F;code&gt; extension in its name, so that rust “scripts” are easily differentiated from “normal” binaries, helping me name them neglectfully.&lt;&#x2F;p&gt;
&lt;p&gt;Putting a &lt;code&gt;consume.rs&lt;&#x2F;code&gt; binary into &lt;code&gt;$PATH&lt;&#x2F;code&gt; is free — almost no chance something else I&#x27;ll be using in the future will collide with it.
Putting a &lt;code&gt;consume&lt;&#x2F;code&gt; binary into &lt;code&gt;$PATH&lt;&#x2F;code&gt; is a lot more questionable.
Pretty dang common word!
I&#x27;d need to take a real think before choosing such a name, and I don&#x27;t want to think!&lt;&#x2F;p&gt;
&lt;p&gt;Now, I keep using the word “script” but at this point it&#x27;s lost most of its meaning.
I&#x27;ve been fine with having a compile step for a while.
I&#x27;m okay with having files around it to make it work, but I really don&#x27;t wanna create a whole ass another directory for a new “script”.
And I&#x27;m not actually running &lt;em&gt;the file&lt;&#x2F;em&gt;, I&#x27;m running the binary that just so happens to be named the same as its source code.&lt;&#x2F;p&gt;
&lt;p&gt;So I say “script”, but I mean “an easily creatable rust binary”.
Doesn&#x27;t quite roll off the tongue as easily though, so I&#x27;m going to keep using the word script.&lt;&#x2F;p&gt;
&lt;p&gt;Rust provides me kinda &lt;strong&gt;exactly&lt;&#x2F;strong&gt; what I want, turns out.
In a rust project, you create a &lt;code&gt;src&#x2F;main.rs&lt;&#x2F;code&gt;, and that is the entry point to your binary program.
You may then also (or instead) create a &lt;code&gt;src&#x2F;lib.rs&lt;&#x2F;code&gt;, and that&#x27;s the entry point to the &lt;em&gt;library&lt;&#x2F;em&gt; side of your program.
You can have both at the same time, or only one of them.&lt;&#x2F;p&gt;
&lt;p&gt;But you can create another special thingymabop: &lt;code&gt;src&#x2F;bin&#x2F;&lt;&#x2F;code&gt;.
You can create rust files in that directory, and each individual file is its &lt;strong&gt;own binary entry point&lt;&#x2F;strong&gt;, like &lt;code&gt;src&#x2F;main.rs&lt;&#x2F;code&gt; is.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      consume.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      zat.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cargo.toml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This turns out to be much more fantastic than the system I would&#x27;ve designed would be.
In a &lt;em&gt;normal&lt;&#x2F;em&gt; project, you just have one binary, and it&#x27;s automatically named the same as the project is called.
&lt;em&gt;Some&lt;&#x2F;em&gt; projects, though, can produce multiple binaries.&lt;&#x2F;p&gt;
&lt;p&gt;Yazi produces &lt;code&gt;yazi&lt;&#x2F;code&gt; and &lt;code&gt;ya&lt;&#x2F;code&gt;, nushell produces &lt;code&gt;nu&lt;&#x2F;code&gt; and a bunch more other binaries for plugins.
In those projects, the “entry points” are defined manually in &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;, but with &lt;code&gt;srs&#x2F;bin&#x2F;&lt;&#x2F;code&gt; we don&#x27;t need to bother doing that!
A file with an &lt;code&gt;.rs&lt;&#x2F;code&gt; extension existing in &lt;code&gt;src&#x2F;bin&#x2F;&lt;&#x2F;code&gt; makes cargo automatically register it as a binary entry point.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;So&lt;&#x2F;strong&gt;, to run or compile a “script”, we refer to it with the &lt;code&gt;--bin&lt;&#x2F;code&gt; flag.
If I want to &lt;code&gt;cargo run&lt;&#x2F;code&gt; the &lt;code&gt;consume.rs&lt;&#x2F;code&gt; script, I do &lt;code&gt;cargo run --bin consume&lt;&#x2F;code&gt;.
Pretty straightforward!&lt;&#x2F;p&gt;
&lt;p&gt;To make this ergonomic to use, I can put &lt;code&gt;:sh cargo run --bin %(buffer_stem)&lt;&#x2F;code&gt; into a &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;harp&#x2F;&quot;&gt;command harp&lt;&#x2F;a&gt; in my helix&lt;a href=&quot;#footnote-1&quot; id=&quot;headnote-1&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
.
With it, I can express “run the script I am currently looking at” (in my editor), on a singular hotkey that I can put into my muscle memory.&lt;&#x2F;p&gt;
&lt;p&gt;Then to “release” a script, I first do &lt;code&gt;cargo build --release --bin %(buffer_stem)&lt;&#x2F;code&gt;, and then &lt;code&gt;cp&lt;&#x2F;code&gt; over the resulting binary into the directory where I hold my wks binaries, appending the &lt;code&gt;.rs&lt;&#x2F;code&gt; extension at the end.
Pretty simple also.
Especially when compared to my previous wks system!&lt;&#x2F;p&gt;
&lt;p&gt;There, to edit an existing script I would need to import it from a file into the “workspace” directory and use a fancy exporting script so that the compilation is targeted from the cache.
If I wanted to create a &lt;em&gt;new&lt;&#x2F;em&gt; script, I would need to first check if I haven&#x27;t forgotten to export the changes in the workspace directory and then use the once again fancy script for bringing in a blank slate, and symlinking everything into place. &lt;br &#x2F;&gt;
Wanted to make an ad-hoc binary for &lt;del&gt;a laugh&lt;&#x2F;del&gt; testing? I&#x27;d need to point it to a path where the source + Cargo.toml would be exported into, even when I don&#x27;t care to actually &lt;em&gt;store&lt;&#x2F;em&gt; the testing source code long-term. &lt;br &#x2F;&gt;
It was a mess!&lt;&#x2F;p&gt;
&lt;p&gt;In the new system, I &lt;em&gt;just&lt;&#x2F;em&gt; create a new &lt;code&gt;.rs&lt;&#x2F;code&gt; file in &lt;code&gt;src&#x2F;bin&#x2F;&lt;&#x2F;code&gt; and I&#x27;m done.&lt;&#x2F;p&gt;
&lt;a href=&quot;#cargotoml&quot; id=&quot;cargotoml&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Next thing that you might see in the file structure, is that all the binaries &lt;em&gt;share&lt;&#x2F;em&gt; a singular &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;.
This is fantastic!
Once I &lt;code&gt;cargo add&lt;&#x2F;code&gt; some dependency, &lt;em&gt;all&lt;&#x2F;em&gt; of my binaries get access to it.
The same version is used for all of them, and crucially the same &lt;em&gt;compile artifacts&lt;&#x2F;em&gt; are used across all of them.
So once I compile &lt;code&gt;clap&lt;&#x2F;code&gt; once, I won&#x27;t need to wait for it to compile for my next binary that also uses clap.
This is also neat for my storage space, as rust compile artifacts like to balloon quite a bit!&lt;&#x2F;p&gt;
&lt;p&gt;The binaries also share a single &lt;em&gt;library&lt;&#x2F;em&gt; entry point.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   lib.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      consume.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      zat.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cargo.toml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This in particular unlocks some incredible power!
I can write abstractions and helpers in &lt;code&gt;lib.rs&lt;&#x2F;code&gt;, that I then continue on to use across a bunch of different binaries.
Where at first, creating some sort of binary might be a pain, after a bunch of iteration I&#x27;ll have made the experience so nice for myself that I might then reach for rust out of &lt;em&gt;desire&lt;&#x2F;em&gt;, not only out of performance needs.&lt;&#x2F;p&gt;
&lt;p&gt;In the old wks system, the default template for a new rust script contained a long paragraph of &lt;code&gt;use&lt;&#x2F;code&gt;s, for structs and traits that I&#x27;m very likely to use in a script.
Having to import only what I need gets annoying quickly if I keep on needing the same things, after all.&lt;&#x2F;p&gt;
&lt;p&gt;But now, I can compact them all into a single&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; wks&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;prelude&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::*&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To do this, I create a new module in &lt;code&gt;lib.rs&lt;&#x2F;code&gt; called &lt;code&gt;prelude&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub mod&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; prelude&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I create &lt;code&gt;prelude.rs&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   lib.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   prelude.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      consume.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      zat.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cargo.toml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And go ham, &lt;code&gt;pub use&lt;&#x2F;code&gt;ing all the imports that I feel like I need most of the time:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;#![allow(unused_imports)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; anyhow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; anyhow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; anyhow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;bail&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; anyhow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;ensure&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; clap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;Parser&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;borrow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;Cow&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;collections&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;HashMap&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;collections&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;HashSet&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;File&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;OpenOptions&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;BufRead&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;Read&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;Seek&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;Write&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;ops&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;Not&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;Path&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;PathBuf&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;FromStr&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;LazyLock&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And now all of those modules, structs and traits are all in scope immediately, in all of my scripts.&lt;&#x2F;p&gt;
&lt;a href=&quot;#alias&quot; id=&quot;alias&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Kind of by habit I still made myself a nice alias to make reaching existing and creating new scripts more ergonomic, but it&#x27;s not even that needed honestly.
I have this simple template file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;#![allow(unused_imports)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;#![allow(unused_variables)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;#![allow(dead_code)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt; wks&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;prelude&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;::*&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That I store in the repo. I then make a fish alias &lt;code&gt;wks&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt; wks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    set&lt;&#x2F;span&gt;&lt;span&gt; -l prevdir &lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;PWD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; test &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;argv[1]&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        cd&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;fes&#x2F;wks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        rsync&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;fes&#x2F;wks&#x2F;template.rs ~&#x2F;fes&#x2F;wks&#x2F;src&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;argv[1]&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        helix&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;fes&#x2F;wks&#x2F;src&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;argv[1]&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    cd&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;fes&#x2F;wks&#x2F;src&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    set&lt;&#x2F;span&gt;&lt;span&gt; -l picked (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;fzf&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;picked&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; ||&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; begin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;prevdir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    cd&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;fes&#x2F;wks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    helix&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;fes&#x2F;wks&#x2F;src&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;picked&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With no arguments provided, it opens &lt;code&gt;fzf&lt;&#x2F;code&gt; for me to pick an existing script to edit, and then opens it in helix from the root of the &lt;code&gt;wks&lt;&#x2F;code&gt; project.
If I &lt;em&gt;do&lt;&#x2F;em&gt; provide an argument, that is the name of the script that I want to create (without the &lt;code&gt;.rs&lt;&#x2F;code&gt; extension) by copying over the template file.&lt;&#x2F;p&gt;
&lt;p&gt;I intentionally don&#x27;t safeguard myself from overriding an existing script this way!
I have a &lt;code&gt;test.rs&lt;&#x2F;code&gt; script that I gitignore.
It&#x27;s meant for various ad-hoc checks and tests.
Any time I want to start testing something from a clean slate, I &lt;em&gt;just&lt;&#x2F;em&gt; &lt;code&gt;wks test&lt;&#x2F;code&gt; and I&#x27;m there!
Whatever the test script used to be before then is wiped clean, and I can immediately get to work.&lt;&#x2F;p&gt;
&lt;p&gt;Recently realized how nice this is in practice.
I was working on a new helix feature as usual, and for some reason &lt;code&gt;the.get(1..)&lt;&#x2F;code&gt; was returning me &lt;code&gt;None&lt;&#x2F;code&gt;, despite &lt;code&gt;the&lt;&#x2F;code&gt; being at least two characters long (in fact more).
I do a simple &lt;code&gt;wks test&lt;&#x2F;code&gt; and check out the test case in a “pure” environment, unlike helix, and was able to figure out the core of the issue&lt;a href=&quot;#footnote-2&quot; id=&quot;headnote-2&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 really quickly :D
It was such a pleasant workflow!&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;wks&quot;&gt;repo that holds wks&lt;&#x2F;a&gt; is public!
Check it out, and maybe make use of the idea for your own nice collection of itty bitty rust “scripts”.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;footnotes&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-1&quot; id=&quot;footnote-1&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 “My” is very significant there, &lt;code&gt;buffer_stem&lt;&#x2F;code&gt; is a custom command expansion in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;my helix fork&lt;&#x2F;a&gt;. Normally you would need to use &lt;code&gt;%(file_path_absolute)&lt;&#x2F;code&gt;, converting it into its basename without the extension in one way or another.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-2&quot; id=&quot;footnote-2&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 The first character was &lt;code&gt;€&lt;&#x2F;code&gt;, a multibyte character. &lt;code&gt;get&lt;&#x2F;code&gt; on a &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; returns &lt;code&gt;None&lt;&#x2F;code&gt; if you try to index inside of a multibyte character.
To work around this, I used &lt;code&gt;the.char_indices().nth(1)&lt;&#x2F;code&gt; to get the index of the second character, and then used that value in the afforementioned &lt;code&gt;get&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>erotic meta feet</title>
          <pubDate>Tue, 11 Nov 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/kanata-layers/</link>
          <guid>https://axlefublr.github.io/kanata-layers/</guid>
          <description xml:base="https://axlefublr.github.io/kanata-layers/">&lt;p&gt;I just figured out a longterm annoyance I&#x27;ve been having with how kanata does layers, and I want to share my findings with you.&lt;&#x2F;p&gt;
&lt;p&gt;Sequences of key presses and releases are really hard to mentally parse when in word form, so I will establish a syntax for expressing those. &lt;br &#x2F;&gt;
&lt;kbd&gt;e↓f&lt;&#x2F;kbd&gt; — hold down &lt;kbd&gt;e&lt;&#x2F;kbd&gt;, and while still holding it down, press and release (i.e. tap) &lt;kbd&gt;f&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
&lt;kbd&gt;e↓f↓j&lt;&#x2F;kbd&gt; — hold down &lt;kbd&gt;e&lt;&#x2F;kbd&gt;, and while still holding it down, also hold down &lt;kbd&gt;f&lt;&#x2F;kbd&gt;, and while still holding &lt;em&gt;both&lt;&#x2F;em&gt; &lt;kbd&gt;e&lt;&#x2F;kbd&gt; and &lt;kbd&gt;f&lt;&#x2F;kbd&gt; down, press and release (tap) &lt;kbd&gt;j&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
&lt;kbd&gt;e↓[jk]&lt;&#x2F;kbd&gt; — while holding down &lt;kbd&gt;e&lt;&#x2F;kbd&gt;, individually tap &lt;kbd&gt;j&lt;&#x2F;kbd&gt; or &lt;kbd&gt;k&lt;&#x2F;kbd&gt;; maybe repeatedly. &lt;br &#x2F;&gt;
&lt;kbd&gt;e↓f↓w↓[jk]f↑[jk]&lt;&#x2F;kbd&gt; — one after the other, start holding down &lt;kbd&gt;e&lt;&#x2F;kbd&gt;, &lt;kbd&gt;f&lt;&#x2F;kbd&gt;, &lt;kbd&gt;w&lt;&#x2F;kbd&gt;. While holding them all, tap &lt;kbd&gt;j&lt;&#x2F;kbd&gt; or &lt;kbd&gt;k&lt;&#x2F;kbd&gt; however many times. Then, release &lt;kbd&gt;f&lt;&#x2F;kbd&gt; but not the other two held keys. While continuing to hold &lt;kbd&gt;e&lt;&#x2F;kbd&gt; and &lt;kbd&gt;w&lt;&#x2F;kbd&gt;, tap &lt;kbd&gt;j&lt;&#x2F;kbd&gt; or &lt;kbd&gt;k&lt;&#x2F;kbd&gt; however many times. &lt;br &#x2F;&gt;
&lt;kbd&gt;efw↓[jk]&lt;&#x2F;kbd&gt; I hold down &lt;kbd&gt;e&lt;&#x2F;kbd&gt;, &lt;kbd&gt;f&lt;&#x2F;kbd&gt; and &lt;kbd&gt;w&lt;&#x2F;kbd&gt; in &lt;em&gt;unspecified order&lt;&#x2F;em&gt; and tap &lt;kbd&gt;j&lt;&#x2F;kbd&gt; or &lt;kbd&gt;k&lt;&#x2F;kbd&gt;. So this might be one of: &lt;kbd&gt;e↓f↓w↓[jk]&lt;&#x2F;kbd&gt;, &lt;kbd&gt;e↓w↓f↓[jk]&lt;&#x2F;kbd&gt;, &lt;kbd&gt;f↓e↓w↓[jk]&lt;&#x2F;kbd&gt;, &lt;kbd&gt;f↓w↓e↓[jk]&lt;&#x2F;kbd&gt;, &lt;kbd&gt;w↓e↓f↓[jk]&lt;&#x2F;kbd&gt;, &lt;kbd&gt;w↓f↓e↓[jk]&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
This notation implies that the order of the presses shouldn&#x27;t matter.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;our-setup&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#our-setup&quot; aria-label=&quot;Anchor link for: our-setup&quot;&gt;our setup&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;m going to create an example config to explain things with. &lt;br &#x2F;&gt;
We will have three layers: meta, erotic, feet. &lt;br &#x2F;&gt;
You enter the “meta” layer with &lt;kbd&gt;w↓&lt;&#x2F;kbd&gt;, the “erotic” layer with &lt;kbd&gt;e↓&lt;&#x2F;kbd&gt;, and the “feet” layer with &lt;kbd&gt;f↓&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
I name them funnily so that their absurdity can help you make them apart more easily 😌 &lt;br &#x2F;&gt;
“Ah yes we have layer a b and c” would get confusing quick imo.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (layer-while-held meta)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (layer-while-held erotic)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (layer-while-held feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The meta layer is actually for the meta modifier. You might also know it as super, or the windows key. &lt;br &#x2F;&gt;
Erotic is the custom layer that has hotkeys for the browser: it makes &lt;kbd&gt;j&lt;&#x2F;kbd&gt; and &lt;kbd&gt;k&lt;&#x2F;kbd&gt; (&lt;kbd&gt;e↓[jk]&lt;&#x2F;kbd&gt;) select the above&#x2F;below tab, to do further actions on. &lt;br &#x2F;&gt;
Feet is the “navigation” layer, remapping &lt;kbd&gt;h&lt;&#x2F;kbd&gt;, &lt;kbd&gt;j&lt;&#x2F;kbd&gt;, &lt;kbd&gt;k&lt;&#x2F;kbd&gt;, &lt;kbd&gt;l&lt;&#x2F;kbd&gt; to the arrow keys (&lt;kbd&gt;←&lt;&#x2F;kbd&gt;, &lt;kbd&gt;↓&lt;&#x2F;kbd&gt;, &lt;kbd&gt;↑&lt;&#x2F;kbd&gt;, &lt;kbd&gt;→&lt;&#x2F;kbd&gt;).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (multi lmet (layer-while-held meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (layer-while-held erotic)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (layer-while-held feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (select-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (select-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   h left&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j down&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   l right&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The meta layer itself doesn&#x27;t need to have any mappings yet — we use it as just the meta modifier for now. &lt;br &#x2F;&gt;
But for that to work, we use &lt;code&gt;multi&lt;&#x2F;code&gt; to &lt;em&gt;also&lt;&#x2F;em&gt; send the meta key down press, as long as we keep holding &lt;kbd&gt;w&lt;&#x2F;kbd&gt;.&lt;a href=&quot;#footnote-1&quot; id=&quot;headnote-1&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Erotic and feet don&#x27;t refer to a real modifier though: they are custom layers, not inherently made to mean anything, and are given purpose by us. &lt;br &#x2F;&gt;
In erotic, I use &lt;code&gt;select-next-tab&lt;&#x2F;code&gt; and &lt;code&gt;select-prev-tab&lt;&#x2F;code&gt; as abstractions for however the fuck I actually do that; the &lt;em&gt;real&lt;&#x2F;em&gt; right side action is unimportant here, and would make things confusing for no benefit :p&lt;&#x2F;p&gt;
&lt;h1 id=&quot;wonderful&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#wonderful&quot; aria-label=&quot;Anchor link for: wonderful&quot;&gt;wonderful&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;, now we can &lt;kbd&gt;f↓[hjkl]&lt;&#x2F;kbd&gt; to get arrow keys, &lt;kbd&gt;e↓[jk]&lt;&#x2F;kbd&gt; to select tabs in the browser, and &lt;kbd&gt;w↓[???]&lt;&#x2F;kbd&gt; to use my compositor (window manager &#x2F; DE &#x2F; etc) actions. &lt;br &#x2F;&gt;
But I start running out of convenient to press hotkeys on just &lt;kbd&gt;w↓&lt;&#x2F;kbd&gt; for my compositor; I now want to make &lt;kbd&gt;wf↓&lt;&#x2F;kbd&gt; hold some of the more “complex” compositor actions.&lt;&#x2F;p&gt;
&lt;p&gt;In niri (the compositor), I make hotkeys on &lt;kbd&gt;meta+left&lt;&#x2F;kbd&gt;, &lt;kbd&gt;meta+down&lt;&#x2F;kbd&gt;, &lt;kbd&gt;meta+up&lt;&#x2F;kbd&gt;, &lt;kbd&gt;meta+right&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
The idea here is that when I combine the meta and feet layer, I should effectively get meta+arrow keys, so I can make mappings on those on the compositor side, and it&#x27;ll work!&lt;&#x2F;p&gt;
&lt;p&gt;But now, we are seemingly in &lt;em&gt;both&lt;&#x2F;em&gt; the layer meta and the layer feet. &lt;br &#x2F;&gt;
That&#x27;s not exactly true!&lt;&#x2F;p&gt;
&lt;p&gt;In kanata, only one layer is your “current” one.
&lt;em&gt;But&lt;&#x2F;em&gt;, kanata remembers the previous layer that you &lt;em&gt;were&lt;&#x2F;em&gt; in.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;w↓&lt;&#x2F;kbd&gt; moves you into the meta layer. It is now your current one. &lt;br &#x2F;&gt;
You start holding &lt;kbd&gt;f&lt;&#x2F;kbd&gt;; the meta layer doesn&#x27;t have a mapping for &lt;kbd&gt;f&lt;&#x2F;kbd&gt;, so the &lt;em&gt;previous&lt;&#x2F;em&gt; layer is looked up for a mapping.  &lt;br &#x2F;&gt;
Our previous layer is “default”, which indeed has a mapping for &lt;kbd&gt;f&lt;&#x2F;kbd&gt; — it moves us into the feet layer. &lt;br &#x2F;&gt;
Where now, this is our sequence of layers: default → meta → feet&lt;&#x2F;p&gt;
&lt;p&gt;In our meta+arrow hotkeys, we rely on the meta layer to hold the meta modifier for us, and on the feet layer to translate &lt;kbd&gt;h&lt;&#x2F;kbd&gt;, &lt;kbd&gt;j&lt;&#x2F;kbd&gt;, &lt;kbd&gt;k&lt;&#x2F;kbd&gt;, &lt;kbd&gt;l&lt;&#x2F;kbd&gt; into arrow keys. &lt;br &#x2F;&gt;
This only works well because the meta layer &lt;em&gt;doesn&#x27;t&lt;&#x2F;em&gt; have any mappings on &lt;kbd&gt;h&lt;&#x2F;kbd&gt;, &lt;kbd&gt;j&lt;&#x2F;kbd&gt;, &lt;kbd&gt;k&lt;&#x2F;kbd&gt;, &lt;kbd&gt;l&lt;&#x2F;kbd&gt;.
Let&#x27;s look at the behavior if it &lt;em&gt;did&lt;&#x2F;em&gt; have them.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (meta)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   h (cmd fish -c &amp;quot;notify-send nuh-uh&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (cmd fish -c &amp;quot;notify-send nuh-uh&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (cmd fish -c &amp;quot;notify-send nuh-uh&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   l (cmd fish -c &amp;quot;notify-send nuh-uh&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now when I &lt;kbd&gt;w↓f↓[hjkl]&lt;&#x2F;kbd&gt;, I can do the more special compositor actions as expected. &lt;br &#x2F;&gt;
But if I do &lt;kbd&gt;f↓w↓[hjkl]&lt;&#x2F;kbd&gt; (notice the different order), all I get is a nuh-uh!&lt;&#x2F;p&gt;
&lt;p&gt;This shows that in kanata, &lt;em&gt;the order matters&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
We are &lt;em&gt;kinda&lt;&#x2F;em&gt; in meta and feet at the same time, but each layer has its own precedence, and this changes depending on which we started holding down first.&lt;&#x2F;p&gt;
&lt;p&gt;Of course I&#x27;m not going to have hotkeys specifically to “nuh-uh” me, so here there&#x27;s conveniently no issue. &lt;br &#x2F;&gt;
It starts to &lt;em&gt;actually&lt;&#x2F;em&gt; come into play once you want this kind of composite layer with &lt;em&gt;two&lt;&#x2F;em&gt;, rather than one fake layer. &lt;br &#x2F;&gt;
Before, we relied on the meta &lt;em&gt;modifier&lt;&#x2F;em&gt; — the actual hotkeys were set in niri, not kanata. &lt;br &#x2F;&gt;
And so, only one fake &#x2F; custom layer was actually in use — feet. &lt;br &#x2F;&gt;
Right now, we&#x27;ll make hotkeys directly in kanata, expecting &lt;kbd&gt;ef↓&lt;&#x2F;kbd&gt; — two custom layers together, erotic + feet.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;e↓[jk]&lt;&#x2F;kbd&gt; selects the next &#x2F; previous tab. &lt;br &#x2F;&gt;
Let&#x27;s make &lt;kbd&gt;ef↓[jk]&lt;&#x2F;kbd&gt; &lt;em&gt;extend&lt;&#x2F;em&gt; that selection.&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;select-extend.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;...Where do we put those hotkeys at, though? &lt;br &#x2F;&gt;
Erotic doesn&#x27;t hold some actual modifier for us, and neither do feet. &lt;br &#x2F;&gt;
To put our new hotkeys, we &lt;strong&gt;have to&lt;&#x2F;strong&gt; make a composite layer!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic-feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (extend-select-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (extend-select-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;You can actually name this layer whatever you want! &lt;br &#x2F;&gt;
I just choose to name it &lt;code&gt;erotic-feet&lt;&#x2F;code&gt; because it makes it clear which other two layers it&#x27;s combining.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Currently though, we can never &lt;em&gt;get&lt;&#x2F;em&gt; to this layer. &lt;br &#x2F;&gt;
&lt;kbd&gt;e↓f↓&lt;&#x2F;kbd&gt; results in default → erotic → feet &lt;br &#x2F;&gt;
&lt;kbd&gt;f↓e↓&lt;&#x2F;kbd&gt; results in default → feet → erotic &lt;br &#x2F;&gt;
Once again, kanata is &lt;em&gt;sequential&lt;&#x2F;em&gt;, &lt;strong&gt;not&lt;&#x2F;strong&gt; combinatory, so we need to explicitly put ourselves into erotic feet somehow.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;For clarity: we are relying on the hotkeys set in the default layer, to move us into erotic or feet.
Erotic doesn&#x27;t have a mapping to enter feet — but the default layer does, and so it&#x27;s used as a fallback. &lt;br &#x2F;&gt;
The opposite is also true: feet don&#x27;t have a mapping to enter erotic — default layer does. &lt;br &#x2F;&gt;
But the default layer, naturally, doesn&#x27;t move us into erotic feet.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;To do this, you&#x27;ll supposed to put the “entering” hotkeys into both of the layers that you want to combine.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (layer-while-held erotic-feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (select-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (select-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (layer-while-held erotic-feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   h left&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j down&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   l right&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we &lt;kbd&gt;e↓&lt;&#x2F;kbd&gt; then &lt;kbd&gt;f↓&lt;&#x2F;kbd&gt;, we get into erotic feet. &lt;br &#x2F;&gt;
If we &lt;kbd&gt;f↓&lt;&#x2F;kbd&gt; then &lt;kbd&gt;e↓&lt;&#x2F;kbd&gt;, we get into erotic feet also.&lt;&#x2F;p&gt;
&lt;p&gt;It is crucial that we put the enterer in &lt;em&gt;both&lt;&#x2F;em&gt; layers — if we didn&#x27;t have the &lt;kbd&gt;e&lt;&#x2F;kbd&gt; hotkey in the feet layer, that would mean that &lt;kbd&gt;e↓f↓&lt;&#x2F;kbd&gt; would work, but &lt;kbd&gt;f↓e↓&lt;&#x2F;kbd&gt; &lt;em&gt;&lt;strong&gt;wouldn&#x27;t&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
What we are trying to express is “while I&#x27;m holding both keys”, rather than “if I start holding down these keys in this specific sequence”.
So we need the enterer in both, to make sure it &lt;em&gt;doesn&#x27;t&lt;&#x2F;em&gt; matter what order you start pressing &lt;kbd&gt;e&lt;&#x2F;kbd&gt; and &lt;kbd&gt;f&lt;&#x2F;kbd&gt; in.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;whoops-no-feet&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#whoops-no-feet&quot; aria-label=&quot;Anchor link for: whoops-no-feet&quot;&gt;whoops no feet&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Remember the compositor meta+arrow keys remaps? &lt;br &#x2F;&gt;
We were relying on kanata&#x27;s sequential layer fallback system, to actually get the arrow keys.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;w↓f↓&lt;&#x2F;kbd&gt; results in default → meta → feet; feet is the current layer, so of course we get our arrow key mappings. &lt;br &#x2F;&gt;
&lt;kbd&gt;f↓w↓&lt;&#x2F;kbd&gt; results in default → feet → meta; the current layer, meta, &lt;em&gt;doesn&#x27;t&lt;&#x2F;em&gt; have the arrow key mappings, but the previous layer (feet) does. So we fall back on it.&lt;&#x2F;p&gt;
&lt;p&gt;Crucially, this only works because we &lt;em&gt;have&lt;&#x2F;em&gt; visited feet. &lt;br &#x2F;&gt;
But have a look at how we get to erotic feet.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;e↓f↓&lt;&#x2F;kbd&gt; results in default → erotic → erotic-feet &lt;br &#x2F;&gt;
&lt;kbd&gt;f↓e↓&lt;&#x2F;kbd&gt; results in default → feet → erotic-feet&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;kbd&gt;e↓f↓&lt;&#x2F;kbd&gt;, we &lt;em&gt;never&lt;&#x2F;em&gt; visit feet — we directly jump to erotic feet. &lt;br &#x2F;&gt;
With &lt;kbd&gt;f↓e↓&lt;&#x2F;kbd&gt;, we &lt;em&gt;never&lt;&#x2F;em&gt; visit erotic — we directly jump to erotic feet.&lt;&#x2F;p&gt;
&lt;p&gt;So if we ever happen to rely on the arrow keys hotkeys existing while in the erotic feet layer, it now again matters how we got there: &lt;kbd&gt;f↓e↓&lt;&#x2F;kbd&gt; will work, but &lt;kbd&gt;e↓f↓&lt;&#x2F;kbd&gt; will not. &lt;br &#x2F;&gt;
That&#x27;s because &lt;kbd&gt;f↓e↓&lt;&#x2F;kbd&gt; includes feet in its layer sequence, but &lt;kbd&gt;e↓f↓&lt;&#x2F;kbd&gt; doesn&#x27;t — so it can&#x27;t rely on the fallback. &lt;br &#x2F;&gt;
Once again, we want the order to &lt;strong&gt;not&lt;&#x2F;strong&gt; matter.&lt;&#x2F;p&gt;
&lt;p&gt;We might not &lt;em&gt;need&lt;&#x2F;em&gt; the arrow keys mappings in erotic feet specifically, but it&#x27;s good practice to simplify things for the future you, and to always have &lt;em&gt;all&lt;&#x2F;em&gt; the children of a composite layer visited — that way, you build mental consistency you can always rely on. &lt;br &#x2F;&gt;
Yesterday, I realized that you &lt;strong&gt;can&lt;&#x2F;strong&gt; &lt;code&gt;layer-while-held&lt;&#x2F;code&gt; multiple layers at the same time, which fixes the issue completely :D &lt;br &#x2F;&gt;
Let&#x27;s look at our entire config again, now with the fixes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (multi lmet (layer-while-held meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (layer-while-held erotic)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (layer-while-held feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (multi (layer-while-held feet) (layer-while-held erotic-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (select-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (select-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (multi (layer-while-held erotic) (layer-while-held erotic-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   h left&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j down&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   l right&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic-feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (extend-select-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (extend-select-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Switching to a composite layer now &lt;em&gt;also&lt;&#x2F;em&gt; holds for us the requisite layer that we expect to be held. &lt;br &#x2F;&gt;
&lt;kbd&gt;f↓e↓&lt;&#x2F;kbd&gt;: default → feet → erotic → erotic-feet &lt;br &#x2F;&gt;
&lt;kbd&gt;e↓f↓&lt;&#x2F;kbd&gt;: default → erotic → feet → erotic-feet&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Now&lt;&#x2F;em&gt; if we relied on the arrow keys in erotic feet for whatever reason, that would work whether we got to erotic feet with &lt;kbd&gt;e↓f↓&lt;&#x2F;kbd&gt; &lt;em&gt;or&lt;&#x2F;em&gt; &lt;kbd&gt;f↓e↓&lt;&#x2F;kbd&gt;, because we visit the other layer “on the way”. &lt;br &#x2F;&gt;
Notably, the &lt;kbd&gt;j&lt;&#x2F;kbd&gt;&#x2F;&lt;kbd&gt;k&lt;&#x2F;kbd&gt; to ↓&#x2F;↑ remaps of feet won&#x27;t work because our current layer (erotic feet) remaps them. &lt;br &#x2F;&gt;
Feet is the &lt;em&gt;fallback&lt;&#x2F;em&gt;, not the override.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;let-s-scale-this&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#let-s-scale-this&quot; aria-label=&quot;Anchor link for: let-s-scale-this&quot;&gt;let&#x27;s scale this&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Awesome! Now that it doesn&#x27;t matter what order I press my modifiers, I want to expand this idea by making more hotkeys for the browser. &lt;br &#x2F;&gt;
You saw in the screen recording, that I currently can &lt;em&gt;select&lt;&#x2F;em&gt; tabs — after I do so, as a separate action, I can &lt;strong&gt;activate&lt;&#x2F;strong&gt; that tab. &lt;br &#x2F;&gt;
Would be nice to &lt;em&gt;also&lt;&#x2F;em&gt; be able to switch to the previous &#x2F; next tab directly, without the activation step.
And I want to be able to &lt;em&gt;move&lt;&#x2F;em&gt; my selected tabs, also.&lt;&#x2F;p&gt;
&lt;p&gt;So in total, I want: &lt;br &#x2F;&gt;
&lt;kbd&gt;e↓[jk]&lt;&#x2F;kbd&gt; to select a tab &lt;br &#x2F;&gt;
&lt;kbd&gt;ef↓[jk]&lt;&#x2F;kbd&gt; to extend the current selection &lt;br &#x2F;&gt;
&lt;kbd&gt;wef↓[jk]&lt;&#x2F;kbd&gt; to move selected tabs &lt;br &#x2F;&gt;
&lt;kbd&gt;we↓[jk]&lt;&#x2F;kbd&gt; to &lt;em&gt;switch&lt;&#x2F;em&gt; to the previous &#x2F; next tab&lt;a href=&quot;#footnote-2&quot; id=&quot;headnote-2&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
.&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;move-switch.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Here is our new config, with all the added enterers and combining layers that we need.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (multi lmet (layer-while-held meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (layer-while-held erotic)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (layer-while-held feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (meta)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (multi (layer-while-held erotic) (layer-while-held erotic-meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (multi (layer-while-held feet) (layer-while-held meta-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (multi (layer-while-held feet) (layer-while-held erotic-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (multi lmet (layer-while-held meta) (layer-while-held erotic-meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (select-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (select-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (multi (layer-while-held erotic) (layer-while-held erotic-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (multi lmet (layer-while-held meta) (layer-while-held meta-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   h left&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j down&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   l right&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (meta-feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (multi (layer-while-held erotic) (layer-while-held erotic-meta) (layer-while-held erotic-feet) (layer-while-held erotic-meta-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic-meta)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (multi (layer-while-held feet) (layer-while-held erotic-feet) (layer-while-held meta-feet) (layer-while-held erotic-meta-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (switch-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (switch-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic-feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (multi lmet (layer-while-held meta) (layer-while-held meta-feet) (layer-while-held erotic-meta) (layer-while-held erotic-meta-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (extend-select-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (extend-select-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic-meta-feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (move-tabs-next)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (move-tabs-prev)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can see how this scales to be quite unreadable, lol :D&lt;&#x2F;p&gt;
&lt;p&gt;The idea here, though, is that every layer has enough enterers for us to be able to get to the final erotic meta feet layer, &lt;em&gt;regardless&lt;&#x2F;em&gt; of the order. &lt;br &#x2F;&gt;
Also, we visit all the other layers that are logically pressed, on the way — so that we can reduce possible head pain in the future.&lt;&#x2F;p&gt;
&lt;p&gt;This works! But with a caveat... A caveat that actually made me sure this blog post needs to exist.&lt;&#x2F;p&gt;
&lt;p&gt;First, I need to select the initial tab, from which I&#x27;ll then extend my selection: &lt;kbd&gt;e↓[jk]&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
After that, I start holding &lt;kbd&gt;f&lt;&#x2F;kbd&gt; to extend: &lt;kbd&gt;f↓[jk]&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
I have selected the tabs that I want to move, so now I also start holding down &lt;kbd&gt;w&lt;&#x2F;kbd&gt;: &lt;kbd&gt;w↓[jk]&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
Wonderful. I have moved my tabs. &lt;br &#x2F;&gt;
Now onto a separate action — I want to &lt;em&gt;switch&lt;&#x2F;em&gt; to the next tab: I release &lt;kbd&gt;f&lt;&#x2F;kbd&gt;, and now only hold &lt;kbd&gt;e&lt;&#x2F;kbd&gt; and &lt;kbd&gt;w&lt;&#x2F;kbd&gt;: &lt;kbd&gt;f↑[jk]&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
Full syntax: &lt;kbd&gt;e↓[jk]f↓[jk]w↓[jk]f↑[jk]&lt;&#x2F;kbd&gt; (try following along on your keyboard, to grasp the sequence a bit better)&lt;&#x2F;p&gt;
&lt;p&gt;Selecting, extending, and moving works.
But when I release &lt;kbd&gt;f&lt;&#x2F;kbd&gt;, instead of me now switching tabs, I &lt;em&gt;still&lt;&#x2F;em&gt; &lt;strong&gt;move&lt;&#x2F;strong&gt; them! Why is that?&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s another instance of how kanata&#x27;s sequential layer system can end up being annoying. &lt;br &#x2F;&gt;
&lt;code&gt;layer-while-held&lt;&#x2F;code&gt; means “on press, add this layer on top of the stack. on release, remove that layer from the stack”. &lt;br &#x2F;&gt;
We move through the layers in this sequence: default → erotic → erotic-feet → erotic-meta-feet (I&#x27;m omitting the “on the way” layers because they don&#x27;t matter here, but they are indeed there). &lt;br &#x2F;&gt;
Erotic makes us a promise: “When you press &lt;kbd&gt;f&lt;&#x2F;kbd&gt;, I will add erotic feet on top of the stack. When you release &lt;kbd&gt;f&lt;&#x2F;kbd&gt;, I will remove erotic feet from the stack.”&lt;&#x2F;p&gt;
&lt;p&gt;That promise (as far as I understand) &lt;em&gt;is&lt;&#x2F;em&gt; actually held.
But a &lt;em&gt;different&lt;&#x2F;em&gt; promise takes priority. &lt;br &#x2F;&gt;
Because &lt;em&gt;erotic feet&lt;&#x2F;em&gt; tells us: “When you press &lt;kbd&gt;w&lt;&#x2F;kbd&gt;, I will add erotic meta feet on top of the stack. When you release &lt;kbd&gt;w&lt;&#x2F;kbd&gt;, I will remove erotic meta feet from the stack.” &lt;br &#x2F;&gt;
So when we release &lt;kbd&gt;f&lt;&#x2F;kbd&gt;, erotic feet is removed from the stack as promised. But that doesn&#x27;t do much because we are not in erotic feet anymore: we are in erotic &lt;em&gt;meta&lt;&#x2F;em&gt; feet. &lt;br &#x2F;&gt;
Since we &lt;em&gt;are&lt;&#x2F;em&gt; still holding &lt;kbd&gt;w&lt;&#x2F;kbd&gt;, the promise of having erotic meta feet in the stack is still held up, by erotic feet.&lt;&#x2F;p&gt;
&lt;p&gt;Our &lt;em&gt;idea&lt;&#x2F;em&gt; with erotic meta feet, is that &lt;strong&gt;all&lt;&#x2F;strong&gt; of &lt;kbd&gt;w&lt;&#x2F;kbd&gt;, &lt;kbd&gt;f&lt;&#x2F;kbd&gt;, &lt;kbd&gt;e&lt;&#x2F;kbd&gt; need to be held at the same time. &lt;br &#x2F;&gt;
If one of them &lt;em&gt;isn&#x27;t&lt;&#x2F;em&gt; currently being held, we need to leave the layer(s!) that require that key to be held.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Kanata&lt;&#x2F;em&gt;&#x27;s idea is to keep the layer in the stack, as long as &lt;em&gt;the specific key that entered it&lt;&#x2F;em&gt;, is still being held.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;virtual-keys&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#virtual-keys&quot; aria-label=&quot;Anchor link for: virtual-keys&quot;&gt;virtual keys&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Turns out, there&#x27;s a solution! &lt;br &#x2F;&gt;
What we want, is to make releasing an enterer key leave not only the &lt;em&gt;specific&lt;&#x2F;em&gt; layer that it enters, but &lt;em&gt;any&lt;&#x2F;em&gt; (and all) layers that logically expect that key to be held.&lt;&#x2F;p&gt;
&lt;p&gt;For this, we can put the &lt;code&gt;on-release&lt;&#x2F;code&gt; action at the end of every enterer&#x27;s &lt;code&gt;multi&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
&lt;code&gt;on-release&lt;&#x2F;code&gt; is one of the actions that require us to pass a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jtroo&#x2F;kanata&#x2F;blob&#x2F;main&#x2F;docs&#x2F;config.adoc#virtual-keys&quot;&gt;virtual key&lt;&#x2F;a&gt; — they are like aliases that can individually respond to a press &#x2F; release, rather than being a compulsory press+release combo (as far as I understand them). &lt;br &#x2F;&gt;
So we will make a couple of virtual keys, that explicitly release &lt;em&gt;all&lt;&#x2F;em&gt; layers that necessarily include some sublayer. &lt;br &#x2F;&gt;
For the record, we do not care about the press &#x2F; release functionality of virtual keys here, we are just required to use them because we need the &lt;code&gt;on-release&lt;&#x2F;code&gt; action.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(defvirtualkeys&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	any-feet   (multi (release-layer feet)   (release-layer erotic-feet) (release-layer meta-feet)   (release-layer erotic-meta-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	any-erotic (multi (release-layer erotic) (release-layer erotic-meta) (release-layer erotic-feet) (release-layer erotic-meta-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	any-meta   (multi (release-layer meta)   (release-layer meta-feet)   (release-layer erotic-meta) (release-layer erotic-meta-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can “call” (tap) one of these virtual keys, to explicitly release any (and all) layers that contain a given sublayer. &lt;br &#x2F;&gt;
Let&#x27;s add the &lt;code&gt;on-release&lt;&#x2F;code&gt; action to the enterers, in the rest of our configuration.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (multi lmet (layer-while-held meta) (on-release tap-vkey any-meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (multi (layer-while-held erotic) (on-release tap-vkey any-erotic))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (multi (layer-while-held feet) (on-release tap-vkey any-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (meta)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (multi (layer-while-held erotic) (layer-while-held erotic-meta) (on-release tap-vkey any-erotic))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (multi (layer-while-held feet) (layer-while-held meta-feet) (on-release tap-vkey any-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (multi (layer-while-held feet) (layer-while-held erotic-feet) (on-release tap-vkey any-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (multi lmet (layer-while-held meta) (layer-while-held erotic-meta) (on-release tap-vkey any-meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (select-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (select-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (multi (layer-while-held erotic) (layer-while-held erotic-feet) (on-release tap-vkey any-erotic))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (multi lmet (layer-while-held meta) (layer-while-held meta-feet) (on-release tap-vkey any-meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   h left&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j down&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   l right&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (meta-feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   e (multi (layer-while-held erotic) (layer-while-held erotic-meta) (layer-while-held erotic-feet) (layer-while-held erotic-meta-feet) (on-release tap-vkey any-erotic))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic-meta)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   f (multi (layer-while-held feet) (layer-while-held erotic-feet) (layer-while-held meta-feet) (layer-while-held erotic-meta-feet) (on-release tap-vkey any-feet))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (switch-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (switch-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic-feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w (multi lmet (layer-while-held meta) (layer-while-held meta-feet) (layer-while-held erotic-meta) (layer-while-held erotic-meta-feet) (on-release tap-vkey any-meta))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (extend-select-next-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (extend-select-prev-tab)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (erotic-meta-feet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   j (move-tabs-next)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   k (move-tabs-prev)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, the release of an enterer key not only leaves the exact layer that it enters, but &lt;em&gt;all&lt;&#x2F;em&gt; layers that we may enter after the fact. &lt;br &#x2F;&gt;
Finally, with this laborious ass configuration, everything works exactly how we want!&lt;&#x2F;p&gt;
&lt;p&gt;I select the initial tab, then extend selection, then move the selected tabs; I then release &lt;kbd&gt;f&lt;&#x2F;kbd&gt; and FINALLY, I &lt;em&gt;switch tab&lt;&#x2F;em&gt; as I expect, rather than continuing to move.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-power&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-power&quot; aria-label=&quot;Anchor link for: the-power&quot;&gt;the power!&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The erotic layer, which is actually called “hack” in my configuration, has for a long time felt iffy to me: when I combined it with other layers to do more “complex” actions in my browser, some of the combinations were not understood by kanata, based on rules I wasn&#x27;t sure existed. &lt;br &#x2F;&gt;
Now that I actually looked into it deeper, and &lt;strong&gt;solved it&lt;&#x2F;strong&gt;, it feels incredible to finally combine layers naturally, and not have to release all of them to switch to a different combination — I can just use these custom layers like I would be using normal modifiers.&lt;&#x2F;p&gt;
&lt;p&gt;You might not yet have a need to make composite layers like this, but hopefully you now know &lt;em&gt;how to&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
If in the future you get a cool idea for a layer that might need composite layers, you can go “this is gonna be a bit annoying but doable” rather than possibly give up on the idea because it “doesn&#x27;t work”.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;footnotes&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-1&quot; id=&quot;footnote-1&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 We don&#x27;t actually need the meta layer at all currently; omitting it entirely and making &lt;kbd&gt;w&lt;&#x2F;kbd&gt; be &lt;em&gt;just&lt;&#x2F;em&gt; &lt;code&gt;lmet&lt;&#x2F;code&gt; on the right side would suffice. But we&#x27;re going to need this layer for later.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-2&quot; id=&quot;footnote-2&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 More specifically, this will skip over unloaded tabs.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>smooth scrolling</title>
          <pubDate>Tue, 16 Sep 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/smooth-scrolling/</link>
          <guid>https://axlefublr.github.io/smooth-scrolling/</guid>
          <description xml:base="https://axlefublr.github.io/smooth-scrolling/">&lt;p&gt;I tried out Zen Browser recently, and one of the many good things about it that I noticed, is how &lt;em&gt;smooth&lt;&#x2F;em&gt; the scrolling feels. &lt;br &#x2F;&gt;
I thought: “surely it&#x27;s not zen-specific!” and turns out that its smoothness is due to &lt;code&gt;about:config&lt;&#x2F;code&gt; settings you can set in &lt;em&gt;any&lt;&#x2F;em&gt; firefox :D&lt;&#x2F;p&gt;
&lt;p&gt;The biggest &#x2F; most important change, that will make your scrolling a &lt;em&gt;lot&lt;&#x2F;em&gt; smoother, is setting &lt;code&gt;general.smoothScroll.msdPhysics.enabled&lt;&#x2F;code&gt; to &lt;code&gt;true&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Honestly, I&#x27;m not sure why it isn&#x27;t true by default! (in non-zen firefoxi)&lt;&#x2F;p&gt;
&lt;p&gt;But of course, I didn&#x27;t stop there. Let&#x27;s take a look at the other relevant settings. &lt;br &#x2F;&gt;
First of all, I&#x27;ll point out that the &lt;em&gt;other&lt;&#x2F;em&gt; &lt;code&gt;general.smoothScroll.*&lt;&#x2F;code&gt; settings, that aren&#x27;t in the &lt;code&gt;msdPhysics&lt;&#x2F;code&gt; section, no longer apply — so you can pretty much just ignore them.
Unsure if that&#x27;s intentional or a bug honestly; I remember seeing some issue that claimed this to be a bug 👀&lt;&#x2F;p&gt;
&lt;p&gt;Anyway! &lt;br &#x2F;&gt;
There are two quite core settings:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mousewheel.default.delta_multiplier_x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mousewheel.default.delta_multiplier_y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pretty self-explanatory — these two multiply the horizontal &#x2F; vertical scrolling speed. &lt;br &#x2F;&gt;
The &lt;em&gt;baseline&lt;&#x2F;em&gt; (but not necessarily the default) is 100 — you can come back to these later to more directly express “please faster” and “please slower”. &lt;br &#x2F;&gt;
I ended up sticking with 100 for both, however.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;general.smoothScroll.msdPhysics.motionBeginSpringConstant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 300&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;general.smoothScroll.msdPhysics.regularSpringConstant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 900&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;general.smoothScroll.msdPhysics.slowdownSpringConstant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 300&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;“Spring” is an animation type. &lt;br &#x2F;&gt;
The constant here is somewhat of an arbitrary number, in not sure which range, but the main idea is that lower is more draggy &#x2F; slow &#x2F; smooth, and higher is more abrupt &#x2F; fast &#x2F; jumpy.&lt;&#x2F;p&gt;
&lt;p&gt;By setting the begin and slowdown springs to a lower number, 300, both starting and ending a scroll feels very &lt;em&gt;smooth&lt;&#x2F;em&gt; and gentle, without being &lt;em&gt;too&lt;&#x2F;em&gt; slow. &lt;br &#x2F;&gt;
The &lt;em&gt;regular&lt;&#x2F;em&gt; constant, though, I have no clue does what!
At least, I wasn&#x27;t able to find a notable difference in my experimentation. &lt;br &#x2F;&gt;
But I set it to 900 for it to feel more “tight”&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;general.smoothScroll.msdPhysics.slowdownMinDeltaMS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 12&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;general.smoothScroll.msdPhysics.slowdownMinDeltaRatio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 1.3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These two I never quite got do what, either.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;general.smoothScroll.msdPhysics.continuousMotionMaxDeltaMS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This, as far as I understand, basically means “every how many milliseconds is the smooth scrolling logic calculated?” &lt;br &#x2F;&gt;
It&#x27;s 12 by default, so 3 is a lot more smooth! At least by an eye test.&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;showcase.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Here&#x27;s how all these settings applied look like! &lt;br &#x2F;&gt;
Keep in mind, there might be some fps loss in the recording, so it likely looks even smoother irl.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;jdugan6240.dev&#x2F;posts&#x2F;python_a_beautiful_mess&quot;&gt;The blog post I was scrolling&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;mouse-mode&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#mouse-mode&quot; aria-label=&quot;Anchor link for: mouse-mode&quot;&gt;mouse mode&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I don&#x27;t actually use my real mouse when scrolling, most of the time; &lt;br &#x2F;&gt;
I have two keys in my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;erm&#x2F;&quot;&gt;mouse mode&lt;&#x2F;a&gt; that send &lt;kbd&gt;WheelUp&lt;&#x2F;kbd&gt; and &lt;kbd&gt;WheelDown&lt;&#x2F;kbd&gt;, so that&#x27;s how I scroll most of the time.&lt;&#x2F;p&gt;
&lt;p&gt;Did a bit of an optimization on the side of my mouse mode, to make scrolling even smoother.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;o (mwheel-up    30 60)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;i (mwheel-down  30 60)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;w (mwheel-left  20 60)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;r (mwheel-right 20 60)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The default “length” of a singular scroll (a nudge?) is 120 — it&#x27;s noticeably more jumpy than the 60 I&#x27;m now using. &lt;br &#x2F;&gt;
To account for the loss of speed, I send the nudges more frequently: 30 instead of whatever value I used to have prior. &lt;br &#x2F;&gt;
&lt;em&gt;This&lt;&#x2F;em&gt; is what you&#x27;re seeing me use in the recording, btw!&lt;&#x2F;p&gt;
&lt;p&gt;Kanata does warn me, though, that setting the length to something else than a multiple of 120 is error-prone — some programs might get utterly confused. &lt;br &#x2F;&gt;
I already came across an example of that happening, with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;woelper&#x2F;oculante&quot;&gt;oculante&lt;&#x2F;a&gt;; but it wouldn&#x27;t be the last issue oculante has anyway :p &lt;br &#x2F;&gt;
So I&#x27;ll gladly optimize for the #1 place where I scroll — my browser 😌&lt;&#x2F;p&gt;
&lt;h1 id=&quot;acceleration&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#acceleration&quot; aria-label=&quot;Anchor link for: acceleration&quot;&gt;acceleration&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;There are another two settings that are interesting to play with.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mousewheel.acceleration.factor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mousewheel.acceleration.start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 20&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Start is “after how many nudges do we increase the scrolling speed?” and factor is “by how many times?” &lt;br &#x2F;&gt;
Using these two, you can make it so you start to scroll &lt;em&gt;faster&lt;&#x2F;em&gt; after some amount of continuous scrolling. &lt;br &#x2F;&gt;
Unfortunately factor has to be an integer :&amp;lt; so we can&#x27;t speed up just slightly.&lt;&#x2F;p&gt;
&lt;p&gt;I ended up going without this feature (setting start to &lt;code&gt;-1&lt;&#x2F;code&gt;), but it might work for you 😼&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>i overuse anki</title>
          <pubDate>Sun, 31 Aug 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/i-overuse-anki/</link>
          <guid>https://axlefublr.github.io/i-overuse-anki/</guid>
          <description xml:base="https://axlefublr.github.io/i-overuse-anki/">&lt;p&gt;No, I have not burned out on anki. &lt;br &#x2F;&gt;
All the advice I share in my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;how-to-anki&#x2F;&quot;&gt;how to anki&lt;&#x2F;a&gt; blog post still works… &lt;br &#x2F;&gt;
A little too well, actually??&lt;&#x2F;p&gt;
&lt;p&gt;A very common issue anki users face is that your workload creeps up on you over time, constantly increasing and eventually burning you out. &lt;br &#x2F;&gt;
My system, however, is designed specifically to not allow that! &lt;br &#x2F;&gt;
What is “it only seems free!!” for others, &lt;em&gt;is&lt;&#x2F;em&gt; quite free for me.&lt;&#x2F;p&gt;
&lt;p&gt;What this resulted in, is that I don&#x27;t take notes &lt;strong&gt;at all&lt;&#x2F;strong&gt;. &lt;br &#x2F;&gt;
I either make an anki card, or discard the information. &lt;br &#x2F;&gt;
This has been working really well as I&#x27;ve already expressed, but has a more &lt;em&gt;hidden&lt;&#x2F;em&gt; caveat I noticed only recently.&lt;&#x2F;p&gt;
&lt;a href=&quot;#quickshell&quot; id=&quot;quickshell&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I want to make myself an analog clock :3 &lt;br &#x2F;&gt;
Maybe a window, maybe an overlay widget; &lt;br &#x2F;&gt;
Some sort of easily and quickly openable gadget that would allow me to &lt;em&gt;feel&lt;&#x2F;em&gt; the time.&lt;&#x2F;p&gt;
&lt;p&gt;Istg I&#x27;ve never been to the military, but I can only &lt;em&gt;feel&lt;&#x2F;em&gt; time on an analog clock; &lt;br &#x2F;&gt;
Digital ones &lt;em&gt;tell&lt;&#x2F;em&gt; me the time, but they don&#x27;t &lt;em&gt;show&lt;&#x2F;em&gt; me it, yk?&lt;&#x2F;p&gt;
&lt;p&gt;In my fairly short adventure of trying to find an analog clock thingymabop, I haven&#x27;t found anything that I actually feel like &lt;em&gt;using&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;TUI clocks are god awfully ugly and therefore impractical — too cell dependent to be graphically accurate and neat-looking.&lt;&#x2F;p&gt;
&lt;p&gt;The browser is often a common platform to build guis in, and quite importantly &lt;em&gt;easy&lt;&#x2F;em&gt; to build guis in. &lt;br &#x2F;&gt;
I found &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;abhishekgurjar-in&#x2F;Analog-Clock&quot;&gt;a project&lt;&#x2F;a&gt; that is a basic analog clock website, then &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;annabirch&quot;&gt;forked it&lt;&#x2F;a&gt; to make my changes. &lt;br &#x2F;&gt;
I quite like it!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;i-overuse-anki&#x2F;.&#x2F;annabirch.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;However the issue is that it &lt;em&gt;is&lt;&#x2F;em&gt; in my browser. &lt;br &#x2F;&gt;
Something I&#x27;d like to be able to do is look at the time, ad-hoc, while doing anything else at the time. &lt;br &#x2F;&gt;
If, say, I&#x27;m watching a youtube video in fullscreen, and then open the clock in a new tab, well now I&#x27;ve unfullscreened my video and it&#x27;s a bit unpleasant :&#x2F; &lt;br &#x2F;&gt;
If I force open it in a new browser window, it&#x27;s now &lt;strong&gt;slow&lt;&#x2F;strong&gt; to open!
And that&#x27;s no good...&lt;&#x2F;p&gt;
&lt;p&gt;So I need some sort of “just a window” clock app &#x2F; program, that opens &lt;strong&gt;fast&lt;&#x2F;strong&gt; and is still styled how I like it to be. &lt;br &#x2F;&gt;
I found &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Depau&#x2F;wlclock&quot;&gt;this project&lt;&#x2F;a&gt; which might actually fulfill my needs, but I need to edit C++ code to customize it. &lt;br &#x2F;&gt;
Some very basic things are defined as uhhhhhh C header variables? (idk, don&#x27;t ask me), but to make it be how I want it, I need to edit the normal source too. &lt;br &#x2F;&gt;
Somehow, in all my trying, I could &lt;strong&gt;not&lt;&#x2F;strong&gt; for the life of me figure out how to make the background of the app fully transparent. &lt;br &#x2F;&gt;
Funny thing is, the &lt;em&gt;sides&lt;&#x2F;em&gt; are already transparent, suggesting that it &lt;em&gt;is&lt;&#x2F;em&gt; something the program is able to do, but there&#x27;s a square background defined god knows where, configured by god knows what!
And I cannot change it 😭 At least, I don&#x27;t know how...&lt;&#x2F;p&gt;
&lt;p&gt;I was meaning to get back into trying to figure this out, after initially failing, but now I&#x27;m feeling like it&#x27;s a bit of a fool&#x27;s errand. &lt;br &#x2F;&gt;
How about I employ a fun learning trick I like to use?&lt;&#x2F;p&gt;
&lt;p&gt;Instead of focusing &lt;em&gt;only&lt;&#x2F;em&gt; and &lt;strong&gt;exactly&lt;&#x2F;strong&gt; on my specific usecase, I&#x27;ll use that problem as a motivator to go learn something larger.&lt;&#x2F;p&gt;
&lt;p&gt;I want to make hotkeys that use &lt;code&gt;niri --json&lt;&#x2F;code&gt; to do various windowing actions — cool, I&#x27;ll learn nushell as it lets me operate on json conveniently, &lt;em&gt;among many other things&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
Would be cool if &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;floorp&#x2F;&quot;&gt;floorp&lt;&#x2F;a&gt;&#x27;s wrapped tabs were all of equal size, rather than the last row expanding the tabs on it — epic, I&#x27;ll learn css grid and only &lt;em&gt;after&lt;&#x2F;em&gt; realize that the idea was not feasible&lt;a href=&quot;#footnote-1&quot; id=&quot;headnote-1&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 &lt;br &#x2F;&gt;
I want an analog clock — nice, I&#x27;ll learn &lt;em&gt;quickshell&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;How exciting!
New learning project :D &lt;br &#x2F;&gt;
I start reading quickshell&#x27;s docs, and open the docs of QtQuick… Only to find myself in &lt;strong&gt;terror&lt;&#x2F;strong&gt;. &lt;br &#x2F;&gt;
There is &lt;strong&gt;so much&lt;&#x2F;strong&gt;!&lt;a href=&quot;#footnote-2&quot; id=&quot;headnote-2&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;So many pages, so many thingies, &lt;em&gt;so much to learn&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
And all of this somooch (💋) will end up as anki cards, maintained in my memory forever, only for me possibly to never use like, 90% of it. &lt;br &#x2F;&gt;
There&#x27;s a good chance I&#x27;ll actually never get to making the clock, and leave after making a volume change osd. &lt;br &#x2F;&gt;
Yet, despite not being used information, I&#x27;ll remember it until the end of time...&lt;&#x2F;p&gt;
&lt;p&gt;THAT is when I finally noticed, that the &lt;em&gt;volume&lt;&#x2F;em&gt; of how I use anki, actually &lt;em&gt;restricts&lt;&#x2F;em&gt; me.&lt;&#x2F;p&gt;
&lt;p&gt;Because of how strongly I rely on anki, it is the only source of information I&#x27;ll often use. &lt;br &#x2F;&gt;
If I have something ankied, I will sometimes wait for the next review of some piece of knowledge, rather than just look it up again — doing so feels like a waste. &lt;br &#x2F;&gt;
A waste, because I&#x27;m effectively messing up the anki algorithm by doing another review that anki doesn&#x27;t know about. &lt;br &#x2F;&gt;
Yes, having anki work correctly is apparently more important to my brain than the information I&#x27;m trying to remember in the first place 😮‍💨&lt;&#x2F;p&gt;
&lt;p&gt;Biggest example of this happening is alphabet indexes: I have them all as anki cards, and I expect &lt;em&gt;anki&lt;&#x2F;em&gt; to ensure I remember them all. &lt;br &#x2F;&gt;
This works quite well of course, but I have some letters the indexes of I&#x27;m not &lt;em&gt;sure&lt;&#x2F;em&gt; about. &lt;br &#x2F;&gt;
&lt;em&gt;Pretty&lt;&#x2F;em&gt; sure p is 16, u is 21, q is 17 and s is 19, but I wouldn&#x27;t bet my life on it, you know? &lt;br &#x2F;&gt;
When &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;consider-sorting&#x2F;&quot;&gt;manually sorting&lt;&#x2F;a&gt; something, I&#x27;ll sometimes be in this strange state of unsureness, yet refuse to &lt;em&gt;simply&lt;&#x2F;em&gt; check. &lt;br &#x2F;&gt;
It wouldn&#x27;t even take much time to do, either! But I&#x27;m stubborn on letting anki do its job.&lt;&#x2F;p&gt;
&lt;p&gt;This phenomenon happens even with information that is still “new”, rather than thoroughly reviewed in anki. &lt;br &#x2F;&gt;
I rely on anki to solve what it hasn&#x27;t even gotten to yet!&lt;&#x2F;p&gt;
&lt;p&gt;Say I learn a new programming language.
I make anki cards for everything that I learn while reading its book, and eventually finish reading it, “completing” my language learning. &lt;br &#x2F;&gt;
However, that&#x27;s &lt;em&gt;not&lt;&#x2F;em&gt; exactly how it is in my head. &lt;br &#x2F;&gt;
Intead of the more natural flow of learn a bit + practice &#x2F; use a bit, because of &lt;strong&gt;anki&lt;&#x2F;strong&gt; I&#x27;ve built up this strange expectation of “learn everything first, then use everything after”.&lt;&#x2F;p&gt;
&lt;p&gt;My most recent big learning adventure was nushell, and it&#x27;s exactly how it went — I was for the most part dead set on not using nushell until I&#x27;ve “finished” learning it, whatever the fuck that means. &lt;br &#x2F;&gt;
I believe this is due to anki once again (although autism plays a part too) — if I haven&#x27;t gotten through some card, I don&#x27;t &lt;em&gt;know&lt;&#x2F;em&gt; that information. &lt;br &#x2F;&gt;
Which is an awfully restrictive way to learn!&lt;&#x2F;p&gt;
&lt;p&gt;Now, if I simply went through the new cards quickly, this wouldn&#x27;t be much of a concern. &lt;br &#x2F;&gt;
But then I&#x27;d have a different issue! The massive workload 😔&lt;&#x2F;p&gt;
&lt;p&gt;So what I do instead, is have a queue of new cards that are went through slowly but surely. &lt;br &#x2F;&gt;
Quite often, to get to the new cards of the topic I&#x27;m &lt;em&gt;currently&lt;&#x2F;em&gt; learning, I&#x27;d effectively need to wait like 20 days, sometimes more. &lt;br &#x2F;&gt;
Learn something. Wait 20 days. Use it. &lt;br &#x2F;&gt;
I&#x27;m exagerating quite a bit, but putting it into words helps highlight just how silly my learning approach is.&lt;&#x2F;p&gt;
&lt;p&gt;Due to the queueic nature of my learning, any small and big new learning adventures feel bigger than they need to be: “it&#x27;s gonna be a while until I fully finish this” is what I subconciously think. &lt;br &#x2F;&gt;
God forbid I simply learn what I need in quickshell, and continue on with my life! &lt;br &#x2F;&gt;
Noooooo, I need to have all the niche details specifically memorized for some reason. Stupid.&lt;&#x2F;p&gt;
&lt;p&gt;Learning feels big, because it&#x27;s a bad idea to try to memorize information out of context. &lt;br &#x2F;&gt;
Intead of memorizing some big specific way of doing a task, understand and remember the parts that make it work — that&#x27;ll make it a lot easier to reproduce on a whim. &lt;br &#x2F;&gt;
To make this work, I feel required to “consume” the entire documentation of some software to be able to use it all, often times. &lt;br &#x2F;&gt;
And then I carry the chain and balls of the eventual effort it takes to memorize that entire documentation.&lt;&#x2F;p&gt;
&lt;p&gt;Some things really do not deserve it! &lt;br &#x2F;&gt;
And yet I can&#x27;t know ahead of time what I&#x27;ll be needing all the time, and what is a waste of energy to remember.&lt;&#x2F;p&gt;
&lt;p&gt;The time and energy spent on remembering, is not spent on learning the next new thing, which results in a very “spiky” overall knowledge — I know some things very well, but almost refuse to know some things at all.&lt;&#x2F;p&gt;
&lt;p&gt;If only there was some way to store information without metaphorically nailing it to the wall of my brain... Hmmm...&lt;&#x2F;p&gt;
&lt;h1 id=&quot;duh&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#duh&quot; aria-label=&quot;Anchor link for: duh&quot;&gt;duh&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;It is &lt;strong&gt;that&lt;&#x2F;strong&gt; chain of thought that finally led me to create my noting system :D &lt;br &#x2F;&gt;
Yes, I literally did not have one before!&lt;&#x2F;p&gt;
&lt;p&gt;I have &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;magazines&#x2F;&quot;&gt;magazines&lt;&#x2F;a&gt; of course, and they are INCREDIBLE, but they solve a different usecase than personal documentation-like notes. &lt;br &#x2F;&gt;
Trying to expand magazines to fulfill this new usecase I&#x27;ve acquired would be a misdesign.&lt;&#x2F;p&gt;
&lt;p&gt;First, I create a directory named &lt;code&gt;mdw&lt;&#x2F;code&gt;, according to my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;optimizing-paths&#x2F;&quot;&gt;optimize paths&lt;&#x2F;a&gt; blog post. &lt;br &#x2F;&gt;
However, turns out I don&#x27;t need to zoxide to there often at all! &lt;br &#x2F;&gt;
That&#x27;s because I make a global hotkey that opens the directory in yazi.&lt;&#x2F;p&gt;
&lt;p&gt;Now, usually I&#x27;d make it open in &lt;em&gt;helix&lt;&#x2F;em&gt;, but as I&#x27;ll be converting most of more than 4000 anki cards, I&#x27;ll probably be creating a bunch of note files!
And doing so from helix is a bit of a pain... But quite nifty in yazi!&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;fzf&lt;&#x2F;code&gt; action in yazi is &lt;em&gt;almost&lt;&#x2F;em&gt; as good as I need it to be.
In helix, the fuzzy file picker &lt;em&gt;opens&lt;&#x2F;em&gt; the file that you accept, but in yazi you are simply moved onto it. &lt;br &#x2F;&gt;
That&#x27;s reasonable don&#x27;t get me wrong, but having to press enter twice to open any file sounds hilariously laborious, so I soft-forked the &lt;code&gt;fzf.yazi&lt;&#x2F;code&gt; plugin to automatically &lt;em&gt;open&lt;&#x2F;em&gt; the resulting file :3 &lt;br &#x2F;&gt;
This way, I&#x27;m just a single key (&lt;kbd&gt;i&lt;&#x2F;kbd&gt;) away from fuzzy searching files I want to open, compared to the equivalent helix global hotkey variant. &lt;br &#x2F;&gt;
Except, I get a bunch more other actions I can do easily, and methods I can use to travel to some file or directory, which is very helpful.&lt;&#x2F;p&gt;
&lt;p&gt;So helpful in fact, that &lt;code&gt;mdw&lt;&#x2F;code&gt; having an optimized name is not actually that useful — I&#x27;ve zoxided into it &lt;em&gt;maybe&lt;&#x2F;em&gt; once or twice so far&lt;a href=&quot;#footnote-3&quot; id=&quot;headnote-3&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
. I just do everything from the yazi that my global hotkey opens! &lt;br &#x2F;&gt;
But there are plenty of possible optimized names, so it&#x27;s not that big of a deal to overoptimize 😌
After all, I really like how &lt;code&gt;mdw&lt;&#x2F;code&gt; fits semantically as a name :3&lt;&#x2F;p&gt;
&lt;p&gt;Another pretty important piece of the puzzle is my fish &lt;code&gt;autocommit&lt;&#x2F;code&gt; function — it automatically makes commits out of the files in the working tree, making helpful-enough messages. &lt;br &#x2F;&gt;
A &lt;em&gt;bunch&lt;&#x2F;em&gt; of my directories are automatically &lt;code&gt;autocommit&lt;&#x2F;code&gt;ed daily, and &lt;code&gt;mdw&lt;&#x2F;code&gt; is one of them! &lt;br &#x2F;&gt;
It&#x27;s also autopushed, so I &lt;em&gt;really&lt;&#x2F;em&gt; don&#x27;t have to worry about my notes not getting backed up.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;splitting&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#splitting&quot; aria-label=&quot;Anchor link for: splitting&quot;&gt;splitting&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;My idea for &lt;code&gt;mdw&lt;&#x2F;code&gt; is a “personal documentation-like directory”.
That&#x27;s most things! &lt;br &#x2F;&gt;
But I noticed that I have a few pieces of information that feel &lt;em&gt;off&lt;&#x2F;em&gt; to store in &lt;code&gt;mdw&lt;&#x2F;code&gt;, despite it technically being the correct place.&lt;&#x2F;p&gt;
&lt;p&gt;I have a hotkey for Enter the Gungeon that gives me a random active item;
To do this, I store the list of all active items in a file. &lt;br &#x2F;&gt;
This isn&#x27;t strictly cache or data-like — it feels more like “user information”; something I might actually wanna check manually as well. &lt;br &#x2F;&gt;
Because of this, putting it into &lt;code&gt;~&#x2F;.local&#x2F;share&lt;&#x2F;code&gt; or &lt;code&gt;~&#x2F;.cache&lt;&#x2F;code&gt; feels a bit wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Another two files I have store important phone numbers, and chatgpt context prompts. &lt;br &#x2F;&gt;
Yeah, definitely &lt;em&gt;off&lt;&#x2F;em&gt; from &lt;code&gt;mdw&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I create another directory named &lt;code&gt;tiq&lt;&#x2F;code&gt;! &lt;br &#x2F;&gt;
The rough semantic for it is “would usually be a magazine, but would be a waste of a magazine”; Which is a much more understandable semantic for me than I initially expected it to be :D&lt;&#x2F;p&gt;
&lt;p&gt;It now stores other neat things, like alphabet indexes, neat phrases like “thanks for being my voice”, my note to self about how I do my finances, what mods I play slay the spire with and how they should be configured. &lt;br &#x2F;&gt;
All things that would both be in the way in &lt;code&gt;mdw&lt;&#x2F;code&gt;, and would also be harder to remember the existence of.&lt;&#x2F;p&gt;
&lt;p&gt;It is the “optimize paths” idea that makes this directory&#x27;s existence viable, in a sense. &lt;br &#x2F;&gt;
By using arbitrary-ish names, that don&#x27;t inherently mean something, I can assign a &lt;em&gt;feel&lt;&#x2F;em&gt; meaning to them. &lt;br &#x2F;&gt;
How would I name the two directories naturally? “documentation” and “information”? &lt;br &#x2F;&gt;
I guess that&#x27;s not too bad... But still! I&#x27;d think 7 more times before creating the second one, if I couldn&#x27;t put it unsuccinctly.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;got-hands&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#got-hands&quot; aria-label=&quot;Anchor link for: got-hands&quot;&gt;got hands&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;This whole adventure got started by me beginning to learn quickshell, but it&#x27;s going to be quite a bit more time until I continue. &lt;br &#x2F;&gt;
My goal now is to &lt;em&gt;process&lt;&#x2F;em&gt; all of my anki cards; to go through all of them, and decide on a case by case basis what should simply be a note and what should &lt;em&gt;also&lt;&#x2F;em&gt; (note the also) be an anki card.&lt;&#x2F;p&gt;
&lt;p&gt;4000 cards is no joke! Not something I could conceivably convert in a day, so it&#x27;s taking me quite some time. &lt;br &#x2F;&gt;
As a motivator, I decided to write down my progress as I do it, so that eventually I could figure out how many days it&#x27;ll take me to finish. &lt;br &#x2F;&gt;
Here&#x27;s the data so far:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.12    0 of 4000 (not a data point)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.15  160 of 3928 =  4.0%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.15  173 of 3920 =  4.4%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.15  352 of 3920 =  8.9%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.15  692 of 3883 = 17.8%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.16  702 of 3844 = 18.3%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.18  703 of 3797 = 18.5%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.19  755 of 3759 = 20.1%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.21  763 of 3716 = 20.5%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.21  780 of 3688 = 21.1%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.21  874 of 3644 = 24.0%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.22  899 of 3619 = 24.8%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.25 1089 of 3595 = 30.3%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25.08.25 1099 of 3555 = 30.9%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s taken me roughly 2 weeks to process roughly a third of all my cards.
You might naturally assume that to finish processing them, it&#x27;ll take me roughly another month. &lt;br &#x2F;&gt;
But that&#x27;s not the full picture!
Take a look at the quite big jumps: from 8.9 to 17.8, 21.1 to 24.0, 24.8 to 30.3 &lt;br &#x2F;&gt;
That is me processing cards that I either don&#x27;t intend to note, or are really easy to note in bulk.&lt;&#x2F;p&gt;
&lt;p&gt;More precisely, those are cards for country flags, country locations on a map, alphabet indexes, decimal and hex indexes of ascii characters, hiragana, katakana, and morse code. &lt;br &#x2F;&gt;
So my data is a bit skewed in a positive direction, for me to be able to draw the “around a month more” conclusion; &lt;br &#x2F;&gt;
It&#x27;s likely going to take more than a month, but how much exactly I&#x27;m not sure 🤷‍♀️&lt;&#x2F;p&gt;
&lt;h1 id=&quot;semantics&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#semantics&quot; aria-label=&quot;Anchor link for: semantics&quot;&gt;semantics&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;As I process cards, over time I&#x27;m feeling out what my semantics are, for what is a note and what is a card. &lt;br &#x2F;&gt;
At first, fueled by the strength of my new belief, I was quite delety — “I overuse anki, and should heavily lean towards notes” is the idea that I&#x27;m running with. &lt;br &#x2F;&gt;
But over time I&#x27;m figuring out the grey area a bit more complexly.&lt;&#x2F;p&gt;
&lt;p&gt;Some things are hard to note, because how do I name their section conveniently? &lt;br &#x2F;&gt;
&lt;code&gt;weird behavior of programming language #72&lt;&#x2F;code&gt; will get tiring quickly, so I come up with heading titles on a best effort basis.&lt;&#x2F;p&gt;
&lt;p&gt;This puts into perspective the power of anki for the usecase of &lt;em&gt;knowledge you don&#x27;t know you don&#x27;t know&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
There are quite many things that are &lt;em&gt;surprising&lt;&#x2F;em&gt;, and hence things that you won&#x27;t &lt;em&gt;think&lt;&#x2F;em&gt; to search for, in your notes. &lt;br &#x2F;&gt;
Using anki to retain at least the knowledge of the weirdosity of the behavior is quite effective, because of that! &lt;br &#x2F;&gt;
And then your notes can expand on the itty bitty details.&lt;&#x2F;p&gt;
&lt;p&gt;Despite that though, quite a lot of this type I still convert fully into notes, deleting the original anki cards. &lt;br &#x2F;&gt;
I care about knowing about niche but significant behaviors for things I actively use, but that&#x27;s not all the knowledge I store: &lt;br &#x2F;&gt;
I have quite a few cards for python, but I don&#x27;t use the language much, and want to use less of it :p &lt;br &#x2F;&gt;
So basically every python card gets converted into a note, no matter how awkwardly I have to word it.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s kind of the nice thing about it: instead of having to decide to completely discard my python knowledge, I can simply sweep it under the rug by putting it all into a note. &lt;br &#x2F;&gt;
If I ever need to refresh my snake skills, I know where to go — my note for python! &lt;br &#x2F;&gt;
I&#x27;ll then go through the entire file, going “oh huh! good to know” until I&#x27;m ready to use the language again.
Or, you know, just search within the note for things that are relevant :p&lt;&#x2F;p&gt;
&lt;p&gt;There are quite a few other things, that truthfully I should have never carded in the first place. &lt;br &#x2F;&gt;
Systemd-related information is unfathomably difficult to memorize.
All the various properties you have access to, are named incredibly inconsistently, so as soon as you start to develop a helpful memory semantic, another property completely breaks it.
Is it “delay” or “interval”? You never know 😌&lt;&#x2F;p&gt;
&lt;p&gt;Programs that I use in some limited capacity, and probably will never use the full power of, simply due to lack of need. &lt;br &#x2F;&gt;
The two examples that come to my head immediately are &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;zola&quot;&gt;&lt;code&gt;zola&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; (the SSG I use for this website) and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;casey&#x2F;just&quot;&gt;&lt;code&gt;just&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; (project-specific command executor) &lt;br &#x2F;&gt;
There&#x27;s quite a few niche and hyperspecific details I memorize about both, that I have literally never used and likely won&#x27;t. &lt;br &#x2F;&gt;
But as usual, just straight up losing that knowledge would feel bad :c &lt;br &#x2F;&gt;
Really really excited to convert this genre of cards into notes, to never have to plague my mind with maintaining it in my memory.&lt;&#x2F;p&gt;
&lt;p&gt;Then there&#x27;s the &lt;em&gt;really&lt;&#x2F;em&gt; wack kind — programs I literally never even used, but learned. &lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sinclairtarget&#x2F;git-who&quot;&gt;&lt;code&gt;git-who&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is one of them.
A really nifty program for viewing history of contributions over time, getting a better overview about who contributed where at which periods of time. &lt;br &#x2F;&gt;
Pretty awesome! However, I don&#x27;t think I have &lt;em&gt;ever&lt;&#x2F;em&gt; used git blame :p &lt;br &#x2F;&gt;
So you can probably see how I wouldn&#x27;t have yet used &lt;code&gt;git-who&lt;&#x2F;code&gt; either — yet the anki cards remain. Simply hilarious!&lt;&#x2F;p&gt;
&lt;a href=&quot;#conclusion&quot; id=&quot;conclusion&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I can&#x27;t wait until I finish converting all of this and that into notes, and can get back into &lt;em&gt;learning&lt;&#x2F;em&gt; new things.&lt;&#x2F;p&gt;
&lt;p&gt;Now, unbounded by anki, I&#x27;ll be able to learn in a much different way than before. &lt;br &#x2F;&gt;
Yesterday, I got a taste of this new way of learning, and it is RAVENOUS &#x2F;pos&lt;&#x2F;p&gt;
&lt;p&gt;I have a couple of interactive ffmpeg functions I wrote for myself in fish shell: I get asked a series of questions and that results in some specific ffmpeg command to be executed. &lt;br &#x2F;&gt;
The logic is of course written by me, but the ffmpeg flags I figured out with ai.&lt;&#x2F;p&gt;
&lt;p&gt;Now, it all &lt;em&gt;works&lt;&#x2F;em&gt;, but I&#x27;m well aware that I shouldn&#x27;t trust an ai to give me &lt;em&gt;the best&lt;&#x2F;em&gt; &#x2F; most optimized output; &lt;br &#x2F;&gt;
Learning ffmpeg would be insurmountable with my previous anki workflow, but now that I &lt;em&gt;don&#x27;t need to&lt;&#x2F;em&gt; have 100% correct knowledge, I can far more reasonably just “look around” the ffmpeg manpages, the internet, and more &lt;strong&gt;naturally&lt;&#x2F;strong&gt; collect information, not requiring myself to learn from the absolute base.&lt;&#x2F;p&gt;
&lt;p&gt;It was &lt;strong&gt;so&lt;&#x2F;strong&gt; fun! &lt;br &#x2F;&gt;
Like, holy shit! I always assumed learning ffmpeg in any capacity would be basically impossible, but no, not really!&lt;&#x2F;p&gt;
&lt;p&gt;As I looked through the flags my functions were using, I discovered and learned about them bit by bit. &lt;br &#x2F;&gt;
Intead of a third of my energy being spent worrying about how to anki the details succinctly, I was free to roam in the flowers, &lt;em&gt;exploring&lt;&#x2F;em&gt; the sea of ffmpeg options, and to be enthralled by the process.&lt;&#x2F;p&gt;
&lt;p&gt;No longer was that learning that I had to “get through” — no, the journey itself became much more enjoyable, because the expectations are much more reasonable. &lt;br &#x2F;&gt;
I now have a nice note about ffmpeg, where all I know so far is collected, no matter how wrong or inprecise; as now, more naturally, it&#x27;s something that can be developed over time, not set in stone while I&#x27;m not even certain about the material.&lt;&#x2F;p&gt;
&lt;p&gt;It is &lt;em&gt;heavenly&lt;&#x2F;em&gt;!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-quote&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-quote&quot; aria-label=&quot;Anchor link for: a-quote&quot;&gt;a quote&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I announced writing this blog post on my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;discord.gg&#x2F;bgVSg362dK&quot;&gt;discord server&lt;&#x2F;a&gt;, and got this absolute peak response: &lt;br &#x2F;&gt;
“Is the blog post one full document, or is it broken up into anki cards that cover each individual aspect?”&lt;&#x2F;p&gt;
&lt;p&gt;Really puts into words, how silly my obsession of “anki only, no notes” was. &lt;br &#x2F;&gt;
Now all that&#x27;s left, is to &lt;strong&gt;not&lt;&#x2F;strong&gt; develop the opposite one, where I refuse anki for very good-to-anki things :p&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;footnotes&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-1&quot; id=&quot;footnote-1&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 I&#x27;m not mad about this btw — the main goal was to learn css grid, but hide the effort from my psyche with the promise of something really cool. &lt;br &#x2F;&gt;
I didn&#x27;t get that something cool, sure, but by the time I finish learning, the urgency of the motivator has already died down — it was &lt;em&gt;used&lt;&#x2F;em&gt; as coal for the fire of learning 🔥&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-2&quot; id=&quot;footnote-2&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 Actually I ended up deciding to learn &lt;code&gt;eww&lt;&#x2F;code&gt; instead, because the quickshell package has a package conflict that hasn&#x27;t been solved in more than a week now. But I&#x27;m checking every once and again if it&#x27;s fixed, and might end up learning quickshell still. Quite &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=F986K5yNwWQ&quot;&gt;tea with honey without honey no tea&lt;&#x2F;a&gt; of me :3&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-3&quot; id=&quot;footnote-3&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 It&#x27;s been 10 days since I started converting cards and using &lt;code&gt;mdw&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>blammo</title>
          <pubDate>Wed, 30 Jul 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/blammo/</link>
          <guid>https://axlefublr.github.io/blammo/</guid>
          <description xml:base="https://axlefublr.github.io/blammo/">&lt;p&gt;I use the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sxyazi&#x2F;yazi&quot;&gt;yazi&lt;&#x2F;a&gt; file manager, and like it a lot! &lt;br &#x2F;&gt;
Most of my file operations, including even &lt;code&gt;cd&lt;&#x2F;code&gt;ing sometimes, is done directly from yazi. &lt;br &#x2F;&gt;
Which is why I add a couple of powerful special hotkeys to it!&lt;&#x2F;p&gt;
&lt;p&gt;For example, I quite often need to cut videos; &lt;br &#x2F;&gt;
Unlike a normal person, I refuse to use an actual editing app, and instead I do it with &lt;code&gt;ffmpeg&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I wrote some &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;fish&#x2F;fun&#x2F;ffmpeg.fish&quot;&gt;interactive ffmpeg fish functions&lt;&#x2F;a&gt;, and integrated them into yazi: &lt;br &#x2F;&gt;
On a press of a hotkey, all the files that I selected in yazi get passed to the function, and iterated on one by one.
I then answer “questions” to edit the videos however I wish.&lt;&#x2F;p&gt;
&lt;p&gt;This is really neat, but not super scaleable in a sense: &lt;br &#x2F;&gt;
I can&#x27;t make a hotkey for every ad-hoc action, can I?&lt;&#x2F;p&gt;
&lt;p&gt;It makes sense to have shortcuts to the really common actions, but you won&#x27;t know if an action is common or not until you&#x27;ve already done it quite a few times. &lt;br &#x2F;&gt;
If you&#x27;re too quick, you might end up with a “dead” hotkey in your configuration, &lt;br &#x2F;&gt;
But if you don&#x27;t provide yourself &lt;em&gt;any&lt;&#x2F;em&gt; shortcut, doing The™ Action™ might be really laborious.&lt;a href=&quot;#footnote-1&quot; id=&quot;headnote-1&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;I came up with an idea that lets me seamlessly connect yazi&#x27;s selected files to my shell, and I find the design really cool and nushell-like :D&lt;&#x2F;p&gt;
&lt;h1 id=&quot;fishangling&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fishangling&quot; aria-label=&quot;Anchor link for: fishangling&quot;&gt;fishangling&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s start with how I reached the idea in the first place; why it even needed to exist.&lt;&#x2F;p&gt;
&lt;p&gt;Yazi allows you to make mappings that call shell commands. &lt;br &#x2F;&gt;
In those, you have access to &lt;code&gt;$@&lt;&#x2F;code&gt;, which means “absolute filespaths to all the currently selected files”. &lt;br &#x2F;&gt;
To handle spaces, you seem to need to specifically enclose the &lt;code&gt;$@&lt;&#x2F;code&gt; in doublequotes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;shell --confirm -- ouch decompress &amp;quot;$@&amp;quot;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;--&lt;&#x2F;code&gt; argument allows us to not have to quote the command itself — everything after &lt;code&gt;--&lt;&#x2F;code&gt; is considered a raw part of the actual command.&lt;&#x2F;p&gt;
&lt;p&gt;This works, as you&#x27;d expect! &lt;br &#x2F;&gt;
I can select multiple archives and decompress them all with a hotkey&lt;a href=&quot;#footnote-2&quot; id=&quot;headnote-2&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
. &lt;br &#x2F;&gt;
But it&#x27;s rare for me to just call commands directly; &lt;br &#x2F;&gt;
Often times, I write some sort of functionality in a fish shell function, and invoke it with &lt;code&gt;fish -c&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
All my various ffmpeg functions are written in fish, for example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;shell --block --confirm -- fish -c &amp;#39;ffmpeg_convert_to_mp3 &amp;quot;$@&amp;quot;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Except... this doesn&#x27;t work. &lt;br &#x2F;&gt;
&lt;code&gt;&quot;$@&quot;&lt;&#x2F;code&gt;, that &lt;em&gt;just&lt;&#x2F;em&gt; expanded absolutely correctly, no longer does inside of an argument to &lt;code&gt;fish -c&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You see, I immediately assumed that the &lt;code&gt;$@&lt;&#x2F;code&gt; syntax in yazi is its &lt;em&gt;own&lt;&#x2F;em&gt; thing, rather than the usual POSIX &lt;code&gt;$@&lt;&#x2F;code&gt;; &lt;br &#x2F;&gt;
Fish shell actually uses &lt;code&gt;$argv&lt;&#x2F;code&gt; to mean the same thing, so I guess I can simply use that, neat :D&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;shell --block --confirm -- fish -c &amp;#39;ffmpeg_convert_to_mp3 &amp;quot;$argv&amp;quot;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Except...... It also doesn&#x27;t work. &lt;br &#x2F;&gt;
So &lt;code&gt;$@&lt;&#x2F;code&gt; &lt;em&gt;is&lt;&#x2F;em&gt; a yazi-specific thing, and perhaps it only expands correctly when provided as a separate argument, on its own, rather than part of a bigger argument 🧐&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m being pretty vague here, with “doesn&#x27;t work”, but that&#x27;s because the semantics I still don&#x27;t fully understand, and my experiences with them are very blurry. &lt;br &#x2F;&gt;
I feel that sometimes, it expanded all the paths into a single string, rather than multiple arguments, &lt;br &#x2F;&gt;
other times, didn&#x27;t expand anything at all, &lt;br &#x2F;&gt;
maybe it didn&#x27;t handle spaces correctly?&lt;&#x2F;p&gt;
&lt;p&gt;Regardless, I decided to create my own solution for providing the list of arguments into fish from yazi, that worked by far more clear and guessable rules.&lt;&#x2F;p&gt;
&lt;p&gt;Welcome to “blammo”! &lt;br &#x2F;&gt;
Yeah, I really didn&#x27;t think much about the name of this thing, and it just kinda stayed “blammo” forever 😭 &lt;br &#x2F;&gt;
If you&#x27;ve been reading my blog posts for some time, you might&#x27;ve noticed how much I love this word, lol. &lt;br &#x2F;&gt;
Fun fact, my insane overuse of it comes directly after &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Eqo7rMUKm9A&quot;&gt;this video&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;blammation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#blammation&quot; aria-label=&quot;Anchor link for: blammation&quot;&gt;blammation&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I wrote this simple yazi plugin:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #928374;&quot;&gt;--- @sync entry&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;	entry&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;		local&lt;&#x2F;span&gt;&lt;span&gt; collector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; _, url&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; pairs&lt;&#x2F;span&gt;&lt;span&gt;(cx.active.selected) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			collector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; collector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; tostring&lt;&#x2F;span&gt;&lt;span&gt;(url) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #928374;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;		end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; #&lt;&#x2F;span&gt;&lt;span&gt;collector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			collector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; tostring&lt;&#x2F;span&gt;&lt;span&gt;(cx.active.current.hovered.url) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #928374;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;		end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;		local&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; io.open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;#39;&#x2F;home&#x2F;axlefublr&#x2F;.cache&#x2F;mine&#x2F;blammo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;#39;w&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			file:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(collector)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			file:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;		end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;	end&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yazi is in very active development, for more better than for the worse; &lt;br &#x2F;&gt;
So don&#x27;t expect this to straight up work if you&#x27;re reading this post in the future.&lt;&#x2F;p&gt;
&lt;p&gt;The main idea, though, is pretty simple: &lt;br &#x2F;&gt;
We take the full paths of all files we have selected, and convert them into a string which has one path per line. &lt;br &#x2F;&gt;
If we don&#x27;t have any &lt;em&gt;selected&lt;&#x2F;em&gt;, we simply take the filepath that our cursor is currently on. &lt;br &#x2F;&gt;
And we write that to some file.&lt;&#x2F;p&gt;
&lt;p&gt;The path doesn&#x27;t matter, but I like to use &lt;code&gt;~&#x2F;.cache&#x2F;mine&lt;&#x2F;code&gt; to hold various cache-like files that I don&#x27;t want removed on reboots, which would happen if I put it in &lt;code&gt;&#x2F;tmp&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I have the opposite idea also, where I hold files I &lt;em&gt;do&lt;&#x2F;em&gt; want eventually auto-cleared in &lt;code&gt;&#x2F;tmp&#x2F;mine&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, after you put the above code into &lt;code&gt;~&#x2F;.config&#x2F;yazi&#x2F;plugins&#x2F;blammo.yazi&#x2F;main.lua&lt;&#x2F;code&gt;, you can now access it in your yazi mappings with &lt;code&gt;plugin blammo&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
When you call the plugin, it stamps the current selected files into a file, which you can immediately read as a list of arguments. &lt;br &#x2F;&gt;
In shells, you can &lt;code&gt;cat some-file&lt;&#x2F;code&gt;, and it will convert each line in a separate argument. &lt;br &#x2F;&gt;
Which is very clean, simple, safe, and nifty!&lt;&#x2F;p&gt;
&lt;p&gt;We can now fix the previous ffmpeg mapping I was trying to create:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ &amp;#39;plugin blammo&amp;#39;, &amp;#39;shell --block --confirm -- fish -c &amp;quot;ffmpeg_convert_video (cat ~&#x2F;.cache&#x2F;mine&#x2F;blammo)&amp;quot;&amp;#39; ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this &lt;strong&gt;does&lt;&#x2F;strong&gt; work 🥳&lt;&#x2F;p&gt;
&lt;p&gt;Having to type out the blammo filepath for every hotkey is a bit laborious, though, so I made myself a nifty little fish alias:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt; blammo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    cat&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;.cache&#x2F;mine&#x2F;blammo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So now, the yazi mapping is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ &amp;#39;plugin blammo&amp;#39;, &amp;#39;shell --block --confirm -- fish -c &amp;quot;ffmpeg_convert_video (blammo)&amp;quot;&amp;#39; ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This solves the issue I had at the time, but highlights something interesting: &lt;br &#x2F;&gt;
I was just able to, effectively, reach into the context of yazi, from outside of yazi 🤔 &lt;br &#x2F;&gt;
As long as it&#x27;s properly updated, nothing is stopping me from using &lt;code&gt;(blammo)&lt;&#x2F;code&gt; just interactively in my shell!&lt;&#x2F;p&gt;
&lt;p&gt;I made my quit and &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;suspend&#x2F;&quot;&gt;suspend&lt;&#x2F;a&gt; hotkeys &lt;code&gt;blammo&lt;&#x2F;code&gt; first, so that leaving yazi ensures the blammations are up to date.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{ on = &amp;#39;:&amp;#39;, run = [ &amp;#39;plugin blammo&amp;#39;, &amp;#39;quit&amp;#39; ], desc = &amp;#39;Exit the process&amp;#39; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{ on = &amp;#39;&amp;lt;C-z&amp;gt;&amp;#39;, run = [ &amp;#39;plugin blammo&amp;#39;, &amp;#39;suspend&amp;#39; ], desc = &amp;#39;Suspend the process&amp;#39; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now I can select some files in yazi, suspend with &lt;kbd&gt;ctrl+z&lt;&#x2F;kbd&gt;, and execute some arbitrary shell command on the files I had selected!&lt;&#x2F;p&gt;
&lt;p&gt;I recently had a usecase, where I wanted to convert a video into webp (which you can apparently do):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;magick&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;blammo&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;blammo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; path&lt;&#x2F;span&gt;&lt;span&gt; change-extension webp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I love it!! &lt;br &#x2F;&gt;
But it&#x27;s a &lt;em&gt;biiiiit&lt;&#x2F;em&gt; wordy — typing out &lt;code&gt;(blammo)&lt;&#x2F;code&gt; is more syntax than I&#x27;d like 🤔&lt;&#x2F;p&gt;
&lt;p&gt;So I came up with a funny but reasonably solid hack! &lt;br &#x2F;&gt;
At the end of my &lt;code&gt;fish_prompt&lt;&#x2F;code&gt; function, I put the following line:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt; -g&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;blammo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; 2&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;dev&#x2F;null)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;fish_prompt&lt;&#x2F;code&gt; is the function that runs every time your prompt needs to be drawn. &lt;br &#x2F;&gt;
Meaning, &lt;em&gt;before every command&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
So, we put yazi&#x27;s latest selected files into a global variable &lt;code&gt;in&lt;&#x2F;code&gt;, that we can then use directly as the list of filepaths!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;magick&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;in (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt; change-extension webp &lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;in)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And if we do indeed select multiple files, you could blammo a loop:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; the &lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    magick&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;the (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt; change-extension webp &lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;the)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Semantically, this is quite a bit better :D&lt;&#x2F;p&gt;
&lt;p&gt;In nushell, &lt;code&gt;$in&lt;&#x2F;code&gt; means “whatever was piped into the current thing”, so here it&#x27;s as if we&#x27;re piping the list of filenames into fish, quite neat!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;p-s&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#p-s&quot; aria-label=&quot;Anchor link for: p-s&quot;&gt;p.s.&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Ahhhh... no better way to get the correct solution than to post the wrong one on the internet 😌&lt;a href=&quot;#footnote-3&quot; id=&quot;headnote-3&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 &lt;br &#x2F;&gt;
The &lt;em&gt;yazi author&lt;&#x2F;em&gt; read this blog post, and shared the more proper way of doing what &lt;code&gt;(blammo)&lt;&#x2F;code&gt; was initially made for!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;shell --block -- fish -c &amp;#39;ffmpeg_convert_to_mp3 &amp;quot;$argv&amp;quot;&amp;#39; &amp;quot;$@&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First of all, you can now omit the &lt;code&gt;--confirm&lt;&#x2F;code&gt; flag. &lt;br &#x2F;&gt;
But more importantly, you can probably intuit the semantics of yazi&#x27;s &lt;code&gt;&quot;$@&quot;&lt;&#x2F;code&gt; now.&lt;&#x2F;p&gt;
&lt;p&gt;It is only resolved as a &lt;em&gt;top level&lt;&#x2F;em&gt; argument to the overall command; it&#x27;s not a find and replace across all text of all arguments. &lt;br &#x2F;&gt;
So here, we specify &lt;em&gt;the fish program&lt;&#x2F;em&gt; in the string after &lt;code&gt;-c&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
The program makes use of the arguments provided to it. &lt;br &#x2F;&gt;
After the stringed fish program, we pass arguments to it with &lt;code&gt;&quot;$@&quot;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;em&gt;this&lt;&#x2F;em&gt; knowledge, you can now avoid needing blammo to pass selected files to predefined mappings, and can use this concept to pass arguments into other interpreted programming languages, like nushell probably.&lt;&#x2F;p&gt;
&lt;p&gt;But the main idea of blammo, and why I wrote this in the first place — connecting yazi&#x27;s selected files into your shell — is still alive and useful, even with this new discovery! :D&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;footnotes&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-1&quot; id=&quot;footnote-1&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 Sounds similar to the types of situations that &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;harp&#x2F;&quot;&gt;harp&lt;&#x2F;a&gt; solves, doesn&#x27;t it? &lt;br &#x2F;&gt;
You&#x27;re correct! Harp could be implemented into yazi to provide a pretty nice productivity boost, but &lt;em&gt;so far&lt;&#x2F;em&gt; I don&#x27;t find myself executing enough commands from the context of yazi to really need harp.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-2&quot; id=&quot;footnote-2&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 I&#x27;m aware of the built in yazi unarchiver, but it&#x27;s been super wonky for me. &lt;br &#x2F;&gt;
I&#x27;d much rather use the behavior I&#x27;m more familiar with, using &lt;code&gt;ouch&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
This hotkey still exists, but I actually made “opening” archives automatically use &lt;code&gt;ouch decompress&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
How did I do that? Exercise for the reader 😌&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-3&quot; id=&quot;footnote-3&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 To be fair, I never &lt;em&gt;asked&lt;&#x2F;em&gt; anywhere for how to solve the issue of passing arguments to fish, neither have I searched. &lt;br &#x2F;&gt;
I have a tendency to solve my problems my own way before considering grabbing some pre-existing solution :&amp;gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>proxy things</title>
          <pubDate>Sun, 27 Jul 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/proxies/</link>
          <guid>https://axlefublr.github.io/proxies/</guid>
          <description xml:base="https://axlefublr.github.io/proxies/">&lt;p&gt;I&#x27;m unfortunately in russia. &lt;br &#x2F;&gt;
Since the start of the war, most services have left the country, now requiring a vpn to use.&lt;&#x2F;p&gt;
&lt;p&gt;But funny thing — so did the &lt;em&gt;vpns&lt;&#x2F;em&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;First, some now required a vpn to access them (the another vpn). &lt;br &#x2F;&gt;
Sounds pretty useless, but I could conceivably use some bad free vpn to then enable the good one, disconnect the free one and continue using the good one until I reboot. &lt;br &#x2F;&gt;
So that worked to an extent, but it didn&#x27;t last that long. &lt;br &#x2F;&gt;
One by one, vpns started massively throttling, taking tens of minutes to connect, and eventually just not connecting at all. &lt;br &#x2F;&gt;
Express, Nord, Air, Surfshark, CyberGhost, Private Internet Access, Proton, Windscribe, Mullvad — are all vpns I&#x27;ve used or tried using, until ultimately they &lt;em&gt;&lt;strong&gt;all&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; broke.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m in quite a salted vegetable here, I certainly need to access things like discord, youtube, spotify, and most of the internet honestly; what do I do?&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-name-of-this-heading-would-be-a-spoiler-to-the-dramatic-tension-of-the-previous-sentence&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-name-of-this-heading-would-be-a-spoiler-to-the-dramatic-tension-of-the-previous-sentence&quot; aria-label=&quot;Anchor link for: the-name-of-this-heading-would-be-a-spoiler-to-the-dramatic-tension-of-the-previous-sentence&quot;&gt;the name of this heading would be a spoiler to the dramatic tension of the previous sentence&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;VPNs are not the first technology that allows you to avoid geo-restrictions. &lt;br &#x2F;&gt;
Thanks to my friend&#x27;s effortful history lesson on networking, I got a better idea of what a &lt;em&gt;proxy&lt;&#x2F;em&gt; is. &lt;br &#x2F;&gt;
Better enough to now consider it as a possible solution.&lt;&#x2F;p&gt;
&lt;p&gt;A proxy, in my understanding, is a server that can make requests &lt;em&gt;for you&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
It&#x27;s exactly like sexism actually:&lt;a href=&quot;#footnote-1&quot; id=&quot;headnote-1&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 you, the russian woman, saying something to another server is rejected. &lt;br &#x2F;&gt;
So you ask a man (the proxy) to say the same thing &lt;em&gt;for you&lt;&#x2F;em&gt;, and give you the response — now it suddenly works.&lt;&#x2F;p&gt;
&lt;p&gt;VPNs often work globally on your system which is very convenient,
but you do tend to &lt;em&gt;need&lt;&#x2F;em&gt; geo-restriction-unlocking for only a few places. &lt;br &#x2F;&gt;
Those few places, usually, allow you to configure the proxy!&lt;&#x2F;p&gt;
&lt;p&gt;There are HTTP proxies you can find out there for free, but really shouldn&#x27;t:
the S part of HTTPS is very important for the &lt;em&gt;security&lt;&#x2F;em&gt; of your data, as without TLS,
the data you send will be visible to the proxy itself — a bank password that you enter, for example. &lt;br &#x2F;&gt;
Finding free HTTP&lt;em&gt;S&lt;&#x2F;em&gt; proxies is then a &lt;em&gt;privacy&lt;&#x2F;em&gt; concern, so I decided to &lt;em&gt;buy&lt;&#x2F;em&gt; one instead.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;for-the-russians&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#for-the-russians&quot; aria-label=&quot;Anchor link for: for-the-russians&quot;&gt;for the russians&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;In this section I&#x27;ll go over my exact process for buying a proxy, &lt;br &#x2F;&gt;
but if you&#x27;re not russian you&#x27;re better off using some store that&#x27;s not specifically tailored to russians. &lt;br &#x2F;&gt;
Google for “buy https proxy” and you&#x27;ll probably get there.&lt;&#x2F;p&gt;
&lt;p&gt;Although, I&#x27;d recommend actually going through with my suggestions in the blog post, after you&#x27;ve completed it — I will be omitting some things until later notice for dramatic effect.&lt;&#x2F;p&gt;
&lt;p&gt;As a hilarious way to force non-russian readers to skip this section, I&#x27;ll write it &lt;em&gt;in&lt;&#x2F;em&gt; russian.&lt;&#x2F;p&gt;
&lt;p&gt;Нашла сайт, где можно купить прокси: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;proxys.io&#x2F;en&quot;&gt;https:&#x2F;&#x2F;proxys.io&#x2F;en&lt;&#x2F;a&gt; &lt;br &#x2F;&gt;
Когда юзала VPNы, самые лучшие результаты у меня были используя сервера в Нидердландах, поэтому решила купить и прокси там же.&lt;&#x2F;p&gt;
&lt;p&gt;Я плачу криптой, если честно уже не помню почему; &lt;br &#x2F;&gt;
Для этого я использую сервис &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lk.matbea.com&#x2F;en&quot;&gt;MATBEA&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
У них ещё есть приложение на андроид, оно мне кажется более приветливым, так что обычно использую его.&lt;&#x2F;p&gt;
&lt;p&gt;С помощью MATBEA, можно обменяться валютой с человеком —
вы отправляете классические деньги со своего банка (тинькофф например&lt;a href=&quot;#footnote-2&quot; id=&quot;headnote-2&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
), &lt;br &#x2F;&gt;
они подтверждают что пришло, &lt;br &#x2F;&gt;
и крипта, которую MATBEA держит во время операции&lt;a href=&quot;#footnote-3&quot; id=&quot;headnote-3&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 приходит к вам на аккаунт.&lt;&#x2F;p&gt;
&lt;p&gt;Но на протяжении этой операции, есть несколько коммиссий из-за которых сложно предугадать сколько денег в итоге попадёт на счёт proxys.io. &lt;br &#x2F;&gt;
Так что моя личная стратегия, ложить на 30% больше денег на счёт матби, чем я собираюсь в итоге получить на счёт proxys.io. &lt;br &#x2F;&gt;
Не волнуйтесь, реальная коммиссия не буквально 30%, это больше для безопасности, чтобы потом в жопу не ебаться когда вдруг не хватает 0.003 биткоина. &lt;br &#x2F;&gt;
Как моя подруга сказала на этот счёт: “лучше перебдеть чем недобдеть”.&lt;&#x2F;p&gt;
&lt;p&gt;И так, план следующий:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Выберите https прокси которую хотите купить&lt;&#x2F;li&gt;
&lt;li&gt;Оплата через крипту&lt;&#x2F;li&gt;
&lt;li&gt;Вам выставится адрес, на который нужно отправить какое-то количество скорее всего биткоина&lt;&#x2F;li&gt;
&lt;li&gt;Идите на матби&lt;&#x2F;li&gt;
&lt;li&gt;Переводите чуть побольше чем надо на матби аккаунт с помощью “Пополнить”&lt;&#x2F;li&gt;
&lt;li&gt;Сделайте “Обмен” на валюту, которую proxys.io от вас хочет&lt;&#x2F;li&gt;
&lt;li&gt;Жмите “Отправить”, на адрес получателя&lt;&#x2F;li&gt;
&lt;li&gt;Восемь раз отмерьте (проверьте что правильно скопировали и вставили адрес, или просканиуйте qr-код)&lt;&#x2F;li&gt;
&lt;li&gt;Один раз отрежьте (отправляйте, но поставьте низкий приоритет чтобы не было ебейших комиссий)&lt;&#x2F;li&gt;
&lt;li&gt;Ждите миллиард лет, пока деньги дойдут до proxys.io. У меня это обычно занимает где-то час&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Готово! Теперь у вас есть прокси 🥳 &lt;br &#x2F;&gt;
Юпииииии&lt;&#x2F;p&gt;
&lt;p&gt;Блять ненавижу писать по-русски, это намного сложнее чем по английски 😭 &lt;br &#x2F;&gt;
Но “бит” смешной так что надо было 😤&lt;&#x2F;p&gt;
&lt;h1 id=&quot;po-susekam&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#po-susekam&quot; aria-label=&quot;Anchor link for: po-susekam&quot;&gt;по сусекам&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I have an https proxy now! :D &lt;br &#x2F;&gt;
And I paid just 2.67$ (monthly) for it!&lt;&#x2F;p&gt;
&lt;p&gt;VPN prices generally &lt;em&gt;start&lt;&#x2F;em&gt; at 5$, so that&#x27;s a pretty damn stellar deal,
considering how effective the proxy later became for me. &lt;br &#x2F;&gt;
So even if you aren&#x27;t in my situation, and VPNs &lt;em&gt;do&lt;&#x2F;em&gt; work for you, using a proxy might still be more cost-effective, if nothing else!&lt;&#x2F;p&gt;
&lt;a href=&quot;#information&quot; id=&quot;information&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The proxy comes with a set of “information” that you&#x27;re going to use to plug it into places. &lt;br &#x2F;&gt;
Let&#x27;s name all of them, so that they&#x27;re a bit more familiar!&lt;a href=&quot;#footnote-4&quot; id=&quot;headnote-4&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;4&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;thingy&lt;&#x2F;th&gt;&lt;th&gt;namey&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;162.3.164.178&lt;&#x2F;td&gt;&lt;td&gt;ip address &#x2F; hostname&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;8676&lt;&#x2F;td&gt;&lt;td&gt;port&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;user223767&lt;&#x2F;td&gt;&lt;td&gt;username&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;eIwB7xB&lt;&#x2F;td&gt;&lt;td&gt;password&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The ip address + port are probably discoverable enough&lt;a href=&quot;#footnote-5&quot; id=&quot;headnote-5&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;5&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 where someone unwanted could get access to your proxy, so it will usually come with a username and password as well. &lt;br &#x2F;&gt;
You are meant to keep these secret 😼&lt;&#x2F;p&gt;
&lt;p&gt;A lot of places that let you configure a proxy, simply have separate fields for each of the 4 values. &lt;br &#x2F;&gt;
But some don&#x27;t!&lt;&#x2F;p&gt;
&lt;p&gt;The following syntax is something you might see yourself using in those other places:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;user223767:eIwB7xB@162.3.164.178:8676&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;i.e.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;username:password@ip:port&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s rare to use them bare like this though, usually you&#x27;re expected to give a link:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:&#x2F;&#x2F;user223767:eIwB7xB@162.3.164.178:8676&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:&#x2F;&#x2F;username:password@ip:port&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;it-works-sorta&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#it-works-sorta&quot; aria-label=&quot;Anchor link for: it-works-sorta&quot;&gt;it works... sorta&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The main, and almost &lt;em&gt;only&lt;&#x2F;em&gt; place where I need georestriction unlocking, is my browser. &lt;br &#x2F;&gt;
Through some steps (that I&#x27;ll teach you later), I was successfully able to use my new proxy, &lt;br &#x2F;&gt;
and no longer needed to jump through 5 free vpns :D&lt;&#x2F;p&gt;
&lt;p&gt;It seemed surprisingly straightforward, and continued working for a while, until I switched to &lt;a href=&quot;&#x2F;content&#x2F;floorp&#x2F;index.md&quot;&gt;floorp&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
In firefox, everything worked just how you&#x27;d expect. &lt;br &#x2F;&gt;
But on floorp, suddenly, youtube videos were not playing 🤔&lt;&#x2F;p&gt;
&lt;p&gt;Note, the entire rest of the website was working, just not actual playback. &lt;br &#x2F;&gt;
At the time, this put me into anxiety mode; I was considoring&lt;a href=&quot;#footnote-6&quot; id=&quot;headnote-6&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;6&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 using firefox specifically for youtube, but that sounded like quite a shitty tradeoff. &lt;br &#x2F;&gt;
Firefox and floorp handle proxies differently &lt;em&gt;somehow&lt;&#x2F;em&gt;.
I wasn&#x27;t quite sure why yet.&lt;&#x2F;p&gt;
&lt;p&gt;My favorite puppy&lt;a href=&quot;#footnote-7&quot; id=&quot;headnote-7&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;7&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 helped me solve this, with some bespoke setup that involved its VPS&#x27; socks4 proxy. &lt;br &#x2F;&gt;
Still not exactly sure what all this is, but now I&#x27;m hearing this 🧦 term when it comes to proxies. Interesting.&lt;&#x2F;p&gt;
&lt;p&gt;And so, I was paying for my own proxy to use for most things, and using my partner&#x27;s socks4 proxy for youtube. &lt;br &#x2F;&gt;
Feels kinda bleghy, right? &lt;br &#x2F;&gt;
Shouldn&#x27;t my own proxy already accomplish everything?&lt;&#x2F;p&gt;
&lt;p&gt;I realized my grave underunderstanding recently, while trying to set up discord. &lt;br &#x2F;&gt;
&lt;em&gt;Web&lt;&#x2F;em&gt; discord is just fine for me, but it&#x27;s crucially missing the ctrl+123456789 hotkeys, so I really wanted to try out vesktop to get those. &lt;br &#x2F;&gt;
Both fortunately and unfortunately, &lt;em&gt;there&lt;&#x2F;em&gt; the proxy setup was more difficult to figure out. &lt;br &#x2F;&gt;
As I was trying different things, I came across a new nugget of knowlege: &lt;br &#x2F;&gt;
“https proxies are solid for TCP, but fucky for UDP. socks5 solves this though”&lt;&#x2F;p&gt;
&lt;p&gt;Through my friend&#x27;s networking history lesson, I got a slightly better idea of what TCP and UDP are usually used for. &lt;br &#x2F;&gt;
And UDP, crucially, is used for &lt;em&gt;video playback&lt;&#x2F;em&gt;, among other things!&lt;&#x2F;p&gt;
&lt;p&gt;Huh! The exact thing that&#x27;s &lt;em&gt;not&lt;&#x2F;em&gt; working off of my proxy in floorp. &lt;br &#x2F;&gt;
Hmmm… So if I had a socks5 proxy, this might get solved?&lt;&#x2F;p&gt;
&lt;p&gt;I was playing around in my proxys.io (where I bought my proxy) account, and happened to enter into the proxy&#x27;s information page again. &lt;br &#x2F;&gt;
I discovered a new field, that I never understood or paid attention to before: “socks5 port”.&lt;&#x2F;p&gt;
&lt;p&gt;Well holy shit! &lt;br &#x2F;&gt;
Does this mean that my proxy is a socks5 proxy &lt;em&gt;too&lt;&#x2F;em&gt;, rather than only https?&lt;&#x2F;p&gt;
&lt;p&gt;I reconfigure the proxy in my browser to use socks5 instead of https, and provide the new port. &lt;br &#x2F;&gt;
I restart my browser and rush into youtube, to be completely dumbfounded by seeing that &lt;em&gt;&lt;strong&gt;it works&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Hoooooooly fucking shit I was paying for this proxy for more than half a year at this point, and all I fucking needed to do was realize that socks5 is a level up from https, rather than being some fancy other genre,
and that it&#x27;s simply something I should be using everywhere I can,
to make more things work more easily.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;ok-ok-let-s-use-this-proxy-let-s-use-this-proxy-in-our-apps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ok-ok-let-s-use-this-proxy-let-s-use-this-proxy-in-our-apps&quot; aria-label=&quot;Anchor link for: ok-ok-let-s-use-this-proxy-let-s-use-this-proxy-in-our-apps&quot;&gt;ok ok let&#x27;s use this proxy, let&#x27;s use this proxy in our apps&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;(&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=H1M7Fj6T91c&quot;&gt;&#x2F;ref&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;Socks5 is the new nugget of information, because of which I wanted you to read more before acting; &lt;br &#x2F;&gt;
When buying a proxy, make sure it&#x27;s &lt;em&gt;both&lt;&#x2F;em&gt; an https &lt;em&gt;and&lt;&#x2F;em&gt; a socks5 proxy —
that makes it much more powerful and appliable in more scenarios.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with the most common one!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;firefox&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#firefox&quot; aria-label=&quot;Anchor link for: firefox&quot;&gt;firefox&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The firefox &#x2F; floorp &#x2F; zen &#x2F; etc setup is pretty simple. &lt;br &#x2F;&gt;
It &lt;em&gt;should&lt;&#x2F;em&gt; be as simple in chromium-based browsers, for the record, but you&#x27;ll have to find that out yourself :p&lt;&#x2F;p&gt;
&lt;p&gt;Install the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;addons.mozilla.org&#x2F;en-GB&#x2F;firefox&#x2F;addon&#x2F;foxyproxy-standard&#x2F;&quot;&gt;FoxyProxy extension&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
Grant it the permissions it&#x27;s asking for, and allow it to run in private windows. &lt;br &#x2F;&gt;
Go to the extension&#x27;s settings → Proxies.&lt;&#x2F;p&gt;
&lt;p&gt;Here we&#x27;re going to add our proxy &lt;em&gt;as a socks5 one&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
Press the “Add” button, and fill in the hostname, port (specifically the socks5 one, not the https one!), username, password. &lt;br &#x2F;&gt;
Set “Type” to SOCKS5. &lt;br &#x2F;&gt;
I have “Proxy DNS” enabled, but I&#x27;m not sure if we need to honestly.&lt;&#x2F;p&gt;
&lt;p&gt;Now, add these patterns:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;cludation&lt;&#x2F;th&gt;&lt;th&gt;pattern&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;include&lt;&#x2F;td&gt;&lt;td&gt;*&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;exclude&lt;&#x2F;td&gt;&lt;td&gt;*localhost*&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;exclude&lt;&#x2F;td&gt;&lt;td&gt;*127.0.0.1*&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;As you use the proxy, you may find places that you specifically don&#x27;t want to proxy, and will be able to exclude them here. &lt;br &#x2F;&gt;
Crucially, though, we begin by excluding localhost —
you don&#x27;t want to proxy your own computer&#x27;s local network.&lt;&#x2F;p&gt;
&lt;p&gt;You can also handle this the other way around: by &lt;strong&gt;not&lt;&#x2F;strong&gt; proxying anything by default, and adding stuff to proxy as you go. &lt;br &#x2F;&gt;
But if you&#x27;re a russian reading this blog post, you probably want to proxy everything by default, due to how much stuff is blocked in russia nowadays. &lt;br &#x2F;&gt;
If you&#x27;re in China, similar idea probably applies.&lt;&#x2F;p&gt;
&lt;p&gt;Now, press “Save” and enable the proxy by clicking on the extension button, and pressing “Proxy by patterns” —
That variant uses the patterns that we just provided above.&lt;&#x2F;p&gt;
&lt;p&gt;After a browser restart for good measure (shouldn&#x27;t be needed usually), your proxy should be working! 🥳&lt;&#x2F;p&gt;
&lt;h2 id=&quot;android&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#android&quot; aria-label=&quot;Anchor link for: android&quot;&gt;android&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;It is the socks5 revelation that let me use my proxy on my &lt;em&gt;phone&lt;&#x2F;em&gt; too, while in the past I could only use it helpfully on my pc. &lt;br &#x2F;&gt;
We&#x27;re going to use an app called “Drony”. &lt;br &#x2F;&gt;
It&#x27;s not on play store, so simply google “drony apk” and pick your favorite sketchy website to download it from.&lt;&#x2F;p&gt;
&lt;p&gt;In the app, swipe right to get to settings, go to “not wi-fi (mobile, ethernet, …)”. &lt;br &#x2F;&gt;
Fill in the hostname, port, username, password; set “Proxy type” to “SOCKS5”. &lt;br &#x2F;&gt;
Go back, and now press on “Wi-fi”. &lt;br &#x2F;&gt;
If you don&#x27;t have any networks listed, you&#x27;re probably chill already.
Otherwise, pick the first one probably, and fill in the details exactly like above, again.&lt;&#x2F;p&gt;
&lt;p&gt;Go back twice and swipe left back to the log tab, and press the “Off” button so that it&#x27;s “On”. &lt;br &#x2F;&gt;
The proxy should now be working, globally, on your phone 🥳&lt;&#x2F;p&gt;
&lt;p&gt;After figuring this out, I have effectively doubled the value I get from my proxy for the price that I pay for it. &lt;br &#x2F;&gt;
2.67$ for my pc &lt;em&gt;and&lt;&#x2F;em&gt; phone? Insane!&lt;&#x2F;p&gt;
&lt;p&gt;I was really excited about how straightforward this solution is, and wanted to help out some russian that I know. &lt;br &#x2F;&gt;
Found a friend that was also doing the 5 vpns strat, and made them go through the setup process, using my proxy&#x27;s information. &lt;br &#x2F;&gt;
It worked perfectly!&lt;&#x2F;p&gt;
&lt;p&gt;Kinda strange, isn&#x27;t it? &lt;br &#x2F;&gt;
Usually, setting up something one &lt;em&gt;someone else&lt;&#x2F;em&gt;&#x27;s device is bound to not work in many strange ways, but this time everything just worked perfectly with no finagling. &lt;br &#x2F;&gt;
So it seems like it&#x27;s reproducible! :D&lt;&#x2F;p&gt;
&lt;p&gt;“Works on my machine”? Nah! “Works on &lt;em&gt;your&lt;&#x2F;em&gt; machine”.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;etc&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#etc&quot; aria-label=&quot;Anchor link for: etc&quot;&gt;etc&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now onto the more interesting to explain genre of proxiable things: “other”. &lt;br &#x2F;&gt;
I&#x27;m assuming you&#x27;re on linux, btw.&lt;&#x2F;p&gt;
&lt;p&gt;There are these three interesting environment variables: &lt;code&gt;http_proxy&lt;&#x2F;code&gt;, &lt;code&gt;https_proxy&lt;&#x2F;code&gt;, &lt;code&gt;all_proxy&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
One &#x2F; some &#x2F; all of them are understood by various apps, including but not limited to cli programs, to configure their proxy. &lt;br &#x2F;&gt;
Interestingly, they are indeed specified as lowercase, rather than uppercase, which is quite unusual for environment variables.&lt;&#x2F;p&gt;
&lt;p&gt;In my usage, I could never just stick to providing one of them, and for them to work, so the safest best is to provide all three. &lt;br &#x2F;&gt;
All of them use the &lt;code&gt;https:&#x2F;&#x2F;username:password@ip:port&lt;&#x2F;code&gt; syntax, so to launch some app with your proxy, you&#x27;d do something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;http_proxy=https:&#x2F;&#x2F;username:password@ip:port https_proxy=https:&#x2F;&#x2F;username:password@ip:port all_proxy=https:&#x2F;&#x2F;username:password@ip:port some-app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;m not 100% sure, but like 80% sure that you still can provide http&lt;em&gt;s&lt;&#x2F;em&gt; to the http_proxy variable, despite it seemingly expecting the proxy without TLS. &lt;br &#x2F;&gt;
Both &lt;code&gt;http_proxy&lt;&#x2F;code&gt; and &lt;code&gt;https_proxy&lt;&#x2F;code&gt; expect the &lt;em&gt;http&lt;&#x2F;em&gt; version of your proxy, rather than socks5; &lt;br &#x2F;&gt;
&lt;code&gt;all_proxy&lt;&#x2F;code&gt; doesn&#x27;t have such a restriction, so you can provide the socks5 version of your proxy with &lt;code&gt;socks5:&#x2F;&#x2F;username:password@ip:port&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But both of that, I believe, is a “usually” — &lt;code&gt;http_proxy&lt;&#x2F;code&gt; and &lt;code&gt;https_proxy&lt;&#x2F;code&gt; &lt;em&gt;might&lt;&#x2F;em&gt; allow socks5 in some apps, and sometimes &lt;code&gt;all_proxy&lt;&#x2F;code&gt; will not understand socks5.&lt;&#x2F;p&gt;
&lt;p&gt;All this “knowledge” is collected by me via experience and reading random stuff, so I&#x27;m very much farming corrections here :D &lt;br &#x2F;&gt;
Dm me on discord @Axlefublr or &lt;a href=&quot;mailto:axlefublr.ls@gmail.com&quot;&gt;email me&lt;&#x2F;a&gt; if I&#x27;m wrong on some things directly above, I&#x27;d love to learn!&lt;&#x2F;p&gt;
&lt;p&gt;The 3 variables you can quite easily expect to work in various networking-related cli programs, like &lt;code&gt;curl&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
But otherwise, their usefulness can be quite varied.&lt;&#x2F;p&gt;
&lt;p&gt;If a given program allows you to pass the proxy to it directly, via a flag or a config option or some such, &lt;em&gt;that&lt;&#x2F;em&gt; is much more likely to work. &lt;br &#x2F;&gt;
But the three &lt;del&gt;proxyteers&lt;&#x2F;del&gt; variables can potentially save your ass if you don&#x27;t seem to have a more “proper” way to provide a proxy, yet they (the vars) surprisingly work.&lt;&#x2F;p&gt;
&lt;p&gt;Now let&#x27;s talk about proxying something that &lt;em&gt;doesn&#x27;t&lt;&#x2F;em&gt; care about the proxyteers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;electron&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#electron&quot; aria-label=&quot;Anchor link for: electron&quot;&gt;electron&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Discord is an Electron app; &lt;br &#x2F;&gt;
I believe Electron doesn&#x27;t come pre-built with &lt;code&gt;(https?|all)_proxy&lt;&#x2F;code&gt; support,
so whether you can use the variables depends on the specific app. &lt;br &#x2F;&gt;
Well, for discord it doesn&#x27;t work at least, neither does it for vesktop.&lt;&#x2F;p&gt;
&lt;p&gt;However! I found a cool electron flag: &lt;code&gt;--proxy-server&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
&lt;em&gt;This&lt;&#x2F;em&gt; should be supported in &lt;em&gt;any&lt;&#x2F;em&gt; electron app, as I assume electron takes care of the networking things, including the proxy. &lt;br &#x2F;&gt;
It has an interesting limitation that we haven&#x27;t yet considered, though:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use a specified proxy server, which overrides the system setting. &lt;br &#x2F;&gt;
This switch only affects requests with HTTP protocol, including HTTPS and WebSocket requests. &lt;br &#x2F;&gt;
It is also noteworthy that not all proxy servers support HTTPS and WebSocket requests. &lt;br &#x2F;&gt;
The proxy URL does not support username and password authentication per Chromium issue.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Our proxy requires a username and password, so we can&#x27;t pass it directly into the flag, how we usually can. &lt;br &#x2F;&gt;
Electron not understanding username + password proxies might actually be the reason &lt;br &#x2F;&gt;
why &lt;code&gt;(https?|all)_proxy&lt;&#x2F;code&gt; don&#x27;t work —
maybe they actually do, just not when username and password are required.&lt;&#x2F;p&gt;
&lt;p&gt;To work around this, we need to somehow convert our proxy to a non-passworded one, so that we could just provide the hostname:port.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;privoxy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#privoxy&quot; aria-label=&quot;Anchor link for: privoxy&quot;&gt;privoxy&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;↑ is the program that will allow us to do that!&lt;&#x2F;p&gt;
&lt;p&gt;Really frequently, various programs that allow you to do fancy things with proxies are really fucking complicated to make work. &lt;br &#x2F;&gt;
How often have you heard “just use wireguard”? And yet I find it extremely overwhelming... &lt;br &#x2F;&gt;
So I was both quite surprised and happy that privoxy &lt;em&gt;isn&#x27;t&lt;&#x2F;em&gt; like that, and its setup was incredibly simple :D&lt;&#x2F;p&gt;
&lt;p&gt;First of all, install it of course.
On arch, it&#x27;s just &lt;code&gt;privoxy&lt;&#x2F;code&gt; in the repos. &lt;br &#x2F;&gt;
On not arch, I hope it&#x27;s also just as easily installable :3&lt;&#x2F;p&gt;
&lt;p&gt;The default config file is in &lt;code&gt;&#x2F;etc&#x2F;privoxy&#x2F;config&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Add the following at the absolute end of it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;forward-socks5 &#x2F; username:password@address:port .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With your &lt;em&gt;actual&lt;&#x2F;em&gt; username, password, ip address, and 🧦🧦🧦🧦🧦 port, of course.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s the entire config!! It&#x27;s literally that shrimple :&amp;gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can now enable the systemd service that should come with your installation, with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; systemctl enable --now privoxy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It will both start the privoxy service right &lt;em&gt;now&lt;&#x2F;em&gt;, &lt;strong&gt;and&lt;&#x2F;strong&gt; on subsequent logins. &lt;br &#x2F;&gt;
If you don&#x27;t have the systemd service for one reason or another, &lt;br &#x2F;&gt;
just run it yourself with &lt;code&gt;privoxy &#x2F;etc&#x2F;privoxy&#x2F;config&lt;&#x2F;code&gt; — it daemonizes by default anyway.&lt;&#x2F;p&gt;
&lt;p&gt;Right! I forgot to explain what it even does hehehehe&lt;&#x2F;p&gt;
&lt;p&gt;Basically, we&#x27;re starting a uhhhhh thingy on our local network, into which we can send requests. &lt;br &#x2F;&gt;
I think it&#x27;s not a lie to just call it a proxy? Yeah we&#x27;re starting a proxy locally I think! &lt;br &#x2F;&gt;
So this local proxy can accept requests, and &lt;em&gt;relays&lt;&#x2F;em&gt; them to our main, &lt;em&gt;actual&lt;&#x2F;em&gt; (and passworded) proxy. &lt;br &#x2F;&gt;
Meaning that we get to specify an address + port without needing to specify the username + password 🥳&lt;&#x2F;p&gt;
&lt;p&gt;The “information” of privoxy is &lt;code&gt;127.0.0.1&lt;&#x2F;code&gt; for the ip address, and &lt;code&gt;8118&lt;&#x2F;code&gt; for the port, by default. &lt;br &#x2F;&gt;
You can check if it&#x27;s actually working with this command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span&gt; --proxy http:&#x2F;&#x2F;127.0.0.1:8118 https:&#x2F;&#x2F;httpbin.org&#x2F;ip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It should 1. not infinitely hold and 2. show you information about your &lt;em&gt;actual&lt;&#x2F;em&gt; proxy !&lt;&#x2F;p&gt;
&lt;p&gt;Coming back to the discord situation, I was eventually able to run it with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;discord&lt;&#x2F;span&gt;&lt;span&gt; --proxy-server=127.0.0.1:8118&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which is so awesome! &lt;br &#x2F;&gt;
I&#x27;m surprised I was able to figure out so much in one day and &lt;em&gt;actually&lt;&#x2F;em&gt; make discord work, rather than giving up. &lt;br &#x2F;&gt;
The power of proxies seems to scale indefinitely, directly proportional to your networking skills; &lt;br &#x2F;&gt;
Slowly but surely, I seem to gain those, due to the consequences of this stupid ass war. &lt;br &#x2F;&gt;
Although I sure wish I didn&#x27;t have to do this out of requirement! lol&lt;&#x2F;p&gt;
&lt;h1 id=&quot;final-battle&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-battle&quot; aria-label=&quot;Anchor link for: final-battle&quot;&gt;final battle&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Now using the discord &lt;em&gt;app&lt;&#x2F;em&gt;, I start to type out some message sharing my excitement; &lt;br &#x2F;&gt;
But I get stopped when trying to use yet another “fancy quote” or 🤯 or ←↓↑→ — the horror! &lt;br &#x2F;&gt;
Discord doesn&#x27;t support &lt;code&gt;wtype&lt;&#x2F;code&gt;...&lt;&#x2F;p&gt;
&lt;p&gt;I have &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;erm&#x2F;&quot;&gt;a lot&lt;&#x2F;a&gt; of direct hotkeys to various symbols and emojis, and &lt;em&gt;all&lt;&#x2F;em&gt; of them use &lt;code&gt;wtype&lt;&#x2F;code&gt; to be entered. &lt;br &#x2F;&gt;
This is a really big deal to me, much more than ctrl+number hotkeys :(&lt;&#x2F;p&gt;
&lt;p&gt;A pretty obvious first idea is “it&#x27;s probably some wayland thing” — discord is probably running in xwayland mode unecessarily, so &lt;strong&gt;w&lt;&#x2F;strong&gt;type not working is not surprising. &lt;br &#x2F;&gt;
But funny thing is, discord &lt;em&gt;doesn&#x27;t&lt;&#x2F;em&gt; have a wayland version anyway! How the fuck did this happen lmao!&lt;&#x2F;p&gt;
&lt;p&gt;So I try to handle this by using vesktop instead 🧐 &lt;br &#x2F;&gt;
There, forcing wayland &lt;em&gt;is&lt;&#x2F;em&gt; actually a thing you can do, but no dice on the wtype issue anyway :c&lt;&#x2F;p&gt;
&lt;p&gt;Since there is no one singular way to force wayland for apps, I decided to just keep throwing shit at the wall until it worked. &lt;br &#x2F;&gt;
I started with the basic variables and flags, but at the end I ended up with this monstrosity:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MOZ_ENABLE_WAYLAND&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; NATIVE_WAYLAND&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; ELECTRON_OZONE_PLATFORM_HINT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;GDK_BACKEND=wayland QT_QPA_PLATFORM=wayland SDL_VIDEODRIVER=wayland&lt;&#x2F;span&gt;&lt;span style=&quot;color: #928374;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vesktop --proxy-server=127.0.0.1:8118 --ozone-platform-hint=wayland&lt;&#x2F;span&gt;&lt;span style=&quot;color: #928374;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--ozone-platform=wayland --enable-features=WaylandWindowDecorations&lt;&#x2F;span&gt;&lt;span style=&quot;color: #928374;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--enable-features=WebRTCPipeWireCapturer --enable-features=UseOzonePlatform --gtk-version=4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The shit, to everyone&#x27;s great surprise, did &lt;em&gt;not&lt;&#x2F;em&gt; work. How curious.&lt;&#x2F;p&gt;
&lt;p&gt;Actually, after I forced wayland (even the normal-er way), some hotkeys that &lt;em&gt;were&lt;&#x2F;em&gt; still somehow working, &lt;em&gt;stopped&lt;&#x2F;em&gt; working. &lt;br &#x2F;&gt;
By some wild magic, vesktop running in x11 mode supported &lt;em&gt;some&lt;&#x2F;em&gt; &lt;code&gt;wtype&lt;&#x2F;code&gt;s, but not most.
No clue what semantic it used, ngl. &lt;br &#x2F;&gt;
You&#x27;d think that &lt;strong&gt;w&lt;&#x2F;strong&gt;type would be better supported on &lt;strong&gt;w&lt;&#x2F;strong&gt;ayland, rather than x11, so that still throws me for a loop.&lt;&#x2F;p&gt;
&lt;p&gt;“Alright” I thought, &lt;br &#x2F;&gt;
“That&#x27;s not a very fruitful thought” the reader replied, &lt;br &#x2F;&gt;
— I&#x27;ll try webcord!&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d much rather be using vesktop; a lot of people I know praise it to heaven, and I&#x27;ve heard of webcord like once or twice. &lt;br &#x2F;&gt;
But honestly I just want my symbol hotkeys to work in a discord that is also a separate app, so I&#x27;ll take what I can get. &lt;br &#x2F;&gt;
Except, &lt;code&gt;wtype&lt;&#x2F;code&gt; doesn&#x27;t work there either :&#x2F;&lt;&#x2F;p&gt;
&lt;p&gt;I say &lt;code&gt;wtype&lt;&#x2F;code&gt;, but this isn&#x27;t really program-specific! &lt;br &#x2F;&gt;
There&#x27;s this global linux hotkey &lt;kbd&gt;ctrl+shift+u&lt;&#x2F;kbd&gt;, that allows you to type in a symbol&#x27;s unicode, and replaces your input with the actual symbol. &lt;br &#x2F;&gt;
&lt;code&gt;wtype&lt;&#x2F;code&gt; uses the same mechanism for inserting the symbol, just skips the unicode input step.&lt;&#x2F;p&gt;
&lt;p&gt;This hotkey is really neat actually! &lt;br &#x2F;&gt;
I used to memorize unicodes and enter symbols directly using it, in the past 🤓 &lt;br &#x2F;&gt;
This was back on x11, where &lt;code&gt;xdotool type&lt;&#x2F;code&gt; was incredibly slow for me for whatever reason; so take note that the existence of the hotkey is not even wayland-specific!&lt;&#x2F;p&gt;
&lt;p&gt;The downside of it, as we now see, is that it doesn&#x27;t work in &lt;em&gt;some&lt;&#x2F;em&gt; (incredibly rare) apps. &lt;br &#x2F;&gt;
Anki is one example, but I can easily forgo being able to use my symbol hotkeys there, as I use my own card adding solution anyway, that allows me to use helix instead. &lt;br &#x2F;&gt;
But a &lt;em&gt;chat&lt;&#x2F;em&gt; app?...&lt;&#x2F;p&gt;
&lt;p&gt;Conclusion: there is no way (yes, dear reader, I&#x27;m baiting you to potentially solve my entire problem if you happen to know how) to make wtype work on any discord apps that are worth using. &lt;br &#x2F;&gt;
This is a massive dealbreaker for me, soooo I guess I&#x27;m sticking with web discord?&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;d think I&#x27;m saying “aw dang” right about now, but actually I&#x27;m not that sad about how this adventure turned out! &lt;br &#x2F;&gt;
Sure, I end up without app discord, but in return I learned &lt;br &#x2F;&gt;
the difference between https and socks5 proxies, &lt;br &#x2F;&gt;
the fact that my proxy is &lt;em&gt;also&lt;&#x2F;em&gt; a socks5 one, &lt;br &#x2F;&gt;
how I can make use of socks5 to make the proxy more powerful,
&lt;em&gt;&lt;strong&gt;and&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; work on mobile, &lt;br &#x2F;&gt;
helped a friend cave out of the same awful vpn situation, &lt;br &#x2F;&gt;
and learned how to strip my proxy off of its username + password, &lt;br &#x2F;&gt;
including now being able to proxy &lt;em&gt;any&lt;&#x2F;em&gt; electron applications, &lt;br &#x2F;&gt;
oh and I fixed spotify btw :D using the privoxy trick once again.&lt;&#x2F;p&gt;
&lt;p&gt;Similar to my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;my-usb-drive-experience&#x2F;&quot;&gt;other journeys&lt;&#x2F;a&gt;, the reward of &lt;em&gt;knowledge&lt;&#x2F;em&gt; is much more valuable than the &lt;em&gt;practicality&lt;&#x2F;em&gt; of the result. &lt;br &#x2F;&gt;
Hell, I could conceivably sell my knowledge to normies, helping them set up a proxy! &lt;br &#x2F;&gt;
Is that a &lt;em&gt;job&lt;&#x2F;em&gt; I&#x27;m thinking about? 🤯&lt;&#x2F;p&gt;
&lt;p&gt;Considering the sheer price difference between a vpn, as well as (usually) much better performance, setting up a proxy for someone is a genuine service that will end up saving them money in the long term 🤔 something to think about :&amp;gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;footnotes&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-1&quot; id=&quot;footnote-1&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 I found this analogy hilarious more than anything, don&#x27;t take it too seriously :D&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-2&quot; id=&quot;footnote-2&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 До сих пор злюсь немного на их ребрендинг. &lt;br &#x2F;&gt;
Какой нахуй Т-банк?? Тинькофф звучит намного более приятно.... &lt;br &#x2F;&gt;
Это как твиттер → х. &lt;br &#x2F;&gt;
Х блять!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-3&quot; id=&quot;footnote-3&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 Благодаря чему эта, казалось бы рисковая, операция, на самом деле безопасная!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-4&quot; id=&quot;footnote-4&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;4&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 These are all example values; the “information”s of your proxy will be different, but are going to &lt;em&gt;look&lt;&#x2F;em&gt; about the same, so this serves as a reference.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-5&quot; id=&quot;footnote-5&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;5&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 Sheer guess.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-6&quot; id=&quot;footnote-6&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;6&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 The wrong spelling is tribute to my friend skoove :3 &lt;br &#x2F;&gt;
It&#x27;s one of her cutest misspellings&lt;&#x2F;p&gt;
&lt;p&gt;Am I overusing footnotes? &lt;br &#x2F;&gt;
I feel that you being able to jump &lt;em&gt;back&lt;&#x2F;em&gt; easily makes me spam them a lot more strongly than I should otherwise hahaha&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-7&quot; id=&quot;footnote-7&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;7&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 Reference to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@ChuckleSandwich&quot;&gt;Chuckle Sandwich&lt;&#x2F;a&gt;, while mentioning my puppygirl partner at the same time.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>harp</title>
          <pubDate>Sun, 20 Jul 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/harp/</link>
          <guid>https://axlefublr.github.io/harp/</guid>
          <description xml:base="https://axlefublr.github.io/harp/">&lt;p&gt;Travelling to files in text editors is very slow at best.&lt;&#x2F;p&gt;
&lt;p&gt;There are four main ways to travel to a file from your text editor. Let&#x27;s discuss them.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;fuzzy-picker&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fuzzy-picker&quot; aria-label=&quot;Anchor link for: fuzzy-picker&quot;&gt;fuzzy picker&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Your telescope, or snacks file picker; your helix file picker. Your vscode &lt;kbd&gt;ctrl+p&lt;&#x2F;kbd&gt; fuzzy file picker, even. The classic.&lt;&#x2F;p&gt;
&lt;p&gt;You search through a list of all files in the current directory, using a fuzzy search algorithm — you can type &lt;code&gt;aaa&lt;&#x2F;code&gt; and it will match &lt;code&gt;banana&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This approch is what neovim users claim to be the silver bullet to file traversal. Something that &lt;em&gt;solves&lt;&#x2F;em&gt; travelling between files quickly and efficiently. &lt;br &#x2F;&gt;
“I can get to any file in just a few keystrokes!” is a notion I reject categorically. &lt;br &#x2F;&gt;
Efficient fuzzy searching is non-intuitive; it&#x27;s something you actively learn to do.&lt;&#x2F;p&gt;
&lt;p&gt;Think of lsp suggestions. Say you want to complete a function with a really long name: &lt;code&gt;here_is_my_longly_named_function&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
The efficient approach to matching it is probably going to be &lt;code&gt;himlnf&lt;&#x2F;code&gt; — type in the first letter of each subword, to almost guarantee that it will be the first match. &lt;br &#x2F;&gt;
Let&#x27;s not kid ourselves; this is not intuitive. &lt;br &#x2F;&gt;
Despite me knowing the &lt;code&gt;himlnf&lt;&#x2F;code&gt; trick, I&#x27;ll still &lt;em&gt;naturally&lt;&#x2F;em&gt; start typing &lt;code&gt;here_…&lt;&#x2F;code&gt;, and then complete the name of the function once it appears in my lsp suggestions. &lt;br &#x2F;&gt;
Fuzzy lsp suggestion matching is something I have to make the &lt;em&gt;active decision&lt;&#x2F;em&gt; to do. Or perhaps, something that I would have to &lt;em&gt;train&lt;&#x2F;em&gt; myself to always do. I don&#x27;t think I&#x27;m alone in this.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not saying fuzzy matching is &lt;em&gt;bad&lt;&#x2F;em&gt;. Hell no! I&#x27;ll pick fuzzy matching almost always over substring matching. &lt;br &#x2F;&gt;
But this is not my point. My point is that &lt;em&gt;efficient&lt;&#x2F;em&gt; fuzzy matching spends mental cycles; in most cases what you&#x27;ll end up doing is just typing in a substring rather than a heavily optimized fuzzy matcher.&lt;&#x2F;p&gt;
&lt;p&gt;Coming back to the fuzzy file picker. &lt;br &#x2F;&gt;
Most files in a project you probably don&#x27;t have to visit often, so simply using a substring is no big deal. &lt;br &#x2F;&gt;
But there will be some files you interact with over and over again, where using simply a substring over and over again will become very painful. &lt;br &#x2F;&gt;
And &lt;em&gt;that&#x27;s&lt;&#x2F;em&gt; where you decide to put in the extra mental effort, and figure out an efficient enough, and nice-to-type enough fuzzy matcher.&lt;&#x2F;p&gt;
&lt;p&gt;“I can get to any file in just a few keystrokes!” — this is where we disagree: my definition of &quot;few&quot; and your definition of &quot;few&quot; seems to be quite different. &lt;br &#x2F;&gt;
Or rather, if &quot;few&quot; is to be taken literally, that&#x27;s an unacceptable cost to me.&lt;&#x2F;p&gt;
&lt;p&gt;From experience of coming up with these good fuzzy matching strings, they tend to be 4-5 characters. &lt;br &#x2F;&gt;
We add in the extra 2 keys pressed to invoke the picker to begin with, and pressing &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt; to accept the result. &lt;br &#x2F;&gt;
That is 7-9 keys pressed to get to a single file. SEVEN TO NINE ENTIRE KEYS.&lt;&#x2F;p&gt;
&lt;p&gt;Alright fair enough, mister seven-to-nine keys man (what a weird nickname you have, too), I don&#x27;t mean to yuck your yum. &lt;br &#x2F;&gt;
You got your perfect sequence of keys to press to get to a specific file, and now you&#x27;re golden. &lt;br &#x2F;&gt;
Sure, it&#x27;s kinda a lot of keys to press, but you got it in your muscle memory now, and you&#x27;re super quick at entering those now!&lt;&#x2F;p&gt;
&lt;p&gt;Until tragedy befalls you… You create a new file 😨 What horror! &lt;br &#x2F;&gt;
And now it&#x27;s &lt;em&gt;that&lt;&#x2F;em&gt; file that appears first in the result list, after entering your perfect fuzzy matcher, &lt;br &#x2F;&gt;
rather than the file that you were aiming for!&lt;&#x2F;p&gt;
&lt;p&gt;And now you sheepishly refine the query you got so used to, to match the old file correctly again. &lt;br &#x2F;&gt;
You might&#x27;ve needed to add one or two extra keys to press for the query, too. &lt;br &#x2F;&gt;
And the scariest part? In the future, this may happen again… &lt;br &#x2F;&gt;
Worse yet, there will be files that you are &lt;strong&gt;unable&lt;&#x2F;strong&gt; to place as the first result, making you always have to press &lt;kbd&gt;Down&lt;&#x2F;kbd&gt; or &lt;kbd&gt;ctrl+p&lt;&#x2F;kbd&gt; or what have you.&lt;&#x2F;p&gt;
&lt;p&gt;Obviously I&#x27;m being dramatic here, but this both conveys my point and is probably fun for you to read :) &lt;br &#x2F;&gt;
Fuzzy searching to travel across files you travel to &lt;em&gt;really really&lt;&#x2F;em&gt; frequently is both inefficient &lt;em&gt;and&lt;&#x2F;em&gt; inconsistent. Reasonable enough for rare files though.&lt;&#x2F;p&gt;
&lt;p&gt;Aside from the optimal query being &lt;em&gt;long&lt;&#x2F;em&gt;, it has a pretty big chance to not be enjoyable to type in anyway. &lt;br &#x2F;&gt;
It&#x27;s common that file structures of projects are made in such a way, that you end up needing to match really annoying paths. &lt;br &#x2F;&gt;
And you can&#x27;t exactly optimize your file structure to fit the fuzzying need; at least not for every project.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;file-explorers&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#file-explorers&quot; aria-label=&quot;Anchor link for: file-explorers&quot;&gt;file explorers&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;File trees, or file lists, like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;stevearc&#x2F;oil.nvim&quot;&gt;oil.nvim&lt;&#x2F;a&gt; (my beloved) — UI that presents the files visually, and tends to allow you to do file operations, like creating new files, deleting them, renaming them, etc, but also &lt;em&gt;opening&lt;&#x2F;em&gt; them.&lt;&#x2F;p&gt;
&lt;p&gt;Where these shine is &lt;em&gt;file operations&lt;&#x2F;em&gt;, rather than being a fast way to &lt;em&gt;get&lt;&#x2F;em&gt; to some file. &lt;br &#x2F;&gt;
“Open file tree in the parent directory of the current buffer” very much comes in handy to jump between multiple closely related files. &lt;br &#x2F;&gt;
Also, using a tree &#x2F; file list helps to get a better grasp of the overall project structure; something that&#x27;s hard to do with a fuzzy file picker.&lt;&#x2F;p&gt;
&lt;p&gt;But actually ←↓↑→ing through directories and files to jump to some file is of course inefficient — it&#x27;s more so something you do when you aren&#x27;t sure what file you even want. &lt;br &#x2F;&gt;
In other words, file explorers are good, but for other usecases; not for fast and efficient file traversal.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;lsp-actions&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#lsp-actions&quot; aria-label=&quot;Anchor link for: lsp-actions&quot;&gt;lsp actions&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Go to: definition, declaration, type definition, implementation; Open fuzzy picker for: symbols in the current buffer, the entire project, outgoing calls, incoming calls, references.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;del&gt;All&lt;&#x2F;del&gt; most of those are instrumental for a normal dev workflow, and of course I use them actively.&lt;&#x2F;p&gt;
&lt;p&gt;But the reason why they don&#x27;t solve the entire question completely, is because they are all lsp reliant. &lt;br &#x2F;&gt;
You have to have an lsp for the given language, and set up to actually work; also, it needs to implement the above lsp actions. &lt;br &#x2F;&gt;
Then, your &lt;em&gt;editor&lt;&#x2F;em&gt; needs to be able to interpret them, too (helix doesn&#x27;t have incoming&#x2F;outgoing calls, for example).&lt;&#x2F;p&gt;
&lt;p&gt;And even after all of that, lsp tends to take quite some time to start up. &lt;br &#x2F;&gt;
In rust, especially, by the time the lsp gives you the ability to use its actions, you probably would&#x27;ve already travelled to the file and place that you wanted to get to, by using any combination of the other methods.&lt;&#x2F;p&gt;
&lt;p&gt;Once the lsp is started up and working, the usecase question still exists: you don&#x27;t always want to jump to a type, or function, or a part of the source code, even. &lt;br &#x2F;&gt;
For its intended usecase, lsp actions are very helpful and powerful, but definitely not a generic cure for every usecase.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;edit-command&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#edit-command&quot; aria-label=&quot;Anchor link for: edit-command&quot;&gt;:edit command&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;code&gt;:edit&lt;&#x2F;code&gt; in neovim, &lt;code&gt;:open&lt;&#x2F;code&gt; in helix; basically, opening a file by typing in its relative (or full) path directly.&lt;&#x2F;p&gt;
&lt;p&gt;The big part of this method is the existence of &lt;kbd&gt;Tab&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Say you want to complete the path &lt;code&gt;~&#x2F;programming&#x2F;dotfiles&#x2F;colors.css&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
You start typing &lt;code&gt;~&#x2F;p&lt;&#x2F;code&gt; and press &lt;kbd&gt;Tab&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
In your home directory, you also have directory &lt;code&gt;progesterone&lt;&#x2F;code&gt;, so you get shown both results; &lt;br &#x2F;&gt;
Pressing &lt;kbd&gt;Tab&lt;&#x2F;kbd&gt; once accepts &lt;code&gt;progesterone&lt;&#x2F;code&gt;, pressing it twice will accept &lt;code&gt;programming&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Basically, you have to rotate through the results.&lt;&#x2F;p&gt;
&lt;p&gt;However, if you typed &lt;code&gt;~&#x2F;progr&lt;&#x2F;code&gt; and pressed &lt;kbd&gt;Tab&lt;&#x2F;kbd&gt;, now you &lt;em&gt;don&#x27;t&lt;&#x2F;em&gt; have to choose: there is only one valid match for the substring &lt;code&gt;progr&lt;&#x2F;code&gt;! And it&#x27;s &lt;code&gt;programming&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
So, to complete the path &lt;code&gt;~&#x2F;programming&#x2F;dotfiles&#x2F;colors.css&lt;&#x2F;code&gt; most efficiently, I&#x27;d type &lt;code&gt;~&#x2F;progr&amp;lt;Tab&amp;gt;&#x2F;d&amp;lt;Tab&amp;gt;&#x2F;colo&amp;lt;Tab&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can pretty quickly realize how it&#x27;s beneficial for a path to become unique quickly; &lt;code&gt;Downloads&lt;&#x2F;code&gt; and &lt;code&gt;Documents&lt;&#x2F;code&gt; both existing make me kinda mad for this reason. &lt;br &#x2F;&gt;
While you can &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;optimizing-paths&#x2F;&quot;&gt;optimize directory names&lt;&#x2F;a&gt; like &lt;code&gt;Downloads&lt;&#x2F;code&gt;, &lt;code&gt;Documents&lt;&#x2F;code&gt;, etc to be faster and easier to tab complete (or type in), there will ultimately be some directories that you cannot &#x2F; should not optimize, like &lt;code&gt;~&#x2F;.config&lt;&#x2F;code&gt;, &lt;code&gt;~&#x2F;.local&#x2F;share&lt;&#x2F;code&gt;, &lt;code&gt;~&#x2F;.cache&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
They unfortunately also carry wonderful semantics, that make a lot of sense to make use of. And of course, they are used by all of your programs! But getting to them is a pain! :c&lt;&#x2F;p&gt;
&lt;p&gt;With perfect fuzzy queries, you at least have a bit more space to move around in. &lt;br &#x2F;&gt;
With tab completing a path, you need to complete each part of the path separately, rather than being able to match the entirety of the full path with some perfect fuzzy query. &lt;br &#x2F;&gt;
Considering that it&#x27;s not often that tab completing supports fuzzy matching, it makes the most sense to get used to (and internalize) perfect tab queries for the paths you might want to travel to often.&lt;&#x2F;p&gt;
&lt;p&gt;Why even use this method ever? &lt;br &#x2F;&gt;
Fuzzy matching file pickers generally open within your current working directory, and if you&#x27;re in &lt;code&gt;~&#x2F;fes&#x2F;dot&lt;&#x2F;code&gt; rather than &lt;code&gt;~&#x2F;.config&lt;&#x2F;code&gt;, you won&#x27;t be able to pick a file that&#x27;s in &lt;code&gt;~&#x2F;.config&lt;&#x2F;code&gt;. So that&#x27;s the main reason you&#x27;d ever use &lt;code&gt;:edit&lt;&#x2F;code&gt; over fuzzy picking. &lt;br &#x2F;&gt;
Once again, this solution is not the bees knees; matter of fact, it might be the absolute worst approach, depending on how you look at it! :»&lt;&#x2F;p&gt;
&lt;h1 id=&quot;bookmarking&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#bookmarking&quot; aria-label=&quot;Anchor link for: bookmarking&quot;&gt;bookmarking&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;As you find pathing pain points, you might be led towards a certain idea.&lt;&#x2F;p&gt;
&lt;p&gt;You find yourself editing some specific config file over and over again; &lt;br &#x2F;&gt;
&lt;code&gt;cd&lt;&#x2F;code&gt;ing into some same directory. &lt;br &#x2F;&gt;
So you decide to make a mapping in your editor to open that file, &lt;br &#x2F;&gt;
And an alias in your shell to &lt;code&gt;cd&lt;&#x2F;code&gt; to the directory.&lt;&#x2F;p&gt;
&lt;p&gt;Yay! Now a pain point is gone :» &lt;br &#x2F;&gt;
You can navigate to things you navigate to often, quicker and more comfortably. &lt;br &#x2F;&gt;
But there&#x27;s an issue: this method doesn&#x27;t scale that well.&lt;&#x2F;p&gt;
&lt;p&gt;First, you start with having aliases for &lt;code&gt;~&#x2F;.config&lt;&#x2F;code&gt;, &lt;code&gt;~&#x2F;.local&#x2F;share&lt;&#x2F;code&gt;, &lt;code&gt;~&#x2F;.cache&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
All directories that you will for sure be jumping to over and over again. &lt;br &#x2F;&gt;
But then you suddenly realize you need to jump to a directory &lt;code&gt;~&#x2F;.local&#x2F;share&#x2F;Steam&#x2F;steamapps&#x2F;common&#x2F;Enter the Gungeon&#x2F;mods&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Navigating into your config (which you have on a mapping, let&#x27;s say), finding the new place where you&#x27;d like to add the alias (&lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;consider-sorting&#x2F;&quot;&gt;unless that&#x27;s not a problem for you&lt;&#x2F;a&gt;), and typing in that path + the syntax for making an alias is undeniably a bit of a workflow break. &lt;br &#x2F;&gt;
It is something you stop to do, and at best will spend 20 seconds on. Then “wait, what was I doing again? ah right”. I experienced this many times.&lt;&#x2F;p&gt;
&lt;p&gt;So you might be led to making some hotkey that creates an alias for you, and also adds it to your configuration. But while that solves the stoppage issue, it has another one.&lt;&#x2F;p&gt;
&lt;p&gt;You create an alias for that enter the gungeon mods directory, and after some time you realize you don&#x27;t play the game anymore, and haven&#x27;t been using its alias for a long time. &lt;br &#x2F;&gt;
This alias indeed used to be quite a useful one, but now it&#x27;s just trash in your shell configuration; something that you need to scroll through &#x2F; think through when doing something unrelated. Unclean.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;solution&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#solution&quot; aria-label=&quot;Anchor link for: solution&quot;&gt;solution&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I created a bookmarking system, where I both “get” and “set” the data interactively, on a hotkey, and therefore don&#x27;t experience any stoppages. &lt;br &#x2F;&gt;
The name of each bookmark is simply a &lt;em&gt;key&lt;&#x2F;em&gt; that I press, rather than a name I have to type out. &lt;br &#x2F;&gt;
All of these bookmarks are kept in a json file, so that I can easily back them up, and so the same bookmarks could be reused in multiple different programs for possibly different purposes, and different contexts.&lt;&#x2F;p&gt;
&lt;p&gt;This is how the program &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;harp&quot;&gt;harp&lt;&#x2F;a&gt; came to life.&lt;&#x2F;p&gt;
&lt;p&gt;There are multiple concepts that harp the idea (rather than harp the program) brings to the table.&lt;&#x2F;p&gt;
&lt;p&gt;First, I need to be able to store multiple separate sets of bookmarks (a bookmark is called a “harp”): in our beginner example, I want a set of harps which stores file paths, and another set of harps that stores directory paths. &lt;br &#x2F;&gt;
To accomodate this, harp has “sections”. A section is a namespace, that isolates a set of harps, so that they don&#x27;t conflict with other sets of harps. &lt;br &#x2F;&gt;
So I may have a harp section named &lt;code&gt;harp_files&lt;&#x2F;code&gt; that will store file paths, and another harp section named &lt;code&gt;harp_dirs&lt;&#x2F;code&gt; that will store directory paths.&lt;&#x2F;p&gt;
&lt;p&gt;Next, I mentioned that a given harp (bookmark) is named via me pressing some key. I have a harp &lt;code&gt;a&lt;&#x2F;code&gt;, a harp &lt;code&gt;f&lt;&#x2F;code&gt;, a harp &lt;code&gt;ctrl+j&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
These harp keys &#x2F; names are called “registers”. &lt;br &#x2F;&gt;
You can think of vim registers, that you access via &lt;code&gt;&quot;a&lt;&#x2F;code&gt; — harp registers are a very similar idea. &lt;br &#x2F;&gt;
Under each register, we hold some data. &lt;br &#x2F;&gt;
So, file path harp &lt;code&gt;a&lt;&#x2F;code&gt; may store the path &lt;code&gt;~&#x2F;fes&#x2F;dot&#x2F;colors.css&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Directory harp &lt;code&gt;alt+k&lt;&#x2F;code&gt; may store the path &lt;code&gt;~&#x2F;fes&#x2F;lai&#x2F;bog&lt;&#x2F;code&gt;&lt;a href=&quot;#footnote-1&quot; id=&quot;headnote-1&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
. &lt;br &#x2F;&gt;
The data of a register is called a “harp”.&lt;&#x2F;p&gt;
&lt;p&gt;Since registers are simply keys that I press, they can start to collide pretty quick: &lt;br &#x2F;&gt;
&lt;em&gt;this&lt;&#x2F;em&gt; is why we have sections to separate the sets of registers — I can simultenously have a file harp &lt;code&gt;a&lt;&#x2F;code&gt;, and a directory harp &lt;code&gt;a&lt;&#x2F;code&gt;, and they won&#x27;t conflict.&lt;&#x2F;p&gt;
&lt;p&gt;To accomodate this entire idea, I would need to interact with a &lt;code&gt;HashMap&amp;lt;HashMap&amp;lt;String, Vec&amp;lt;String&amp;gt;&amp;gt;&amp;gt;&lt;&#x2F;code&gt; in every program that I want to implement harp in. &lt;br &#x2F;&gt;
I would also need to interact with the json file that actually holds this data, deserializing it into the program, and then serializing it again. &lt;br &#x2F;&gt;
This is quite doable in some programs, but completely impossible in others; &lt;br &#x2F;&gt;
That&#x27;s where harp &lt;em&gt;the program&lt;&#x2F;em&gt; comes into play: it&#x27;s a single, simple interface to interact with harps.&lt;&#x2F;p&gt;
&lt;p&gt;In most places, I simply use &lt;code&gt;harp&lt;&#x2F;code&gt; as an external shell command, to either supply data, or get data from stdout of. &lt;br &#x2F;&gt;
In other cases where I&#x27;m editing the rust source code, I can use &lt;code&gt;harp&lt;&#x2F;code&gt; as a library. &lt;br &#x2F;&gt;
This ends up making it &lt;em&gt;much&lt;&#x2F;em&gt; simpler and faster to integrate harp into a given program, as all the boilerplate steps are taken care of for me by &lt;code&gt;harp&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;harp-actions&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#harp-actions&quot; aria-label=&quot;Anchor link for: harp-actions&quot;&gt;harp actions&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s start looking into what a harp implementation ends up looking like on a more practical scale, now that we have the main concepts understood. &lt;br &#x2F;&gt;
I&#x27;ll be showcasing the harp implementation I have in my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;helix fork&lt;&#x2F;a&gt;, but the ideas are quite flexible and can be implemented into other editors and various programs.&lt;&#x2F;p&gt;
&lt;p&gt;The main idea of how harp is practically useful is via “harp action”s. &lt;br &#x2F;&gt;
Each harp action has a “set” and a “get” method. &lt;br &#x2F;&gt;
“set” takes some data from the environment, and stores it. &lt;br &#x2F;&gt;
“get” retrieves that stored data, and uses it somehow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;file-harps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#file-harps&quot; aria-label=&quot;Anchor link for: file-harps&quot;&gt;file harps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The most basic harp action, the one that started it all: file harps. &lt;br &#x2F;&gt;
File harp &lt;em&gt;set&lt;&#x2F;em&gt; takes the filepath of the current buffer, and stores it. &lt;br &#x2F;&gt;
File harp &lt;em&gt;get&lt;&#x2F;em&gt; retrieves the stored path, and &lt;em&gt;opens&lt;&#x2F;em&gt; it in the editor.&lt;&#x2F;p&gt;
&lt;p&gt;Even just this is flabbergastingly powerful. &lt;br &#x2F;&gt;
All of your various offshoot config files that you want to jump to frequently? &lt;br &#x2F;&gt;
Set file harps for them, and now you can get to them incredibly quickly.&lt;&#x2F;p&gt;
&lt;p&gt;Most of what I do is edit config files… So I use this a &lt;em&gt;lot&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
I have file harps bound on &lt;kbd&gt;space+s&lt;&#x2F;kbd&gt;, so to get to all of my most wanted files, I only need to press three keys. &lt;br &#x2F;&gt;
Helix config — &lt;kbd&gt;space+s+c&lt;&#x2F;kbd&gt; &lt;br &#x2F;&gt;
Foot config (what a strange combination of words) — &lt;kbd&gt;space+s+f&lt;&#x2F;kbd&gt; &lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;eli&#x2F;setup&#x2F;dode.fish&quot;&gt;Program setups&lt;&#x2F;a&gt; — &lt;kbd&gt;space+s+d&lt;&#x2F;kbd&gt;; yada yada etc etc.&lt;&#x2F;p&gt;
&lt;p&gt;Now, how did I &lt;em&gt;set&lt;&#x2F;em&gt; all of those harps? &lt;br &#x2F;&gt;
&lt;kbd&gt;space+S&lt;&#x2F;kbd&gt; is my file harp &lt;em&gt;set&lt;&#x2F;em&gt; hotkey! pretty natural, right? :3 &lt;br &#x2F;&gt;
I get to the file that I want to mark, and press &lt;kbd&gt;space+S+some_key&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
Similar to how the get action interactively asks me for a key to press, the set action does too.&lt;&#x2F;p&gt;
&lt;p&gt;Immediately as I realize I want to access the same file over and over again, I set a harp for it on the fly, and just continue on: I don&#x27;t need to divert myself into some config file, I just press a key!&lt;&#x2F;p&gt;
&lt;a href=&quot;#why-config&quot; id=&quot;why-config&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I strangely specify “config files”; there&#x27;s nothing about file harps that enforces you to use them only for config files though! &lt;br &#x2F;&gt;
Why did I choose that wording?&lt;&#x2F;p&gt;
&lt;p&gt;You will set file harps for the files that you visit the most often, as I mentioned. &lt;br &#x2F;&gt;
When coming up with a harp you&#x27;ll like using for a file, you go through an interesting process.&lt;&#x2F;p&gt;
&lt;p&gt;Say I want to make a harp for my helix config. &lt;br &#x2F;&gt;
I access it so often that I don&#x27;t want to press &lt;kbd&gt;h&lt;&#x2F;kbd&gt; for it, which would be the most obvious key to pick. &lt;br &#x2F;&gt;
&lt;kbd&gt;c&lt;&#x2F;kbd&gt; feels quite comfortable to press, so I&#x27;ll go with that.&lt;&#x2F;p&gt;
&lt;p&gt;I have a file where I store various &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;colors.css&quot;&gt;colors I use often&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
The obvious harp key for it is &lt;kbd&gt;c&lt;&#x2F;kbd&gt;, but it&#x27;s already taken by my helix config! &lt;br &#x2F;&gt;
I could of course just move the helix config to somewhere else, but I don&#x27;t want to: it&#x27;s far more important and common than going to my colors file. &lt;br &#x2F;&gt;
Next idea is to put the colors file at capital &lt;kbd&gt;C&lt;&#x2F;kbd&gt;, but whoops! It&#x27;s already taken by my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;how-to-anki&#x2F;&quot;&gt;anki&lt;&#x2F;a&gt; css file. &lt;em&gt;That&lt;&#x2F;em&gt; one I could reasonably move as it&#x27;s not particularly important, but I decide I don&#x27;t wanna bother right now, &lt;br &#x2F;&gt;
and arrive at &lt;kbd&gt;ctrl+c&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Because of &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;erm&#x2F;&quot;&gt;home row mods&lt;&#x2F;a&gt;, it&#x27;s actually still quite convenient to press for me, so it&#x27;s still a good harp key. &lt;br &#x2F;&gt;
But you can probably see how, as you harp more and more files, you&#x27;ll end up making bigger and bigger compromises with yourself, coming up with less and less memorable harps, which ends up in you underusing them — you&#x27;re never quite sure what that one harp was for that one file, because it&#x27;s &lt;kbd&gt;ctrl+alt+y&lt;&#x2F;kbd&gt; or some shit at this point.&lt;&#x2F;p&gt;
&lt;p&gt;This poor scalability is the reason why I specify “config files” — within this scope, I absolutely have more than enough potential nice harps to use, and don&#x27;t have to get to the &lt;kbd&gt;ctrl+alt+y&lt;&#x2F;kbd&gt; point (unless it specifically makes sense for some given file). &lt;br &#x2F;&gt;
But this poor scalability is what will make it unpleasant &#x2F; unlikely &#x2F; unreasonable to use harps for temporary-ish files, like files in some project you&#x27;re working on.&lt;&#x2F;p&gt;
&lt;p&gt;Now this is the part where you&#x27;ll shit you&#x27;re pants. I solved this.&lt;&#x2F;p&gt;
&lt;p&gt;I present to you the next harp concept 🗣️✍️🔥:&lt;&#x2F;p&gt;
&lt;h1 id=&quot;relativity&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#relativity&quot; aria-label=&quot;Anchor link for: relativity&quot;&gt;relativity&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The default harp relativity is “global” — it&#x27;s not relative to anything and the sections used for the harp actions are also normal: &lt;code&gt;harp_files&lt;&#x2F;code&gt;, &lt;code&gt;harp_dirs&lt;&#x2F;code&gt;, etc. &lt;br &#x2F;&gt;
When you set a global harp, you&#x27;ll be able to get to it no matter where you are. &lt;br &#x2F;&gt;
This is the default behavior for all harp actions.&lt;&#x2F;p&gt;
&lt;p&gt;But other relativities, aside from “global”, work in a different way. &lt;br &#x2F;&gt;
They limit the &lt;em&gt;scope&lt;&#x2F;em&gt; of your reach depending on some context from your editor.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s learn with an example. &lt;br &#x2F;&gt;
Say I&#x27;m working on my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;helix fork&lt;&#x2F;a&gt;, and noticed a file that I want to harp: &lt;code&gt;helix-term&#x2F;src&#x2F;commands.rs&lt;&#x2F;code&gt; &lt;br &#x2F;&gt;
The obvious harp key that comes to mind is &lt;kbd&gt;c&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
But as you&#x27;ve now seen above, all of &lt;kbd&gt;c&lt;&#x2F;kbd&gt;, &lt;kbd&gt;C&lt;&#x2F;kbd&gt; and even &lt;kbd&gt;ctrl+c&lt;&#x2F;kbd&gt; are already taken; &lt;br &#x2F;&gt;
And I sure as hell don&#x27;t want to use &lt;kbd&gt;alt+c&lt;&#x2F;kbd&gt; for this.&lt;&#x2F;p&gt;
&lt;p&gt;The “directory” relativity comes to the rescue! &lt;br &#x2F;&gt;
Rather than using the global &lt;code&gt;harp_files&lt;&#x2F;code&gt; section, the directory relativity creates a new section by using your current working directory. &lt;br &#x2F;&gt;
I store my helix fork at path &lt;code&gt;~&#x2F;fes&#x2F;ork&#x2F;hx&lt;&#x2F;code&gt;, and when I open the editor to work on the editor (lol), &lt;br &#x2F;&gt;
&lt;code&gt;~&#x2F;fes&#x2F;ork&#x2F;hx&lt;&#x2F;code&gt; &lt;em&gt;also&lt;&#x2F;em&gt; becomes the current working directory of &lt;em&gt;helix&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
&lt;strong&gt;That&lt;&#x2F;strong&gt; is what&#x27;s used by the directory relativity, and you end up using the section &lt;code&gt;harp_files_~&#x2F;fes&#x2F;ork&#x2F;hx&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Notice how the path to the current working directory became a part of the section name! &lt;br &#x2F;&gt;
This is how all relativities are implemented :3&lt;&#x2F;p&gt;
&lt;p&gt;What this actually &lt;em&gt;gives&lt;&#x2F;em&gt; us, is the following behavior.&lt;&#x2F;p&gt;
&lt;p&gt;I press &lt;kbd&gt;space+S&lt;&#x2F;kbd&gt; to set a new harp for &lt;code&gt;helix-term&#x2F;src&#x2F;commands.rs&lt;&#x2F;code&gt;, &lt;br &#x2F;&gt;
and see &lt;code&gt;harp file set (global)&lt;&#x2F;code&gt; in my prompt, notifying me that I&#x27;m currently in the global relativity (using section &lt;code&gt;harp_files&lt;&#x2F;code&gt;). &lt;br &#x2F;&gt;
Next, I press &lt;kbd&gt;.&lt;&#x2F;kbd&gt; to switch to the directory relativity, &lt;br &#x2F;&gt;
and notice that in my prompt: &lt;code&gt;harp file set (directory)&lt;&#x2F;code&gt; (now using section &lt;code&gt;harp_files_~&#x2F;fes&#x2F;ork&#x2F;hx&lt;&#x2F;code&gt;). &lt;br &#x2F;&gt;
I now press the actual key I want to use for the harp — &lt;kbd&gt;c&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
The harp is now set! And it will not conflict with that other harp I have on &lt;kbd&gt;c&lt;&#x2F;kbd&gt; for my helix config, because it&#x27;s stored in a different section!&lt;&#x2F;p&gt;
&lt;p&gt;Chances are, if I want to go to &lt;code&gt;helix-term&#x2F;src&#x2F;commands.rs&lt;&#x2F;code&gt;, that means that I already opened the helix fork directory and started helix there. &lt;br &#x2F;&gt;
So storing the harp for the file &lt;em&gt;globally&lt;&#x2F;em&gt; doesn&#x27;t really make any sense — it&#x27;s quite a waste! &lt;br &#x2F;&gt;
Storing it “inside” the only directory from which I&#x27;ll ever want to access it is far more efficent.&lt;&#x2F;p&gt;
&lt;p&gt;So, to reiterate, now I press &lt;kbd&gt;space+s+c&lt;&#x2F;kbd&gt; to harp into my helix config (from anywhere), &lt;br &#x2F;&gt;
and press &lt;kbd&gt;space+s+.+c&lt;&#x2F;kbd&gt; to harp into &lt;code&gt;helix-term&#x2F;src&#x2F;commands.rs&lt;&#x2F;code&gt; (from &lt;code&gt;~&#x2F;fes&#x2F;ork&#x2F;hx&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;I can create and use project specific harps, resulting in the seemingly restrictive system being quite scaleable!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;All&lt;&#x2F;em&gt; relativities&lt;a href=&quot;#footnote-2&quot; id=&quot;headnote-2&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 exist for &lt;em&gt;all&lt;&#x2F;em&gt; harp actions&lt;a href=&quot;#footnote-3&quot; id=&quot;headnote-3&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
. &lt;br &#x2F;&gt;
Some relativities don&#x27;t make logical sense for some harp actions, so I&#x27;ll introduce the other ones as they come up in usefulness for the other harp actions, as we go.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-2&quot; id=&quot;footnote-2&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 You only know “global” and “directory” so far. &lt;br &#x2F;&gt;
&lt;a href=&quot;#headnote-3&quot; id=&quot;footnote-3&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 You only know harp files and have &lt;em&gt;heard&lt;&#x2F;em&gt; of harp directories so far.&lt;&#x2F;p&gt;
&lt;p&gt;You might find yourself almost always using the directory relativity for file harps; That&#x27;s a pretty reasonable approach! &lt;br &#x2F;&gt;
You can change the default relativity &lt;em&gt;per&lt;&#x2F;em&gt; harp action. &lt;br &#x2F;&gt;
For example, you could set file harps to automatically assume the “directory” relativity. &lt;br &#x2F;&gt;
Then to access the global relativity again, you&#x27;d have to press &lt;kbd&gt;&#x27;&lt;&#x2F;kbd&gt; before the harp key, but would no longer need to press &lt;kbd&gt;.&lt;&#x2F;kbd&gt; every single time for the directory relativity — &lt;em&gt;that&lt;&#x2F;em&gt; is now your default instead of “global”. &lt;br &#x2F;&gt;
As you discover your own harp workflow, you&#x27;ll find the relativities you use most for each harp action, and will be able to make it more ergonomic and fast 🚀 for yourself :3&lt;&#x2F;p&gt;
&lt;h2 id=&quot;directory-harps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#directory-harps&quot; aria-label=&quot;Anchor link for: directory-harps&quot;&gt;directory harps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Harps don&#x27;t have to be exclusive to your editor! &lt;br &#x2F;&gt;
This harp action exists for me both in helix, &lt;em&gt;and&lt;&#x2F;em&gt; fish shell!&lt;&#x2F;p&gt;
&lt;p&gt;Zoxide is wonderful, but still requires me to type at least a few characters to get to a specific directory that I want. &lt;br &#x2F;&gt;
And if I stand my ground and use only one character, it&#x27;ll likely jump me to the wrong directory; &lt;br &#x2F;&gt;
at least, I can never tell ahead of time where I&#x27;ll end up in, and so it all ends up being a waste of mental cycles.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, I use directory harps! &lt;br &#x2F;&gt;
“set” takes my current working directory,
“get” &lt;code&gt;cd&lt;&#x2F;code&gt;s into it.&lt;&#x2F;p&gt;
&lt;p&gt;My shell, of course, has a current working directory; but did you know your editor (helix &#x2F; nvim) has its own, separate, current working directory? That&#x27;s the reason I have directory harps for both!&lt;&#x2F;p&gt;
&lt;p&gt;I do a lot of configuration, so I always need to travel to my dotfiles directory quickly and directly. &lt;br &#x2F;&gt;
Directory harp &lt;code&gt;d&lt;&#x2F;code&gt; lets me jump to &lt;code&gt;~&#x2F;fes&#x2F;dot&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
My blog, similarly, is something I need to get to often; &lt;code&gt;~&#x2F;fes&#x2F;lai&#x2F;bog&lt;&#x2F;code&gt; is on harp &lt;code&gt;x&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
The various notes I have that may or may not be temporary are extra important to be instantenous: &lt;code&gt;~&#x2F;fes&#x2F;foe&lt;&#x2F;code&gt; on &lt;code&gt;k&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I fuck up something in a &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;magazines&#x2F;&quot;&gt;magazine&lt;&#x2F;a&gt; — use harp &lt;code&gt;m&lt;&#x2F;code&gt; to quickly get to &lt;code&gt;~&#x2F;.local&#x2F;share&#x2F;magazine&lt;&#x2F;code&gt; and &lt;code&gt;git reset&lt;&#x2F;code&gt; some magazine action.&lt;&#x2F;p&gt;
&lt;p&gt;I used the keys&#x2F;letters that were easiest for me to remember for each path, so they got into my muscle memory pretty quickly. &lt;br &#x2F;&gt;
I now consistently save mental effort getting to these directories, and can instead think about anything else instead :&amp;gt; &lt;br &#x2F;&gt;
I never had to type out any of those paths to &lt;em&gt;set&lt;&#x2F;em&gt; them, either! &lt;br &#x2F;&gt;
I simply get to that directory somehow (maybe by using zoxide, too!), then press &lt;kbd&gt;ctrl+alt+m+some_key&lt;&#x2F;kbd&gt; in my shell. &lt;br &#x2F;&gt;
My current working directory is automatically passed, so no need to provide it manually!&lt;&#x2F;p&gt;
&lt;p&gt;Then in helix, if I ever realize I need to change directory to one of those paths, I can use the directory harp action &lt;em&gt;within helix&lt;&#x2F;em&gt; — I made &lt;em&gt;shell&lt;&#x2F;em&gt; directory harps and &lt;em&gt;helix&lt;&#x2F;em&gt; directory harps share the same section, so setting a harp in one will set it in the other! Very convenient.&lt;&#x2F;p&gt;
&lt;p&gt;The pain point of &lt;code&gt;~&#x2F;.config&lt;&#x2F;code&gt;, &lt;code&gt;~&#x2F;.local&#x2F;share&lt;&#x2F;code&gt;, etc, is also completely solved by directory harps! And &lt;em&gt;you&lt;&#x2F;em&gt; get to decide what key makes the most sense to you to press to get to them. &lt;br &#x2F;&gt;
With fuzzying, you get your perfect query enforced on you — with harp, &lt;em&gt;you&lt;&#x2F;em&gt; get to name it. &lt;br &#x2F;&gt;
&lt;code&gt;~&#x2F;.local&#x2F;share&lt;&#x2F;code&gt; makes you feel like pressing &lt;kbd&gt;z&lt;&#x2F;kbd&gt;? Sure whatever. &lt;br &#x2F;&gt;
&lt;code&gt;~&#x2F;.cache&lt;&#x2F;code&gt; is &lt;kbd&gt;ctrl+alt+h&lt;&#x2F;kbd&gt;? You go girl.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;i-lied&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#i-lied&quot; aria-label=&quot;Anchor link for: i-lied&quot;&gt;I lied&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;None of the relativities are particularly useful with directory harps! So let&#x27;s talk about a lie I told you.&lt;&#x2F;p&gt;
&lt;p&gt;My harp file &lt;em&gt;set&lt;&#x2F;em&gt; hotkey is not actually &lt;kbd&gt;space+S&lt;&#x2F;kbd&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;Changing relativities is not a one time deal: &lt;kbd&gt;.&lt;&#x2F;kbd&gt; to switch to the directory relativity, &lt;kbd&gt;&#x27;&lt;&#x2F;kbd&gt; to switch to the global one, and other relativities you do not yet know, all act as &lt;em&gt;hotkeys&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You press those keys to change your current ‘mode’. &lt;br &#x2F;&gt;
What this means, is that you can press them as many times as you want — you can jump between the relativities, doing like 15 “nevermind”s, before ultimately deciding (or cancelling with &lt;kbd&gt;Escape&lt;&#x2F;kbd&gt;) on the one that you want and pressing the actual harp key. &lt;br &#x2F;&gt;
&lt;kbd&gt;.&#x27;.&#x27;.&#x27;&#x27;.&#x27;.&#x27;..&#x27;.&#x27;..&#x27;&lt;&#x2F;kbd&gt; is something you can press in sequence while using a harp action, and it&#x27;s completely normal.&lt;&#x2F;p&gt;
&lt;p&gt;It didn&#x27;t always function this way, and I am really satisfied with my recent harp refactor that made this behavior possible. &lt;br &#x2F;&gt;
I really enjoy not being rushed to pick, and instead be able to stay 🤔ing for a while until I decide.&lt;&#x2F;p&gt;
&lt;p&gt;My previous set hotkey &lt;em&gt;was&lt;&#x2F;em&gt; &lt;kbd&gt;space+S&lt;&#x2F;kbd&gt; at the time, and I quite disliked how I needed to think &lt;em&gt;ahead of time&lt;&#x2F;em&gt; (which is quite &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;why-even-helix&#x2F;&quot;&gt;unhelix-like&lt;&#x2F;a&gt;) whether I wanted to set or to get. &lt;br &#x2F;&gt;
Then also, having to hold shift for the set variants made a certain upcoming harp action kind of not worth it to use, to its fullest extent. &lt;br &#x2F;&gt;
And that&#x27;s why I made the change:&lt;&#x2F;p&gt;
&lt;p&gt;Pressing &lt;kbd&gt;Space&lt;&#x2F;kbd&gt; while in a harp action toggles between the &lt;code&gt;get&lt;&#x2F;code&gt; variant, and the &lt;code&gt;set&lt;&#x2F;code&gt; variant. &lt;br &#x2F;&gt;
Instead of pressing your “harp file get” hotkey to open a file, and your “harp file set” hotkey to harp it, you &lt;em&gt;simply&lt;&#x2F;em&gt; use your “harp file” mapping, and &lt;em&gt;then&lt;&#x2F;em&gt; decide. &lt;br &#x2F;&gt;
You start off in the &lt;code&gt;get&lt;&#x2F;code&gt; mode, but can press &lt;kbd&gt;Space&lt;&#x2F;kbd&gt; to go into the set mode. &lt;br &#x2F;&gt;
Then if you realized you didn&#x27;t want to set, you can simply press &lt;kbd&gt;Space&lt;&#x2F;kbd&gt; again to go back to get. &lt;br &#x2F;&gt;
And you can do this infinitely! Very stimmy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;relative-file-harps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#relative-file-harps&quot; aria-label=&quot;Anchor link for: relative-file-harps&quot;&gt;relative file harps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As I started actively using harp, I noticed an interesting pattern. &lt;br &#x2F;&gt;
Project structures are often not that unique!&lt;&#x2F;p&gt;
&lt;p&gt;In a rust project, there will always be &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;, one or both of &lt;code&gt;src&#x2F;main.rs&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;src&#x2F;lib.rs&lt;&#x2F;code&gt;. Possibly &lt;code&gt;.rustfmt.toml&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
In lua, &lt;code&gt;.luarc.json&lt;&#x2F;code&gt; might be something you want to access every so often. &lt;br &#x2F;&gt;
Basically every project will have a &lt;code&gt;README.md&lt;&#x2F;code&gt;, maybe a &lt;code&gt;CONTRIBUTING.md&lt;&#x2F;code&gt;; some of my projects have a &lt;code&gt;RELEASE.md&lt;&#x2F;code&gt; that is automatically attached to the github release.&lt;&#x2F;p&gt;
&lt;p&gt;With harp, you might find yourself &lt;em&gt;set&lt;&#x2F;em&gt;ting the same relative paths over and over again, per each project. &lt;br &#x2F;&gt;
And the file first needs to exist and be open, for you to &lt;em&gt;set&lt;&#x2F;em&gt; it, so that&#x27;s a lil extra effort as well. &lt;br &#x2F;&gt;
Seems like a bit of a waste, no?&lt;&#x2F;p&gt;
&lt;p&gt;Relative file harps solve this.&lt;&#x2F;p&gt;
&lt;p&gt;When normal file harps store the &lt;em&gt;full&lt;&#x2F;em&gt; path, relative file harps only store the &lt;em&gt;relative&lt;&#x2F;em&gt; path of the buffer, from your current working directory.&lt;&#x2F;p&gt;
&lt;p&gt;So say your cwd is &lt;code&gt;~&#x2F;fes&#x2F;dot&lt;&#x2F;code&gt; and you have &lt;code&gt;~&#x2F;fes&#x2F;dot&#x2F;project.txt&lt;&#x2F;code&gt; open. &lt;br &#x2F;&gt;
If you set a normal file harp for it, the entire &lt;code&gt;~&#x2F;fes&#x2F;dot&#x2F;project.txt&lt;&#x2F;code&gt; would be stored, and you would only be able to travel to &lt;code&gt;~&#x2F;fes&#x2F;dot&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;project.txt&lt;&#x2F;code&gt; file. &lt;br &#x2F;&gt;
But if you set a &lt;em&gt;relative&lt;&#x2F;em&gt; file harp, only &lt;code&gt;project.txt&lt;&#x2F;code&gt; is stored. &lt;br &#x2F;&gt;
And now, whenever you &lt;em&gt;get&lt;&#x2F;em&gt; the harp, you will open the &lt;code&gt;project.txt&lt;&#x2F;code&gt; file of the &lt;em&gt;current&lt;&#x2F;em&gt; project, rather than some exact file.&lt;&#x2F;p&gt;
&lt;p&gt;What this lets you do is access files that do not even exist yet! &lt;br &#x2F;&gt;
Rather than having to first create the file somehow, you immediately jump to where it would be, and on your next write it will automatically get created. &lt;br &#x2F;&gt;
So we&#x27;re solving two problems here:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;having to set harps for the same files for every project is laborious&lt;&#x2F;li&gt;
&lt;li&gt;having to first create the files to then make harps for is laborious also&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;To reiterate: use relative file harps when you might want to get to different &lt;em&gt;actual&lt;&#x2F;em&gt; files, but that are of the same &lt;em&gt;structure&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
Use normal file harps when you want to get to &lt;em&gt;exact&lt;&#x2F;em&gt; files.&lt;&#x2F;p&gt;
&lt;p&gt;Here are my relative harps:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Register&lt;&#x2F;th&gt;&lt;th&gt;Filepath&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;kbd&gt;r&lt;&#x2F;kbd&gt;&lt;&#x2F;td&gt;&lt;td&gt;README.md&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;kbd&gt;e&lt;&#x2F;kbd&gt;&lt;&#x2F;td&gt;&lt;td&gt;RELEASE.md&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;kbd&gt;k&lt;&#x2F;kbd&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;magazines&#x2F;&quot;&gt;project.txt&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;kbd&gt;g&lt;&#x2F;kbd&gt;&lt;&#x2F;td&gt;&lt;td&gt;.gitignore&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;kbd&gt;j&lt;&#x2F;kbd&gt;&lt;&#x2F;td&gt;&lt;td&gt;justfile&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;kbd&gt;l&lt;&#x2F;kbd&gt;&lt;&#x2F;td&gt;&lt;td&gt;lib.rs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;kbd&gt;c&lt;&#x2F;kbd&gt;&lt;&#x2F;td&gt;&lt;td&gt;Cargo.toml&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;kbd&gt;m&lt;&#x2F;kbd&gt;&lt;&#x2F;td&gt;&lt;td&gt;main.rs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;I underuse relative harps honestly; I should harp some more 🗣️&lt;&#x2F;p&gt;
&lt;h2 id=&quot;register-harps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#register-harps&quot; aria-label=&quot;Anchor link for: register-harps&quot;&gt;register harps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;re a vim &#x2F; helix &#x2F; kakoune user, you might have noticed how using harps is kinda similar to using vim registers. &lt;br &#x2F;&gt;
With vim registers, you access a “key”, and then get text that you can interact with in some way; usually by pasting it.&lt;&#x2F;p&gt;
&lt;p&gt;In helix, the contents of your registers do not stay across sessions, making them fairly useless. &lt;br &#x2F;&gt;
And that&#x27;s why register &lt;em&gt;harps&lt;&#x2F;em&gt; is a very useful idea!&lt;&#x2F;p&gt;
&lt;p&gt;As I (hopefully) mentioned already, &lt;em&gt;set&lt;&#x2F;em&gt;ting a harp makes it &lt;em&gt;instantly&lt;&#x2F;em&gt; available in &lt;em&gt;all&lt;&#x2F;em&gt; sessions, &lt;br &#x2F;&gt;
so you don&#x27;t have to worry about helix “forgetting” the contents of your registers after you exit it.&lt;&#x2F;p&gt;
&lt;p&gt;To &lt;em&gt;set&lt;&#x2F;em&gt; a register harp, first simply copy (yank) something to your &lt;code&gt;default-yank-register&lt;&#x2F;code&gt; &lt;br &#x2F;&gt;
(&lt;code&gt;&quot;&lt;&#x2F;code&gt; by default (meaning that you simply copy normally, no special magic required)). &lt;br &#x2F;&gt;
This is the “context” that this harp action uses for the set action: it takes the contents in the &lt;code&gt;default-yank-register&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Later on when you &lt;em&gt;get&lt;&#x2F;em&gt; that register, it places the stored contents back into your &lt;code&gt;default-yank-register&lt;&#x2F;code&gt;, letting you paste them normally.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m gitty of the power of this harp action, and explaining it to you!! &lt;br &#x2F;&gt;
But first, let&#x27;s introduce &lt;em&gt;another&lt;&#x2F;em&gt; relativity :o&lt;&#x2F;p&gt;
&lt;h2 id=&quot;filetype-relativity&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#filetype-relativity&quot; aria-label=&quot;Anchor link for: filetype-relativity&quot;&gt;filetype relativity&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can make a harp relative to the current buffer&#x27;s filetype. &lt;br &#x2F;&gt;
It uses the filetype that helix sets for the buffer, rather than just taking the buffer&#x27;s file extension! &lt;br &#x2F;&gt;
So if you use the filetype relativity on a markdown file, &lt;code&gt;!markdown&lt;&#x2F;code&gt; will be appended to the section name, rather than &lt;code&gt;!.md&lt;&#x2F;code&gt; that you may have expected. &lt;br &#x2F;&gt;
The filetype relativity even works for files that don&#x27;t &lt;em&gt;have&lt;&#x2F;em&gt; a “real” filetype! &lt;br &#x2F;&gt;
When the buffer doesn&#x27;t resolve to any real filetype, its filetype is set to “text”. &lt;br &#x2F;&gt;
So, if you use the filetype relativity in an &lt;code&gt;example.txt&lt;&#x2F;code&gt; file, &lt;code&gt;!text&lt;&#x2F;code&gt; will be appended to the section name.&lt;&#x2F;p&gt;
&lt;p&gt;To switch to the filetype relativity, press &lt;kbd&gt;;&lt;&#x2F;kbd&gt; while accessing a harp action.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;back-to-register-harps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#back-to-register-harps&quot; aria-label=&quot;Anchor link for: back-to-register-harps&quot;&gt;back to register harps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The filetype relativity + register harps lets us create a simple snippet system!&lt;&#x2F;p&gt;
&lt;p&gt;For example, &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;why-i-hate-lua&#x2F;&quot;&gt;I despise lua&lt;&#x2F;a&gt;, and don&#x27;t like how long it takes to type in the syntax for a function object &#x2F; closure, and I also happen to dislike the default snippets that the lua language server provides for them.&lt;&#x2F;p&gt;
&lt;p&gt;I could yank the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  →&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(the &lt;code&gt;→&lt;&#x2F;code&gt; there is a tab)&lt;&#x2F;p&gt;
&lt;p&gt;And put it into a filetype-relative register harp (just make sure you&#x27;re in a lua file while you do this). &lt;br &#x2F;&gt;
Now I can “summon” it whenever I want, by pressing &lt;code&gt;&amp;lt;space&amp;gt;w;f&lt;&#x2F;code&gt; + the paste key&lt;a href=&quot;#footnote-4&quot; id=&quot;headnote-4&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;4&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
.&lt;&#x2F;p&gt;
&lt;p&gt;Pressing 4 keys to get to it &lt;em&gt;may&lt;&#x2F;em&gt; be not worth it for you for the specific example, but you can probably see how a bunch of various language-specific boilerplate you don&#x27;t like typing out can instead be harped, consistently saving you effort :3 &lt;br &#x2F;&gt;
In my personal usage, I find myself using the filetype relativity the most often with register harps, so I set it as my default relativity for them. &lt;br &#x2F;&gt;
In other words, getting that function object syntax example is just &lt;code&gt;&amp;lt;space&amp;gt;wf&lt;&#x2F;code&gt; for me.&lt;&#x2F;p&gt;
&lt;p&gt;Also, I use register harps really frequently for shebang lines! &lt;br &#x2F;&gt;
For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #928374;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env fish&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I store this in register harp &lt;kbd&gt;#&lt;&#x2F;kbd&gt;, relative to the &lt;code&gt;fish&lt;&#x2F;code&gt; language. Then I store the following relative to &lt;code&gt;nushell&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #928374;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env -S nu -n --no-std-lib&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once again, &lt;em&gt;also&lt;&#x2F;em&gt; in harp &lt;kbd&gt;#&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So you can create a semantic for yourself that makes it easy to remember the &lt;em&gt;intent&lt;&#x2F;em&gt; behind a harp, yet store many different ones thanks the various relativities. &lt;br &#x2F;&gt;
Here, it makes sense for me that a shebang line starts with a &lt;kbd&gt;#&lt;&#x2F;kbd&gt;, and so I use that key as a neat mnemonic. &lt;br &#x2F;&gt;
Making use of easy to remember mnemonics &#x2F; going with what feels the most natural is a great way to make a good use of harp.&lt;&#x2F;p&gt;
&lt;a href=&quot;#another-alternative&quot; id=&quot;another-alternative&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Another good default relativity you could use instead of global, is the directory relativity. &lt;br &#x2F;&gt;
Then, by default, you will simply have vim-like registers that are scoped to a project, so you can use them a bit more willy-nillily than global ones or filetype-relative ones, and simply temporarily switch your relativity when you &lt;em&gt;do&lt;&#x2F;em&gt; want those.&lt;&#x2F;p&gt;
&lt;p&gt;No need to worry about your registers disappearing, and no need to worry what else you saved for later while working on a completely different project.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes, I keep them for long, though! &lt;br &#x2F;&gt;
For example, I keep the syntax required to make a footnote&lt;a href=&quot;#footnote-5&quot; id=&quot;headnote-5&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;5&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 in this blog, as two register harps — &lt;br &#x2F;&gt;
one for the head part of the note (the uppercase number in the previous sentence) and another for the foot part of the note (what you are jumped to). &lt;br &#x2F;&gt;
I need to type in the index myself, so to make it easy to do so, I leave in &lt;code&gt;j&lt;&#x2F;code&gt; in place of the number. &lt;br &#x2F;&gt;
Once I paste the syntax, I can hop directly to &lt;code&gt;j&lt;&#x2F;code&gt; to then replace with the index. &lt;br &#x2F;&gt;
This workflow makes it much more comfortable to create footnotes!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;search-harps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#search-harps&quot; aria-label=&quot;Anchor link for: search-harps&quot;&gt;search harps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Whenever you search for something, the search pattern you used is stored in the &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; register. &lt;br &#x2F;&gt;
Interestingly, this works not only for the &lt;code&gt;search&lt;&#x2F;code&gt; action (&lt;kbd&gt;&#x2F;&lt;&#x2F;kbd&gt;), but also for the “ripgrep project” action (&lt;code&gt;global_search&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;When you &lt;em&gt;set&lt;&#x2F;em&gt; a search harp, the regex pattern in your &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; register is stored. &lt;br &#x2F;&gt;
When you &lt;em&gt;get&lt;&#x2F;em&gt; a search harp, the pattern is taken from storage and placed back into your &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; register.&lt;&#x2F;p&gt;
&lt;p&gt;The way that searching and the &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; register works in helix specifically makes this a very nice to use and flexible functionality. &lt;br &#x2F;&gt;
You see, &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; doesn&#x27;t store “your &lt;em&gt;last&lt;&#x2F;em&gt; search”, it stores “your search”. &lt;br &#x2F;&gt;
So when you change the contents of your &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; register, you change what you will be searching for when you press &lt;kbd&gt;n&lt;&#x2F;kbd&gt;&#x2F;&lt;kbd&gt;N&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
There&#x27;s no need for the harp action to automatically trigger a “and now you jump to the match!” action, &lt;em&gt;you&lt;&#x2F;em&gt; get to decide how you proceed. &lt;br &#x2F;&gt;
So you can get a search harp, and then decide to jump backwards with &lt;kbd&gt;N&lt;&#x2F;kbd&gt;, or forwards with &lt;kbd&gt;n&lt;&#x2F;kbd&gt; — harp doesn&#x27;t make the decision for you because helix&#x27;s design doesn&#x27;t require it to, muah!&lt;&#x2F;p&gt;
&lt;p&gt;But another really powerful thing that filling the &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; register does for you, comes back to &lt;code&gt;global_search&lt;&#x2F;code&gt; once again. &lt;br &#x2F;&gt;
If you open &lt;code&gt;global_search&lt;&#x2F;code&gt; and don&#x27;t type in any pattern yet, it shows the pattern stored in the &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; register, greyed out. &lt;br &#x2F;&gt;
Now, if you press &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt;, it is automatically accepted as your input.&lt;&#x2F;p&gt;
&lt;p&gt;In other words, you could get a search harp, then invoke &lt;code&gt;global_search&lt;&#x2F;code&gt; and simply press enter, to search for a stored query!&lt;&#x2F;p&gt;
&lt;p&gt;This capability is not unique to &lt;code&gt;global_search&lt;&#x2F;code&gt; though, as if you press &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; to do a buffer search, you will &lt;em&gt;also&lt;&#x2F;em&gt; see the same greyed out search pattern that you can accept with &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
Ooooor, you can press &lt;kbd&gt;Up&lt;&#x2F;kbd&gt; to actually paste in that pattern, for you to &lt;em&gt;edit&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Searching and the search register semantics in helix are very clean, as you can see; &lt;br &#x2F;&gt;
It is thanks to this that register harps is the first harp action that makes great use of &lt;em&gt;every&lt;&#x2F;em&gt; relativity! &lt;br &#x2F;&gt;
Let&#x27;s go through them.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;directory&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#directory&quot; aria-label=&quot;Anchor link for: directory&quot;&gt;directory&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;global_search&lt;&#x2F;code&gt; capability lets us have lsp-like capabilities without relying on an lsp! &lt;br &#x2F;&gt;
First you notice what things you keep searching for in the project, and interactively try to match them with regex by using &lt;kbd&gt;&#x2F;&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can take your time doing so, trying out different approaches until you confirm it works by simply &lt;kbd&gt;n&lt;&#x2F;kbd&gt;ing to it. &lt;br &#x2F;&gt;
Then, you set a harp for that, using the directory relativity.&lt;&#x2F;p&gt;
&lt;p&gt;Now, whenever you want to search for the query again, you &lt;em&gt;get&lt;&#x2F;em&gt; this search harp you created, open &lt;code&gt;global_search&lt;&#x2F;code&gt; and press enter. &lt;br &#x2F;&gt;
Especially if the directory relativity is your default one for search harps, this is not too bad! &lt;br &#x2F;&gt;
Considering it&#x27;s your first result, you simply press &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt; again, but you don&#x27;t &lt;em&gt;necessarily&lt;&#x2F;em&gt; have to use this functionality for intentionally a single result. &lt;br &#x2F;&gt;
You can also make a query that searches for potentially many things, so that you can quickly gain an overlay over all of them. &lt;br &#x2F;&gt;
The simplest example of this in the context of the directory relativity, is checking the &lt;em&gt;usage&lt;&#x2F;em&gt; of some given thing.&lt;&#x2F;p&gt;
&lt;p&gt;But of course, if you can use an lsp for this sort of basic functionality, use it. &lt;br &#x2F;&gt;
The benefit of using search harps instead is for when you don&#x27;t have access to an lsp, or it is obscenely slow, or you want to check references for a thing which is not technically a symbol (“get all comments”, as an example).&lt;&#x2F;p&gt;
&lt;p&gt;Plus, the lsp starts loading once you&#x27;re actually in some file, and generally to get all references of a symbol, you need to first &lt;em&gt;arrive&lt;&#x2F;em&gt; at that symbol. &lt;br &#x2F;&gt;
There will be some situations where it&#x27;s just much faster to use a search harp, especially if you keep reopening this given project and travelling to the same thing.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;filetype&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#filetype&quot; aria-label=&quot;Anchor link for: filetype&quot;&gt;filetype&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We created a basic snippet system with register harps, and now we can use &lt;em&gt;search&lt;&#x2F;em&gt; harps to create a basic textobject system!&lt;&#x2F;p&gt;
&lt;p&gt;The idea is pretty simple: you create regexes to jump to some syntactical structures.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a search harp I made for rust:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&amp;gt; [^ ]+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using it, I can jump to a function&#x27;s output type:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;    self&lt;&#x2F;span&gt;&lt;span&gt;.count.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;map_or&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; v.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, I would arrive at &lt;code&gt;-&amp;gt; usize&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, helix uses rust regex, rather than &lt;code&gt;fancyregex&lt;&#x2F;code&gt;, so backreferences are not possible; I&#x27;d like to remove the &lt;code&gt;-&amp;gt; &lt;&#x2F;code&gt; from the selection that&#x27;s made, but still use it in the pattern — currently that&#x27;s not a thing I can do.&lt;&#x2F;p&gt;
&lt;p&gt;I looked into replacing &lt;code&gt;regex&lt;&#x2F;code&gt; with &lt;code&gt;fancyregex&lt;&#x2F;code&gt; in helix, but I couldn&#x27;t even figure out where to start, ngl. &lt;br &#x2F;&gt;
Maybe in the future, me or someone else will do this, and then search-based text objects are going to become even more powerful than they already can be.&lt;&#x2F;p&gt;
&lt;a href=&quot;#pubfun&quot; id=&quot;pubfun&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;You can jump to the previous &#x2F; next function using &lt;kbd&gt;[f&lt;&#x2F;kbd&gt; and &lt;kbd&gt;]f&lt;&#x2F;kbd&gt;, in helix. &lt;br &#x2F;&gt;
This is pretty neat and useful, but often has inconvenient semantics. &lt;br &#x2F;&gt;
&lt;em&gt;Closures&lt;&#x2F;em&gt; generally count as functions, and if you have a function inside of a function, that will count too. &lt;br &#x2F;&gt;
While in reality, I want to “jump to the next function” the most often for the usecase of travelling through the file the fastest, arriving at some top level function. &lt;br &#x2F;&gt;
Having to travel through every itty bitty closure makes this not particularly viable.&lt;&#x2F;p&gt;
&lt;p&gt;We can once again use filetype search harps for this usecase, using a simple pattern:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;^pub fn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here I specificially search for all &lt;em&gt;public&lt;&#x2F;em&gt; functions that are top level; &lt;br &#x2F;&gt;
So &lt;em&gt;methods&lt;&#x2F;em&gt; wouldn&#x27;t get caught with this — this can be either beneficial or detrimental depending on what you want, but you have the power to define what exactly you want, by changing the regex! :D&lt;&#x2F;p&gt;
&lt;p&gt;Maybe jumping to a &lt;em&gt;function&lt;&#x2F;em&gt; specifically is not that useful to you, but overall being able to jump to the next public top-level &lt;em&gt;symbol&lt;&#x2F;em&gt; is — you could simply use &lt;code&gt;^pub &lt;&#x2F;code&gt; in that case. &lt;br &#x2F;&gt;
Regardless of what you want, &lt;em&gt;you&lt;&#x2F;em&gt; get to decide what search “shortcuts” you have, by creating them all to fit &lt;em&gt;your&lt;&#x2F;em&gt; specific needs. &lt;br &#x2F;&gt;
Not having to make do with overly specific design restrictions is part of why I love harp so much.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;global&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#global&quot; aria-label=&quot;Anchor link for: global&quot;&gt;global&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Coming back to how we used search harps with the directory relativity, we can also make use of &lt;code&gt;global_search&lt;&#x2F;code&gt; with the global relativity.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;TODO&lt;&#x2F;code&gt;, &lt;code&gt;FIXME&lt;&#x2F;code&gt;, &lt;code&gt;BUG&lt;&#x2F;code&gt;, &lt;code&gt;HACK&lt;&#x2F;code&gt;, etc are something that you may either see or even use in your code, as pointers for things to take a look at in the future. &lt;br &#x2F;&gt;
You could make a global search harp for them all (or some of them), to be able to quickly get an overview of all places of note, via &lt;code&gt;global_search&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;\bTODO|FIXME|BUG|HACK\b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;…And here you go.&lt;&#x2F;p&gt;
&lt;p&gt;So far this is the only pattern that I can expect to be useful in any language and any project, but I&#x27;m sure there are more things like that! &lt;br &#x2F;&gt;
For example, the &lt;code&gt;[[sort etc]]&lt;&#x2F;code&gt; of &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;consider-sorting&#x2F;&quot;&gt;my autosorter&lt;&#x2F;a&gt; could potentially be a useful pattern to keep stored 🤔&lt;&#x2F;p&gt;
&lt;h3 id=&quot;buffer&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#buffer&quot; aria-label=&quot;Anchor link for: buffer&quot;&gt;buffer&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;And now I introduce to you the last, fourth harp relativity: buffer. &lt;br &#x2F;&gt;
You can make your harps local to the absolute filepath of the current buffer. &lt;br &#x2F;&gt;
You can access it by pressing &lt;kbd&gt;,&lt;&#x2F;kbd&gt; while using a harp action.&lt;&#x2F;p&gt;
&lt;p&gt;Vim-like marks, inherently, store a line+column position. &lt;br &#x2F;&gt;
What this means, is that if you add or remove line(s) before that position, you invalidate the stored position. &lt;br &#x2F;&gt;
At best, you&#x27;ll be slightly off, but at worst you&#x27;re now storing a completely useless position. &lt;br &#x2F;&gt;
With vim-like marks, you will find yourself updating the position over and over again, making yourself disheartened to use marks at all.&lt;&#x2F;p&gt;
&lt;p&gt;With buffer-relative search harps, we can implement a marking system that completely avoids this issue.&lt;&#x2F;p&gt;
&lt;p&gt;Select some area of your code, that is like a landmark. Then, press &lt;kbd&gt;*&lt;&#x2F;kbd&gt; to search for it. &lt;br &#x2F;&gt;
Now if you set a search harp for it relative to the buffer, you can invoke it at any time to quickly jump to it! &lt;br &#x2F;&gt;
I use this so frequently, that buffer relativity is my default one for search harps.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;kbd&gt;*&lt;&#x2F;kbd&gt;, you don&#x27;t actually need to enter the search pattern yourself a lot of the time, making the &lt;em&gt;set&lt;&#x2F;em&gt; process quite comfortable. &lt;br &#x2F;&gt;
In this same sense, you can consider how helpful it can be for the previous relativities of search harps, too.&lt;&#x2F;p&gt;
&lt;p&gt;To show how I use buffer-relative search harps, let&#x27;s take my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;helix&#x2F;generator.py&quot;&gt;helix config generating script&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To define my mappings, I have hashmaps per each mode combination that I want to have mappings for. &lt;br &#x2F;&gt;
Basically, I can just add a mapping to &lt;code&gt;normal_select_mappings&lt;&#x2F;code&gt; to add it to both modes, rather than having to separately add it to &lt;code&gt;normal_mappings&lt;&#x2F;code&gt; and &lt;code&gt;select_mappings&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Since all of these hashmaps are huge, it&#x27;s incredibly helpful to be able to jump to each of them individually. &lt;br &#x2F;&gt;
The variable definitions are unique, and that helps them be unique search patterns!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;normal_select_mappings: dict[str, Any] = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;normal_mappings: dict[str, Any] = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;select_mappings: dict[str, Any] = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With all of them, I can simply select the entire line and press &lt;kbd&gt;*&lt;&#x2F;kbd&gt; to search for it; &lt;br &#x2F;&gt;
This way, I can make a search harp with no extra hassle. &lt;br &#x2F;&gt;
I&#x27;m not going to a line+column position, but &lt;em&gt;searching&lt;&#x2F;em&gt; for &lt;code&gt;normal_select_mappings: dict[str, Any] = {&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Thanks to it being a search, I will always land at where the landmark is actually located, not at where it &lt;em&gt;was&lt;&#x2F;em&gt; located.&lt;&#x2F;p&gt;
&lt;p&gt;You don&#x27;t necessarily need to only match a single thing, though. &lt;br &#x2F;&gt;
You can also make a buffer-relative search harp that can take you to multiple places.&lt;&#x2F;p&gt;
&lt;p&gt;I have two layers in my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;erm&#x2F;&quot;&gt;kanata config&lt;&#x2F;a&gt;, that let me launch programs quickly. &lt;br &#x2F;&gt;
In the config file, I might want to jump to either of the two layers, and so I unify them under a single search harp! &lt;br &#x2F;&gt;
This is how the two layer definitions start:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (apps)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(deflayermap (apps-revengeance)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So I can use the pattern &lt;code&gt;\(deflayermap \(apps&lt;&#x2F;code&gt; to grab them &lt;em&gt;both&lt;&#x2F;em&gt; in a single search harp, and then simply press &lt;kbd&gt;n&lt;&#x2F;kbd&gt; to get to either one I want to get to.&lt;&#x2F;p&gt;
&lt;p&gt;Aside from being genuinely specific to some file, the buffer relativity can act as your “I really don&#x27;t wanna think about harps conflicts right now” relativity, that you can use for the truly ad-hoc harp that you don&#x27;t intend to use later.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mark-harps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#mark-harps&quot; aria-label=&quot;Anchor link for: mark-harps&quot;&gt;mark harps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Search harps for navigating to some specific place, still, are best suited for things that you intend to get back to at least every so often. &lt;br &#x2F;&gt;
After all, you need to think about whether the given search pattern will stay valid (are you sure you aren&#x27;t going to change the contents of the line you&#x27;re using as a landmark?), and you do need to press an extra key (&lt;kbd&gt;n&lt;&#x2F;kbd&gt; usually) or even multiple keys (when using &lt;code&gt;global_search&lt;&#x2F;code&gt; + searh harps).&lt;&#x2F;p&gt;
&lt;p&gt;But for ad-hoc things (“I just need to store this position quickly, I&#x27;ll come back to it in a sec”), or for things that you&#x27;re sure will remain unchanging for the most part, &lt;em&gt;mark harps&lt;&#x2F;em&gt; are a better pick.&lt;&#x2F;p&gt;
&lt;p&gt;Setting a mark harp stores the filepath of the current buffer, and your line + column position in it. &lt;br &#x2F;&gt;
Getting a mark harp opens the stored filepath, and travels to the line + column position stored.&lt;&#x2F;p&gt;
&lt;p&gt;This makes it a much better ad-hoc harp action, as to set one, you don&#x27;t need to come up with an appropriate search pattern, you simply &lt;em&gt;set&lt;&#x2F;em&gt; and go on with your day. &lt;br &#x2F;&gt;
The position invalidation argument I made in the search harp section still remains true, so mark harps are best used for when an invalidated position wouldn&#x27;t matter that much.&lt;&#x2F;p&gt;
&lt;p&gt;The helix jump list is not trustworthy, it keeps invalidating itself for seemingly no good reason. &lt;br &#x2F;&gt;
And when &lt;em&gt;it&lt;&#x2F;em&gt; invalidates, the position you explicitly stored with &lt;kbd&gt;ctrl+s&lt;&#x2F;kbd&gt; is simply &lt;em&gt;gone&lt;&#x2F;em&gt;, rather than just &lt;em&gt;off&lt;&#x2F;em&gt;, like it &lt;em&gt;might&lt;&#x2F;em&gt; be with mark harps.&lt;&#x2F;p&gt;
&lt;p&gt;I find the directory relativity to make the most sense as a default for mark harps&lt;a href=&quot;#footnote-6&quot; id=&quot;headnote-6&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;6&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
. &lt;br &#x2F;&gt;
You scope your ad-hocs per project, so you never need to worry about overriding something you were working on 5 seconds ago, in a different project. &lt;br &#x2F;&gt;
Yet, it&#x27;s not as restrictive as defaulting to the buffer relativity: since mark harps remember the buffer path as well, you can more freely express “wherever I last been” — you don&#x27;t need to first remember which file you were in, to then jump to a position inside of.&lt;&#x2F;p&gt;
&lt;p&gt;This harp action is the most recent, actually! &lt;br &#x2F;&gt;
Search harps are so good, that I didn&#x27;t feel the need for this harp action to exist; &lt;br &#x2F;&gt;
I also trusted the jumplist more than I should have.&lt;&#x2F;p&gt;
&lt;p&gt;Pressing an uppercase letter to set something this “fast”, also felt like a bad value proposition. &lt;br &#x2F;&gt;
So it&#x27;s &lt;em&gt;this&lt;&#x2F;em&gt; harp action that sparked the “space to toggle get&#x2F;set” change, as well as the refactor that made it possible.&lt;&#x2F;p&gt;
&lt;p&gt;Now that I have mark harps, they&#x27;re really nice! &lt;br &#x2F;&gt;
Being able to turn my brain off and not worry about losing my train of workflow is really convenient.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;command-harps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#command-harps&quot; aria-label=&quot;Anchor link for: command-harps&quot;&gt;command harps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;On set, the last command mode :command you executed (stored in the &lt;code&gt;:&lt;&#x2F;code&gt; register) is stored. &lt;br &#x2F;&gt;
On get, it is &lt;em&gt;executed&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In classic harp fashion, the process of setting is interactive. &lt;br &#x2F;&gt;
First, you try out the command, until you finalize it into the one you want to store. &lt;br &#x2F;&gt;
Only &lt;em&gt;after&lt;&#x2F;em&gt; do you actually “commit” it.&lt;&#x2F;p&gt;
&lt;p&gt;If I just made you enter the command into an inputbox, you could have a typo, or simply be using the command incorrectly, and never be the wiser! &lt;br &#x2F;&gt;
At least, not until the next time you plan to &lt;em&gt;use&lt;&#x2F;em&gt; that harp, where it may be crucial to not distract yourself with fixing some harp command :p&lt;&#x2F;p&gt;
&lt;p&gt;Of course, there might be some commands that you want to store without necessarily running them first; Something destructive perhaps? &lt;br &#x2F;&gt;
For those usecases, you can simply write out the command in some buffer, and copy it directly into the &lt;code&gt;:&lt;&#x2F;code&gt; register. &lt;br &#x2F;&gt;
That will allow you to fill the “context” that command harps use, without running the command just yet.&lt;&#x2F;p&gt;
&lt;a href=&quot;#command-expansions&quot; id=&quot;command-expansions&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;This is by far the most &lt;em&gt;powerful&lt;&#x2F;em&gt; harp action, and is my second most used one, after file harps. &lt;br &#x2F;&gt;
The kakoune design, that helix takes after, makes storing :commands quite flexible.&lt;&#x2F;p&gt;
&lt;p&gt;First, helix has command expansions. Variables that expand to some string, depending on some context. &lt;br &#x2F;&gt;
The most useful one that immediately comes to mind, is &lt;code&gt;%(buffer_name)&lt;&#x2F;code&gt; — it resolves to the path of the buffer. &lt;br &#x2F;&gt;
Through trying it out, though, I found it largely inconsistent and strange, so my fork adds the following 4 useful command expansions:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;full_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;relative_path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;buffer_parent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;working_directory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can probably guess what they resolve to; otherwise you can read about their semantics in the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;readme of the fork&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I &lt;em&gt;believe&lt;&#x2F;em&gt; that command expansions can be used in &lt;em&gt;any&lt;&#x2F;em&gt; :command. &lt;br &#x2F;&gt;
But there are a couple of most useful ones.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;:run-shell-command&lt;&#x2F;code&gt;, or just &lt;code&gt;:sh&lt;&#x2F;code&gt;, lets you execute a shell command asyncronously, and will show its output in a popup, once it finishes.&lt;&#x2F;p&gt;
&lt;p&gt;You don&#x27;t always want to do things asyncronously, though; &lt;br &#x2F;&gt;
We can use the &lt;code&gt;%sh()&lt;&#x2F;code&gt; command expansion for the syncronous usecases! &lt;br &#x2F;&gt;
&lt;code&gt;%sh(echo hi)&lt;&#x2F;code&gt; will execute the shell command &lt;code&gt;echo hi&lt;&#x2F;code&gt;, wait for it to finish, and then resolve to the output.&lt;&#x2F;p&gt;
&lt;p&gt;The call of a :command itself is syncronous, so &lt;code&gt;%sh()&lt;&#x2F;code&gt; &lt;em&gt;must&lt;&#x2F;em&gt; resolve to a value before the :command that contains the &lt;code&gt;%sh()&lt;&#x2F;code&gt; actually runs.&lt;&#x2F;p&gt;
&lt;p&gt;To make use of this property, you have the &lt;code&gt;:echo&lt;&#x2F;code&gt; command. &lt;br &#x2F;&gt;
It displays the arguments given to it in the messages line (rather than in a popup). &lt;br &#x2F;&gt;
You can use &lt;code&gt;%sh()&lt;&#x2F;code&gt; inside of &lt;code&gt;:echo&lt;&#x2F;code&gt; to effectively mimic &lt;code&gt;:sh&lt;&#x2F;code&gt;, but ensure it&#x27;s syncronous. &lt;br &#x2F;&gt;
This little bit of knowledge may especially be useful for your mappings, not just harps.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;:noop&lt;&#x2F;code&gt; is exactly like &lt;code&gt;:echo&lt;&#x2F;code&gt;, except it doesn&#x27;t show the output in the messages line. &lt;br &#x2F;&gt;
It&#x27;s made basically specifically for doing &lt;code&gt;%sh()&lt;&#x2F;code&gt;, but when you don&#x27;t care about the output.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;:insert-output&lt;&#x2F;code&gt; and &lt;code&gt;:append-output&lt;&#x2F;code&gt; are like &lt;code&gt;:sh&lt;&#x2F;code&gt;, but will insert the output of the command before&#x2F;after the cursor; syncronously.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;:pipe&lt;&#x2F;code&gt; pipes the contents of your selections into a shell command, and replaces them (contents) with the output of that shell command. &lt;br &#x2F;&gt;
Each selection is piped individually, rather than collected somehow.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;:pipe-to&lt;&#x2F;code&gt; is the same thing as &lt;code&gt;:pipe&lt;&#x2F;code&gt;, but the contents of your selection(s) are not replaced. &lt;br &#x2F;&gt;
Basically, you can &lt;em&gt;use&lt;&#x2F;em&gt; your selection(s) as input to a command, without caring about the output.&lt;&#x2F;p&gt;
&lt;p&gt;With such powerful building blocks, you can create quite complex editing actions, without the editor having to provide them for you. &lt;br &#x2F;&gt;
However, typing in a lot of powerful commands can quickly become impractical. &lt;br &#x2F;&gt;
Sure, you can &lt;code&gt;:pipe&lt;&#x2F;code&gt; into &lt;code&gt;shuf&lt;&#x2F;code&gt; and not worry much about it&lt;a href=&quot;#footnote-7&quot; id=&quot;headnote-7&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;7&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
, but what about more complex commandlines?&lt;&#x2F;p&gt;
&lt;p&gt;For really really common things you do you might create hotkeys. &lt;br &#x2F;&gt;
But for many other ones, doing so is highly impractical for many different reasons!&lt;&#x2F;p&gt;
&lt;p&gt;Having to modify your config for something you aren&#x27;t even sure you&#x27;re going to use yet, is painful. &lt;br &#x2F;&gt;
If that hotkey is actually project specific, now you&#x27;re polluting a project with yet another config file (for helix). &lt;br &#x2F;&gt;
What if you only need this command for this specific file, or for a filetype?&lt;&#x2F;p&gt;
&lt;p&gt;A lot of power that&#x27;s impractical to use is a good hint that harp could make it a lot better. &lt;br &#x2F;&gt;
And oh god does it do exactly that!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;global-1&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#global-1&quot; aria-label=&quot;Anchor link for: global-1&quot;&gt;global&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You might want to &lt;code&gt;:toggle-option&lt;&#x2F;code&gt; something in a highly specific way, that doesn&#x27;t happen often enough to warrant a hotkey. &lt;br &#x2F;&gt;
For example, I don&#x27;t use my left gutter at all.
But I &lt;em&gt;could&lt;&#x2F;em&gt; foresee wanting to temporarily enable it to see the git hunks in a buffer.&lt;&#x2F;p&gt;
&lt;p&gt;I used to have a hotkey for this, but I found myself using it so rarely that I kept forgetting what the hotkey is. &lt;br &#x2F;&gt;
That&#x27;s because all the other, more convenient &#x2F; easy to remember hotkeys are already occupied by other things, so the “toggle gutter” hotkey is in a rough spot. &lt;br &#x2F;&gt;
I can now simply move it to be a command harp, on something like global harp &lt;code&gt;g&lt;&#x2F;code&gt;, and be quite happy about it!&lt;&#x2F;p&gt;
&lt;p&gt;My &lt;code&gt;:write&lt;&#x2F;code&gt; hotkey is just &lt;kbd&gt;&#x27;&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
Just a few days ago, a new flag has been added to &lt;code&gt;:write&lt;&#x2F;code&gt;, that allows you to write &lt;em&gt;without&lt;&#x2F;em&gt; formatting the file first — &lt;code&gt;--no-format&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
This sounds pretty useful of a thing! But I&#x27;m not yet sure if I&#x27;d actually use it in my workflow. &lt;br &#x2F;&gt;
So I can blammo it on global command harp &lt;code&gt;w&lt;&#x2F;code&gt; and let time tell me if I need the functionality or not. &lt;br &#x2F;&gt;
This is because I will &lt;em&gt;never&lt;&#x2F;em&gt; bother typing in the long ass &lt;code&gt;--no-format&lt;&#x2F;code&gt; flag normally — I &lt;em&gt;need&lt;&#x2F;em&gt; a shortcut of some kind to even consider using the feature.&lt;&#x2F;p&gt;
&lt;p&gt;Being able to “try out” things before considering putting them into your direct mappings, I&#x27;ve found to be incredibly helpful.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;open&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#open&quot; aria-label=&quot;Anchor link for: open&quot;&gt;:open&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Command harps are so powerful that they can completely mimic a whole entire different harp action! &#x2F;hj&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;:open&lt;&#x2F;code&gt; command lets you open some file, which is exactly what file harps do. &lt;br &#x2F;&gt;
You could, if you wanted to, make a &lt;em&gt;command&lt;&#x2F;em&gt; harp that &lt;code&gt;:open&lt;&#x2F;code&gt;s some file, which is really funny. &lt;br &#x2F;&gt;
But there&#x27;s a genuine usecase for this, too — opening &lt;em&gt;directories&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you try to &lt;code&gt;:open&lt;&#x2F;code&gt; a directory rather than a file, a fuzzy file search is opened for that directory instead&lt;a href=&quot;#footnote-8&quot; id=&quot;headnote-8&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;8&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 &lt;br &#x2F;&gt;
So if you keep finding yourself specifically fuzzy searching for files in some directory, making a command harp with &lt;code&gt;:open&lt;&#x2F;code&gt; for it could be a pretty great solution.&lt;&#x2F;p&gt;
&lt;p&gt;Directory harps exist, sure, but they are more so meant to travel to directories that you intend to &lt;em&gt;stay&lt;&#x2F;em&gt; in. &lt;br &#x2F;&gt;
If &lt;em&gt;all&lt;&#x2F;em&gt; you ever want to do is open a singular file in a directory, travelling to it, opening the fuzzy finder, and then &lt;code&gt;:cd -&lt;&#x2F;code&gt;ing feels like a bit of a waste.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-8&quot; id=&quot;footnote-8&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;8&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 Fun fact: this also works on the commandline. &lt;br &#x2F;&gt;
&lt;code&gt;helix .&lt;&#x2F;code&gt; will open helix, and immediately launch the file picker, for example.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;filetype-1&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#filetype-1&quot; aria-label=&quot;Anchor link for: filetype-1&quot;&gt;filetype&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The filetype relativity is where it&#x27;s really at. &lt;br &#x2F;&gt;
You can make harps harps to do language-specific run-like things.&lt;&#x2F;p&gt;
&lt;p&gt;Almost every filetype you can “run” in some sort of sense. &lt;br &#x2F;&gt;
Interpreted languages usually go like &lt;code&gt;:sh intlang %(full_path)&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Compiled languages want you to compile and &lt;em&gt;then&lt;&#x2F;em&gt; run the file, so that&#x27;s something like &lt;code&gt;:sh complang compile %(full_path) ; .&#x2F;build&#x2F;debug&#x2F;bin&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Some have a convenient command to compile+run in a single step, like &lt;code&gt;:sh coollang run&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
For something like html, you might just want to use your browser with &lt;code&gt;:sh xdg-open %(full_path)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s just “run”!
You don&#x27;t have to stop there. &lt;br &#x2F;&gt;
You can have filetype command harps for “lint”, “build”, “build but use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nukesor&#x2F;pueue&quot;&gt;pueue&lt;&#x2F;a&gt;”, “test”, “open docs”, “pipe my selection into the interpreter, rather than the whole file”, and any other language specific &lt;em&gt;actions&lt;&#x2F;em&gt; that you might wanna do.&lt;&#x2F;p&gt;
&lt;p&gt;What I recommend for this workflow, is to try to use the same keys for the same sort of semantic, so that they&#x27;re easier to remember. &lt;br &#x2F;&gt;
Just like always using &lt;code&gt;#&lt;&#x2F;code&gt; for the shebang register harps, remember? &lt;br &#x2F;&gt;
My “run” is always on &lt;code&gt;s&lt;&#x2F;code&gt;, my “open docs” always on &lt;code&gt;d&lt;&#x2F;code&gt;, “build” always on &lt;code&gt;b&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;a href=&quot;#piping&quot; id=&quot;piping&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;&lt;code&gt;:pipe&lt;&#x2F;code&gt; can come in useful for implementing custom code actions, by using a custom script. &lt;br &#x2F;&gt;
You could use &lt;code&gt;:insert-output&lt;&#x2F;code&gt; as a way to generate some boilerplate for a language (if, for example, it is not static (where it&#x27;d make more sense to use a register harp instead)).&lt;&#x2F;p&gt;
&lt;p&gt;As an example, you could make a command harp that generates the java class boilerplate. &lt;br &#x2F;&gt;
Usually the name of the class is the same as the name of the file, so you could use &lt;code&gt;%sh(full_path)&lt;&#x2F;code&gt;, then extract the basename, and pass it on to your script that outputs the boilerplate.&lt;&#x2F;p&gt;
&lt;p&gt;If the &lt;em&gt;input&lt;&#x2F;em&gt; to the script is not deterministic like that, you could instead use &lt;code&gt;:pipe&lt;&#x2F;code&gt; — &lt;br &#x2F;&gt;
Type in the input in the buffer, then select it and use the command harp that &lt;code&gt;:pipe&lt;&#x2F;code&gt;s it into the afforementioned script.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to all this, filetype-relative command harps can become a very useful extension to your lsps.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;directory-1&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#directory-1&quot; aria-label=&quot;Anchor link for: directory-1&quot;&gt;directory&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Some actions are &lt;em&gt;project&lt;&#x2F;em&gt; specific, not just language specific.&lt;&#x2F;p&gt;
&lt;p&gt;To “run” a markdown file, I&#x27;ll probably want to convert it to html and open that html in my browser. &lt;br &#x2F;&gt;
For this blog though, I use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;zola&quot;&gt;&lt;code&gt;zola&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
So, I made myself a &lt;em&gt;directory&lt;&#x2F;em&gt;-relative command harp that “compiles” the blog with zola and opens it in my browser.&lt;&#x2F;p&gt;
&lt;p&gt;Because of treesitters, I can&#x27;t just &lt;code&gt;cargo build --release&lt;&#x2F;code&gt; my helix fork normally, so my &lt;em&gt;language&lt;&#x2F;em&gt;-relative build harp for rust isn&#x27;t sufficient. &lt;br &#x2F;&gt;
And so, I have a project-relative harp to install my helix fork.&lt;&#x2F;p&gt;
&lt;p&gt;It doesn&#x27;t have to be so language action focused, though. &lt;br &#x2F;&gt;
Ultimately, if you find yourself running &lt;em&gt;some&lt;&#x2F;em&gt; command frequently, shell or not, for a given project, directory-relative command harps can help you. &lt;br &#x2F;&gt;
You can think of them as your personal justfile directly in your editor, that you don&#x27;t need to gitignore or commit upstream.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;buffer-1&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#buffer-1&quot; aria-label=&quot;Anchor link for: buffer-1&quot;&gt;buffer&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You can sometimes find yourself doing hyperspecific transformations in specific files, over and over again.&lt;&#x2F;p&gt;
&lt;p&gt;In my loago&lt;a href=&quot;#footnote-9&quot; id=&quot;headnote-9&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;9&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 helper script, I have this section…&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;nushell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; known&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	razor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	bed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	towels&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	vacuum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	update&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	bottle&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 15&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	keyboard&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 30&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	filter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 45&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	fsrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 60&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	toothbrush&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 122&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;…That I constantly want to sort by the &lt;em&gt;numbers&lt;&#x2F;em&gt;, rather than key names. &lt;br &#x2F;&gt;
I don&#x27;t know of a way to express this semantic directly (and so I&#x27;ll write a crystal program for this eventually), but in this file specifically all the numbers are the second &lt;em&gt;field&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
So I can use &lt;code&gt;:pipe sort -nk 2&lt;&#x2F;code&gt; as a buffer-relative command harp, to solve this usecase 🥳&lt;&#x2F;p&gt;
&lt;p&gt;This is pretty convenient — instead of feeling rushed to create a generic solution for the problem, I can for now make a hyperspecific one, and use the buffer relativity to store it in a convenient way.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;This is the conclusion part of the blog post, that sums up everything you&#x27;ve read, and provides an emotional release to all the effort you&#x27;ve spent reading. &lt;br &#x2F;&gt;
It creates a logical stop to the experience, naturally leading you to exclaim “wow! what a read”, or some such.&lt;&#x2F;p&gt;
&lt;a href=&quot;#fr-now&quot; id=&quot;fr-now&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I&#x27;ve been on and off writing this blog post for over 50 days so I wanted to spare myself writing a genuine conclusion hahahaha &lt;br &#x2F;&gt;
I&#x27;m sure you&#x27;re tired from reading, too, genuine thank you for taking the time. &lt;br &#x2F;&gt;
Hope you can now take the harp concept, and make it as, if not even &lt;em&gt;more&lt;&#x2F;em&gt; useful for yourself, as it is for me.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;sike&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#sike&quot; aria-label=&quot;Anchor link for: sike&quot;&gt;sike&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I come back yet again! &lt;br &#x2F;&gt;
It&#x27;s now 2025.12.10 (i.e. almost half a year since this post&#x27;s initial release), and I have new thoughts (and features :o)&lt;&#x2F;p&gt;
&lt;p&gt;Harp doesn&#x27;t have a “view all currently set registers” feature, half on purpose and half due to my laziness.&lt;&#x2F;p&gt;
&lt;p&gt;If you are given a chance to &lt;em&gt;look&lt;&#x2F;em&gt; at your existing registers, you will ultimately feel encouraged to &lt;em&gt;clean them up&lt;&#x2F;em&gt; all the time. &lt;br &#x2F;&gt;
It can feel like a bit of a waste of time, considering how relativities give you essentially infinite registers, that you&#x27;ll then indefinitely clean. &lt;br &#x2F;&gt;
My thought process was that if you need some sort of view to remember what key you placed some harp on, &lt;br &#x2F;&gt;
it&#x27;s probably because you placed it on an unmemorable key, and should instead re-make the harp on a better one.&lt;&#x2F;p&gt;
&lt;p&gt;This is the hotkey master in me talking, mainly: &lt;strong&gt;the&lt;&#x2F;strong&gt; thing I am best at, is creating hotkey systems. &lt;br &#x2F;&gt;
So both creating memorable hotkeys and remembering them is my forte.&lt;&#x2F;p&gt;
&lt;p&gt;My thinking works quite well for &lt;em&gt;most&lt;&#x2F;em&gt; harp actions.
There&#x27;s not much effort in making a file or cwd harp for example. &lt;br &#x2F;&gt;
But once you get into the more fancy harp actions, my approach starts to crumble.&lt;&#x2F;p&gt;
&lt;p&gt;Making &lt;em&gt;any&lt;&#x2F;em&gt; harp is somewhat of a mental energy investment: “what key should I use, that feels the most ‘correct’ for this file &#x2F; working directory &#x2F; search pattern &#x2F; etc?”, “what relativity should I use for this?”, “should I store this as a mark or as a search harp?”. &lt;br &#x2F;&gt;
This investment is worth it mainly because of how much mental energy you &lt;em&gt;save&lt;&#x2F;em&gt; in the future, over time.&lt;&#x2F;p&gt;
&lt;p&gt;You decide to pay this price, and make a somewhat complex &#x2F; long command harp. &lt;br &#x2F;&gt;
It sets up the testing environment for this project in some specific way, massively helping you iterate on it faster. &lt;br &#x2F;&gt;
You use it quite a lot, feeling sheer bliss over how productive it helps you be.&lt;&#x2F;p&gt;
&lt;p&gt;But new excitements come! &lt;br &#x2F;&gt;
You switch to working on a new project for a while, with it own harps and gimmicks.
Many months go by, and you come back to the first project again. &lt;br &#x2F;&gt;
“Uhhhhhh what was that useful harp again?”&lt;a href=&quot;#footnote-10&quot; id=&quot;headnote-10&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;10&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 — you try the most likely key that you might&#x27;ve placed it on, but it does a completely different command, maybe starting some build that now you need to annoyingly figure out how to cancel. &lt;br &#x2F;&gt;
“Hmmm what about this one?” — ‘harp &lt;code&gt;h&lt;&#x2F;code&gt; unset’ it tells you.&lt;&#x2F;p&gt;
&lt;p&gt;Well... I don&#x27;t want to just keep mashing keys until I find it.
Maybe some of my command harps are quite destructive, after all.
Ugh, it&#x27;s frustrating but I think it&#x27;s not worth trying to re-find the harp, let me remake it again.&lt;&#x2F;p&gt;
&lt;p&gt;But here&#x27;s a caveat when it comes to making things, as a developer. &lt;br &#x2F;&gt;
The first time, the energy investment is fueled by your excitement at how cool the thing you&#x27;re creating is going to be.
For example, you&#x27;re learning nushell! And making this specific command is great practice that you&#x27;re quite pumped for. &lt;br &#x2F;&gt;
But the &lt;em&gt;second&lt;&#x2F;em&gt; time solving the same exact problem, you&#x27;re not quite as excited. &lt;br &#x2F;&gt;
Well, it would be one thing if it was the same &lt;em&gt;problem&lt;&#x2F;em&gt;, but no you solved LITERALLY this already, so it feels even worse to have to redo.&lt;&#x2F;p&gt;
&lt;p&gt;This wouldn&#x27;t matter much if the command was short and simple, but you made quite a bit of a monster of a command harp. &lt;br &#x2F;&gt;
It inserts the dates in some specific way, autofills some info by curling an api, and even does your dishes for you. &lt;br &#x2F;&gt;
“Grrrr I don&#x27;t wanna do all that again”.&lt;&#x2F;p&gt;
&lt;p&gt;You toss it up as a skill issue with using harp and do indeed do it again. &lt;br &#x2F;&gt;
But this experience will be remembered by your psyche. &lt;br &#x2F;&gt;
Maybe next time, you won&#x27;t feel so ready to make a harp &lt;em&gt;as&lt;&#x2F;em&gt; complex. &lt;br &#x2F;&gt;
“What if I lose it again?”&lt;&#x2F;p&gt;
&lt;a href=&quot;#discovery&quot; id=&quot;discovery&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Yes, what I noticed over months of using harp, is that the current system &lt;em&gt;discourages&lt;&#x2F;em&gt; you from using harps to their full potential, hilariously. &lt;br &#x2F;&gt;
You will be taught to only make harps that you&#x27;re &lt;strong&gt;sure&lt;&#x2F;strong&gt; you can remember, or only if they&#x27;re easy enough to remake. &lt;br &#x2F;&gt;
The latter type you end up using once and never again, because it&#x27;s too much of a pain to try to remember where you put them.&lt;&#x2F;p&gt;
&lt;p&gt;What&#x27;s the point of all these infinite potential keys if my human brain can only remember a subsection of them!&lt;&#x2F;p&gt;
&lt;p&gt;NOT ANYMORE!&lt;&#x2F;p&gt;
&lt;p&gt;Now harp actually &lt;strong&gt;does&lt;&#x2F;strong&gt; show you all of the set registers you have. &lt;br &#x2F;&gt;
In every harp action, in every relativity. &lt;br &#x2F;&gt;
You don&#x27;t need to go into some submode to take a look — they are displayed to you automatically in the whichkey-like window&lt;a href=&quot;#footnote-11&quot; id=&quot;headnote-11&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;11&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Now you press your hotkey for command harps, and immediately see all the registers you have for your default relativity (which let&#x27;s say stays &lt;code&gt;global&lt;&#x2F;code&gt;). &lt;br &#x2F;&gt;
You press &lt;kbd&gt;.&lt;&#x2F;kbd&gt; and go into the directory relativity: the whichkey window changes to now show the command harps in the directory relativity. &lt;br &#x2F;&gt;
You can keep changing relativities, or get&#x2F;set, and throughout all of that, the whichkey menu will continue reminding you what you currently have set.&lt;&#x2F;p&gt;
&lt;p&gt;This reopens harp possibilities to insane extents! &lt;br &#x2F;&gt;
I&#x27;ve already noticed just how much more harps I&#x27;m using, thanks to me never &lt;em&gt;losing&lt;&#x2F;em&gt; any. &lt;br &#x2F;&gt;
If I can be sure I can &lt;em&gt;keep&lt;&#x2F;em&gt; the harp with me forever, I feel a lot more &lt;em&gt;encouraged&lt;&#x2F;em&gt; to completely abuse them 🚀 &lt;br &#x2F;&gt;
(which is the whole point!!)&lt;&#x2F;p&gt;
&lt;p&gt;I forked a gtk theme and am “fixing” it; but the file is fucking six to seven thousand lines long so it&#x27;s a massive pain in the asss to traverse. &lt;br &#x2F;&gt;
Despite that, before making this whichkey feature, I was rawdogging travel for the most part! No harps for what can so benefit from them. &lt;br &#x2F;&gt;
But &lt;em&gt;after&lt;&#x2F;em&gt; implementing it? Oooh boy!&lt;&#x2F;p&gt;
&lt;p&gt;I made a command harp to reopen gtk3-widget-factory on loop for me (useful to test how my changes look),
started using marks a lot more frequently for quick “remember this position” movements,
made command harps for converting colors (no hsl in gtk3 😭),
register harps for common colors I&#x27;m using in the theme,
and now also &lt;em&gt;search&lt;&#x2F;em&gt; harps to jump to various rules quickly.&lt;&#x2F;p&gt;
&lt;p&gt;I am now &lt;em&gt;actually&lt;&#x2F;em&gt; living the harp dream, making use of them as much as I intended for them to be used. &lt;br &#x2F;&gt;
I used to say quite frequently: “oh yeah even I underuse harps, I should use them more” — this was due to a misdesign!&lt;&#x2F;p&gt;
&lt;a href=&quot;#bad-defaults&quot; id=&quot;bad-defaults&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Even &lt;em&gt;before&lt;&#x2F;em&gt; reigniting my usage of harps, I noticed how &lt;em&gt;uncomfortable&lt;&#x2F;em&gt; it is to switch relativites, with them all being on keys that aren&#x27;t on the home row. &lt;br &#x2F;&gt;
&lt;kbd&gt;,&lt;&#x2F;kbd&gt;, &lt;kbd&gt;.&lt;&#x2F;kbd&gt;, &lt;kbd&gt;;&lt;&#x2F;kbd&gt;, &lt;kbd&gt;&#x27;&lt;&#x2F;kbd&gt; all make &lt;em&gt;sense&lt;&#x2F;em&gt; as defaults, but if you use relativities a LOT, pressing those keys becomes jarring after a while.&lt;&#x2F;p&gt;
&lt;p&gt;I changed them to &lt;kbd&gt;j&lt;&#x2F;kbd&gt; → buffer, &lt;kbd&gt;k&lt;&#x2F;kbd&gt; → global, &lt;kbd&gt;l&lt;&#x2F;kbd&gt; → directory. &lt;br &#x2F;&gt;
Yay, now they&#x27;re all on the home row! And are a &lt;em&gt;lot&lt;&#x2F;em&gt; more pleasant to reach thanks to it. &lt;br &#x2F;&gt;
But they are &lt;em&gt;ridiculous&lt;&#x2F;em&gt; as defaults...&lt;&#x2F;p&gt;
&lt;p&gt;Because now you can&#x27;t use &lt;kbd&gt;j&lt;&#x2F;kbd&gt;&#x2F;&lt;kbd&gt;k&lt;&#x2F;kbd&gt;&#x2F;&lt;kbd&gt;l&lt;&#x2F;kbd&gt; as &lt;em&gt;registers&lt;&#x2F;em&gt;! &lt;br &#x2F;&gt;
I&#x27;m okay losing out on that, but forcing &lt;em&gt;you&lt;&#x2F;em&gt; to, too, feels pretty wack.&lt;&#x2F;p&gt;
&lt;p&gt;So now the hotkeys are configurable! &lt;br &#x2F;&gt;
You can decide for yourself: what keys switch to what relativity, what key switches get&#x2F;set (instead of &lt;kbd&gt;Space&lt;&#x2F;kbd&gt;), and what keys do the mystery XXX and YYY I&#x27;m going to explain in the next section.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;em&gt;defaults&lt;&#x2F;em&gt; stay the “reasonable but kinda yuck to use” &lt;kbd&gt;,&lt;&#x2F;kbd&gt;, &lt;kbd&gt;.&lt;&#x2F;kbd&gt;, &lt;kbd&gt;;&lt;&#x2F;kbd&gt;, &lt;kbd&gt;&#x27;&lt;&#x2F;kbd&gt;, &lt;kbd&gt;Space&lt;&#x2F;kbd&gt;, for the record.&lt;&#x2F;p&gt;
&lt;a href=&quot;#delete&quot; id=&quot;delete&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Now that you can &lt;em&gt;view&lt;&#x2F;em&gt; your set registers, you have to be able to delete some of them, too; so that all the ones you are no longer using aren&#x27;t creating a visual mess that takes up half your screen.&lt;&#x2F;p&gt;
&lt;p&gt;I do still think that it&#x27;s unfortunate that you&#x27;ll be encouraged to clean things up (often a bit of a waste of time), but it&#x27;s just SO worth it considering how much more easily you can rely on and abuse harps, now that you can see them.&lt;&#x2F;p&gt;
&lt;p&gt;When you invoke a harp action, you start in &lt;code&gt;get&lt;&#x2F;code&gt; mode and get a view of all of the set registers. &lt;br &#x2F;&gt;
At this point, you can press &lt;kbd&gt;Backspace&lt;&#x2F;kbd&gt;: after that, the next key that you press will get &lt;em&gt;deleted&lt;&#x2F;em&gt;, the ui will update to reflect that deletion, and you&#x27;ll go back to &lt;code&gt;get&lt;&#x2F;code&gt; mode.&lt;&#x2F;p&gt;
&lt;p&gt;So &lt;code&gt;del&lt;&#x2F;code&gt; is a new mode, along with &lt;code&gt;get&lt;&#x2F;code&gt; and &lt;code&gt;set&lt;&#x2F;code&gt;, but unlike the latter two, it only stays for a single key and &lt;strong&gt;doesn&#x27;t&lt;&#x2F;strong&gt; finish &#x2F; close the harp action (only brings you back to &lt;code&gt;get&lt;&#x2F;code&gt;). &lt;br &#x2F;&gt;
So you can press &lt;kbd&gt;Backspace&lt;&#x2F;kbd&gt;&lt;kbd&gt;a&lt;&#x2F;kbd&gt;&lt;kbd&gt;Backspace&lt;&#x2F;kbd&gt;&lt;kbd&gt;b&lt;&#x2F;kbd&gt;&lt;kbd&gt;Backspace&lt;&#x2F;kbd&gt;&lt;kbd&gt;c&lt;&#x2F;kbd&gt; to delete three different registers in a sequence — you enter the &lt;code&gt;del&lt;&#x2F;code&gt; mode three different times here.&lt;&#x2F;p&gt;
&lt;p&gt;At first, I made the del mode “stay”: once you pressed &lt;kbd&gt;Backspace&lt;&#x2F;kbd&gt;, all of the following keys would be deletions, and you&#x27;d need to press &lt;kbd&gt;Space&lt;&#x2F;kbd&gt; to go back to &lt;code&gt;get&lt;&#x2F;code&gt; when you wanted to. &lt;br &#x2F;&gt;
Very quickly I started to accidentally delete harps that I was meaning to &lt;code&gt;get&lt;&#x2F;code&gt; 💀 &lt;br &#x2F;&gt;
So I changed it to the “chord the next key” variation that is the current behavior — it seems a lot more natural.&lt;&#x2F;p&gt;
&lt;p&gt;If you press &lt;kbd&gt;Backspace&lt;&#x2F;kbd&gt; and go “nevermind actually”, you can go back to &lt;code&gt;get&lt;&#x2F;code&gt; without deleting anything by pressing &lt;kbd&gt;Space&lt;&#x2F;kbd&gt;, or close the action altogether by pressing &lt;kbd&gt;Escape&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There will be some situations where you want to delete &lt;em&gt;all&lt;&#x2F;em&gt; of the registers in a section, and for that you can press &lt;kbd&gt;Alt+Backspace&lt;&#x2F;kbd&gt;, instead of spamming &lt;kbd&gt;Backspace&lt;&#x2F;kbd&gt; + a key. &lt;br &#x2F;&gt;
That hotkey works regardless of the mode you&#x27;re currently in (get &#x2F; set &#x2F; del), and will put you into &lt;code&gt;set&lt;&#x2F;code&gt; after clearing the registers. &lt;br &#x2F;&gt;
The thinking here is that you&#x27;re &lt;em&gt;probably&lt;&#x2F;em&gt; cleaning things up because you want to set a new harp on a blank canvas 🎨&lt;&#x2F;p&gt;
&lt;p&gt;These two hotkeys are the mystery XXX and YYY I mentioned! So you can change them too 😌&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;footnotes&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-1&quot; id=&quot;footnote-1&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 To your possible surprise, yes this is a &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;optimizing-paths&#x2F;&quot;&gt;real file path&lt;&#x2F;a&gt; I have. It&#x27;s for this blog!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-4&quot; id=&quot;footnote-4&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;4&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 Which is &lt;kbd&gt;p&lt;&#x2F;kbd&gt; for you, but &lt;kbd&gt;o&lt;&#x2F;kbd&gt; &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;stray-from-defaults&#x2F;&quot;&gt;for me&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
Also, you don&#x27;t necessarily have to &lt;em&gt;paste&lt;&#x2F;em&gt; it. You can replace your selection with it, for example! &lt;br &#x2F;&gt;
So register harps simply blammo the text into your &lt;code&gt;default-yank-register&lt;&#x2F;code&gt;, and then you can use it how you normally would — no specialcasey usage required!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-5&quot; id=&quot;footnote-5&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;5&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 Like this one!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-6&quot; id=&quot;footnote-6&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;6&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 The global one is still the &lt;em&gt;actual&lt;&#x2F;em&gt; default though, as usual.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-7&quot; id=&quot;footnote-7&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;7&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 Although my fork introduces a :random command that lets you randomize the contents of your selections, rather than specifically lines.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-9&quot; id=&quot;footnote-9&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;9&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 A chore-tracking program of mine that I will eventually write a blog post about.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-10&quot; id=&quot;footnote-10&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;10&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 Hell, do you even remember that that harp exists?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-11&quot; id=&quot;footnote-11&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;11&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 I&#x27;m referring to the menu that appears on the bottom right when you use chorded mappings, or when you try to &lt;code&gt;select_register&lt;&#x2F;code&gt;. In helix terms, its proper name is &lt;code&gt;auto-info&lt;&#x2F;code&gt; — which is a stupid and unmemorable name.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>zoxide misbehavior</title>
          <pubDate>Sun, 08 Jun 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/zoxide-misbehavior/</link>
          <guid>https://axlefublr.github.io/zoxide-misbehavior/</guid>
          <description xml:base="https://axlefublr.github.io/zoxide-misbehavior/">&lt;p&gt;I just found a very surprising behavior zoxide gives fish users, that might be part of the reason why zoxide always felt so useless to me in the past.&lt;&#x2F;p&gt;
&lt;p&gt;I noticed that one of my directories spiked up in its weight every so often; consistently it would get to the maximum, 9999, while I for sure didn&#x27;t zoxide to it nearly that often. &lt;br &#x2F;&gt;
The reason why this is an issue, is because of how zoxide cleans directories: &lt;br &#x2F;&gt;
If a directory&#x27;s weight is too small, &lt;em&gt;compared to the highest directory&lt;&#x2F;em&gt;, the directory may get removed from the zoxide database, being considered unimportant. &lt;br &#x2F;&gt;
But I don&#x27;t even need the spiking directory to be zoxided at all! I navigate to it using a different method of mine, that I&#x27;m currrently writing another blog post about. &lt;br &#x2F;&gt;
So having it destroy the other directories, that I &lt;strong&gt;do&lt;&#x2F;strong&gt; heavily want zoxided, is quite problematic.&lt;&#x2F;p&gt;
&lt;p&gt;I looked through all my config, and all the places where I use the &lt;code&gt;z&lt;&#x2F;code&gt; alias — none of them could&#x27;ve led to me spiking that directory. &lt;br &#x2F;&gt;
The directory I&#x27;m talking about is &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;magazines&#x2F;&quot;&gt;&lt;code&gt;magazine&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; — every time I modify a file in that directory, a fish function gets ran that &lt;em&gt;&lt;code&gt;cd&lt;&#x2F;code&gt;s into the directory&lt;&#x2F;em&gt; and makes a commit. &lt;br &#x2F;&gt;
I made sure that it uses specifically &lt;code&gt;cd&lt;&#x2F;code&gt; rather than &lt;code&gt;z&lt;&#x2F;code&gt; when I made it, because obviously I don&#x27;t want to spike a directory due to a non-interactive, automated action.&lt;&#x2F;p&gt;
&lt;p&gt;So I decided to look into what fish code the below line in my config actually executes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;zoxide&lt;&#x2F;span&gt;&lt;span&gt; init fish |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; source&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;My assumption was that it gives me the &lt;code&gt;z&lt;&#x2F;code&gt; alias, which increments directories I travel to &lt;em&gt;using it&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
But imagine my terror when I realize that it&#x27;s not the semantic it actually uses!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;zoxide init fish&lt;&#x2F;code&gt; actually installs a hook on the &lt;code&gt;$PWD&lt;&#x2F;code&gt; variable; &lt;br &#x2F;&gt;
Every time your current working directory (&lt;code&gt;$PWD&lt;&#x2F;code&gt;) changes, that directory is incremented. &lt;br &#x2F;&gt;
There is nothing about the &lt;code&gt;z&lt;&#x2F;code&gt; alias in specific that increments directories — &lt;em&gt;any&lt;&#x2F;em&gt; method of getting to them does!&lt;&#x2F;p&gt;
&lt;p&gt;That is in theory nice, but in practice it easily makes various directories spike up unfairly; if you do any sort of automatic &#x2F; non-interactive scripting, you might be affected by this.&lt;&#x2F;p&gt;
&lt;p&gt;The simple fix for this issue is to do the following instead:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; status&lt;&#x2F;span&gt;&lt;span&gt; is-interactive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;  zoxide&lt;&#x2F;span&gt;&lt;span&gt; init fish |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; source&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;  alias&lt;&#x2F;span&gt;&lt;span&gt; z cd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you are in an interactive shell session, initialize the hook and give me the &lt;code&gt;z&lt;&#x2F;code&gt; alias. If not, make &lt;code&gt;z&lt;&#x2F;code&gt; just act like &lt;code&gt;cd&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is pretty good, but leaves a poor taste in my mouth. &lt;br &#x2F;&gt;
The semantic in my brain is: “If I&#x27;m using &lt;code&gt;z&lt;&#x2F;code&gt;, that&#x27;s because I want to increment the directory. If I don&#x27;t, I use &lt;code&gt;cd&lt;&#x2F;code&gt;.” &lt;br &#x2F;&gt;
I very much may want to zoxide increment some directory non-interactively too!&lt;&#x2F;p&gt;
&lt;p&gt;A simple usecase I can immediately think of, is some script that sets up all active projects I&#x27;m working on, and zoxides into all of them so that I can jump to them later more easily. &lt;br &#x2F;&gt;
If I can come up with a genuinely viable usecase like that on the spot, I&#x27;m sure that there will be other situations where I don&#x27;t even realize I want to zoxide! &lt;br &#x2F;&gt;
I feel it&#x27;s much better to just carry the simpler semantic of “&lt;code&gt;z&lt;&#x2F;code&gt; to increment, &lt;code&gt;cd&lt;&#x2F;code&gt; to not”, rather than “&lt;code&gt;z&lt;&#x2F;code&gt; to increment, unless it&#x27;s not an interactive session, …”.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s what I put into my config, to achieve that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;zoxide&lt;&#x2F;span&gt;&lt;span&gt; init fish |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; source&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt; __zoxide_hook&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt; __zoxide_z&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    set&lt;&#x2F;span&gt;&lt;span&gt; -l argc (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;builtin&lt;&#x2F;span&gt;&lt;span&gt; count &lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;argv)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; test &lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;argc -eq 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        __zoxide_cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;HOME&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    else if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;argv&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; = -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        __zoxide_cd&lt;&#x2F;span&gt;&lt;span&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    else if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;argc -eq 1 -a -d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;argv[1]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        __zoxide_cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;argv[1]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        command&lt;&#x2F;span&gt;&lt;span&gt; zoxide add -- (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;__zoxide_pwd&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    else if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;argc -eq 2 -a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;argv[1] = --&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        __zoxide_cd&lt;&#x2F;span&gt;&lt;span&gt; -- &lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;argv[2]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        command&lt;&#x2F;span&gt;&lt;span&gt; zoxide add -- (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;__zoxide_pwd&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        set&lt;&#x2F;span&gt;&lt;span&gt; -l result (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;command&lt;&#x2F;span&gt;&lt;span&gt; zoxide query --exclude (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;__zoxide_pwd&lt;&#x2F;span&gt;&lt;span&gt;) -- &lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;argv)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;        and&lt;&#x2F;span&gt;&lt;span&gt; __zoxide_cd &lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;        and&lt;&#x2F;span&gt;&lt;span&gt; command zoxide add -- (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;__zoxide_pwd&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice how now the &lt;code&gt;| source&lt;&#x2F;code&gt; line runs &lt;em&gt;always&lt;&#x2F;em&gt;, regardless of if I&#x27;m in an interactive session or not. &lt;br &#x2F;&gt;
Then, I disable the &lt;code&gt;$PWD&lt;&#x2F;code&gt; variable hook. &lt;br &#x2F;&gt;
Doing so makes &lt;code&gt;z&lt;&#x2F;code&gt; practically just act like &lt;code&gt;cd&lt;&#x2F;code&gt;, so to give it back the power of incrementing, I add in &lt;code&gt;command zoxide add -- (__zoxide_pwd)&lt;&#x2F;code&gt; in the branches where incrementing makes sense.&lt;&#x2F;p&gt;
&lt;p&gt;In the future, zoxide devs might update the &lt;code&gt;__zoxide_z&lt;&#x2F;code&gt; function to make it better in various ways; So if you&#x27;re reading this blog post in the future, let me explain how I figured out which function to even modify, so that you can &lt;em&gt;recreate it&lt;&#x2F;em&gt;, rather than copy a possibly outdated version directly above.&lt;&#x2F;p&gt;
&lt;p&gt;First, do &lt;code&gt;type z&lt;&#x2F;code&gt; — this will show you that &lt;code&gt;z&lt;&#x2F;code&gt; is a fish function, that calls &lt;code&gt;__zoxide_z&lt;&#x2F;code&gt; inside of it. &lt;br &#x2F;&gt;
Now, do &lt;code&gt;funced __zoxide_z&lt;&#x2F;code&gt; to open the function&#x27;s source in your editor; Copy it to your clipboard so that you can blammo it in your &lt;code&gt;config.fish&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Add the &lt;code&gt;command zoxide add -- (__zoxide_pwd)&lt;&#x2F;code&gt; to the various branches similar to how I do above.&lt;&#x2F;p&gt;
&lt;p&gt;To find the function that sets up a hook in the first place, I simply piped &lt;code&gt;zoxide init fish&lt;&#x2F;code&gt; into my pager, and looked through the code. I noticed &lt;code&gt;--on-variable&lt;&#x2F;code&gt;, and the rest is history.&lt;&#x2F;p&gt;
&lt;p&gt;The reason why we aren&#x27;t just modifying the functions directly with &lt;code&gt;funced&lt;&#x2F;code&gt; (which you can usually do), is because they&#x27;re defined dynamically every time you run your shell, rather than being &lt;code&gt;funcsave&lt;&#x2F;code&gt;d and staying as a file. &lt;br &#x2F;&gt;
So if we were to edit the functions directly, they&#x27;d only stay modified for the current session, rather than all future sessions. &lt;br &#x2F;&gt;
That&#x27;s why we need to blammo directly into our config.&lt;&#x2F;p&gt;
&lt;p&gt;Now that things are working correctly, I can finally &lt;em&gt;trust&lt;&#x2F;em&gt; zoxide to work as expected. &lt;br &#x2F;&gt;
I won&#x27;t have to worry about initialized directories randomly disappearing, and with &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;optimizing-paths&#x2F;&quot;&gt;another thing I did&lt;&#x2F;a&gt;, my zoxide is overpowered now.&lt;&#x2F;p&gt;
&lt;p&gt;🍐🚀&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>optimizing paths</title>
          <pubDate>Fri, 06 Jun 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/optimizing-paths/</link>
          <guid>https://axlefublr.github.io/optimizing-paths/</guid>
          <description xml:base="https://axlefublr.github.io/optimizing-paths/">&lt;p&gt;The default paths that you start with, and the paths you might end up creating naturally, can be quite inconvenient to work with.&lt;&#x2F;p&gt;
&lt;p&gt;In your home directory, you probably have &lt;code&gt;Documents&lt;&#x2F;code&gt;, &lt;code&gt;Downloads&lt;&#x2F;code&gt;, &lt;code&gt;Pictures&lt;&#x2F;code&gt;, &lt;code&gt;Videos&lt;&#x2F;code&gt;, etc. &lt;br &#x2F;&gt;
To follow the semantic, you might create directories like &lt;code&gt;Programming&lt;&#x2F;code&gt;, &lt;code&gt;Notes&lt;&#x2F;code&gt;, and the like. &lt;br &#x2F;&gt;
All of them are pretty long words, and annoyingly they all start with an uppercase letter: neither of that helps if you need to type out full paths to things pretty often.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately I do: my biggest usecase is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;eli&#x2F;setup&#x2F;dode.fish&quot;&gt;how I handle program setups&lt;&#x2F;a&gt;, but typing out paths comes up in all sorts of places. &lt;br &#x2F;&gt;
&lt;code&gt;~&#x2F;Programming&#x2F;Projects&#x2F;Mine&#x2F;Rust&#x2F;2025&lt;&#x2F;code&gt; quickly becomes up exhausting to type in, over time. &lt;br &#x2F;&gt;
Tab completing paths &lt;em&gt;helps&lt;&#x2F;em&gt;, but has other issues that I&#x27;ll go over in another upcoming blog post&lt;a href=&quot;#footnote-1&quot; id=&quot;headnote-1&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
.&lt;&#x2F;p&gt;
&lt;p&gt;To minimize effort of typing in paths, as well as travelling to such paths, some time ago I renamed most of my directory structure to all be single characters, basically. Look at the tree below:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  r&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    forks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    proj&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    binaries&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    backup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    info&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tools&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      memes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      themes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      logos&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      icons&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      screenshot1.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      screenshot2.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      screenvideo.mp4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    torrent.torrent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  w&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    random-download.jpeg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The core directories, that I&#x27;ll be typing in the most often, are all single characters. But deeper directories are named normally.&lt;&#x2F;p&gt;
&lt;p&gt;This worked pretty well! Now to get to my screenshots directory, I simply need to type out &lt;code&gt;~&#x2F;i&#x2F;s&lt;&#x2F;code&gt;, rather than &lt;code&gt;~&#x2F;Pictures&#x2F;screenshots&lt;&#x2F;code&gt;&lt;a href=&quot;#footnote-2&quot; id=&quot;headnote-2&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
.
But there are two things that this approach misses.&lt;&#x2F;p&gt;
&lt;p&gt;First, it&#x27;s ugly. &lt;br &#x2F;&gt;
Seeing &lt;code&gt;~&#x2F;r&#x2F;proj&#x2F;harp&lt;&#x2F;code&gt; in my prompt just feels kinda bad :&#x2F; &lt;br &#x2F;&gt;
It&#x27;s extra uglified by the fact that the core directories &lt;em&gt;are&lt;&#x2F;em&gt; single letters, but deeper directories aren&#x27;t, so the path ends up looking unbalanced.&lt;&#x2F;p&gt;
&lt;p&gt;Second, it&#x27;s a massive pain for search for. &lt;br &#x2F;&gt;
If you want to look for &lt;code&gt;Pictures&lt;&#x2F;code&gt;, you might need to filter out the normal word “pictures”, sure, but ultimately you&#x27;re still narrowing things down somewhat. &lt;br &#x2F;&gt;
But searching for &lt;code&gt;i&lt;&#x2F;code&gt;…&lt;&#x2F;p&gt;
&lt;p&gt;I can do &lt;code&gt;i&#x2F;&lt;&#x2F;code&gt;, but then I&#x27;m making the assumption that I immediately refer to another path fragment that is in &lt;code&gt;i&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I could &lt;code&gt;&#x2F;i&lt;&#x2F;code&gt;, but then I&#x27;m possibly missing myself programmatically appending the path &lt;code&gt;i&lt;&#x2F;code&gt; to my home directory (think &lt;code&gt;home_dir + &quot;i&quot;&lt;&#x2F;code&gt;). &lt;br &#x2F;&gt;
&lt;code&gt;\bi\b&lt;&#x2F;code&gt; will show me way too many results.&lt;&#x2F;p&gt;
&lt;p&gt;So no matter how I search, I either have to filter through too many things, or I possibly miss some cases where I &lt;em&gt;do&lt;&#x2F;em&gt; still use the path I want to search for.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, I&#x27;m not doing zoxide any favors. &lt;br &#x2F;&gt;
The core directories might as well be impossible to zoxide to, since their queries would be so non-unique; but they&#x27;re short specifically so that I &lt;em&gt;don&#x27;t have to&lt;&#x2F;em&gt; use zoxide to get to them, to be fair. &lt;br &#x2F;&gt;
But then the deeper directories come back to being normal, common words, so zoxiding to them is &lt;em&gt;also&lt;&#x2F;em&gt; a pain, just of a different genre.&lt;&#x2F;p&gt;
&lt;p&gt;Yesterday, I decided to take on the grueling task of renaming and restructuring directories in my &lt;code&gt;~&lt;&#x2F;code&gt;, to handle all of my concerns.&lt;&#x2F;p&gt;
&lt;p&gt;I had multiple requirements for the new names:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Has to be a short name, but more than 2 characters. &lt;br &#x2F;&gt;
It will still be fast and easy to type in, while not looking too unbalanced and ugly.&lt;&#x2F;li&gt;
&lt;li&gt;Has to be gibberish. &lt;br &#x2F;&gt;
Making it way easier to search for precisely, and making it ideal for zoxide, as a nice side bonus.&lt;&#x2F;li&gt;
&lt;li&gt;Has to &lt;em&gt;feel&lt;&#x2F;em&gt; nice to type in. &lt;br &#x2F;&gt;
Following the point that paths are something I&#x27;ll be typing out again and again in the future, I should have a comfortable time doing so.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Here&#x27;s the tree that I ended up with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ack&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    dot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    eli&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    foe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lai&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ork&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    wks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  go&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  iwm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    dls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lwkc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    msk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    osl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rnt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sco&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tox&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    twemoji&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    vdi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  wlx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, almost all of the directories are complete gibberish. Except go I guess. They really couldn&#x27;t&#x27;ve made it &lt;code&gt;.go&lt;&#x2F;code&gt; instead 🙄 &lt;br &#x2F;&gt;
I sat down, and naturally followed where my fingers like to go after typing each letter. &lt;br &#x2F;&gt;
After I type &lt;code&gt;f&lt;&#x2F;code&gt;, what letter feels nice to type in next? &lt;br &#x2F;&gt;
Then, I considered what directories are going to come after which directories.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;fes&lt;&#x2F;code&gt;, for example, will be coming after typing in &lt;code&gt;~&#x2F;&lt;&#x2F;code&gt;; both ~ and &#x2F; are on the right side of the keyboard (for me), so that&#x27;s why &lt;code&gt;fes&lt;&#x2F;code&gt; is so left-focused. &lt;br &#x2F;&gt;
All the directories inside of &lt;code&gt;fes&lt;&#x2F;code&gt; will come after &lt;code&gt;fes&lt;&#x2F;code&gt;, obviously, so now I optimize their names according to that. &lt;br &#x2F;&gt;
After a heavy left-side, I now introduce the right side keys quite a bit more.&lt;&#x2F;p&gt;
&lt;p&gt;I figured out what felt good by repetitively typing in the full path to the directory, and feeling it out. &lt;br &#x2F;&gt;
For example, &lt;code&gt;fes&lt;&#x2F;code&gt; was first &lt;code&gt;int&lt;&#x2F;code&gt;!&lt;a href=&quot;#footnote-3&quot; id=&quot;headnote-3&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 &lt;br &#x2F;&gt;
But after typing it out a bunch of times, I noticed that pressing &lt;code&gt;n&lt;&#x2F;code&gt; so close after &lt;code&gt;~&#x2F;&lt;&#x2F;code&gt; simply didn&#x27;t feel that good; which is a big nono for such a core, commonly typed directory. Additionally, &lt;code&gt;int&lt;&#x2F;code&gt; is a real thing that may come up in searches, as a false positive, so that&#x27;s another reason to not use it.&lt;&#x2F;p&gt;
&lt;p&gt;After making the highest level directories, I went on to rename a bunch of directories inside of there. Look at a tree again, but now with context of how the directory used to be called.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fes &amp;lt;- r&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ack &amp;lt;- backup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    bin &amp;lt;- binaries&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    dot &amp;lt;- dotfiles&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    eli &amp;lt;- auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    foe &amp;lt;- info&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lai &amp;lt;- proj&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ork &amp;lt;- forks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    wks &amp;lt;- wks, actually. this one hasn&amp;#39;t changed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  go&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  iwm &amp;lt;- i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    dls     &amp;lt;- didn&amp;#39;t exist&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lwkc    &amp;lt;- we don&amp;#39;t talk about this one&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    msk     &amp;lt;- mus&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    osl     &amp;lt;- e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rnt     &amp;lt;- q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sco     &amp;lt;- s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tox     &amp;lt;- tools&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    twemoji&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    vdi     &amp;lt;- v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  wlx &amp;lt;- w&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can see how a bunch of the directories took their previous name in some form, and either expanded it or collapsed it, making sure it&#x27;s gibberish. &lt;br &#x2F;&gt;
&lt;code&gt;tools&lt;&#x2F;code&gt; is a common word -&amp;gt; &lt;code&gt;tox&lt;&#x2F;code&gt; is shorter and not a real thing. &lt;br &#x2F;&gt;
&lt;code&gt;documents&lt;&#x2F;code&gt; is another word -&amp;gt; &lt;code&gt;dls&lt;&#x2F;code&gt; is unique and nice to type in. &lt;br &#x2F;&gt;
&lt;code&gt;backup&lt;&#x2F;code&gt; may even genuinely be used as a directory name all over the place -&amp;gt; &lt;code&gt;ack&lt;&#x2F;code&gt; now has a subdirectory named &lt;code&gt;tua&lt;&#x2F;code&gt; which is hilarious.&lt;&#x2F;p&gt;
&lt;p&gt;All of these directories I can now effortlessly zoxide to, &lt;em&gt;or&lt;&#x2F;em&gt; type in manually without complaining about it. I found a great balance.&lt;&#x2F;p&gt;
&lt;p&gt;A question you may have now is &quot;how the hell will you remember all of these?&quot; — that&#x27;s why the naming stage is so important to take seriously. &lt;br &#x2F;&gt;
When creating a directory name, I let the purpose of the directory guide me into naming it naturally. &lt;br &#x2F;&gt;
Basically, &lt;code&gt;ork&lt;&#x2F;code&gt; &lt;em&gt;feels&lt;&#x2F;em&gt; correct to me to contain my forks, and so is easily memorable. &lt;br &#x2F;&gt;
&lt;code&gt;lai&lt;&#x2F;code&gt; is nonsense, but it looks beautiful to me; &lt;em&gt;that&lt;&#x2F;em&gt; is what makes it makes sense to me, for the purpose of storing &lt;em&gt;my&lt;&#x2F;em&gt; projects. &lt;br &#x2F;&gt;
Because &lt;code&gt;fes&lt;&#x2F;code&gt; used to be &lt;code&gt;int&lt;&#x2F;code&gt;, &lt;code&gt;foe&lt;&#x2F;code&gt; is now really memorable to hold “info” — the path &lt;code&gt;int&#x2F;foe&lt;&#x2F;code&gt; is peak comedy to me. Similarly to &lt;code&gt;ack&#x2F;tua&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is why I cannot give any specific suggestions to what &lt;em&gt;your&lt;&#x2F;em&gt; directory names should be; what feels correctest to &lt;em&gt;you&lt;&#x2F;em&gt; will be similarly heavily personalized. I hope I could inspire you to rethink your directory structure, to make it more &lt;em&gt;enjoyable&lt;&#x2F;em&gt; to traverse and look at.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;footnotes&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-1&quot; id=&quot;footnote-1&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;harp&#x2F;&quot;&gt;Here it is&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-2&quot; id=&quot;footnote-2&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 I&#x27;ll talk about zoxide later, don&#x27;t worry. Part of god&#x27;s plan.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-3&quot; id=&quot;footnote-3&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 The subdirectory &lt;code&gt;eli&lt;&#x2F;code&gt; comes from a pun based on the upper directory being named &lt;code&gt;int&lt;&#x2F;code&gt;. If I named a future project &lt;code&gt;gents&lt;&#x2F;code&gt;, I&#x27;d have a path &lt;code&gt;~&#x2F;int&#x2F;eli&#x2F;gents&lt;&#x2F;code&gt;. Which is of course hilarious.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>autocurling</title>
          <pubDate>Tue, 13 May 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/frizz/</link>
          <guid>https://axlefublr.github.io/frizz/</guid>
          <description xml:base="https://axlefublr.github.io/frizz/">&lt;p&gt;Often times, various programs don&#x27;t provide you a way to look at the default config file locally, but do provide one in the github repo. &lt;br &#x2F;&gt;
Having to 1. need internet and 2. use my browser to get to some default config is quite meh. The documentation being the readme falls into a similar issue. &lt;br &#x2F;&gt;
Cloning the repo so that you have it locally is overkill, too.&lt;&#x2F;p&gt;
&lt;p&gt;Let me explain the idea of how I solve this problem.&lt;&#x2F;p&gt;
&lt;p&gt;You can &lt;code&gt;curl&lt;&#x2F;code&gt; files directly from github&lt;a href=&quot;#footnote-1&quot; id=&quot;headnote-1&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 by converting a normal link to a file into its raw version:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;kanata&#x2F;kanata.kbd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;…Turns into…&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;refs&#x2F;heads&#x2F;main&#x2F;kanata&#x2F;kanata.kbd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, you replace &lt;code&gt;github.com&lt;&#x2F;code&gt; with &lt;code&gt;raw.githubusercontent.com&lt;&#x2F;code&gt;, and replace &lt;code&gt;blob&lt;&#x2F;code&gt; with &lt;code&gt;refs&#x2F;heads&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I wrote a fish function that takes the link from stdin, and converts it for me:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt; lh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    read&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt; replace &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;#39;github.com&amp;#39; &amp;#39;raw.githubusercontent.com&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt; replace blob refs&#x2F;heads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which is useful because in helix, I can pipe my current selection(s) into a shell command, and replace them with the output, letting me transform github links I copied pretty painlessly!&lt;&#x2F;p&gt;
&lt;p&gt;So, once we get the raw link, we can &lt;code&gt;curl &amp;lt;the-link-here&amp;gt; -o output-file&lt;&#x2F;code&gt; to grab a remote github file into a local one. &lt;br &#x2F;&gt;
This is pretty awesome! But just grabbing the file once is not enough — it can become outdated.&lt;&#x2F;p&gt;
&lt;p&gt;My idea is to store all the links I want to keep locally, so that they can be updated daily automatically. &lt;br &#x2F;&gt;
Using a &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;magazines&#x2F;&quot;&gt;magazine&lt;&#x2F;a&gt; is awesome for this usecase, as it&#x27;s both easily accessible and modifiable — adding new links isn&#x27;t going to be bothersome.&lt;&#x2F;p&gt;
&lt;p&gt;My magazine C now contains this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;defconf&#x2F;waybar.jsonc https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;Alexays&#x2F;Waybar&#x2F;refs&#x2F;heads&#x2F;master&#x2F;resources&#x2F;config.jsonc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;defconf&#x2F;niri.kdl https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;YaLTeR&#x2F;niri&#x2F;refs&#x2F;heads&#x2F;main&#x2F;resources&#x2F;default-config.kdl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;defconf&#x2F;dunst.ini https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;dunst-project&#x2F;dunst&#x2F;refs&#x2F;heads&#x2F;master&#x2F;dunstrc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;defconf&#x2F;ov.yaml https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;noborus&#x2F;ov&#x2F;refs&#x2F;heads&#x2F;master&#x2F;ov.yaml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;source&#x2F;systemd-exponential-restart.c https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;systemd&#x2F;systemd&#x2F;refs&#x2F;heads&#x2F;main&#x2F;src&#x2F;core&#x2F;service.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First, I specify a path to where the file should be downloaded; then the actual link. &lt;br &#x2F;&gt;
The path is relative to &lt;code&gt;~&#x2F;.local&#x2F;share&#x2F;frizz&lt;&#x2F;code&gt; — a directory I created specifically for files that will be downloaded like this. &lt;br &#x2F;&gt;
I then have a fish abbreviation (similar to an alias) that &lt;code&gt;cd&lt;&#x2F;code&gt;s me to that directory and does &lt;code&gt;helix .&lt;&#x2F;code&gt; — I can quickly open a new terminal and instantly fuzzy search through my downloaded files this way.&lt;a href=&quot;#footnote-2&quot; id=&quot;headnote-2&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt; frizz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; curlie &lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;tac&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;.local&#x2F;share&#x2F;magazine&#x2F;C)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        set&lt;&#x2F;span&gt;&lt;span&gt; -l bits (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt; split &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;#39; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;curlie)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;bits[2] --create-dirs -o ~&#x2F;.local&#x2F;share&#x2F;frizz&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;bits[1]&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    notify-send&lt;&#x2F;span&gt;&lt;span&gt; frizz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the function that actually does the downloading, by reading the magazine in &lt;em&gt;reverse order&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
The reason to download specifically in reverse order, is that aside from being executed daily, this function is also executed every time magazine C &lt;em&gt;changes&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I add some new link to magazine C, and that new link gets download priority, letting me start doing things with the file quicker, while all the other links are also redownloaded just to be safe.&lt;&#x2F;p&gt;
&lt;p&gt;You can achieve this functionality just by using &lt;code&gt;inotifywait&lt;&#x2F;code&gt; directly, but I find a systemd path unit to feel safer &#x2F; more stable. &lt;br &#x2F;&gt;
Put the following in &lt;code&gt;~&#x2F;.config&#x2F;systemd&#x2F;user&#x2F;frizz.path&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;[Path]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;PathModified&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;%h&#x2F;.local&#x2F;share&#x2F;magazine&#x2F;C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;[Install]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;WantedBy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;paths.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this in &lt;code&gt;~&#x2F;.config&#x2F;systemd&#x2F;user&#x2F;frizz.service&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;[Unit]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;StartLimitBurst&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;StartLimitIntervalSec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;[Service]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;oneshot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;env fish -c frizz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then execute &lt;code&gt;systemctl --user enable --now frizz.path&lt;&#x2F;code&gt;, and you should be good to go.&lt;&#x2F;p&gt;
&lt;a href=&quot;#done&quot; id=&quot;done&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;What I like the most about my approach, is that rather than hyperfocusing on raw github links, it simply wants a &quot;link that will be &lt;code&gt;curl&lt;&#x2F;code&gt;ed&quot;. What exactly you get from it as a result is a completely different question — basically it&#x27;s quite satisfyingly flexible. &lt;br &#x2F;&gt;
Think of the many programs you&#x27;ve seen whose installer is some form of &lt;code&gt;curl link | sh&lt;&#x2F;code&gt;. You could now instead add that link to magazine C and soon open it in your editor, to confirm the safety of; &lt;em&gt;Then&lt;&#x2F;em&gt; you can manually execute it. As a bonus, you get to autoupdate that installation script, if that&#x27;s for some reason something you want to do. &lt;br &#x2F;&gt;
You can curl straight up files this way, too. If there&#x27;s some place that you can curl to download some file (that may update over time), that&#x27;s another usecase for frizz. &lt;br &#x2F;&gt;
Truthfully I don&#x27;t know the extent of this idea, but it sure feels quite powerful!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;footnotes&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-1&quot; id=&quot;footnote-1&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 As well as other git remotes I&#x27;m sure, I just don&#x27;t know how.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-2&quot; id=&quot;footnote-2&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;2&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 This was truthful at the time I wrote it, but at this point it&#x27;s a lie :p &lt;br &#x2F;&gt;
Now I use a harp&lt;a href=&quot;#footnote-3&quot; id=&quot;headnote-3&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 to get to the frizz data directory, and I have an abbreviation &lt;code&gt;e.&lt;&#x2F;code&gt; that resolves to &lt;code&gt;helix .&lt;&#x2F;code&gt;, which is somewhat hilariously significantly nicer than having to &lt;code&gt;e .&lt;&#x2F;code&gt;, which was the case before. Crazy how much of a difference really small things can make! (that&#x27;s what she said)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-3&quot; id=&quot;footnote-3&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;3&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 A &quot;mostly travelling&quot;-related concept I came up with and have been dragging along through programs I use a lot. The actual program behind this is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;harp&quot;&gt;here&lt;&#x2F;a&gt;, but for an actual introduction about what harps can &lt;em&gt;do&lt;&#x2F;em&gt; for you, read the harp section in my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;helix fork&lt;&#x2F;a&gt;. (TLDR is that you can interactively but permanently alias files and directories, for fastest access time)&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>consider sorting</title>
          <pubDate>Thu, 01 May 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/consider-sorting/</link>
          <guid>https://axlefublr.github.io/consider-sorting/</guid>
          <description xml:base="https://axlefublr.github.io/consider-sorting/">&lt;p&gt;I&#x27;m almost certain you have a problem that you either don&#x27;t realize, or don&#x27;t have a good solution for.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes in code, you need to place many things in some sort of order. And sometimes, there&#x27;s no one order that is logically significant. &lt;br &#x2F;&gt;
An example of this is configuration options.&lt;&#x2F;p&gt;
&lt;p&gt;There isn&#x27;t really an &quot;order&quot; to them, within each section: you are setting &lt;em&gt;all&lt;&#x2F;em&gt; of them.&lt;&#x2F;p&gt;
&lt;p&gt;An even more obvious example I have on hand, is a function holding fish script I have, that I use to organize and back up setup processes for various programs: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;eli&#x2F;setup&#x2F;dode.fish&quot;&gt;look here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There too, there isn&#x27;t some particular order to them. Sure, in the initial setup I&#x27;ll make fish work, then git, then niri, then probably waybar; but aside from those &quot;blocking&quot; setups, that basically act like dependencies for other setups, there is no obvious order — most things simply behave like a set, rather than an array.&lt;&#x2F;p&gt;
&lt;p&gt;Something that I started doing some time ago, is explicitly &lt;em&gt;sorting&lt;&#x2F;em&gt; things like this.&lt;&#x2F;p&gt;
&lt;p&gt;Now, looking through this set is organized; it will always be obvious where a given thing is, and additionally it will always be obvious where to insert a new thing, without making the file more messy.&lt;&#x2F;p&gt;
&lt;p&gt;I memorized the indexes of the letters of the alphabet using &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;how-to-anki&#x2F;&quot;&gt;anki&lt;&#x2F;a&gt;, to make this type of manual sorting way easier for me. No need to sing the alphabet song every time. &lt;br &#x2F;&gt;
But that&#x27;s just for the manual sorting I do, like in the setup function holder above; usually things that you may consider sorting are single lines, and those you can easily sort with a command or some such, if you use a half decent text editor.&lt;&#x2F;p&gt;
&lt;p&gt;However even with that functionality, it can still feel a bit too manual to feel worth it, not gonna lie.&lt;&#x2F;p&gt;
&lt;p&gt;This is why I wrote a neat lil program called &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;eli&#x2F;partialsort.rs&quot;&gt;partialsort.rs&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This isn&#x27;t exactly a promo, as the program is written as a &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;rust-scripting&#x2F;&quot;&gt;wks script&lt;&#x2F;a&gt; rather than a normal repo-ed rust program that you could install more easily&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The idea of it, is that I can mark sections of files with &lt;code&gt;[[sort on]]&lt;&#x2F;code&gt; and &lt;code&gt;[[sort off]]&lt;&#x2F;code&gt;. When I run the formatter over the file, the lines between these two markers get sorted!&lt;&#x2F;p&gt;
&lt;!-- [[sort off]] --&gt;
&lt;p&gt;My &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;helix fork&lt;&#x2F;a&gt; then has an integration that allows you to run a global formatter (that can happen to be partialsort.rs) on write. If you use something like neovim, adding a global formatter should, interestingly, be both more &lt;em&gt;and&lt;&#x2F;em&gt; less painful. &lt;br &#x2F;&gt;
Another option I used to use, is to run a formatter like that on git commit hook.&lt;&#x2F;p&gt;
&lt;p&gt;Regardless of how you may simplify the process of sorting things for you, you will soon find out how much cleaner things become. &lt;br &#x2F;&gt;
Especially for various configuration files, which is my main usecase. After writing the config file for the first time, you are likely to be coming back to it again and again, changing, removing, and adding stuff. &lt;br &#x2F;&gt;
It gets so much easier and &lt;em&gt;faster&lt;&#x2F;em&gt; to do so, when the items you intend to change are set in an obvious order! :D&lt;&#x2F;p&gt;
&lt;p&gt;Consider sorting!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>change wallpaper on wake</title>
          <pubDate>Wed, 30 Apr 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/on-wake-actions/</link>
          <guid>https://axlefublr.github.io/on-wake-actions/</guid>
          <description xml:base="https://axlefublr.github.io/on-wake-actions/">&lt;p&gt;I managed to do something really neat.&lt;&#x2F;p&gt;
&lt;p&gt;I wake up at almost random times, and so simply changing my wallpaper every day at 5am will be wonky. &lt;br &#x2F;&gt;
Sure, often times that does match up to be before I wake up, but other times it&#x27;s in the middle of the day for me.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;change-wallpaper&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#change-wallpaper&quot; aria-label=&quot;Anchor link for: change-wallpaper&quot;&gt;change wallpaper&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;First, we start by having a script that will actually do the wallpaper change.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;swww&lt;&#x2F;span&gt;&lt;span&gt; img -t any --transition-fps 255 --transition-duration 3 (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;propose.rs&lt;&#x2F;span&gt;&lt;span&gt; wallpaper 70% ~&#x2F;.local&#x2F;share&#x2F;magazine&#x2F;T)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;m sure you already know what it is for you, assuming that you already set up a wallpaper daemon. &lt;br &#x2F;&gt;
If you haven&#x27;t, I strongly believe &lt;code&gt;swww&lt;&#x2F;code&gt; is just directly the best one (for wayland).&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Wtf is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;eli&#x2F;propose.rs&quot;&gt;propose.rs&lt;&#x2F;a&gt;&quot; you might ask? Ah! It is proof that &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;randomization-sucks&#x2F;&quot;&gt;my idea&lt;&#x2F;a&gt; ended up being not that viable, and so I changed my approach. Irrelevant for this blog post though.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;catch-suspend&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#catch-suspend&quot; aria-label=&quot;Anchor link for: catch-suspend&quot;&gt;catch suspend&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The next step is to make the suspend handler. &lt;br &#x2F;&gt;
I assumed at first I would be able to simply use systemd&#x27;s existing mechanisms to make my script run &lt;code&gt;After=&lt;&#x2F;code&gt; suspend.target, but the docs specifically mention how that is not a thing.&lt;&#x2F;p&gt;
&lt;p&gt;Intead, you put all the scripts you want to run on suspend into &lt;code&gt;&#x2F;usr&#x2F;lib&#x2F;systemd&#x2F;system-sleep&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Two caveats with this! The scripts run twice: before &lt;em&gt;and&lt;&#x2F;em&gt; after suspend. &lt;br &#x2F;&gt;
To differentiate, they are passed either &lt;code&gt;pre&lt;&#x2F;code&gt; or &lt;code&gt;post&lt;&#x2F;code&gt; as the first argument, among other things you can learn about by reading &lt;code&gt;man systemd-sleep&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The more annoying to deal with part, is that these scripts are explicitly stated in the docs to not interact with the currently active user graphical session. In simpler words, these scripts should assume that all of your wm, waybar, and significantly &lt;em&gt;wallpaper&lt;&#x2F;em&gt; daemon aren&#x27;t a thing and won&#x27;t work, at the time of execution. &lt;br &#x2F;&gt;
Notably, this is not an issue of running on root level (which it does), that could be solved by the &lt;code&gt;-u&lt;&#x2F;code&gt; flag of &lt;code&gt;sudo&lt;&#x2F;code&gt;; This is simply a timing issue.&lt;&#x2F;p&gt;
&lt;p&gt;This is why we can&#x27;t just make &lt;em&gt;this&lt;&#x2F;em&gt; script run the wallpaper changing script — it won&#x27;t work. &lt;br &#x2F;&gt;
Instead, we will do it in a very roundabout way.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #928374;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env fish&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;argv[1] = post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    touch&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;tmp&#x2F;cami-just-suspended&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    chown&lt;&#x2F;span&gt;&lt;span&gt; axlefublr:axlefublr &#x2F;tmp&#x2F;cami-just-suspended&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When the computer wakes up (&lt;code&gt;post&lt;&#x2F;code&gt;), we will creat a file that is both accessible by root and the user. I &lt;code&gt;chown&lt;&#x2F;code&gt; it for good measure, but I&#x27;m not sure it&#x27;s necessary.&lt;&#x2F;p&gt;
&lt;p&gt;Next, we create a &lt;em&gt;user&lt;&#x2F;em&gt;-level systemd path unit. A path unit is simply a thingy that watches for filechanges. You could alternatively simply have a script that uses &lt;code&gt;inotifywait&lt;&#x2F;code&gt;, but I find a systemd unit to be more trustworthy.&lt;&#x2F;p&gt;
&lt;p&gt;Place this file as &lt;code&gt;~&#x2F;.config&#x2F;systemd&#x2F;user&#x2F;wake.path&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;[Path]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;PathExists&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;tmp&#x2F;cami-just-suspended&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;[Install]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;WantedBy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;paths.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this file as &lt;code&gt;~&#x2F;.config&#x2F;systemd&#x2F;user&#x2F;wake.service&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;[Unit]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;Requisite&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;graphical-session.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;After&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;graphical-session.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7DAEA3;&quot;&gt;[Service]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;oneshot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;rm &#x2F;tmp&#x2F;cami-just-suspended&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;home&#x2F;username&#x2F;r&#x2F;dot&#x2F;scripts&#x2F;wallpaper-change-script.fish&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To enable this, you&#x27;d run &lt;code&gt;systemctl --user enable --now wake.path&lt;&#x2F;code&gt;. Thanks to the &lt;code&gt;--now&lt;&#x2F;code&gt; flag, it will activate immediately. &lt;br &#x2F;&gt;
Thanks to the &lt;code&gt;WantedBy&lt;&#x2F;code&gt; in the &lt;code&gt;[Install]&lt;&#x2F;code&gt; section of the path unit configuration, this will autostart on your next boots 👢&lt;&#x2F;p&gt;
&lt;p&gt;Because I&#x27;m not sure how soon the suspend handling scripts come into effect, I&#x27;d reboot for good measure. &lt;br &#x2F;&gt;
But in case you don&#x27;t need to, test it out!&lt;&#x2F;p&gt;
&lt;p&gt;Sleep &#x2F; suspend the computer, then wake it up. The wallpaper should change! :D&lt;&#x2F;p&gt;
&lt;p&gt;If you set this all up, and &lt;code&gt;systemctl --user status wake.service&lt;&#x2F;code&gt; shows an error saying &quot;wallpaper-change-script.fish wasn&#x27;t found&quot;, it is entirely your fault.¹ &#x2F;j&lt;&#x2F;p&gt;
&lt;a href=&quot;#ps&quot; id=&quot;ps&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;¹ I&#x27;m making fun of the strawman reader that didn&#x27;t intuit to change &lt;code&gt;&#x2F;home&#x2F;username&#x2F;r&#x2F;dot&#x2F;scripts&#x2F;wallpaper-change-script.fish&lt;&#x2F;code&gt; to the actual location of their wallpaper changing script. &lt;br &#x2F;&gt;
In the case you forgot to chmod the script (or the suspend handling one), that&#x27;s far more understandable.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>every row modifiers</title>
          <pubDate>Mon, 14 Apr 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/erm/</link>
          <guid>https://axlefublr.github.io/erm/</guid>
          <description xml:base="https://axlefublr.github.io/erm/">&lt;p&gt;An AI hallucinated, and god am I thankful that it did.&lt;&#x2F;p&gt;
&lt;a href=&quot;#start&quot; id=&quot;start&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I&#x27;ve been trying to find reasons to finally switch to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jtroo&#x2F;kanata&quot;&gt;kanata&lt;&#x2F;a&gt;: I&#x27;ve tried it before in the past, and while it was really cool, ultimately it didn&#x27;t feel worth the effort.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;But&lt;&#x2F;strong&gt;! If I collect enough significant advantages over &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;xremap&#x2F;xremap&quot;&gt;xremap&lt;&#x2F;a&gt;, I&#x27;ll be able to power through the magnitudional task of reading through the docs, and processing the very hard concept of how remapping works in kanata.&lt;&#x2F;p&gt;
&lt;p&gt;First, my friend &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;discord.com&#x2F;users&#x2F;660129612256247845&quot;&gt;amandin&lt;&#x2F;a&gt; &lt;em&gt;swears by&lt;&#x2F;em&gt; homerow mods. I&#x27;ve tried them out before and they didn&#x27;t work out :c &lt;br &#x2F;&gt;
But maybe there&#x27;s something special about his approach that is only possible in kanata? (spoiler: yes but not his).&lt;&#x2F;p&gt;
&lt;p&gt;My &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;magazines&#x2F;&quot;&gt;magazine&lt;&#x2F;a&gt; implementation is like, 900+ lines of yaml. Hilariously, I want to add even more! But doing this with xremap is just not viable anymore... Maybe kanata has the answer, with all its extra functionality?&lt;&#x2F;p&gt;
&lt;p&gt;I was talking with chatgpt, trying to compare xremap to kanata before I decide to embark on this journey. &lt;br &#x2F;&gt;
It told me that xremap operates on a higher level than kanata: kanata using evdev, and xremap being on the OS level. &lt;br &#x2F;&gt;
For a remapping program, it&#x27;s better to be lower, so this got me convinced that I should switch to kanata!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;thank-the-hallucinaton&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#thank-the-hallucinaton&quot; aria-label=&quot;Anchor link for: thank-the-hallucinaton&quot;&gt;thank the hallucinaton!&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Turns out that both xremap and kanata operate on the same level (evdev). &lt;br &#x2F;&gt;
Thankfully I realized this only &lt;em&gt;after&lt;&#x2F;em&gt; I finished my switch to kanata: thinking that I&#x27;ll get a performance benefit (smaller delays) helped me stay motivated :3&lt;&#x2F;p&gt;
&lt;p&gt;Little did I know that I&#x27;ll be getting myself into &lt;em&gt;larger&lt;&#x2F;em&gt; delays! Because I now use home row mods 🥳&lt;&#x2F;p&gt;
&lt;h1 id=&quot;every-row-mods&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#every-row-mods&quot; aria-label=&quot;Anchor link for: every-row-mods&quot;&gt;every row mods&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The basic idea of home row mods, is for you to make &lt;kbd&gt;a&lt;&#x2F;kbd&gt;, &lt;kbd&gt;s&lt;&#x2F;kbd&gt;, &lt;kbd&gt;d&lt;&#x2F;kbd&gt;, &lt;kbd&gt;f&lt;&#x2F;kbd&gt;, &lt;kbd&gt;j&lt;&#x2F;kbd&gt;, &lt;kbd&gt;k&lt;&#x2F;kbd&gt;, &lt;kbd&gt;l&lt;&#x2F;kbd&gt;, &lt;kbd&gt;;&lt;&#x2F;kbd&gt; into tapholdy modifiers. &lt;br &#x2F;&gt;
If you just tap the key, it produces the key. If you &lt;em&gt;hold&lt;&#x2F;em&gt; the key, it becomes a modifer like &lt;kbd&gt;Shift&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The computer does not (yet) read your mind, so it needs some semantic to figure out what is a tap and what is a hold. &lt;br &#x2F;&gt;
Usually tapholdies wait for a timeout, after which the key will act as its hold variation. If you &lt;em&gt;released&lt;&#x2F;em&gt; the key before this timeout elapsed, it will fire the tap variation.&lt;&#x2F;p&gt;
&lt;p&gt;So this is pretty interesting! &lt;br &#x2F;&gt;
Your muscle memory is &lt;em&gt;strongly&lt;&#x2F;em&gt; used to keys doing their action as soon as you &lt;em&gt;press&lt;&#x2F;em&gt; them, not &lt;em&gt;release&lt;&#x2F;em&gt; them. &lt;br &#x2F;&gt;
When you first try home row modifiers, they feel very weird exactly for this reason.&lt;&#x2F;p&gt;
&lt;p&gt;But the biggest reason for why people might give up on home row modifiers, is because of the &lt;em&gt;home row&lt;&#x2F;em&gt; part. &lt;br &#x2F;&gt;
&lt;em&gt;Some&lt;&#x2F;em&gt;, but not &lt;strong&gt;all&lt;&#x2F;strong&gt; keys acting only on release feels &lt;em&gt;very&lt;&#x2F;em&gt; confusing and spotty! You can reasonably get used to this behavior if all keys acted the same way, but if only &lt;em&gt;some&lt;&#x2F;em&gt; of them do, it&#x27;s way too tricky to get comfortable with!&lt;&#x2F;p&gt;
&lt;p&gt;So I came up with a 💥ive idea: I will make &lt;em&gt;every single key&lt;&#x2F;em&gt; tapholdy, even if I don&#x27;t yet have a usecase for the hold behavior. This is just to get consistency across &lt;em&gt;all&lt;&#x2F;em&gt; keys I press (except &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt; for now, incidentally), while also allowing easier addition of extra behavior onto key holds, without having to retrain my muscle memory every time.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;an-important-caveat&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#an-important-caveat&quot; aria-label=&quot;Anchor link for: an-important-caveat&quot;&gt;an important caveat&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Having to actively wait for a timeout to elapse to use &lt;em&gt;any&lt;&#x2F;em&gt; modifier doesn&#x27;t sound like a good value proposition. &lt;br &#x2F;&gt;
This is why kanata provides an alternative variant of the usual &lt;code&gt;tap-hold&lt;&#x2F;code&gt; action: &lt;code&gt;tap-hold-release&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you press and release a key while holding a tapholdy, it will automatically be considered as a holdy. &lt;br &#x2F;&gt;
This variation is our second thing that makes tapholdies viable! I hate it when &lt;em&gt;waiting&lt;&#x2F;em&gt; is an input; but if I can learn an alternative way to use my keyboard to circumvent it, I&#x27;m far more excited about the whole idea!&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s fairly difficult to get used to, don&#x27;t get me wrong, but I assume I&#x27;ll eventually get very comfortable at making sure to release keys before releasing their respective tapholdy.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s another variation, that sounds even better, until you actually use it :p &lt;br &#x2F;&gt;
&lt;code&gt;tap-hold-press&lt;&#x2F;code&gt; considers a tapholdy to be a holdy if you &lt;em&gt;press&lt;&#x2F;em&gt; another key while holding it. &lt;br &#x2F;&gt;
Rather than press and &lt;em&gt;release&lt;&#x2F;em&gt; of the above action, &lt;em&gt;just&lt;&#x2F;em&gt; the press is enough.&lt;&#x2F;p&gt;
&lt;p&gt;This makes using modifiers heavenly! But typing normally? Hellish! &lt;br &#x2F;&gt;
You don&#x27;t realize how often you&#x27;re pressing another key before releasing the first one, until you try to use &lt;code&gt;tap-hold-press&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I encourage you to try, though! There&#x27;s probably a level of typing speed at which this doesn&#x27;t matter that much, but at mine (~75) it&#x27;s pretty unbearable.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-goodies&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-goodies&quot; aria-label=&quot;Anchor link for: the-goodies&quot;&gt;the goodies&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Now that we&#x27;ve talked about how to make tapholdies viable, let me share how I made them useful for myself!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;kanata&#x2F;kanata.kbd&quot;&gt;Here&#x27;s my kanata config.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;First, I made &lt;kbd&gt;d&lt;&#x2F;kbd&gt;&#x2F;&lt;kbd&gt;k&lt;&#x2F;kbd&gt; to holdy into &lt;kbd&gt;ctrl&lt;&#x2F;kbd&gt;, &lt;kbd&gt;s&lt;&#x2F;kbd&gt;&#x2F;&lt;kbd&gt;l&lt;&#x2F;kbd&gt; -&amp;gt; &lt;kbd&gt;shift&lt;&#x2F;kbd&gt;, &lt;kbd&gt;f&lt;&#x2F;kbd&gt;&#x2F;&lt;kbd&gt;j&lt;&#x2F;kbd&gt; -&amp;gt; &lt;kbd&gt;alt&lt;&#x2F;kbd&gt;, and &lt;kbd&gt;w&lt;&#x2F;kbd&gt;&#x2F;&lt;kbd&gt;o&lt;&#x2F;kbd&gt; -&amp;gt; &lt;kbd&gt;meta&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I never need to press &lt;kbd&gt;shift&lt;&#x2F;kbd&gt; along with &lt;kbd&gt;meta&lt;&#x2F;kbd&gt;, which allowed me to free up &lt;kbd&gt;a&lt;&#x2F;kbd&gt;&#x2F;&lt;kbd&gt;;&lt;&#x2F;kbd&gt; for other uses, where pressing possibly &lt;em&gt;all&lt;&#x2F;em&gt; modifiers (except &lt;kbd&gt;meta&lt;&#x2F;kbd&gt;) at once is significant.&lt;&#x2F;p&gt;
&lt;p&gt;So now, my tapholdy &lt;kbd&gt;a&lt;&#x2F;kbd&gt; acts as an arrow keys layer! Along with things like &lt;kbd&gt;pagedown&lt;&#x2F;kbd&gt;, &lt;kbd&gt;pageup&lt;&#x2F;kbd&gt;, &lt;kbd&gt;home&lt;&#x2F;kbd&gt;, &lt;kbd&gt;end&lt;&#x2F;kbd&gt;, &lt;kbd&gt;backspace&lt;&#x2F;kbd&gt;, &lt;kbd&gt;delete&lt;&#x2F;kbd&gt;, &lt;kbd&gt;tab&lt;&#x2F;kbd&gt;, and even &lt;kbd&gt;enter&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Back in xremap, I also had an arrow keys layer similar to this one. However, instead of being a &lt;em&gt;while held&lt;&#x2F;em&gt; layer, it was a &lt;em&gt;toggleable&lt;&#x2F;em&gt; layer, that was much more of a pain to use because even for a single arrow down I&#x27;d have to press &lt;kbd&gt;capslock+f&lt;&#x2F;kbd&gt; twice.&lt;&#x2F;p&gt;
&lt;p&gt;But now that I can just hold &lt;kbd&gt;a&lt;&#x2F;kbd&gt; instead of trying to come up with a modifier for which I have no available key, I can easily use the arrow keys layer as a &quot;while held&quot;! &lt;br &#x2F;&gt;
Absolutely stupid hotkeys like discord&#x27;s &lt;kbd&gt;ctrl+shift+alt+[down|up]&lt;&#x2F;kbd&gt; and firefox&#x27;s &lt;kbd&gt;ctrl+shift+[pgup|pgdn]&lt;&#x2F;kbd&gt; are now not just viable, but &lt;em&gt;easy&lt;&#x2F;em&gt; to press!&lt;&#x2F;p&gt;
&lt;p&gt;I value remappability in programs so strongly (and it&#x27;s part of the reason why I &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;floorp&#x2F;&quot;&gt;switched to floorp&lt;&#x2F;a&gt;) because I refuse to press the really uncomfortable default hotkeys that plague every program. &lt;kbd&gt;ctrl+f&lt;&#x2F;kbd&gt;? &lt;kbd&gt;ctrl+d&lt;&#x2F;kbd&gt;? No thank you. &lt;br &#x2F;&gt;
But now they&#x27;re not a problem!&lt;&#x2F;p&gt;
&lt;p&gt;So aside from just making things more comfortable, home row mods also allow me to &lt;em&gt;chill&lt;&#x2F;em&gt; about remapping every program I use to make it viable: since I can press anything easily now, I can just stick with the defaults of most things and not worry about it!&lt;&#x2F;p&gt;
&lt;p&gt;Tapholdy &lt;kbd&gt;;&lt;&#x2F;kbd&gt; is my numpad layer. Always hated reaching for the number row, so now I have this neat virtual numpad: 1234567890 = fdsrewvcxa &lt;br &#x2F;&gt;
Tapholdy &lt;kbd&gt;&#x2F;&lt;&#x2F;kbd&gt; leads me to the function key layer (F1-F12), and mimics the number layout of the numpad layer. F11 goes on q, F12 on z. Sue me. &lt;br &#x2F;&gt;
&lt;kbd&gt;e&lt;&#x2F;kbd&gt;, &lt;kbd&gt;i&lt;&#x2F;kbd&gt; and &lt;kbd&gt;&#x27;&lt;&#x2F;kbd&gt; are layers for the various &quot;global functionality&quot; hotkeys I used to have in xremap. &lt;br &#x2F;&gt;
Things that used to be on capslock or the meta key, possibly with extra modifiers, are just a single key away now!&lt;&#x2F;p&gt;
&lt;p&gt;I hate the effort it takes to type various symbols, like @*#`&amp;amp;, etc. This is why some time ago in xremap, I made capslock + the right side keys to output all these symbols, placed how I like! &lt;br &#x2F;&gt;
The downside is that with a single modifier, I can&#x27;t exactly place &lt;em&gt;all&lt;&#x2F;em&gt; the special characters on the keys that I&#x27;d like, and some of them still need to be on an extra modifier aside from capslock, to fit. &lt;br &#x2F;&gt;
This is why I use &lt;kbd&gt;x&lt;&#x2F;kbd&gt; and &lt;kbd&gt;c&lt;&#x2F;kbd&gt; as my &lt;em&gt;two&lt;&#x2F;em&gt; symbol layers!&lt;&#x2F;p&gt;
&lt;p&gt;Now not only do I get to place all of the symbols onto my preferred keys, but I also get a bunch of unoccupied spaces! That&#x27;s where the next thing comes in.&lt;&#x2F;p&gt;
&lt;p&gt;On linux, you can press &lt;kbd&gt;ctrl+shift+u&lt;&#x2F;kbd&gt; almost everywhere to insert a unicode symbol by typing in its codepoint. &lt;br &#x2F;&gt;
Kanata has an interesting hacky action called &lt;code&gt;unicode&lt;&#x2F;code&gt; that uses this exact mechanism, to allow you to enter unicodes on a whim.&lt;&#x2F;p&gt;
&lt;p&gt;To my great surprise, it actually works and does so consistently! So I made use of the free spaces on my symbol layer, to have them &lt;code&gt;unicode&lt;&#x2F;code&gt; other things I commonly use: “”—‼️™&lt;&#x2F;p&gt;
&lt;p&gt;But the concept of the &lt;kbd&gt;x&lt;&#x2F;kbd&gt; and &lt;kbd&gt;c&lt;&#x2F;kbd&gt; layers is still, for the most part, for &quot;special characters&quot; rather than emojis. And I use emojis a lot! &lt;br &#x2F;&gt;
So that&#x27;s why I decided to add &lt;em&gt;another&lt;&#x2F;em&gt; layer that is specifically for entering emojis. This layer uses the keys &lt;kbd&gt;r&lt;&#x2F;kbd&gt; and &lt;kbd&gt;u&lt;&#x2F;kbd&gt; so that I can comfortably use both sides of my keyboard to assign emoji shortcuts. Here are some of the emojis that are on this layer now: 😭🤯👏✍️🗣️💀🔥🚀🐐←↓↑→😋🥺❌✅&lt;&#x2F;p&gt;
&lt;h2 id=&quot;this-deserves-a-section&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#this-deserves-a-section&quot; aria-label=&quot;Anchor link for: this-deserves-a-section&quot;&gt;this deserves a section&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now onto the final tapholdy, the one that fully wraps me in excitement and awe at my decision to switch to 1. kanata 2. every row modifiers. A layer so good that it can make the entire journey worth it by itself. &lt;br &#x2F;&gt;
Meet the venerable 𝕄𝕆𝕌𝕊𝔼 𝕄𝕆𝔻𝔼&lt;&#x2F;p&gt;
&lt;p&gt;(I just went and made a doublestruck letter layer for this, lol)&lt;&#x2F;p&gt;
&lt;p&gt;I have tried many times to make mouse mode work, and have attempted multiple very different approaches. &lt;br &#x2F;&gt;
All of them ended up being constantly forgotten about, as none of them are truly &lt;em&gt;comfortable&lt;&#x2F;em&gt; to use.&lt;&#x2F;p&gt;
&lt;p&gt;Since I have so many free modifiers, and am interested in making full use of kanata, I decided to try making a mouse mode again. I did not expect for it to be this amazing!&lt;&#x2F;p&gt;
&lt;p&gt;I hold &lt;kbd&gt;Space&lt;&#x2F;kbd&gt; to enable the layer, and that&#x27;s quite important for reasons I&#x27;ll explain later. &lt;br &#x2F;&gt;
&lt;kbd&gt;h&lt;&#x2F;kbd&gt;, &lt;kbd&gt;j&lt;&#x2F;kbd&gt;, &lt;kbd&gt;k&lt;&#x2F;kbd&gt;, &lt;kbd&gt;l&lt;&#x2F;kbd&gt; move the mouse directionally.&lt;&#x2F;p&gt;
&lt;p&gt;For the first 300ms, the moving speed is quite slow. But after that, the mouse moves at a good pace. &lt;br &#x2F;&gt;
I found that, for better or worse, it&#x27;s most natural for me to get &quot;more or less there&quot; with the mouse, and then do microadjustments to actually pinpoint the place I want to click. &lt;br &#x2F;&gt;
By starting slow, I can play into this naturality: I can easily tap multiple times to adjust the precise position, but move plentily fast on hold!&lt;&#x2F;p&gt;
&lt;p&gt;As I mentioned, usually the mouse mode is something I didn&#x27;t use in normal operation, but instead only when I felt like being extra. But &lt;em&gt;this&lt;&#x2F;em&gt; I actually feel like using almost always, over the real mouse!&lt;&#x2F;p&gt;
&lt;p&gt;Initially I went with the obvious &lt;kbd&gt;u&lt;&#x2F;kbd&gt;, &lt;kbd&gt;i&lt;&#x2F;kbd&gt;, &lt;kbd&gt;o&lt;&#x2F;kbd&gt; for the left, middle, right clicks, but during usage I realized something interesting: moving the mouse with the mouse mode feels &lt;em&gt;so&lt;&#x2F;em&gt; good, that I can actually consider click-dragging over text to select it... Yes really! &lt;br &#x2F;&gt;
Holding &lt;kbd&gt;u&lt;&#x2F;kbd&gt; with one of, or multiple of &lt;kbd&gt;h&lt;&#x2F;kbd&gt;, &lt;kbd&gt;j&lt;&#x2F;kbd&gt;, &lt;kbd&gt;k&lt;&#x2F;kbd&gt;, &lt;kbd&gt;l&lt;&#x2F;kbd&gt; feels really uncomfortable, as I didn&#x27;t design with the thought in mind. &lt;br &#x2F;&gt;
That&#x27;s why I put &lt;kbd&gt;f&lt;&#x2F;kbd&gt; to be left click, &lt;kbd&gt;d&lt;&#x2F;kbd&gt; to right click, &lt;kbd&gt;s&lt;&#x2F;kbd&gt; to middle click, and this is also the reason why &lt;kbd&gt;Space&lt;&#x2F;kbd&gt;, rather than my initial &lt;kbd&gt;z&lt;&#x2F;kbd&gt;, is the key that enables mouse mode.&lt;&#x2F;p&gt;
&lt;p&gt;Sounds perfect at this point, right? Now I can move and then click with no interruption, as well as easily be able to click and drag, with any of the three mouse buttons! &lt;br &#x2F;&gt;
But I got another idea: since I&#x27;m already supporting click dragging with all three buttons, why wouldn&#x27;t I also support holding modifiers while clicking? &lt;br &#x2F;&gt;
&lt;kbd&gt;s&lt;&#x2F;kbd&gt;, &lt;kbd&gt;d&lt;&#x2F;kbd&gt; and &lt;kbd&gt;f&lt;&#x2F;kbd&gt; would be required for this, so I moved left click onto &lt;kbd&gt;a&lt;&#x2F;kbd&gt;, right click to &lt;kbd&gt;;&lt;&#x2F;kbd&gt;, middle click to &lt;kbd&gt;&#x27;&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Incidentally, mouse wheel scrolling are ←↑↓→ on &lt;kbd&gt;m&lt;&#x2F;kbd&gt;, &lt;kbd&gt;,&lt;&#x2F;kbd&gt;, &lt;kbd&gt;.&lt;&#x2F;kbd&gt;, &lt;kbd&gt;&#x2F;&lt;&#x2F;kbd&gt; and the back &#x2F; forward buttons are on &lt;kbd&gt;[&lt;&#x2F;kbd&gt; &#x2F; &lt;kbd&gt;]&lt;&#x2F;kbd&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;It took me around 3 days to get comfortable using this entire system. I might be spotty at some hotkeys here and there, but normal operation feels quite solid already. &lt;br &#x2F;&gt;
This sounds like a pretty fast learning curve to me!&lt;&#x2F;p&gt;
&lt;p&gt;Not having to cry over horrendous hotkeys, or over keys being too far away to be viable to press, is truly heavenly. &lt;br &#x2F;&gt;
If you haven&#x27;t tried every row mods, and &lt;strong&gt;especially&lt;&#x2F;strong&gt; if you have and gave up, I encourage you to apply my approaches and tips to make this system viable for yourself too. It&#x27;s a lifechanger!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>bye bye firefox</title>
          <pubDate>Tue, 08 Apr 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/floorp/</link>
          <guid>https://axlefublr.github.io/floorp/</guid>
          <description xml:base="https://axlefublr.github.io/floorp/">&lt;p&gt;You might reasonably expect me to have switched off from firefox due to the recent privacy concerns drama. &lt;br &#x2F;&gt;
&lt;del&gt;But it was me, Dio!&lt;&#x2F;del&gt; But I actually could not care less about my privacy. Matter of fact, I think it&#x27;s strange and silly to expect your browser to be private about your data. The web is so huge that I can&#x27;t get how this can ever be an expectation or even a hope.&lt;&#x2F;p&gt;
&lt;p&gt;The actual reasons are somewhat muddy, and because of that I couldn&#x27;t collect enough energy to actually start the switching process: my firefox switch took an ABHORRENT amount of energy, and repeating that again felt quite scary.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;My partner really loves this browser, and wants me to try it out a lot&lt;&#x2F;li&gt;
&lt;li&gt;It allows you to change hotkeys&lt;&#x2F;li&gt;
&lt;li&gt;It has built in workspaces&lt;&#x2F;li&gt;
&lt;li&gt;Browser level css is &quot;better&quot; (I didn&#x27;t quite know in which way yet, but trusted it)&lt;&#x2F;li&gt;
&lt;li&gt;Because of being able to change hotkeys inside, I offload the need for xremap, as I intend to switch to kanata soon&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;css&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#css&quot; aria-label=&quot;Anchor link for: css&quot;&gt;css&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The browser level css configuration turned out way better than advertised. Truly stunning! &lt;br &#x2F;&gt;
Whatever I try to do just works practically immediately, everything is obvious and straightforward. &lt;br &#x2F;&gt;
It took me &lt;em&gt;multiple days&lt;&#x2F;em&gt; to get firefox just right, and yet I&#x27;m almost there on floorp after a few measly hours. That&#x27;s wild! &lt;br &#x2F;&gt;
To be fair, there&#x27;s likely a big bias at play: after cssing firefox, I&#x27;ve gotten a lot better at doing so, and am now judging floorp as if I have the same level of knowledge as I did &lt;em&gt;before&lt;&#x2F;em&gt; cssing firefox — this is not the case and it&#x27;s likely my &lt;em&gt;knowledge&lt;&#x2F;em&gt;, &lt;strong&gt;not&lt;&#x2F;strong&gt; the browser that makes it that easy, but still I&#x27;m very happy! :D&lt;&#x2F;p&gt;
&lt;p&gt;To get started cssing the browser, the process is quite a bit more discoverable. &lt;br &#x2F;&gt;
Right click on the workspaces button to enable the menu bar. In it, press CSS -&amp;gt; CSS -&amp;gt; Create Browser CSS file.&lt;&#x2F;p&gt;
&lt;p&gt;In the prompt shown to you, you will create a css file that you&#x27;ll be editing to customize the browser ui. &lt;br &#x2F;&gt;
You can then find the file to edit it as you wish, by clicking &quot;Open CSS Folder&quot; in the same menu. &lt;br &#x2F;&gt;
Unlike the usual firefox userchrome configuration though, you &lt;em&gt;don&#x27;t&lt;&#x2F;em&gt; have to restart the browser for the changes to take effect! &lt;br &#x2F;&gt;
Just press &lt;kbd&gt;alt+r&lt;&#x2F;kbd&gt; to reload your css file into floorp whenever you make a change in it.&lt;&#x2F;p&gt;
&lt;p&gt;Not having to restart the entire browser to check every change is an &lt;em&gt;incredible&lt;&#x2F;em&gt; help for productivity. Although for other things that I might wanna restart my browser for, there&#x27;s another built in hotkey to do so: &lt;kbd&gt;ctrl+alt+r&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Here is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;floorp&#x2F;CSS&#x2F;floorp.css&quot;&gt;my css file&lt;&#x2F;a&gt;. I thought I might as well share it since I&#x27;m talking about it, but I give no guarantees that it will be helpful, well written, documented, or even work for you.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;workspaces&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#workspaces&quot; aria-label=&quot;Anchor link for: workspaces&quot;&gt;workspaces&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I used sidebery for a single reason: &quot;workspaces&quot;. It calls it &quot;panels&quot;, but no matter. It implements them via hiding and unhiding tabs as you move through the panels (not by default; it&#x27;s an option), so you can probably imagine how hacky it feels to use. &lt;br &#x2F;&gt;
Hilariously, it&#x27;s still faster and smoother than workspaces were on vivaldi. &lt;br &#x2F;&gt;
Well, floorp has workspaces built in! And they are completely and incredibly smooth!&lt;&#x2F;p&gt;
&lt;p&gt;Sidebery requires you to show the sidebar for it to work. Pretty weird ngl, considering that it &lt;em&gt;does&lt;&#x2F;em&gt; allow you to set hotkeys for basically every action. So, I did css to &lt;code&gt;display: none&lt;&#x2F;code&gt; the sidebar, while it still technically was &quot;on&quot; — that allowed me to use the hotkeys as expected. &lt;br &#x2F;&gt;
The downside to doing this is that any time I wanted to add a new workspace (panel), I had to dig into my userchrome.css by finding it in firefox browser devtools, remove the line the removed the sidebar to enable it back, add the workspace, and then remove the sidebar again. &lt;br &#x2F;&gt;
I don&#x27;t create workspaces that often thankfully, but yeah it was definitely a pain.&lt;&#x2F;p&gt;
&lt;p&gt;In floorp, you simply get a small thingy to the left of your tabs, that shows the icon of the current workspace (as well as its name, optionally)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;floorp&#x2F;.&#x2F;workspaces.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s tiny by default, so I made it a bit bigger with css. &lt;br &#x2F;&gt;
Unfortunately in terms of icons, you have to pick among the predefined ones: you can&#x27;t blammo an emoji or svg, how I&#x27;d love to be able to do. But good enough! &lt;br &#x2F;&gt;
A hack you can probably use, and one that I might try out, is to &lt;em&gt;name&lt;&#x2F;em&gt; the workspaces using emojis, and &lt;em&gt;remove&lt;&#x2F;em&gt; the icon with css. That way you&#x27;ll only see the name of the workspace, which just so happens to be an emoji of your choosing.&lt;&#x2F;p&gt;
&lt;a href=&quot;#i-tried-it&quot; id=&quot;i-tried-it&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Couple of days after writing the above sentence, I &lt;em&gt;did&lt;&#x2F;em&gt; try out the idea. &lt;br &#x2F;&gt;
Turns out it&#x27;s awesome! :D&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;floorp&#x2F;.&#x2F;emoji-icon.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now I simply name the workspaces with emojis, and get to have a nicer looking indicator than the default selection of icons I&#x27;d have to otherwise use.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the css to remove the icon:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#workspaces-toolbar-button&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;.toolbarbutton-icon {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  display&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; none&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; !important&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;hotkeys&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#hotkeys&quot; aria-label=&quot;Anchor link for: hotkeys&quot;&gt;hotkeys&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can configure your hotkeys! Quite a few of them, at least. Now I get to have &lt;kbd&gt;alt+h&lt;&#x2F;kbd&gt; &#x2F; &lt;kbd&gt;alt+l&lt;&#x2F;kbd&gt; go the previous &#x2F; next tab, without having to do an xremap hack to achieve that. Your remapping choices aren&#x27;t even close to the power of something like vivaldi, though. Still, much better than not being able to to begin with, like in base firefox.&lt;&#x2F;p&gt;
&lt;p&gt;For example, while you can set hotkeys to go to the previous &#x2F; next workspace, that&#x27;s all you get. Yes, somehow there aren&#x27;t built in actions to move the current tab to the previous &#x2F; next workspace, or really &lt;em&gt;any&lt;&#x2F;em&gt; other workspace related action you can bind to, which is very strange. &lt;br &#x2F;&gt;
I guess I&#x27;ll give some leeway with the excuse that the project is somewhat new and undercooked. But still, I never get how features this obvious are missed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;floorp&#x2F;.&#x2F;actions.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Even these two actions are kinda buggy. When you go to the previous or next workspace, you toggle the workspaces panel (↓).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;floorp&#x2F;.&#x2F;panel.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So say you start on the 🌿 workspace and go to the next workspace (🐛). The workspaces panel is now opened. &lt;br &#x2F;&gt;
You continue going next to 🥕 — the panel is now closed. Then onto 👩‍🏭... and it&#x27;s opened once again???&lt;&#x2F;p&gt;
&lt;p&gt;So as you move through your workspaces, the panel plays peekaboo with you. I&#x27;d be fine with it either showing always as you move, &lt;em&gt;or&lt;&#x2F;em&gt; never showing, but somehow it does the worst possible behavior. &lt;br &#x2F;&gt;
So far I don&#x27;t have a &lt;em&gt;good&lt;&#x2F;em&gt; solution to this, but I solved it well enough: I &lt;code&gt;display: none&lt;&#x2F;code&gt; the workspaces panel as a whole, and enable it whenever I need to add, rename, or move a workspace.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;But wait Terri, didn&#x27;t you complain about having to do this with sidebery?! :o&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yes! But there are reasons why doing practically the same thing in floorp is &lt;em&gt;less&lt;&#x2F;em&gt; of a pain:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I can reload my css via a hotkey&lt;&#x2F;li&gt;
&lt;li&gt;Doing so does not restart the whole browser&lt;&#x2F;li&gt;
&lt;li&gt;I simply edit the css file in helix to then reload, rather than having to change it in browser devtools to avoid a restart (how I needed to in firefox)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Here&#x27;s the css I use to remove the workspaces panel:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#workspacesToolbarButtonPanel {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  display&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; none&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; !important&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;a href=&quot;#moving&quot; id=&quot;moving&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Of course, if I really couldn&#x27;t move tabs across workspaces with my keyboard, I wouldn&#x27;t&#x27;ve switched to floorp. No way. &lt;br &#x2F;&gt;
But a certain feature comes to save me: &quot;Custom actions&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;This is probably the coolest part of floorp, for an experienced user. You can set hotkeys to execute your arbitrary javascript! :o&lt;&#x2F;p&gt;
&lt;p&gt;Go to &lt;code&gt;about:config&lt;&#x2F;code&gt; and search for &lt;code&gt;floorp.custom.shortcutkeysAndActions.customAction1&lt;&#x2F;code&gt;. You set that setting to the javascript you want that action to execute. Then in &lt;code&gt;about:preferences&lt;&#x2F;code&gt; -&amp;gt; Keyboard Shortcuts -&amp;gt; Custom Actions, you can set hotkeys to execute those custom actions. &lt;br &#x2F;&gt;
Interestingly you only get five of them. A bit of an arbitrary restriction, but I&#x27;d usually expect that arbitrary number to be 10, not 5. I already use 3 of them — a bit quick to run out of. &lt;br &#x2F;&gt;
This is also why I don&#x27;t solve the peekaboo problem with custom actions, even though I technically could.&lt;&#x2F;p&gt;
&lt;p&gt;My partner wrote this custom action for me, that moves the current tab to the next workspace:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(async ()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; currentTab&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; window.gBrowser.selectedTab;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; workspaces&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; await&lt;&#x2F;span&gt;&lt;span&gt; gWorkspaces.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;getAllWorkspacesId&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; current&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt; await&lt;&#x2F;span&gt;&lt;span&gt; gWorkspaces.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;getCurrentWorkspaceId&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; currentIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; workspaces.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;indexOf&lt;&#x2F;span&gt;&lt;span&gt;(current);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; destinationIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; currentIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (destinationIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span&gt; workspaces.length) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        destinationIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E491B2;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; destination&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; workspaces.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(destinationIndex);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    await&lt;&#x2F;span&gt;&lt;span&gt; gWorkspaces.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;changeWorkspace&lt;&#x2F;span&gt;&lt;span&gt;(destination,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; null&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How to make this move the tab to the &lt;em&gt;previous&lt;&#x2F;em&gt; workspace is an exercise for the reader. I believe in you.&lt;&#x2F;p&gt;
&lt;p&gt;Another issue I found, that is solved by a custom action: pressing &lt;kbd&gt;Escape&lt;&#x2F;kbd&gt; while in address bar doesn&#x27;t focus the page. &lt;br &#x2F;&gt;
I&#x27;m a vimium c user, so I really don&#x27;t want to use my mouse to focus the page back after focusing the address bar. Being able to do so with the keyboard is a corely important workflow bit for me! &lt;br &#x2F;&gt;
I blammoed &lt;code&gt;document.querySelector(&quot;browser[primary=&#x27;true&#x27;]&quot;).focus()&lt;&#x2F;code&gt; as a custom action and bound it to a hotkey. &lt;br &#x2F;&gt;
I&#x27;d rather &lt;kbd&gt;Escape&lt;&#x2F;kbd&gt; work by itself, but this is good enough I think.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;proxy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#proxy&quot; aria-label=&quot;Anchor link for: proxy&quot;&gt;proxy&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s get to the &lt;em&gt;third&lt;&#x2F;em&gt; thing that would make me give up on the switch, if it wasn&#x27;t for my partner.&lt;&#x2F;p&gt;
&lt;p&gt;Proxying works strangely in firefox for me. The FoxyProxy extension that you may know straight up doesn&#x27;t work for me there. &lt;br &#x2F;&gt;
However, if I configure my proxy in settings of firefox, it &lt;em&gt;does&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In floorp, FoxyProxy started working for me 🥳 &lt;br &#x2F;&gt;
&lt;em&gt;Except&lt;&#x2F;em&gt; for playing videos on youtube... I used the same exact proxy, and it &lt;em&gt;does&lt;&#x2F;em&gt; continue to work like normal in base firefox, so this was very strange! &lt;br &#x2F;&gt;
At first I assumed that it was me changing some setting that fucked things up, but after trying out a blank floorp profile for a test, my proxy didn&#x27;t work there either.&lt;&#x2F;p&gt;
&lt;p&gt;So, my conclusion is that the internals of proxying work differently in floorp, for one reason or another. &lt;br &#x2F;&gt;
In a panic, I start considering my options of solving this. I was too deep at this point to want to go back to firefox (workspaces are too good), and opening firefox just for watching youtube felt assy too. &lt;br &#x2F;&gt;
Alternative youtube frontend? Trying to make yt-dlp work again? Quitting youtube? &#x2F;j &lt;br &#x2F;&gt;
I was saved once again! I now have an extra proxy that &lt;em&gt;does&lt;&#x2F;em&gt; work for loading youtube videos in floorp (not sure why), so I can continue to use this browser in peace 😌&lt;&#x2F;p&gt;
&lt;a href=&quot;#she-cooked&quot; id=&quot;she-cooked&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Overall, the feeling I get from floorp is that it&#x27;s a bit undercooked, but gives you the power to cook it to your preference. That is exactly how I approach most software, for better or worse, so that&#x27;s a green flag for me :3&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>randomization sucks</title>
          <pubDate>Tue, 25 Mar 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/randomization-sucks/</link>
          <guid>https://axlefublr.github.io/randomization-sucks/</guid>
          <description xml:base="https://axlefublr.github.io/randomization-sucks/">&lt;p&gt;You might instantly think that I&#x27;m going to be talking about how there&#x27;s almost no &lt;em&gt;real&lt;&#x2F;em&gt; randomness in computers, and instead mostly pseudo randomization. &lt;br &#x2F;&gt;
Interestingly, I have the exact opposite issue: randomization feels &lt;em&gt;too&lt;&#x2F;em&gt; random!&lt;&#x2F;p&gt;
&lt;p&gt;Say you want to pick 5 random numbers in a range of 1 to 10. &lt;br &#x2F;&gt;
A fairly human sequence is something like this: [7, 5, 1, 8, 3] &lt;br &#x2F;&gt;
I simply put in random numbers in the range as they came to my head. Yet look how balanced they are! And no duplicates, too!&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re tasked with picking random numbers like this, you&#x27;re unlikely to choose duplicates. It simply feels unnatural to do. &lt;br &#x2F;&gt;
A &lt;em&gt;computer&lt;&#x2F;em&gt;, however, will have not mental blocks like that. You (unless trolling) are unable to produce the following set: [7, 7, 7, 7, 7]. &lt;br &#x2F;&gt;
Computers &lt;em&gt;can&lt;&#x2F;em&gt; (although it is very unlikely).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;perceived-randomization&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#perceived-randomization&quot; aria-label=&quot;Anchor link for: perceived-randomization&quot;&gt;perceived randomization&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;randomization-sucks&#x2F;.&#x2F;random-points.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If tasked to distribute points on an area randomly, a human will probably start doing the 3rd option, think &quot;wait I&#x27;m being too predictable&quot; and switch to the second option. While in reality, true randomness will look more like the 1st option.&lt;&#x2F;p&gt;
&lt;p&gt;We expect randomness to behave in a spread out way, but that&#x27;s not how it actually works! &lt;br &#x2F;&gt;
And it&#x27;s the reason why normal randomness tends to feel kinda &lt;em&gt;incorrect&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;shuffle&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#shuffle&quot; aria-label=&quot;Anchor link for: shuffle&quot;&gt;shuffle&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Biggest example of randomization feeling bad is the shuffle button in your music app. &lt;br &#x2F;&gt;
It will often feel like it has a preference for some songs, and never plays some others.&lt;&#x2F;p&gt;
&lt;p&gt;You start to shuffle some playlist with 100 songs and listen to 20 of them. Then you switch to listen to something else, and come back to the playlist, reshuffling it. &lt;br &#x2F;&gt;
You have now broken the shuffle, somewhat. Previously, in a singular shuffle, the music app wouldn&#x27;t repeat the same songs until you&#x27;ve listened to them all. &lt;br &#x2F;&gt;
But because you &lt;em&gt;re&lt;&#x2F;em&gt;shuffled, it picks out of &lt;em&gt;all&lt;&#x2F;em&gt; 100 songs again, and because of true randomization that I pointed out in the above section, it very much might pick a song you listened like 5 minutes ago, rather than picking a song you haven&#x27;t heard in a while, which would &quot;feel&quot; more random to you.&lt;&#x2F;p&gt;
&lt;p&gt;I have around 5000 liked tracks, so this issue becomes very noticeable at scale. &lt;br &#x2F;&gt;
This is why I created 50 playlists!&lt;&#x2F;p&gt;
&lt;p&gt;Say I added 10 more tracks to liked. &lt;br &#x2F;&gt;
The first one will go to playlist 1, the second one to playlist 10, 3 -&amp;gt; 19, 4 -&amp;gt; 28, 5 -&amp;gt; 37, 6 -&amp;gt; 46, 7 -&amp;gt; 5, 8 -&amp;gt; 14, 9 -&amp;gt; 23, 10 -&amp;gt; 32.&lt;&#x2F;p&gt;
&lt;p&gt;If I split 5000 tracks into &lt;em&gt;50&lt;&#x2F;em&gt; playlists like this, each playlist will have around 100 tracks, and the reshuffling issue ends up being wayyyyy smaller. &lt;br &#x2F;&gt;
Also I increment the next playlist by 9 rather than 1, so that none of the playlists have a &quot;theme&quot;, or are discernable from one another, and feel correctly random.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-point&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-point&quot; aria-label=&quot;Anchor link for: the-point&quot;&gt;the point&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Anyway, this is not what I actually started this blog post for, lol.&lt;&#x2F;p&gt;
&lt;p&gt;I got a recent obsession about wallpapers, as I made it so a random wallpaper would be chosen every day. &lt;br &#x2F;&gt;
As you&#x27;d expect, some wallpapers feel like they&#x27;re picked all the time, while some others I never see.&lt;&#x2F;p&gt;
&lt;p&gt;So I thought: &quot;what if I &lt;strong&gt;ensured&lt;&#x2F;strong&gt; this could not happen?&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;My idea is the following: &lt;br &#x2F;&gt;
I&#x27;ll have a cache that remembers how many times each individual option has been picked before. &lt;br &#x2F;&gt;
Before picking out of the options, we filter out all the options whose &quot;count&quot; is bigger than the minimum count of all the items.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with an example. We have four options: apple, banana, orange, tomato. All of them start with a count of 0, because none of them were picked yet. &lt;br &#x2F;&gt;
We begin the randomization process, and banana was randomly picked. Its count is now 1. &lt;br &#x2F;&gt;
We randomize again. We go through all the options and check the counts. We realize that the lowest count any option has is 0 (as every other option hasn&#x27;t been picked yet), but banana has a count of 1. We filter out banana, and only pick out of apple, orange, tomato.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;banana - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;lowest: 0. picking out of:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;banana&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;banana. next iteration.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;banana - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;lowest: 0. picking out of:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;apple. next iteration.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;banana - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;lowest: 0. picking out of:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;orange. next iteration.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;banana - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;lowest: 0. picking out of:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;tomato. next iteration.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;banana - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;lowest: 1. picking out of:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;banana&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;orange. next iteration.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;banana - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange - 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;lowest: 1. picking out of:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;banana&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;...etc etc&lt;&#x2F;p&gt;
&lt;h1 id=&quot;next-visual-section-of-the-blog-post&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#next-visual-section-of-the-blog-post&quot; aria-label=&quot;Anchor link for: next-visual-section-of-the-blog-post&quot;&gt;next visual section of the blog post&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;This works so well! Despite being randomization, it &lt;strong&gt;guarantees&lt;&#x2F;strong&gt; that you will never see a given option more than once in a cycle. &lt;br &#x2F;&gt;
If you think about it for a bit though, you will notice that the following is possible for the algorithm to give us: [apple, banana, orange, tomato, tomato, orange, banana, apple] (we made 8 iterations, 2 full cycles) &lt;br &#x2F;&gt;
Isn&#x27;t it kinda annoying? Despite the guarantee within &lt;em&gt;a&lt;&#x2F;em&gt; cycle, nobody is stopping the algorithm from making some items very close or very far from each other between &lt;em&gt;two&lt;&#x2F;em&gt; cycles. &lt;br &#x2F;&gt;
So in effect, it can end up being worse, right?&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s compare this to the more obvious approach: caching the last n items. &lt;br &#x2F;&gt;
As you randomly pick items, you &quot;write them down&quot;. When you pick the next item, if it&#x27;s in the n recent items, you mark it as invalid and try to pick again. &lt;br &#x2F;&gt;
Basically, you won&#x27;t see something if you saw it just recently.&lt;&#x2F;p&gt;
&lt;p&gt;However, what this method lacks, is guarantees about the &lt;em&gt;other&lt;&#x2F;em&gt; items.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;banana&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orange&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tomato&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fresh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;blues&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sheriff&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;harmful&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;heating&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;announces&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Say you check the last 2 items. It is practically impossible, in terms of probability, but there are no &lt;em&gt;guarantees&lt;&#x2F;em&gt; that &quot;harmful&quot;, &quot;sheriff&quot;, and &quot;heating&quot; won&#x27;t get picked over and over again, but never &quot;apple&quot; for example. &lt;br &#x2F;&gt;
What is just an unlucky coincidence will feel like a preference to your human brain, and hence will feel like &quot;worse&quot; randomization.&lt;&#x2F;p&gt;
&lt;p&gt;Even though my algorithm might show me the same thing twice in a row, it &lt;strong&gt;guarantees&lt;&#x2F;strong&gt; that afterwards, I won&#x27;t see it for a while, while &lt;em&gt;also&lt;&#x2F;em&gt; guaranteeing I will see all the other wallpapers, with &lt;strong&gt;no&lt;&#x2F;strong&gt; off-chance &quot;preference&quot; for any of them.&lt;&#x2F;p&gt;
&lt;p&gt;When I see a wallpaper I saw just recently, I no longer worry: I know that after this one, I&#x27;ll get to enjoy my entire collection, and none will be forgotten. &lt;br &#x2F;&gt;
This made me take picking wallpapers more seriously, actually! There is no way I just happen to not see a given wallpaper for a while due to random chance, so I filter out which wallpapers I actually want to use more aggressively.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;eli&#x2F;suggest.rs&quot;&gt;source code&lt;&#x2F;a&gt; for the program that I wrote for this. It is very much a &quot;for myself&quot; thing so I don&#x27;t intend to publish it in a convenient way; this blog post more so exists to give you ideas to approach randomization differently, and make it work better for yourself.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>the journey of noise</title>
          <pubDate>Thu, 13 Mar 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/journey-of-noise/</link>
          <guid>https://axlefublr.github.io/journey-of-noise/</guid>
          <description xml:base="https://axlefublr.github.io/journey-of-noise/">&lt;p&gt;I&#x27;m autistic! Noise affects me more than the average person. I often fantasize about going deaf. &lt;br &#x2F;&gt;
After always having laptops, recently I finally got my first pc! &lt;br &#x2F;&gt;
Little did I know how LOUD it can be...&lt;&#x2F;p&gt;
&lt;p&gt;Let me take you on a journey of how I dealt with the devil that is &lt;strong&gt;noise&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;first-impression&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#first-impression&quot; aria-label=&quot;Anchor link for: first-impression&quot;&gt;first impression&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I plug in the computer and start going through the motions of initial setup. &lt;br &#x2F;&gt;
Despite being distracted by my horrendous monitor (and the following two, before I got my 4th one which is great; but that&#x27;s a separate story), what was even more clear is how LOUD the fans were.&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully my partner is goated, and thanks to it I know that a &quot;fan curve&quot; is a concept that exists. &lt;br &#x2F;&gt;
You can define the rotation speed for your fans, depending on the current temperature of your cpu. &lt;br &#x2F;&gt;
(That is both wrong and inprecise, keep in mind I&#x27;m telling the story as I knew things at the time, I now know more).&lt;&#x2F;p&gt;
&lt;p&gt;You do this configuration in the BIOS. The place you get into by mashing (usually) the &lt;kbd&gt;Delete&lt;&#x2F;kbd&gt; key when rebooting. &lt;br &#x2F;&gt;
As I was looking through the settings, I got surprised at how many more there were, compared to my laptop! No wonder though: with more replaceable parts that you have in a proper computer, there is also more opportunity to configure them all. &lt;br &#x2F;&gt;
But despite the amount of extra settings, I never found the dreamed fan graph.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;journey-of-noise&#x2F;.&#x2F;fan-graph.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I was only able to find the overall &quot;modes&quot; that also happened to affect fan speeds: Normal, Turbo, or Silent. &lt;br &#x2F;&gt;
Picking the Slay the Spire character in my bios didn&#x27;t help make things quiet, though. Both fans were still overwhelmingly loud, at ~1800 rpm.&lt;&#x2F;p&gt;
&lt;p&gt;I removed the exhaust fan, but there isn&#x27;t that much noise difference between 2 1800rpm fans, and 1 1800rpm fan — it&#x27;s loud as hell regardless.&lt;&#x2F;p&gt;
&lt;p&gt;I know that&#x27;s it&#x27;s a &quot;bad idea&quot; or whatever, but what if remove the cpu fan too, and let the heatsink do all the work? I just need it to not &lt;em&gt;over&lt;&#x2F;em&gt;heat for now, so maybe it&#x27;ll be fine? &lt;br &#x2F;&gt;
I do exactly that and then cautiously stare at the cpu temperature while in bios.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sure, the temperature rises, but very slowly! Maybe this will work out?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Is what I think, but eventually it gets to 70°C. Nope, this is not viable :c&lt;&#x2F;p&gt;
&lt;p&gt;I put my pc to sleep. I can&#x27;t use it like this, I&#x27;ll fucking die! &lt;br &#x2F;&gt;
I put off the setup process for when I figure this out.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;oh-that-exists&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#oh-that-exists&quot; aria-label=&quot;Anchor link for: oh-that-exists&quot;&gt;oh that exists?&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;There are certain expectations I had of a working computer, and a couple of them were broken. &lt;br &#x2F;&gt;
The computer I bought isn&#x27;t new, but instead made by some cryptomining guy.&lt;&#x2F;p&gt;
&lt;p&gt;First I realize that the pc doesn&#x27;t have wifi! Wtf! &lt;br &#x2F;&gt;
I went and bought an Ethernet cable (😭 it&#x27;s actually called dog8 😭 &amp;lt;- you probably), pathed the snake from the router to my room, and got myself internet. &lt;br &#x2F;&gt;
As a result, my internet is now way faster and more consistent than it used to be before, so I&#x27;m happy I did that rather than buy a wifi adapter, but I&#x27;m still surprised that missing one was a possibility.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, there was no bluetooth adapter. Thankfully my headphones (JBL Tune 750BTNC) can also be wired, so fixing that issue wasn&#x27;t a rush.&lt;&#x2F;p&gt;
&lt;p&gt;Oh and I forgot to mention: the pc didn&#x27;t come with a power supply plug. Yeah, even something that simple wasn&#x27;t there.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s why I got a hunch that the fans were shitty as well. &lt;br &#x2F;&gt;
I go through fans I could buy to replace the existing ones, and notice an interesting metric: minimum rpm. &lt;br &#x2F;&gt;
And then it hit me: my fans&#x27; minimum rpm was fucking 1800!!! No wonder they were loud :o&lt;&#x2F;p&gt;
&lt;p&gt;Later on I figured out the extra factor of their shittiness: it&#x27;s not that their minimum rpm is so high, it&#x27;s that their rpm isn&#x27;t &lt;em&gt;controllable&lt;&#x2F;em&gt;: they&#x27;re missing &quot;PWM&quot;. &lt;br &#x2F;&gt;
PWM is a thingy (don&#x27;t ask me) that lets your motherboard control the speed of your fans. Since my fans weren&#x27;t PWM, they couldn&#x27;t change their speed, and &lt;em&gt;that&#x27;s&lt;&#x2F;em&gt; why they have the 1800 minimum: it&#x27;s also their maximum!&lt;&#x2F;p&gt;
&lt;p&gt;So I was looking through fans that had a low minimum rpm (I didn&#x27;t quite get the pwm memo at the time), and noticed that for the most part, 500 was the lowest they went.&lt;&#x2F;p&gt;
&lt;p&gt;Now, aside from product availability differences (I&#x27;m in russia 😭), I &lt;em&gt;was&lt;&#x2F;em&gt; stupid: I didn&#x27;t just buy a fan, I bought a whole ass cooler. &lt;br &#x2F;&gt;
See, I already have a heat sink on my cpu, and it at least looks very nice and capable. Especially so for my needs, and I imagine the cryptomining guy had higher cooling needs than me. &lt;br &#x2F;&gt;
So instead of buying &lt;em&gt;just&lt;&#x2F;em&gt; a fan, I incorrectly searched and found heatsink + fan combos.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, I take just the fan part from the combo, after realizing my mistake, and try to attach it to my heatsink. &lt;br &#x2F;&gt;
The heatsink uses these interestingly shaped metal holders that you&#x27;re supposed to grab onto the fan to hold it in place; my new fan didn&#x27;t have anything to hold on to, though :c&lt;&#x2F;p&gt;
&lt;p&gt;And here we go 😈 &lt;br &#x2F;&gt;
In my classic fashion, I decide to do some redneck engineering, and pull out the zip ties 🗣️🔥&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;journey-of-noise&#x2F;.&#x2F;this-shit-is-so-ass.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Blammoing a ziptie around the fan and heatsink to hold them together turned out to be far more effective than I expected! Now &lt;em&gt;this&lt;&#x2F;em&gt; is starting to look like my setup :D&lt;&#x2F;p&gt;
&lt;p&gt;Using &lt;em&gt;just&lt;&#x2F;em&gt; the cpu fan for my entire pc&#x27;s cooling (aside from gpu&#x27;s builtin fans) feels assy, but it&#x27;s something I can at least fix later — if this new fan is sufficient for the cpu cooling, then I&#x27;m set to actually use my pc comfortably!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;comfortably-right&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#comfortably-right&quot; aria-label=&quot;Anchor link for: comfortably-right&quot;&gt;comfortably, right?&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;It definitely got quieter! But not exactly &lt;em&gt;silent&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I came back to the bios to see 1200rpm. Didn&#x27;t expect that last 600 to make such a big difference! &lt;br &#x2F;&gt;
However, this is still not the 500 minimum I was promised. It definitely seems like a configuration issue 🤔.&lt;&#x2F;p&gt;
&lt;p&gt;Remember those bios modes? Normal, Turbo, and Ironclad? &lt;br &#x2F;&gt;
Interestingly, despite &lt;em&gt;everything&lt;&#x2F;em&gt; being in Defect mode, Watcher didn&#x27;t affect the fans as much as it could: fans also have modes of their own! :o&lt;&#x2F;p&gt;
&lt;p&gt;After setting the fan mode to Silent too, it got down to 900rpm. Another significant improvement, although not as huge of a jump as 1800 -&amp;gt; 1200. &lt;br &#x2F;&gt;
Still, that&#x27;s no 500! And I&#x27;m determined to get it.&lt;&#x2F;p&gt;
&lt;p&gt;There is something even more forcing than Ironclad: &lt;em&gt;Manual&lt;&#x2F;em&gt; mode. &lt;br &#x2F;&gt;
Aha! This must be my motherboard&#x27;s way of setting the fan graph! &lt;br &#x2F;&gt;
Although, it&#x27;s not as clear or understandable as your normal fan graph: you don&#x27;t get a visual representation of how the speed &lt;em&gt;rises&lt;&#x2F;em&gt;, and the wording is confusing, especially to someone who doesn&#x27;t know how this works prior.&lt;&#x2F;p&gt;
&lt;p&gt;For example, in a normal fan graph, you can make your fans not spin at all (!!) before the cpu reaches 40°C, then start spinning them at 500 before 50°C, then linearly increase their speed until 70°C, and then make a &lt;strong&gt;steep&lt;&#x2F;strong&gt; rise once the temperature reaches more than that.&lt;&#x2F;p&gt;
&lt;p&gt;My motherboard doesn&#x27;t support such fine grained control. Most cryingly, it doesn&#x27;t allow my fans to have &lt;em&gt;no&lt;&#x2F;em&gt; rpm under a certain temperature :c&lt;&#x2F;p&gt;
&lt;p&gt;Sure, now that I have literally just a single fan, I &lt;em&gt;should&lt;&#x2F;em&gt; always have &lt;em&gt;some&lt;&#x2F;em&gt; rpm at least, but in the future when I buy better and more fans, kinda sad to be required to always spin them :c&lt;&#x2F;p&gt;
&lt;p&gt;Anyway! The method I have access to is the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;set the maximum temperature, after which the fans spin at maximum speed&lt;&#x2F;li&gt;
&lt;li&gt;what is the maximum speed, in that case?&lt;&#x2F;li&gt;
&lt;li&gt;set the minimum temperature, &lt;em&gt;&lt;strong&gt;before&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; which the fans spin at minimum speed&lt;&#x2F;li&gt;
&lt;li&gt;what is the minimum speed?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Initially, it&#x27;s worded more confusingly and it&#x27;s never mentioned how the rpm changes &lt;em&gt;between&lt;&#x2F;em&gt; the minimum and maximum temperature. My guess is that it&#x27;s linear, but I don&#x27;t actually know. A fan graph would make this clear &lt;em&gt;and&lt;&#x2F;em&gt; configurable.&lt;&#x2F;p&gt;
&lt;a href=&quot;#temperatures&quot; id=&quot;temperatures&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I have no clue what temperatures are &quot;good&quot;. I never had the ability to optimize fan speed, and so I never had a reason to monitor temperatures. &lt;br &#x2F;&gt;
The information I&#x27;ve been able to find is that &quot;as long as you&#x27;re under 90, you&#x27;re fine!&quot; but that&#x27;s not very helpful! I won&#x27;t listen because that &lt;em&gt;sounds&lt;&#x2F;em&gt; like awful advice! &lt;br &#x2F;&gt;
Chatgpt told me that 30-50 while idle and 60-70 while under load is a good spot. &lt;br &#x2F;&gt;
But first, trusting an ai on this isn&#x27;t the brightest idea; even if I do, 30-50 is an awfully big range! And what does &quot;under load&quot; mean? Is watching a youtube video considered &quot;load&quot;?&lt;&#x2F;p&gt;
&lt;p&gt;I asked a more trustworthy robot about this, and turns out setting minimum temperature to even 60°C is fine! :o&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s very good to know, but to be really safe, I put down my minimum temperature to 45°C, and maximum to 60°C, rather than the 30°C minimum I set at first. &lt;br &#x2F;&gt;
Maximum speed to 100% — temperature over 60°C should never be reached, and if it is, I&#x27;m afraid of it; so a lot of fan noise &lt;em&gt;sometimes&lt;&#x2F;em&gt; is a good deal to help my anxiousness, while having as little as possible fan noise in the general case.&lt;&#x2F;p&gt;
&lt;p&gt;I mentioned that my bios doesn&#x27;t let me completely stop the fans under a certain temperature. This is because even in manual mode, I cannot set the minimum speed to less than 20% — the bios doesn&#x27;t allow accept the value. So, even under the minimum temperature, the fans will spin at at least 20% capacity. &lt;br &#x2F;&gt;
Which suuuuuucks 😩&lt;&#x2F;p&gt;
&lt;p&gt;The fan is audible, and it really shouldn&#x27;t be when my temperatures are super fine. I got my desired 500rpm, but it turned out it&#x27;s not ideal...&lt;&#x2F;p&gt;
&lt;p&gt;In the same store where I couldn&#x27;t find fans under 500rpm, my partner &lt;em&gt;was&lt;&#x2F;em&gt; able to! She found 200rpm minimum fans :O &lt;br &#x2F;&gt;
I know what my next goal is now 🔥🔥🔥&lt;&#x2F;p&gt;
&lt;h1 id=&quot;voiding-the-warranty&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#voiding-the-warranty&quot; aria-label=&quot;Anchor link for: voiding-the-warranty&quot;&gt;voiding the warranty&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;After some time I was able to purchase that 200rpm fan, and replaced the previous cpu fan with it. &lt;br &#x2F;&gt;
My expectation was to get a completely silent computer, but in reality I only got a marginal benefit.&lt;&#x2F;p&gt;
&lt;p&gt;...How is that possible?&lt;&#x2F;p&gt;
&lt;p&gt;You see, gpus tend to come with abhorrently bad fans. They end up producing the majority of the noise, mostly counteracting your otherwise quiet fans.&lt;&#x2F;p&gt;
&lt;p&gt;Alright, time for more redneck engineering! But far more scary now!&lt;&#x2F;p&gt;
&lt;p&gt;I will remove the plastic container from my gpu, and instead of the fans that come with it, I&#x27;ll blammo in the previous cpu fan that I have no use for now, by using a zip tie once again.&lt;&#x2F;p&gt;
&lt;p&gt;Sounds like a dangerous idea, right? &lt;br &#x2F;&gt;
At that point in time, I was monstrously exhausted from constant noise, and if suddenly my computer stopped working, I wouldn&#x27;t even be that anxious about it. I was really really exhausted with the constant overbearing noise that my computer made, so I was willing to take a bigger risk than usual.&lt;&#x2F;p&gt;
&lt;p&gt;I power off, and remove two random wires (I later realized they&#x27;re connecting to the psu), placing them in a way that would help me remember how to plug them back in. &lt;br &#x2F;&gt;
Then, I remove the gpu from its socket. So far so good.&lt;&#x2F;p&gt;
&lt;p&gt;The first two screws that were holding the plastic together with the rest of the gpu were very easy to reach, but the other two were positioned &quot;inside&quot;, where I couldn&#x27;t reach them normally. &lt;br &#x2F;&gt;
To get to them, I have to unscrew the 4 screws on the bottom of the gpu.&lt;&#x2F;p&gt;
&lt;p&gt;I get to doing exactly that and see a small sticker on one of the screws: &quot;unscrewing voids warranty&quot;. &lt;br &#x2F;&gt;
This is a used computer — I don&#x27;t &lt;em&gt;have&lt;&#x2F;em&gt; warranty. Reading it still sent chills down my spine. Ack!&lt;&#x2F;p&gt;
&lt;p&gt;After removing the plastic, I was expecting to see a 4-pin port for the fan. I did see a port, but it was actually &lt;em&gt;5&lt;&#x2F;em&gt;-pin! &lt;br &#x2F;&gt;
As usual I ask chatgpt on advice, and the tldr is &quot;it&#x27;s fucky, don&#x27;t bother&quot;. &lt;br &#x2F;&gt;
Well shit, how do I cool my gpu now?&lt;&#x2F;p&gt;
&lt;p&gt;The cpu fan is connected to the cpu port. What that actually means, is that the hotter my cpu is, the faster the fan will spin. &lt;br &#x2F;&gt;
Not being able to use the gpu port removes this flexibility for the gpu cooling. &lt;br &#x2F;&gt;
For most of my usage, I can just set the gpu fan to like 700rpm and that&#x27;ll be fine. But if I open a game, the fan won&#x27;t react to the much higher load!&lt;&#x2F;p&gt;
&lt;p&gt;To add more flexibility (although still wonky of a solution), I&#x27;ll plug the gpu fan into the cpu fan port. My reasoning is that if the gpu is getting hotter, the cpu probably is too! The cpu fan will start spinning faster, and so will the gpu fan. Hopefully it&#x27;s going to be good enough?&lt;&#x2F;p&gt;
&lt;p&gt;To make sure, I made this loop in fish shell, that would play a soundeffect if the gpu&#x27;s temperature went to or over 75°C, and then started playing Dishonored to test it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;  test&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;sys&#x2F;devices&#x2F;pci0000:00&#x2F;0000:00:01.0&#x2F;0000:01:00.0&#x2F;hwmon&#x2F;hwmon4&#x2F;temp1_input) -ge 75000 &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;paplay&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;m&#x2F;soundeffects&#x2F;camera-shutter.oga&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;  sleep&lt;&#x2F;span&gt;&lt;span&gt; 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fascinatingly, I never heard the sound effect, in even 30 minutes of playtime! So it seems like this cooling setup is good enough :D&lt;&#x2F;p&gt;
&lt;h1 id=&quot;but-not-forever&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#but-not-forever&quot; aria-label=&quot;Anchor link for: but-not-forever&quot;&gt;but not forever&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;While this works, I feel it would be both dangerous and stupid to leave it be like this till the end of time. &lt;br &#x2F;&gt;
After all, the gpu used to have &lt;em&gt;two&lt;&#x2F;em&gt; fans (although smaller), and now I only have one. &lt;br &#x2F;&gt;
To make sure that the cooling is good enough, I think it&#x27;s a good idea to &lt;em&gt;over&lt;&#x2F;em&gt;cool the gpu, so that even in the worst case scenario (only gpu heats up but not cpu) it&#x27;s not going to overheat.&lt;&#x2F;p&gt;
&lt;p&gt;Some time later I bought another 200rpm fan, and replaced the 500 one with it. &lt;br &#x2F;&gt;
Just to test! Before I&#x27;d eventually add back the 500rpm fan. &lt;br &#x2F;&gt;
But I ended up noticing a very interesting effect! For the first time ever, my fans started spinning &lt;em&gt;slower&lt;&#x2F;em&gt; than 500rpm! :o&lt;&#x2F;p&gt;
&lt;p&gt;It turns out that the 500rpm fan, because of its minimum, was &lt;em&gt;speeding up&lt;&#x2F;em&gt; the other, 200rpm fans. &lt;br &#x2F;&gt;
Also, after removing the 500rpm fan, things got significantly quieter! &lt;br &#x2F;&gt;
It turns out that most of the noise was coming from not from the rpm specifically, but from the 500rpm fan being &lt;em&gt;smaller&lt;&#x2F;em&gt; and &lt;em&gt;shitter&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I later learnt that the bigger the fan is, the quieter it is while transporting the same volume of air. &lt;br &#x2F;&gt;
The smaller fan was both trying harder, &lt;em&gt;and&lt;&#x2F;em&gt; doing a poorer job! &lt;br &#x2F;&gt;
I got to confirm that after testing my temperatures again, with &lt;em&gt;only&lt;&#x2F;em&gt; the new bigger fan, and saw that my temperatures were &lt;em&gt;lower&lt;&#x2F;em&gt;! &lt;br &#x2F;&gt;
Matter of fact, surprisingly significantly lower! At this point I don&#x27;t &lt;em&gt;need&lt;&#x2F;em&gt; the previous fan at all!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;physical-equality&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#physical-equality&quot; aria-label=&quot;Anchor link for: physical-equality&quot;&gt;physical equality&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;At the time of me writing this blog post, I do still only have the two 200rpm fans. I plan to buy two more: one exhaust fan, and one intake fan. &lt;br &#x2F;&gt;
However, I found something on the &lt;em&gt;software&lt;&#x2F;em&gt; side that let me eliminate the gpu temperature flexibility worry &lt;em&gt;completely&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;fancontrol&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
A program you can run as a service, that changes your fans&#x27; speeds depending on the temperature.&lt;&#x2F;p&gt;
&lt;p&gt;I actually knew about it way at the start of the pc journey, but I couldn&#x27;t get it to &lt;em&gt;work&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
And my thought process was that even if I &lt;em&gt;did&lt;&#x2F;em&gt; get it to work, it wouldn&#x27;t allow me to have no rpm anyway, since in my head it was my motherboard that completely didn&#x27;t allow that to happen.&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully, I was very wrong! But god, was it a spiky path to set it up. Even now, I&#x27;m not &lt;em&gt;exactly&lt;&#x2F;em&gt; sure of all the steps I took to make it work, but here are the basic ones (on arch):&lt;&#x2F;p&gt;
&lt;p&gt;Install &lt;code&gt;lm_sensors&lt;&#x2F;code&gt; and run &lt;code&gt;sudo sensors-detect&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
This will allow you to run &lt;code&gt;sensors&lt;&#x2F;code&gt;: a neat program that shows you various information about your system. Here&#x27;s my output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;amdgpu-pci-0100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Adapter: PCI adapter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fan1:             N&#x2F;A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;edge:         +39.0°C  (crit = +120.0°C, hyst = +90.0°C)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;coretemp-isa-0000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Adapter: ISA adapter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Package id 0:  +41.0°C  (high = +80.0°C, crit = +100.0°C)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Core 0:        +39.0°C  (high = +80.0°C, crit = +100.0°C)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Core 1:        +40.0°C  (high = +80.0°C, crit = +100.0°C)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Core 2:        +40.0°C  (high = +80.0°C, crit = +100.0°C)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Core 3:        +37.0°C  (high = +80.0°C, crit = +100.0°C)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;acpitz-acpi-0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Adapter: ACPI interface&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;temp1:        +27.8°C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;temp2:        +29.8°C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;nct6791-isa-0290&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Adapter: ISA adapter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Vcore:                 888.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in1:                     1.03 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;AVCC:                    3.33 V  (min =  +2.98 V, max =  +3.63 V)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+3.3V:                   3.33 V  (min =  +2.98 V, max =  +3.63 V)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in4:                   1000.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in5:                     2.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in6:                   808.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3VSB:                    3.41 V  (min =  +2.98 V, max =  +3.63 V)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Vbat:                    3.28 V  (min =  +2.70 V, max =  +3.63 V)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in9:                     1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in10:                  224.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in11:                  184.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in12:                  1000.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in13:                    1.03 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in14:                  232.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fan1:                   793 RPM  (min =    0 RPM)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fan2:                   818 RPM  (min =    0 RPM)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SYSTIN:                  +8.0°C  (high =  +0.0°C, hyst =  +0.0°C)  ALARM  sensor = thermistor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;CPUTIN:                 +37.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;AUXTIN0:                +36.5°C    sensor = thermistor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;AUXTIN1:               +101.0°C    sensor = thermistor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;AUXTIN2:                +99.0°C    sensor = thermistor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;AUXTIN3:               +101.0°C    sensor = thermistor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PECI Agent 0:           +37.0°C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PCH_CHIP_CPU_MAX_TEMP:   +0.0°C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PCH_CHIP_TEMP:           +0.0°C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PCH_CPU_TEMP:            +0.0°C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PCH_MCH_TEMP:            +0.0°C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PCH_DIM0_TEMP:           +0.0°C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;intrusion0:            ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;intrusion1:            ALARM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;beep_enable:           disabled&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Most things are either invalid or useless, but some values are actually of use to us.&lt;&#x2F;p&gt;
&lt;p&gt;Under &lt;code&gt;amdgpu-pci-0100&lt;&#x2F;code&gt;, we see that my gpu likes edging, but it&#x27;s not very hot because of that yet. You probably have a different gpu than me, so you&#x27;ll likely see a different section name, but should be able to find it pretty easily. I assume it&#x27;ll have &lt;code&gt;gpu&lt;&#x2F;code&gt; in its name still. &lt;br &#x2F;&gt;
&lt;code&gt;coretemp-isa-0000&lt;&#x2F;code&gt; is the temperature of the actual cpu. But according to chatgpt (lol), you&#x27;re not meant to use that temperature reading for cooling purposes, and should instead consider &lt;code&gt;CPUTIN&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Right next to it, we also see &lt;code&gt;fan1&lt;&#x2F;code&gt; and &lt;code&gt;fan2&lt;&#x2F;code&gt;, with their speeds in rpm. &lt;br &#x2F;&gt;
&lt;code&gt;sensors&lt;&#x2F;code&gt; is how I did all of my temperature testing throughout this blog post.&lt;&#x2F;p&gt;
&lt;p&gt;All the values here are actually read from device (?) files, so if you run &lt;code&gt;sensors -j&lt;&#x2F;code&gt;, you&#x27;ll be able to find those paths, to be used in your waybar, and more importantly to find out the correct temperature paths for our next step.&lt;&#x2F;p&gt;
&lt;p&gt;Now that you have the sensors working, you should run &lt;code&gt;sudo pwmconfig&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
It moves you through a series of questions to generate the config file that &lt;code&gt;fancontrol&lt;&#x2F;code&gt; will use.&lt;&#x2F;p&gt;
&lt;p&gt;Go through it one or maybe even more times, to get familiar with what it can even ask you. Because &lt;code&gt;pwmconfig&lt;&#x2F;code&gt; &lt;em&gt;just&lt;&#x2F;em&gt; generates a config file, it is absolutely safe to fuck up in this step, as we haven&#x27;t started &lt;code&gt;fancontrol&lt;&#x2F;code&gt; yet, haven&#x27;t reloaded it to the new generated config, and we&#x27;re going to manually edit the config after generating it anyway.&lt;&#x2F;p&gt;
&lt;p&gt;The main concept of fancontrol, is that you decide which temperature sensor is the controlling one. &lt;br &#x2F;&gt;
&quot;The higher the temperature is in x, the faster you should spin the y fan.&quot;. And you get to decide all the xes and the yes.&lt;&#x2F;p&gt;
&lt;p&gt;As I mentioned above, we can figure out the relevant temperature paths thanks to &lt;code&gt;sensors -j&lt;&#x2F;code&gt;, but how do we figure out which &lt;em&gt;fan&lt;&#x2F;em&gt; is which? &lt;br &#x2F;&gt;
That&#x27;s where the pwmconfig process is handy: while it&#x27;s testing your fans&#x27; pwm-ness, it will speed them up and stop them. Look inside of your case to figure out which fan path refers to which fan. Kinda crude I know, but that&#x27;s how I figured it out.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;config&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#config&quot; aria-label=&quot;Anchor link for: config&quot;&gt;config&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;After going through the process, you now have a generated config file in &lt;code&gt;&#x2F;etc&#x2F;fancontrol&lt;&#x2F;code&gt;. In theory. &lt;br &#x2F;&gt;
Yours will look different from mine, as I manually edited it after &lt;em&gt;and&lt;&#x2F;em&gt; we have different paths for everything. But I&#x27;ll explain the idea of what everything is so that you can feel more comfortable with using pwmconfig and manually editing the config in the future.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #928374;&quot;&gt;# Configuration file generated by pwmconfig, changes will be lost&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;INTERVAL&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;DEVPATH&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;hwmon3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;devices&#x2F;platform&#x2F;nct6775.656 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;hwmon4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;devices&#x2F;pci0000:00&#x2F;0000:00:01.0&#x2F;0000:01:00.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;DEVNAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;hwmon3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;nct6791 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;hwmon4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;amdgpu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;FCTEMPS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon3&#x2F;temp2_input hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon4&#x2F;temp1_input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;FCFANS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon3&#x2F;fan2_input hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon3&#x2F;fan1_input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;MINTEMP&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;45 hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;45&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;MAXTEMP&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;70 hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;70&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;MINSTART&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80 hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;MINSTOP&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80 hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;MINPWM&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80 hwmon3&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #78BF84;&quot;&gt;pwm1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I wouldn&#x27;t touch the first 3 lines. &lt;br &#x2F;&gt;
&lt;code&gt;FCTEMPS&lt;&#x2F;code&gt; is the main juice of fancontrol: which pwm controller (and consequently which fans) to speed up in relation to which temperature. &lt;br &#x2F;&gt;
I mentioned that &lt;code&gt;fancontrol&lt;&#x2F;code&gt; is what completely solved my cooling wackness: this is because now the gpu fan is plugged into the chassis port, and depends on the temperature of the gpu (&lt;code&gt;hwmon4&#x2F;temp1_input&lt;&#x2F;code&gt;). &lt;br &#x2F;&gt;
Even though the port is absolutely not the gpu&#x27;s port, I control its speed via the gpu&#x27;s temperature! Isn&#x27;t that nice :3 \&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;FCFANS&lt;&#x2F;code&gt; is which pwm controller controlls which fan. &lt;code&gt;pwmconfig&lt;&#x2F;code&gt; should&#x27;ve configured this correctly; I haven&#x27;t touched this option myself.&lt;&#x2F;p&gt;
&lt;p&gt;If your thingy is lower than &lt;code&gt;MINTEMP&lt;&#x2F;code&gt; in temperature, its correlated fan will spin at &lt;code&gt;MINPWM&lt;&#x2F;code&gt; of speed. If you don&#x27;t specify &lt;code&gt;MINPWM&lt;&#x2F;code&gt;, it defaults to 0, meaning it completely stops your fans!! :D&lt;&#x2F;p&gt;
&lt;p&gt;If your thingy is higher than &lt;code&gt;MAXTEMP&lt;&#x2F;code&gt; in temperature, its correlated fan will spin at &lt;code&gt;MAXPWM&lt;&#x2F;code&gt; of speed, which defaults to 255 (the maximum speed).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;MINSTART&lt;&#x2F;code&gt; is meant to be the minumum PWM value at which your fans &lt;em&gt;start&lt;&#x2F;em&gt; spinning, and &lt;code&gt;MINSTOP&lt;&#x2F;code&gt; is meant to be the maximum PWM value at which your fans are still NOT spinning. &lt;br &#x2F;&gt;
However, fancontrol for some reason will add extra 20 to your specified &lt;code&gt;MINSTART&lt;&#x2F;code&gt; value, for stability I think? Kinda weird.&lt;&#x2F;p&gt;
&lt;p&gt;At first I enjoyed the expected setup where the fans don&#x27;t spin up until a certain temperature &lt;em&gt;at all&lt;&#x2F;em&gt;, and then start ramping up. &lt;br &#x2F;&gt;
It was so (comparatively) quiet, in fact, that I decided to change my setup to be &quot;louder&quot;!&lt;&#x2F;p&gt;
&lt;p&gt;Having my ear right next to the case makes me hear the fan &lt;em&gt;faintly&lt;&#x2F;em&gt;, when it&#x27;s spinning at 800rpm. &lt;br &#x2F;&gt;
My pc is placed on the floor, hiding behind the right side of my table — in other words, it&#x27;s impossible for me to hear that level of noise. &lt;br &#x2F;&gt;
And that&#x27;s why I set &lt;code&gt;MINSTART&lt;&#x2F;code&gt;, &lt;code&gt;MINSTOP&lt;&#x2F;code&gt;, &lt;code&gt;MINPWM&lt;&#x2F;code&gt; all to the same values per fan controller: I want the fans to spin at &lt;em&gt;at least&lt;&#x2F;em&gt; 800rpm at their minimum, but ramp up after 45°C. &lt;br &#x2F;&gt;
This way, I keep my system at 39°C for the gpu and 37°C for the cpu under normal circumstances, with no noise downside. &lt;br &#x2F;&gt;
In the future when I get two extra fans, those temperatures are likely going to be even better! :D &lt;br &#x2F;&gt;
Although keep in mind they are already wonderful temperatures.&lt;&#x2F;p&gt;
&lt;p&gt;After getting the config to your preferred state, simply &lt;code&gt;systemctl enable --now fancontrol.service&lt;&#x2F;code&gt; and it should work! &lt;br &#x2F;&gt;
&lt;code&gt;fancontrol&lt;&#x2F;code&gt; sometimes breaks after reboots and suspending (sleeping), so make yourself an alias to &lt;code&gt;systemctl restart fancontrol.service&lt;&#x2F;code&gt; to fix those cases. &lt;br &#x2F;&gt;
Although in my current venture of learning how to use systemd deeper, I might just fix the &lt;code&gt;.service&lt;&#x2F;code&gt; file to do this automatically for me.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;next-enemy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#next-enemy&quot; aria-label=&quot;Anchor link for: next-enemy&quot;&gt;next enemy&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;With all this configuration and fan minmaxing, fans are officially &lt;strong&gt;not&lt;&#x2F;strong&gt; a problem anymore 🥳&lt;&#x2F;p&gt;
&lt;p&gt;However, my pc is still too noisy!&lt;&#x2F;p&gt;
&lt;p&gt;I never considered it, but now it&#x27;s actually my PSU that&#x27;s making the most noise! So, except the two extra fans, my next pc upgrade will definitely be a PSU upgrade. However it&#x27;s pretty pricy 😬 so that&#x27;s probably not going to be soon.&lt;&#x2F;p&gt;
&lt;p&gt;Aside from that, I&#x27;ve had a constant hum over the course of &lt;em&gt;months&lt;&#x2F;em&gt;; I think my neighbors are cryptomining. &lt;br &#x2F;&gt;
I went through quite a lot of struggles in minmaxing that noise as well, which I&#x27;ve omitted here, but you can imagine how it added salt into the already loud scenario.&lt;&#x2F;p&gt;
&lt;p&gt;Throughout all this time I&#x27;ve started using earplugs WAY more often, to the point that now I have to minmax how long I use them to not damage my ears. &lt;br &#x2F;&gt;
I bought passive noise cancelling headphones to help with that, but they&#x27;re a bit shit. &lt;br &#x2F;&gt;
I bought &lt;em&gt;active&lt;&#x2F;em&gt; noise cancelling headphones as well, but they turned out to be very overwhelming :c and so I returned them.&lt;&#x2F;p&gt;
&lt;p&gt;I would love to move, to solve the currently unsolvable problem of my neighbors being shitty :p&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>wayland screen recording</title>
          <pubDate>Sun, 16 Feb 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/screen-recording/</link>
          <guid>https://axlefublr.github.io/screen-recording/</guid>
          <description xml:base="https://axlefublr.github.io/screen-recording/">&lt;p&gt;I recently switched to wayland, and now my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;2567bb72827619c45a4d2e554148195be6c94b74&#x2F;scripts&#x2F;screen-record.fish&quot;&gt;ffmpeg screen recording script&lt;&#x2F;a&gt; no longer works, as it depends on x11. &lt;br &#x2F;&gt;
To my surprise, screen recording on wayland is &lt;em&gt;easier&lt;&#x2F;em&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ammen99&#x2F;wf-recorder&quot;&gt;wf-recorder&lt;&#x2F;a&gt;, this is all you need:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;wf-recorder&lt;&#x2F;span&gt;&lt;span&gt; -Dyf ~&#x2F;output.mkv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;-y&lt;&#x2F;code&gt; skips the confirmation check to overwrite the file, &lt;code&gt;-D&lt;&#x2F;code&gt; only grabs more frames if anything changed on the screen, in theory reducing filesize. &lt;br &#x2F;&gt;
Pass &lt;code&gt;-a&lt;&#x2F;code&gt; if you wanna record audio. There are also other useful flags: one of them lets you pick a section of the screen to record, using &lt;code&gt;slurp&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now all you need to do to record a video, is run that command, and press &lt;code&gt;ctrl+c&lt;&#x2F;code&gt; on it once you finish recording. &lt;br &#x2F;&gt;
Through some magic I&#x27;ll explain later, I have it on a hotkey as a toggle.&lt;&#x2F;p&gt;
&lt;p&gt;However! &lt;br &#x2F;&gt;
The #1 place I&#x27;ll be sending screen recordings to is &lt;em&gt;discord&lt;&#x2F;em&gt;, which has a 10mb size limit without a subscription.&lt;&#x2F;p&gt;
&lt;p&gt;This is why I compress the video after, with ffmpeg:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;wf-recorder&lt;&#x2F;span&gt;&lt;span&gt; -Dyf ~&#x2F;i&#x2F;s&#x2F;original.mkv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span&gt; -y -i ~&#x2F;i&#x2F;s&#x2F;original.mkv \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -an&lt;&#x2F;span&gt;&lt;span&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -c&lt;&#x2F;span&gt;&lt;span&gt;:v libx264 -preset medium -crf 21 \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -movflags&lt;&#x2F;span&gt;&lt;span&gt; +faststart \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -b&lt;&#x2F;span&gt;&lt;span&gt;:v 3M -maxrate 4.5M -bufsize 6M \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -vf&lt;&#x2F;span&gt;&lt;span&gt; scale=-1:1080 \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ~&#x2F;iwm&#x2F;sco&#x2F;compressed.mp4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This greatly reduces the size, while not being that huge of a difference in quality. Take a look!&lt;&#x2F;p&gt;
&lt;p&gt;Original, at 19mb:&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;original.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Compressed, at 2.5mb:&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;compressed.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;You probably &lt;em&gt;can&lt;&#x2F;em&gt; tell a difference between the two, but I wouldn&#x27;t say that it&#x27;s staggering. The &lt;em&gt;size&lt;&#x2F;em&gt; difference &lt;strong&gt;is&lt;&#x2F;strong&gt; staggering, though! &lt;br &#x2F;&gt;
The compressed version, in this case, is 8 times smaller! Much easier to fit into the tight limits of discord.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to how I wrote it, the original file is kept too! &lt;br &#x2F;&gt;
So if I&#x27;m not restricted by size, I can choose to send the original. &lt;br &#x2F;&gt;
The recording is also automatically &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;uri-list&#x2F;&quot;&gt;copyl&lt;&#x2F;a&gt;ed, letting me immediately &lt;kbd&gt;ctrl+v&lt;&#x2F;kbd&gt; it wherever I want! :3&lt;&#x2F;p&gt;
&lt;a href=&quot;#toggle&quot; id=&quot;toggle&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Let&#x27;s now get into how I made this into a toggle!&lt;&#x2F;p&gt;
&lt;p&gt;The fact that you can gracefully stop the recording with &lt;kbd&gt;ctrl+c&lt;&#x2F;kbd&gt; isn&#x27;t just some hardcoded hotkey — &lt;kbd&gt;ctrl+c&lt;&#x2F;kbd&gt; actually sends the SIGINT signal to the running process, and it&#x27;s &lt;em&gt;that&lt;&#x2F;em&gt; that &lt;code&gt;wf-recorder&lt;&#x2F;code&gt; is actually listening for.&lt;&#x2F;p&gt;
&lt;p&gt;Meaning, we can gracefully finish the current recording using:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;kill&lt;&#x2F;span&gt;&lt;span&gt; -s INT wf-recorder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This assumes that you only have one &lt;code&gt;wf-recorder&lt;&#x2F;code&gt; instance running at a time, which I feel is a pretty safe assumption.&lt;&#x2F;p&gt;
&lt;p&gt;So I made myself this fish function, that I put on a hotkey in my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;erm&#x2F;&quot;&gt;kanata config&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt; toggle_screen_record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; test -f &#x2F;tmp&#x2F;mine&#x2F;recordilock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        kill&lt;&#x2F;span&gt;&lt;span&gt; -s INT wf-recorder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        screen-record.fish&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then the screen-record.fish script is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #928374;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env fish&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;touch&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;tmp&#x2F;mine&#x2F;recordilock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;wf-recorder&lt;&#x2F;span&gt;&lt;span&gt; -Dyf ~&#x2F;iwm&#x2F;sco&#x2F;original.mp4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span&gt; -y -i ~&#x2F;iwm&#x2F;sco&#x2F;original.mp4 \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -an&lt;&#x2F;span&gt;&lt;span&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -c&lt;&#x2F;span&gt;&lt;span&gt;:v libx264 -preset medium -crf 21 \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -movflags&lt;&#x2F;span&gt;&lt;span&gt; +faststart \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -b&lt;&#x2F;span&gt;&lt;span&gt;:v 3M -maxrate 4.5M -bufsize 6M \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ~&#x2F;iwm&#x2F;sco&#x2F;compressed.mp4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;rm&lt;&#x2F;span&gt;&lt;span&gt; -f &#x2F;tmp&#x2F;mine&#x2F;recordilock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;sl.fish&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;iwm&#x2F;sco&#x2F;compressed.mp4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, to go over the whole process, from a neutral state: &lt;br &#x2F;&gt;
I want to start a recording, so I press my hotkey. &lt;br &#x2F;&gt;
The &lt;code&gt;&#x2F;tmp&#x2F;mine&#x2F;recordilock&lt;&#x2F;code&gt; lockfile doesn&#x27;t exist, so we go into the second branch, starting the screen-record.fish script. &lt;br &#x2F;&gt;
The lockfile is created — the next time we press the hotkey, we&#x27;ll go into the first branch instead of the second one. &lt;br &#x2F;&gt;
We start recording, and waiting for SIGINT to be sent to &lt;code&gt;wf-recorder&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I finish my recording, so I press the same hotkey again to complete it. &lt;br &#x2F;&gt;
This time, since the &lt;code&gt;&#x2F;tmp&#x2F;mine&#x2F;recordilock&lt;&#x2F;code&gt; file exists, we go into the first branch — it sends the SIGINT signal that &lt;code&gt;wf-recorder&lt;&#x2F;code&gt; is waiting for.&lt;&#x2F;p&gt;
&lt;p&gt;Now that the &lt;code&gt;wf-recorder&lt;&#x2F;code&gt; process is finished (which takes some time), the initial script can continue execution. &lt;br &#x2F;&gt;
It does the compressing with ffmpeg, then deletes the lockfile. We could, if we wanted to, immediately start a new recording now. &lt;br &#x2F;&gt;
The &lt;code&gt;copyl&lt;&#x2F;code&gt; that is now called &lt;code&gt;sl.fish&lt;&#x2F;code&gt; because I&#x27;m returning half a year after initially writing this blog post&lt;a href=&quot;#footnote-1&quot; id=&quot;headnote-1&quot; class=&quot;footnote&quot; title=&quot;You&#x27;ll be able to jump back here painlessly.&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 copies the uri link to the recording into my clipboard, letting me easily paste it into anywhere.&lt;&#x2F;p&gt;
&lt;p&gt;This is a lot better!
Than dedicating a terminal window for the recording script, and then manually pressing &lt;kbd&gt;ctrl+c&lt;&#x2F;kbd&gt; on it to finish it. &lt;br &#x2F;&gt;
Doing so is not too bad all things considered, but is a bit too close to the &lt;del&gt;IBS&lt;&#x2F;del&gt; OBS workflow.&lt;&#x2F;p&gt;
&lt;p&gt;So now we &lt;em&gt;don&#x27;t&lt;&#x2F;em&gt; see when the recording starts and ends 🥳... Wait, what? &lt;br &#x2F;&gt;
Right! Let&#x27;s integrate this recording toggle into waybar, so it&#x27;s actually clear to us when we&#x27;re recording, when we&#x27;re compressing, and when we&#x27;re done.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;waybar&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#waybar&quot; aria-label=&quot;Anchor link for: waybar&quot;&gt;waybar&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Are you familiar with named pipes? No? &lt;br &#x2F;&gt;
They&#x27;re really convenient for making waybar widgets the text of which you need to modify externally. &lt;br &#x2F;&gt;
I&#x27;m not gonna explain them in depth, but the relevant manpages are the following: &lt;code&gt;mkfifo.1&lt;&#x2F;code&gt;, &lt;code&gt;fifo.7&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Crucially, FIFOs don&#x27;t operate via writes to disk, despite having filepaths, and are instead in-memory. &lt;br &#x2F;&gt;
That makes them quite a bit faster and a lesser hog of our system resources!&lt;&#x2F;p&gt;
&lt;p&gt;If we use a normal file, we need (should?) to create some sort of logic to intermittently clear up old data in the file. &lt;br &#x2F;&gt;
Or I guess would could blammo it into &lt;code&gt;&#x2F;tmp&lt;&#x2F;code&gt; and hope that we will always be rebooting before the bloat ever becomes a problem. &lt;br &#x2F;&gt;
FIFOs avoid this issue with the semantic that the data is read-once — one side is expected to continuously consume the content, and once it has read something, the data is no longer stored in the fifo. &lt;br &#x2F;&gt;
There can be multiple writers, though — so you don&#x27;t need to create some convoluted writer service or anything 😌&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s create the fifa with ↓&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;mkfifo&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Conveniently, once you create a fifo, it stays forever — it&#x27;s not some temporary file you have to set up on every boot or anything. &lt;br &#x2F;&gt;
You can of course later delete it like a normal file.&lt;&#x2F;p&gt;
&lt;p&gt;Now we create a custom module in waybar ↓&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;custom&#x2F;screen-record&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;  &amp;quot;exec&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;&#x2F;home&#x2F;axlefublr&#x2F;fes&#x2F;dot&#x2F;waybar&#x2F;screen-record.fish&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;  &amp;quot;format&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;  &amp;quot;hide-empty-text&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;re using the output of a script as the text of our module&#x2F;widget. &lt;br &#x2F;&gt;
Every new line that is outputted by the script, &lt;em&gt;replaces&lt;&#x2F;em&gt; the text of the widget; a new &lt;em&gt;blank&lt;&#x2F;em&gt; line resets it.&lt;&#x2F;p&gt;
&lt;p&gt;The script is just:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;tail&lt;&#x2F;span&gt;&lt;span&gt; -f ~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now all we have to do to update the widget, is to &lt;em&gt;somehow&lt;&#x2F;em&gt; write a line into the &lt;code&gt;~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;code&gt; “file”. &lt;br &#x2F;&gt;
It&#x27;s actually not a file 🤓☝️ &lt;br &#x2F;&gt;
And yet, we interact with it exactly how we interact with other files: a simple ↓&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; something &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Will make our widget display “something”. And ↓&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Will clear it.&lt;&#x2F;p&gt;
&lt;p&gt;Now let&#x27;s come back to the toggle function and recording script, to make them interact with our new waybar module :3&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt; toggle_screen_record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; test -f &#x2F;tmp&#x2F;mine&#x2F;recordilock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        echo&lt;&#x2F;span&gt;&lt;span&gt; killing &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        kill&lt;&#x2F;span&gt;&lt;span&gt; -s INT wf-recorder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        echo&lt;&#x2F;span&gt;&lt;span&gt; starting &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;        screen-record.fish&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the toggle function, we report sending the kill signal &#x2F; starting the recording script. &lt;br &#x2F;&gt;
By all accounts, the next step after that happens so fast that we are probably never going to see &lt;code&gt;killing&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;starting&lt;&#x2F;code&gt; in our waybar module, but if anything ever holds up suspiciously long, this can be helpful for debugging.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;touch&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;tmp&#x2F;mine&#x2F;recordilock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; recording &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;wf-recorder&lt;&#x2F;span&gt;&lt;span&gt; -Dyf ~&#x2F;iwm&#x2F;sco&#x2F;original.mp4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; compressing &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span&gt; -y -i ~&#x2F;iwm&#x2F;sco&#x2F;original.mp4 \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -an&lt;&#x2F;span&gt;&lt;span&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -c&lt;&#x2F;span&gt;&lt;span&gt;:v libx264 -preset medium -crf 21 \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -movflags&lt;&#x2F;span&gt;&lt;span&gt; +faststart \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;    -b&lt;&#x2F;span&gt;&lt;span&gt;:v 3M -maxrate 4.5M -bufsize 6M \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ~&#x2F;iwm&#x2F;sco&#x2F;compressed.mp4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;rm&lt;&#x2F;span&gt;&lt;span&gt; -f &#x2F;tmp&#x2F;mine&#x2F;recordilock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; copying &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;sl.fish&lt;&#x2F;span&gt;&lt;span&gt; ~&#x2F;iwm&#x2F;sco&#x2F;compressed.mp4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;.local&#x2F;share&#x2F;mine&#x2F;waybar-screen-record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now it&#x27;s clear what&#x27;s currently happening, if anything! &lt;br &#x2F;&gt;
After you press the hotkey the second time, you can quickly confirm that the recording did indeed complete, and is now compressing. &lt;br &#x2F;&gt;
Once it&#x27;s in the compressing stage, you basically wait for the waybar module to become empty again — &lt;em&gt;that&#x27;s&lt;&#x2F;em&gt; the marker that it &lt;code&gt;copyl&lt;&#x2F;code&gt;ed, and is now pasteable 🚀&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;recording.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;I can&#x27;t exactly show you all the steps, but here&#x27;s my waybar saying “recording”, lol!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;footnotes&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;#headnote-1&quot; id=&quot;footnote-1&quot; class=&quot;headnote&quot; title=&quot;Click to go back&quot;&gt;
  &lt;sup&gt;1&lt;&#x2F;sup&gt;
&lt;&#x2F;a&gt;
 This whole section of me explaining how to make a toggle hotkey for this is new! &lt;br &#x2F;&gt;
Writing this on 2025.08.04 &lt;br &#x2F;&gt;
You see, previously (as can be seen in the example recordings above) I had a wack solution that used kitty&#x27;s &lt;code&gt;send-signal&lt;&#x2F;code&gt; capabilities, that was too hyperspecific to share.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>stop picking on files</title>
          <pubDate>Sun, 16 Feb 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/uri-list/</link>
          <guid>https://axlefublr.github.io/uri-list/</guid>
          <description xml:base="https://axlefublr.github.io/uri-list/">&lt;p&gt;When using linux, over time you might naturally arrive at hating guis and preferring a more terminal-centric workflow. &lt;br &#x2F;&gt;
One thing that always stood out to me as unescapable though, is &lt;em&gt;picking files&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Say you wanna send a file on a messenging app, or maybe blammo an image over another one in krita. &lt;br &#x2F;&gt;
You will most likely need to open a file picker to pick the file that you want, or a gui file manager that will allow you to drag &amp;amp; drop.&lt;&#x2F;p&gt;
&lt;p&gt;Always found it very annoying. &lt;br &#x2F;&gt;
In my terminal, I have tooling like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ajeetdsouza&#x2F;zoxide&quot;&gt;zoxide&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;harp&quot;&gt;harp&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sxyazi&#x2F;yazi&quot;&gt;yazi&lt;&#x2F;a&gt;, &lt;code&gt;fd&lt;&#x2F;code&gt;, &lt;code&gt;rg&lt;&#x2F;code&gt;, and everything else that makes getting to a file a comfortable experience. &lt;br &#x2F;&gt;
But when I need to interact with The™ Outside™ World™ (the browser, mostly), now suddenly that tooling is not very helpful. &lt;br &#x2F;&gt;
What I do now is copy the filepath in the terminal in one way or another, and then paste it in the file picker that gets opened; this is better but still kinda ass to have to do.&lt;&#x2F;p&gt;
&lt;p&gt;Recently my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;titaniumtraveler&quot;&gt;friend&lt;&#x2F;a&gt; showed me something incredible: the uri-list.&lt;&#x2F;p&gt;
&lt;p&gt;Executing the following in my shell:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; file:&#x2F;&#x2F;&#x2F;home&#x2F;axlefublr&#x2F;i&#x2F;e&#x2F;memes&#x2F;blackbeard-writing.gif &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; wl-copy&lt;&#x2F;span&gt;&lt;span&gt; -t text&#x2F;uri-list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Lets me go on discord and just &lt;kbd&gt;ctrl+v&lt;&#x2F;kbd&gt; the file.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;uri-list&#x2F;.&#x2F;blackbeard-writing.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m fairly certain that this is the mechanic that file managers use for drag and drop functionality, so this solves the need for a gui file manager or a file picker in practically every place 🤯&lt;&#x2F;p&gt;
&lt;a href=&quot;#alias&quot; id=&quot;alias&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;First, it makes a lot of sense to make an alias for this. I&#x27;m on fish, so the syntax may differ for you:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt; copyl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;  echo&lt;&#x2F;span&gt;&lt;span&gt; file:&#x2F;&#x2F;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;realpath&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;argv[1])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; wl-copy&lt;&#x2F;span&gt;&lt;span&gt; -t text&#x2F;uri-list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;funcsave&lt;&#x2F;span&gt;&lt;span&gt; copyl &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now I can do something like &lt;code&gt;copyl blackbeard-writing.gif&lt;&#x2F;code&gt; while my current working directory is &lt;code&gt;~&#x2F;i&#x2F;e&#x2F;memes&lt;&#x2F;code&gt;, and that will resolve to the full path that is required, letting me input a file into my clipboard quickly.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t like typing in paths though, so for the usecase of picking a file I will generally use &lt;code&gt;yazi&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I made a mapping that does &lt;code&gt;copyl&lt;&#x2F;code&gt; there, and now the process of sending memes or whatever else is really nice! &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GermainZ&#x2F;xdg-desktop-portal-termfilechooser&quot;&gt;termfilechooser&lt;&#x2F;a&gt; begone!&lt;&#x2F;p&gt;
&lt;a href=&quot;#filotkis&quot; id=&quot;filotkis&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;A more overcomplicated idea, is that now you can put &lt;em&gt;files&lt;&#x2F;em&gt; on &lt;strong&gt;hotkeys&lt;&#x2F;strong&gt;. &lt;br &#x2F;&gt;
Use something like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;xremap&#x2F;xremap&quot;&gt;xremap&lt;&#x2F;a&gt; for hotkeys that put specific files into your clipboard, like above; now you can drive a meme to the ground even faster! This is what you get by learning linux 😎 &lt;br &#x2F;&gt;
For this idea to be slightly more viable though, I heavily recommend using harp. Changing your xremap configuration every time you wanna update your image hotkeys is bound to be very annoying.&lt;&#x2F;p&gt;
&lt;a href=&quot;#screen-record&quot; id=&quot;screen-record&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Also, this is useful for screen recordings. &lt;br &#x2F;&gt;
Screenshotting tools generally put the image into your clipboard, so you just paste it directly. &lt;br &#x2F;&gt;
A screen&lt;em&gt;video&lt;&#x2F;em&gt;ing tool can&#x27;t put the video into your clipboard (?), but you can just make it &lt;code&gt;copyl&lt;&#x2F;code&gt; the file uri, to be practically the same thing as the file being in your clipboard. &lt;br &#x2F;&gt;
Very convenient! Now I can make a screen recording and immediately paste it, no need to open a file picker :3&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>fish shell 4.0.0</title>
          <pubDate>Sat, 25 Jan 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/new-fish-shell/</link>
          <guid>https://axlefublr.github.io/new-fish-shell/</guid>
          <description xml:base="https://axlefublr.github.io/new-fish-shell/">&lt;p&gt;New fish shell major version is coming out! &lt;br &#x2F;&gt;
I want to share with you all the changes that caught my attention. &lt;br &#x2F;&gt;
Incidentally, this blog is my excuse to &lt;em&gt;read&lt;&#x2F;em&gt; the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fishshell.com&#x2F;docs&#x2F;4.0b1&#x2F;relnotes.html&quot;&gt;release notes&lt;&#x2F;a&gt; to begin with c:&lt;&#x2F;p&gt;
&lt;p&gt;First of all, fish shell got rewritten from c++ to rust. This is big because it reduces the barrier of entry for contribution and probably makes fish faster.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;fish_should_add_to_history&lt;&#x2F;code&gt; function lets you decide which commands to add to history or not.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;--command&lt;&#x2F;code&gt; flag for &lt;code&gt;abbr&lt;&#x2F;code&gt; allows you to make command-specific abbreviations. Basically, you get to make subcommand aliases but with the power of your &lt;em&gt;shell&lt;&#x2F;em&gt;, not having to rely on the program to support aliasing.&lt;&#x2F;p&gt;
&lt;p&gt;Take a look at this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span&gt; -n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;variable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;  echo&lt;&#x2F;span&gt;&lt;span&gt; success&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Previously, if &lt;code&gt;variable&lt;&#x2F;code&gt; is &lt;em&gt;unset&lt;&#x2F;em&gt; (rather than an empty string), fish would error out — &lt;code&gt;test -n&lt;&#x2F;code&gt; expects an argument after. &lt;br &#x2F;&gt;
It&#x27;s the reason why it&#x27;s good practice to surround the variable with &lt;code&gt;&quot;&lt;&#x2F;code&gt; like &lt;code&gt;&quot;$variable&quot;&lt;&#x2F;code&gt;, so that it resolves to a single argument even if the variable is unset.&lt;&#x2F;p&gt;
&lt;p&gt;Now &lt;code&gt;test -n&lt;&#x2F;code&gt; and &lt;code&gt;test -z&lt;&#x2F;code&gt; &lt;em&gt;don&#x27;t&lt;&#x2F;em&gt; require an argument after, so passing an unset variable is now valid. &lt;br &#x2F;&gt;
Interestingly, only those two options. All the other options work as they did before.&lt;&#x2F;p&gt;
&lt;p&gt;This feature is not enabled by default, you&#x27;d enable it with &lt;code&gt;set -Ua fish_features test-require-arg&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;bind&lt;&#x2F;code&gt; recognizes more modifier combinations and differentiates more keys, for example it can tell apart &lt;kbd&gt;Tab&lt;&#x2F;kbd&gt; and &lt;kbd&gt;ctrl+i&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Also, a more convenient syntax for specifying the key like &lt;kbd&gt;ctrl-x&lt;&#x2F;kbd&gt; is now available. &lt;br &#x2F;&gt;
Previously you had to use &lt;code&gt;bind -k&lt;&#x2F;code&gt; for that, now you don&#x27;t have to.&lt;&#x2F;p&gt;
&lt;p&gt;Omg, I literally needed this so bad: &lt;code&gt;history append&lt;&#x2F;code&gt; lets you append a command to fish history, without executing it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;?&#x2F;path&#x2F;to&#x2F;file&lt;&#x2F;code&gt; tries reading the file as input; if reading fails for any reason, outputs from &lt;code&gt;&#x2F;dev&#x2F;null&lt;&#x2F;code&gt; (which should be an empty string). &lt;br &#x2F;&gt;
Basically, a way to say &quot;read this file if you can, but don&#x27;t fail if you can&#x27;t&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;New &lt;code&gt;path basename -E&lt;&#x2F;code&gt; is like doing &lt;code&gt;path change-extension &#x27;&#x27; (path basename &#x2F;path&#x2F;to&#x2F;file.txt)&lt;&#x2F;code&gt; — &lt;code&gt;&#x2F;path&#x2F;to&#x2F;file.txt&lt;&#x2F;code&gt; gets turned into &lt;code&gt;file&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Math &lt;code&gt;--scale-mode&lt;&#x2F;code&gt; now allows you to choose how the output value&#x27;s decimal points are handled. &lt;code&gt;truncate&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;round&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;floor&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;ceiling&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Abbreviations can now expand after &lt;code&gt;command&lt;&#x2F;code&gt;. As in, &lt;code&gt;command ls&lt;&#x2F;code&gt; will expand similar to how &lt;em&gt;just&lt;&#x2F;em&gt; &lt;code&gt;ls&lt;&#x2F;code&gt; would. &lt;br &#x2F;&gt;
They now also do after &lt;code&gt;;&lt;&#x2F;code&gt; and &lt;code&gt;|&lt;&#x2F;code&gt;. But if you put a &lt;code&gt;|&lt;&#x2F;code&gt; right after a command without a space in between, you&#x27;re a freak.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;funcsave&lt;&#x2F;code&gt;ing a function indents the body.&lt;&#x2F;p&gt;
&lt;p&gt;If there is no second job, &lt;code&gt;fg %2&lt;&#x2F;code&gt; won&#x27;t activate the latest one, and will instead fail.&lt;&#x2F;p&gt;
&lt;p&gt;Depending on your terminal, now &lt;kbd&gt;shift+enter&lt;&#x2F;kbd&gt; will insert a newline rather than execute the command, and &lt;kbd&gt;ctrl+backspace&lt;&#x2F;kbd&gt; &amp;amp; &lt;kbd&gt;ctrl+delete&lt;&#x2F;kbd&gt; works.&lt;&#x2F;p&gt;
&lt;p&gt;In vim mode, the cursor will no longer be beyond the end of the line. I kinda got used to my cursor being 2 character after the end of the line at this point, lol.&lt;&#x2F;p&gt;
&lt;p&gt;Also, &lt;code&gt;%&lt;&#x2F;code&gt; motion, as well as functions to &lt;code&gt;f&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;t&lt;&#x2F;code&gt; to the matching bracket.&lt;&#x2F;p&gt;
&lt;p&gt;Options can now be fuzzy completed!! So, &lt;code&gt;--fbr&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;--foobar&lt;&#x2F;code&gt; will happen, if there&#x27;s no better match.&lt;&#x2F;p&gt;
&lt;p&gt;When you complete something that has characters that need to be escaped, previously each character would be &lt;em&gt;escaped&lt;&#x2F;em&gt;. Now the completed token uses &lt;em&gt;quotes&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
Say you are completing a directory named &lt;code&gt;my directory&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Previously, it would turn into &lt;code&gt;my\ directory&lt;&#x2F;code&gt;, now it will turn into &lt;code&gt;&#x27;my directory&#x27;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;a href=&quot;#done&quot; id=&quot;done&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I opened the release notes, saw the ridiculously small scrollbar, and got terrified like &quot;HOW HUGE IS THIS UPDATE??&quot;, but turns out the page is so long because it contains &lt;em&gt;all&lt;&#x2F;em&gt; the release notes.&lt;&#x2F;p&gt;
&lt;p&gt;So yeah, everything listed above are the neat changes that I found the most significant for myself. Keep in mind though, I might&#x27;ve skipped some that aren&#x27;t important to me but might be important for you!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>finally, a good pager</title>
          <pubDate>Sat, 11 Jan 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/ov/</link>
          <guid>https://axlefublr.github.io/ov/</guid>
          <description xml:base="https://axlefublr.github.io/ov/">&lt;p&gt;Some time ago, I tried looking for a pager, and found... nothing?
How are we content with &lt;code&gt;less&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sharkdp&#x2F;bat&quot;&gt;&lt;code&gt;bat&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; comes up a lot, but it still uses less under the hood as far as I know.&lt;&#x2F;p&gt;
&lt;p&gt;It gives you syntax highlighting, which is nice, but that&#x27;s the last nice thing about bat that I encountered.&lt;&#x2F;p&gt;
&lt;p&gt;That syntax highlighting? Automatically uses a custom theme, instead of trying to use your terminal theme.
Blammoes a big ass header for the filepath that you opened, and takes up like 4 columns for the line numbers.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;You can change that though&quot; is not really a point: if a program has defaults like these, it&#x27;s clear it&#x27;s not doing what I want from a pager.&lt;&#x2F;p&gt;
&lt;p&gt;I want more &lt;em&gt;functional&lt;&#x2F;em&gt; bells and whistles, rather than visual ones.&lt;&#x2F;p&gt;
&lt;p&gt;And today, I finally came across a pager that satisfies me.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;ov&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ov&quot; aria-label=&quot;Anchor link for: ov&quot;&gt;ov&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;noborus&#x2F;ov&quot;&gt;&lt;code&gt;ov&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is my new favorite puppy.&lt;&#x2F;p&gt;
&lt;p&gt;It introduces a few cool concepts that make it &lt;em&gt;sometimes&lt;&#x2F;em&gt; better than your editor! (For viewing files)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;headers&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#headers&quot; aria-label=&quot;Anchor link for: headers&quot;&gt;headers&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Headers are basically &quot;sticky lines&quot;, that are fixed at the top and shown always, as you scroll through.&lt;&#x2F;p&gt;
&lt;p&gt;Very useful for programs with columnar output that display the column names at the top, for example!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;lsblk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; ov&lt;&#x2F;span&gt;&lt;span&gt; --column-width --column-rainbow -H 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;ov&#x2F;.&#x2F;lsblk.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Well, if you have enough output from &lt;code&gt;lsblk&lt;&#x2F;code&gt; to fill more than a screen, I think you&#x27;re cooked 💀. But you get the idea: &lt;code&gt;-H n&lt;&#x2F;code&gt; to set &lt;code&gt;n&lt;&#x2F;code&gt; first lines to always display at the top.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;columns&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#columns&quot; aria-label=&quot;Anchor link for: columns&quot;&gt;columns&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In the above screenshot, each column in the output of &lt;code&gt;lsblk&lt;&#x2F;code&gt; is colored thanks to the &lt;code&gt;--column-rainbow&lt;&#x2F;code&gt; flag.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ov&lt;&#x2F;code&gt; has the concept of columns quite engrained into its functionality. &lt;br &#x2F;&gt;
You can decide how to split into columns based on width or a delimiter character (&#x2F; regex). &lt;br &#x2F;&gt;
Even nicer than that, you can align input into columns even if it is not aligned in the source.&lt;&#x2F;p&gt;
&lt;p&gt;Say I have this file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apple orange potato&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hi hello why&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;I hate kitty&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, it has three columns, but they aren&#x27;t aligned. Let&#x27;s use the &lt;code&gt;--align&lt;&#x2F;code&gt; flag to fix that!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;ov&lt;&#x2F;span&gt;&lt;span&gt; --column-delimiter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39; &amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; --align --column-mode file.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;ov&#x2F;.&#x2F;now-aligned.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;However, here&#x27;s an interesting behavior:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;ov&lt;&#x2F;span&gt;&lt;span&gt; --column-delimiter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39; &amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; --align --column-mode --column-rainbow file.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;ov&#x2F;.&#x2F;fucked-rainbow.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It seems that if your delimiter (a space) is the same as the aligning character (a space), &lt;code&gt;--column-rainbow&lt;&#x2F;code&gt; doesn&#x27;t work how you&#x27;d expect. Oh well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sections&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#sections&quot; aria-label=&quot;Anchor link for: sections&quot;&gt;sections&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Sections are what excites me most about &lt;code&gt;ov&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Basically, you can specify a regex that defines where to split the input &#x2F; file at; you can then press &lt;kbd&gt;^&lt;&#x2F;kbd&gt; &#x2F; &lt;kbd&gt;Space&lt;&#x2F;kbd&gt; to navigate to the previous &#x2F; next section.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;ov&lt;&#x2F;span&gt;&lt;span&gt; jj.toml --section-delimiter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39;^\[&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;ov&#x2F;.&#x2F;sections.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So using sections, you have a nice semantic way to jump between important parts of a file! &lt;br &#x2F;&gt;
An example of where that is going to be most useful to you, is for &lt;em&gt;diffs&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
You simply define something like &lt;code&gt;^diff&lt;&#x2F;code&gt; and blammo, you can jump across the diffs of multiple files in a very easy way.&lt;&#x2F;p&gt;
&lt;p&gt;About that &quot;very easy way&quot; though. &lt;br &#x2F;&gt;
Yes, it&#x27;s genuinely &lt;kbd&gt;^&lt;&#x2F;kbd&gt; and &lt;kbd&gt;Space&lt;&#x2F;kbd&gt; by default.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, ov has a habit of having ass &#x2F; unexpected default mappings. &lt;br &#x2F;&gt;
For example, &lt;kbd&gt;j&lt;&#x2F;kbd&gt; and &lt;kbd&gt;k&lt;&#x2F;kbd&gt; don&#x27;t work. Yes really!&lt;&#x2F;p&gt;
&lt;p&gt;And that default section header color is quite not readable; I don&#x27;t see what white you need to use for it to be readable.&lt;&#x2F;p&gt;
&lt;p&gt;However, a &lt;em&gt;good&lt;&#x2F;em&gt; habit that ov has, is that you can configure everything! &lt;br &#x2F;&gt;
You can configure the colors that it uses (for example, the &lt;code&gt;--column-rainbow&lt;&#x2F;code&gt; colors are those that I set myself), and the hotkeys. So, I&#x27;ll definitely spend some time reworking like, &lt;em&gt;all&lt;&#x2F;em&gt; of them, lol.&lt;&#x2F;p&gt;
&lt;p&gt;However, if you like &lt;code&gt;less&lt;&#x2F;code&gt; mappings (or just can&#x27;t bother), you can copy a config they suggest in the readme, that mimics &lt;code&gt;less&lt;&#x2F;code&gt; mappings closer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;filtering&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#filtering&quot; aria-label=&quot;Anchor link for: filtering&quot;&gt;filtering&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As you would expect, you can search with &lt;kbd&gt;&#x2F;&lt;&#x2F;kbd&gt; and &lt;kbd&gt;?&lt;&#x2F;kbd&gt;. But that&#x27;s a given and not very interesting.&lt;&#x2F;p&gt;
&lt;p&gt;What I find to be more interesting, is &lt;em&gt;filtering&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Using the &lt;code&gt;--filter&lt;&#x2F;code&gt; flag, you can make &lt;code&gt;ov&lt;&#x2F;code&gt; display &lt;em&gt;only&lt;&#x2F;em&gt; the lines that match a pattern; &lt;br &#x2F;&gt;
with &lt;code&gt;--non-match-filter&lt;&#x2F;code&gt; — display &lt;em&gt;only&lt;&#x2F;em&gt; the lines that &lt;strong&gt;don&#x27;t&lt;&#x2F;strong&gt; match a pattern.&lt;&#x2F;p&gt;
&lt;p&gt;Essentially, you get &lt;code&gt;rg&lt;&#x2F;code&gt; for free!&lt;&#x2F;p&gt;
&lt;p&gt;Why not use &lt;code&gt;rg&lt;&#x2F;code&gt; directly you may ask? Because you can also filter &lt;em&gt;interactively&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Although the default mappings are strange as hell, there is a default mapping for basically every flag!&lt;&#x2F;p&gt;
&lt;p&gt;Setting column mode, column mode by width, rainbow, delimiter, filtering and opposite filtering, searching (can be done with a flag btw), headers, sections, section headers, ...&lt;&#x2F;p&gt;
&lt;p&gt;Basically, in &lt;code&gt;ov&lt;&#x2F;code&gt;, if you can do something with a flag, you can generally also do it with a mapping. And vice versa. Very nice design!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;output-on-exit&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#output-on-exit&quot; aria-label=&quot;Anchor link for: output-on-exit&quot;&gt;output on exit&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;With something like &lt;code&gt;less&lt;&#x2F;code&gt;, you view some output in a pager, and then never see it again ✨&lt;&#x2F;p&gt;
&lt;p&gt;To look at the output again, you need to re-execute the command that you piped into less.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ov -X&lt;&#x2F;code&gt; will do something really neat: show the output in the pager, but &lt;em&gt;also&lt;&#x2F;em&gt; print it to stdout. &lt;br &#x2F;&gt;
So once you close &lt;code&gt;ov&lt;&#x2F;code&gt;, the output you were paging will get printed, letting you look at it while continuing to execute other commands.&lt;&#x2F;p&gt;
&lt;p&gt;You don&#x27;t need to always &lt;code&gt;-X&lt;&#x2F;code&gt; though: use the &lt;code&gt;IsWriteOriginal&lt;&#x2F;code&gt; config option to set it to true, if you want. &lt;br &#x2F;&gt;
And you guessed it! You can &lt;em&gt;also&lt;&#x2F;em&gt; do this with a hotkey (&lt;kbd&gt;shift+q&lt;&#x2F;kbd&gt;)! Yes, really!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-even-page&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#don-t-even-page&quot; aria-label=&quot;Anchor link for: don-t-even-page&quot;&gt;don&#x27;t even page&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Similar to &lt;code&gt;less&lt;&#x2F;code&gt;, you can use the &lt;code&gt;-F&lt;&#x2F;code&gt; flag to not even open &lt;code&gt;ov&lt;&#x2F;code&gt; if the entire output fits on the screen. &lt;br &#x2F;&gt;
&lt;code&gt;QuitSmall&lt;&#x2F;code&gt; is the config option to set if it&#x27;s the behavior you always want.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tailing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tailing&quot; aria-label=&quot;Anchor link for: tailing&quot;&gt;tailing&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can use the &lt;code&gt;-f&lt;&#x2F;code&gt; flag to follow a file, similar to &lt;code&gt;tail -f&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;When it gets interesting, is that you can follow &lt;em&gt;multiple files at once&lt;&#x2F;em&gt; using the &lt;code&gt;-A&lt;&#x2F;code&gt; flag.&lt;&#x2F;p&gt;
&lt;p&gt;Rather than creating panes for each file (which I&#x27;d find annoying), it continuously switches to the file that got updated the most recently. &lt;br &#x2F;&gt;
So for example, you decide to &lt;code&gt;ov -A&lt;&#x2F;code&gt; 3 log files; new line appears in log 3 -&amp;gt; you get switched to look at it immediately.
Then, log 1 gets a new line -&amp;gt; you get switched to log 1 now.&lt;&#x2F;p&gt;
&lt;p&gt;Honestly a very neat solution that I like quite a lot. &lt;br &#x2F;&gt;
But if you don&#x27;t, just keep using the &lt;code&gt;-f&lt;&#x2F;code&gt; flag and use &lt;kbd&gt;[&lt;&#x2F;kbd&gt; &#x2F; &lt;kbd&gt;]&lt;&#x2F;kbd&gt; to switch between the multiple files.&lt;&#x2F;p&gt;
&lt;p&gt;The behavior of &lt;code&gt;-A&lt;&#x2F;code&gt; is so exciting to me: I &lt;em&gt;finally&lt;&#x2F;em&gt; have a good way to track log files :D &lt;br &#x2F;&gt;
I just specify a bunch of log files, and then can look at them &lt;em&gt;all&lt;&#x2F;em&gt; in realtime.&lt;&#x2F;p&gt;
&lt;p&gt;Better yet, &lt;code&gt;ov&lt;&#x2F;code&gt; supports suspending, so this works well in my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;suspend&#x2F;&quot;&gt;suspend-based workflow&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;word-coloring&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#word-coloring&quot; aria-label=&quot;Anchor link for: word-coloring&quot;&gt;word coloring&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Especially in logs, it is common that coloring some words like &lt;code&gt;ERROR&lt;&#x2F;code&gt; and such is very helpful.&lt;&#x2F;p&gt;
&lt;p&gt;Use the &lt;code&gt;-M&lt;&#x2F;code&gt; option to specify a &lt;code&gt;,&lt;&#x2F;code&gt; delimited list of regex expressions that define what to color differently.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;pueue&lt;&#x2F;span&gt;&lt;span&gt; status &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; ov&lt;&#x2F;span&gt;&lt;span&gt; --wrap=false -M&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39;Killed,Running,Queued,Success&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;ov&#x2F;.&#x2F;pueue.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You also can use the &lt;code&gt;-e&lt;&#x2F;code&gt; option to execute the command &lt;em&gt;from&lt;&#x2F;em&gt; ov.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;ov&lt;&#x2F;span&gt;&lt;span&gt; --wrap=false -M&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39;Killed,Running,Queued,Success&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -e pueue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This way, you &lt;em&gt;retain&lt;&#x2F;em&gt; the colors that your command produces, and maybe add some more with &lt;code&gt;-M&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively, you can use &lt;code&gt;unbuffer&lt;&#x2F;code&gt; to trick the program into thinking it&#x27;s writing to a terminal, to retain its colors.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;unbuffer&lt;&#x2F;span&gt;&lt;span&gt; pueue &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; ov&lt;&#x2F;span&gt;&lt;span&gt; --wrap=false -M&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39;Killed,Running,Queued,Success&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&quot;Oh I sure do wonder where to install this useful-sounding program&quot; — no clue, sorry. It&#x27;s &lt;em&gt;somewhere&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;check-it-out&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#check-it-out&quot; aria-label=&quot;Anchor link for: check-it-out&quot;&gt;check it out!&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;My goal isn&#x27;t to teach you the entirety of &lt;code&gt;ov&lt;&#x2F;code&gt;, but to &lt;em&gt;sell you&lt;&#x2F;em&gt; on it. &lt;br &#x2F;&gt;
Go check out &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;noborus&#x2F;ov&quot;&gt;the project&#x27;s readme&lt;&#x2F;a&gt; to learn about it more deeply!&lt;&#x2F;p&gt;
&lt;p&gt;I love how it&#x27;s written: generally I get super overwhelmed when discovering a program of a certain bigness, but ov&#x27;s readme is structured in a pretty nice way where I was able to learn it effectively!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;p-s&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#p-s&quot; aria-label=&quot;Anchor link for: p-s&quot;&gt;P.S.&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;ov has an interesting bug I experienced: &lt;em&gt;sometimes&lt;&#x2F;em&gt;, for &lt;em&gt;some&lt;&#x2F;em&gt; of my configured hotkeys (it&#x27;s random, and doesn&#x27;t apply to all of them at once), they stop getting recognized and get defaulted back to ov&#x27;s defaults.&lt;&#x2F;p&gt;
&lt;p&gt;So, for example, I set &lt;kbd&gt;j&lt;&#x2F;kbd&gt; to go a line down; it sometimes happens that pressing &lt;kbd&gt;j&lt;&#x2F;kbd&gt; will go back to its default function, despite me disabling that in my configuration.&lt;&#x2F;p&gt;
&lt;p&gt;So if you&#x27;re experiencing the same bug as me, build &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;ov&quot;&gt;my fork of ov&lt;&#x2F;a&gt; from source. &lt;br &#x2F;&gt;
All I do in it, is remove &lt;em&gt;all&lt;&#x2F;em&gt; default mappings, so that &lt;em&gt;your&lt;&#x2F;em&gt; configured mappings are guaranteed to work.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>how to anki</title>
          <pubDate>Tue, 07 Jan 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/how-to-anki/</link>
          <guid>https://axlefublr.github.io/how-to-anki/</guid>
          <description xml:base="https://axlefublr.github.io/how-to-anki/">&lt;p&gt;Anki is honestly a very hard to approach program. If you feel like it isn&#x27;t, you&#x27;re using it wrong &#x2F;hj&lt;&#x2F;p&gt;
&lt;p&gt;In this post, I&#x27;m assuming that you already want anki and know &lt;em&gt;why&lt;&#x2F;em&gt; you want anki, so I won&#x27;t be inspiring you; just sharing what I think is the optimal way to use anki.&lt;&#x2F;p&gt;
&lt;p&gt;In the next few sections related to settings, here&#x27;s what you can expect: &lt;br &#x2F;&gt;
If I don&#x27;t mention a setting, it&#x27;s either insignificant or personal choice; you should check it out for yourself regardless. &lt;br &#x2F;&gt;
It&#x27;s also possible you&#x27;re reading this in the future, where a new setting appeared that I don&#x27;t go over (my anki version is 24.06.3).&lt;&#x2F;p&gt;
&lt;p&gt;Settings that I strongly &lt;em&gt;recommend&lt;&#x2F;em&gt; a certain value of are going to be marked by ❗ &lt;br &#x2F;&gt;
Settings that I VERY STRONGLY beg you to set to a certain value will be marked by ‼️&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll be expecting you to have already installed anki; the pc version (which desktop os you have shouldn&#x27;t matter, though).&lt;&#x2F;p&gt;
&lt;p&gt;An extra resource along with this blog post that I can recommend, is this &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Eo1HbXEiJxo&quot;&gt;youtube video&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;global-settings&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#global-settings&quot; aria-label=&quot;Anchor link for: global-settings&quot;&gt;Global settings&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s go to global settings by pressing &lt;kbd&gt;ctrl+p&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;review&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#review&quot; aria-label=&quot;Anchor link for: review&quot;&gt;Review&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;next-day-starts-at&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#next-day-starts-at&quot; aria-label=&quot;Anchor link for: next-day-starts-at&quot;&gt;Next day starts at&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The rule for the best time is to make sure it&#x27;s impossible for you to see the next day&#x27;s cards in the previous day, basically. My default is 5 am.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;learn-ahead-limit&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#learn-ahead-limit&quot; aria-label=&quot;Anchor link for: learn-ahead-limit&quot;&gt;Learn ahead limit&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;0&lt;&#x2F;p&gt;
&lt;p&gt;This setting is very weird.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;TLDR: don&#x27;t use it, but if you&#x27;re still interested, continue reading this section&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Imagine you have a bunch of reviews (green (mature) cards) left to do in the deck;
when you press “Again”, you see the card in 20 minutes.&lt;&#x2F;p&gt;
&lt;p&gt;As you go through your reviews, you might take so long so that you see the “Again” card in the same review session. &lt;br &#x2F;&gt;
Usually you&#x27;re supposed to set &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;how-to-anki&#x2F;#learning-steps&quot;&gt;learning steps&lt;&#x2F;a&gt; to a high enough value where that won&#x27;t happen.&lt;&#x2F;p&gt;
&lt;p&gt;So, you go through all of your reviews, and there are 10 more minutes until you see that “Again” card. &lt;br &#x2F;&gt;
There is &lt;em&gt;nothing&lt;&#x2F;em&gt; left for you to review; you can leave.&lt;&#x2F;p&gt;
&lt;p&gt;What “Learn ahead limit” lets you do, is cut down those 10 (or however many) minutes down to zero. &lt;br &#x2F;&gt;
It starts acting once you &lt;em&gt;finished all reviews&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is different from the default behavior of learning cards (red ones): those usually can appear whenever in your review session, not just after all other ones are finished.&lt;&#x2F;p&gt;
&lt;p&gt;“How is this useful?” you may ask; and my answer is &lt;em&gt;exactly&lt;&#x2F;em&gt;. It is somewhat useless in my experience.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;show-remaining-card-count&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#show-remaining-card-count&quot; aria-label=&quot;Anchor link for: show-remaining-card-count&quot;&gt;Show remaining card count&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Should be set to true&lt;&#x2F;p&gt;
&lt;p&gt;Because it&#x27;s helpful to see whether you are currently on a new &#x2F; learning &#x2F; mature card.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;show-next-review-time-above-answer-buttons&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#show-next-review-time-above-answer-buttons&quot; aria-label=&quot;Anchor link for: show-next-review-time-above-answer-buttons&quot;&gt;Show next review time above answer buttons&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I had this set to true for the longest time, but recently I disabled it! &lt;br &#x2F;&gt;
If you see that pressing “Easy” will make you see the card in 2 years rather than 1.5 years, you will be less likely to actually press it, even if it&#x27;s the correct decision. Similar case for “Hard”. &lt;br &#x2F;&gt;
If you never see the time periods, you make answering decisions that are less biased.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;spacebar-or-enter-also-answers-card&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#spacebar-or-enter-also-answers-card&quot; aria-label=&quot;Anchor link for: spacebar-or-enter-also-answers-card&quot;&gt;Spacebar (or enter) also answers card&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;yep.&lt;&#x2F;p&gt;
&lt;p&gt;Set yourself some answer keys as well. &lt;br &#x2F;&gt;
Anki is more keyboard-supporting than you&#x27;d think!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-bit-of-keyboard-navigation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-bit-of-keyboard-navigation&quot; aria-label=&quot;Anchor link for: a-bit-of-keyboard-navigation&quot;&gt;A bit of keyboard navigation&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;We are now done in global settings.&lt;&#x2F;p&gt;
&lt;p&gt;To discover a bit of the keyboard navigation support anki provides, let&#x27;s move onto creating and configuring a deck.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a Default deck by ...uhhhhhm... default.. Let&#x27;s configure that one!&lt;&#x2F;p&gt;
&lt;p&gt;You could press on the cog with the mouse, but I&#x27;ll teach you to do that with your keyboard.&lt;&#x2F;p&gt;
&lt;p&gt;You can press &lt;kbd&gt;&#x2F;&lt;&#x2F;kbd&gt; to search for a deck to study. &lt;br &#x2F;&gt;
In this menu, you can press &lt;kbd&gt;ctrl+n&lt;&#x2F;kbd&gt; to create a new one (don&#x27;t do it yet). &lt;br &#x2F;&gt;
Currently you only have &lt;code&gt;Default&lt;&#x2F;code&gt; so you could just press &lt;kbd&gt;enter&lt;&#x2F;kbd&gt; immediately to pick it.&lt;&#x2F;p&gt;
&lt;p&gt;This moves you into the screen of your deck. No clue what it&#x27;s actually called, I&#x27;ll be calling it &quot;yipee screen&quot; from now on. Because after you finish your cards, it says “Congratulations!” :3&lt;&#x2F;p&gt;
&lt;p&gt;In this screen, if you had any reviews to do, you would be able to press &lt;kbd&gt;s&lt;&#x2F;kbd&gt; to start the reviews. But that&#x27;s for later; you don&#x27;t have any cards yet.&lt;&#x2F;p&gt;
&lt;p&gt;If you wanted to go back to the main screen of anki, you can press &lt;kbd&gt;d&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
You might be quick to now search for &lt;code&gt;Default&lt;&#x2F;code&gt; using &lt;kbd&gt;&#x2F;&lt;&#x2F;kbd&gt; again, but there&#x27;s no need: the &lt;code&gt;Default&lt;&#x2F;code&gt; deck is already selected. &lt;br &#x2F;&gt;
It&#x27;s going to be more obvious once you have more decks (if there is even a need), but there&#x27;s a semantic of &quot;the selected deck&quot; in anki. You can press &lt;kbd&gt;s&lt;&#x2F;kbd&gt; to jump into the yipee screen of your selected deck.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;s&lt;&#x2F;kbd&gt; then &lt;kbd&gt;d&lt;&#x2F;kbd&gt; then &lt;kbd&gt;s&lt;&#x2F;kbd&gt; then &lt;kbd&gt;d&lt;&#x2F;kbd&gt; then &lt;kbd&gt;s&lt;&#x2F;kbd&gt;...&lt;&#x2F;p&gt;
&lt;p&gt;Alrightie now from the yipee screen we can press &lt;kbd&gt;o&lt;&#x2F;kbd&gt; to open the &lt;em&gt;deck&lt;&#x2F;em&gt;&#x27;s settings.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;deck-settings&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#deck-settings&quot; aria-label=&quot;Anchor link for: deck-settings&quot;&gt;Deck settings&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;ll warn you immediately: if you press &lt;kbd&gt;Escape&lt;&#x2F;kbd&gt; from this point, it just discards your changes. You specifically need to press “Save” to save your deck&#x27;s settings.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;daily-limits&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#daily-limits&quot; aria-label=&quot;Anchor link for: daily-limits&quot;&gt;Daily limits&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;new-cards-day&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#new-cards-day&quot; aria-label=&quot;Anchor link for: new-cards-day&quot;&gt;New cards&#x2F;day&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You might be quick to set this to a pretty high value. &lt;br &#x2F;&gt;
You are motivated and excited about anki, you&#x27;re even reading a blog about it! You might&#x27;ve even watched a whole ass hour long youtube video about it. “Surely I can set it to like 50, right?”&lt;&#x2F;p&gt;
&lt;p&gt;WRONG. You have no idea just how strongly seemingly small effort compiles. You may be absolutely fine with 50 new cards one day, maybe even a whole week, but you&#x27;re not using anki for a week&#x27;s worth of memory, are you? &lt;br &#x2F;&gt;
Anki is &lt;em&gt;made&lt;&#x2F;em&gt; and &lt;em&gt;designed&lt;&#x2F;em&gt; to be &lt;em&gt;very&lt;&#x2F;em&gt; longform. &quot;Your entire life&quot; type deal. &lt;br &#x2F;&gt;
If you rush to set your new cards to some big amount, there&#x27;s a good chance you&#x27;ll burn out in like a month and maybe skip a day or two, then come back to 500 reviews and fully quit.&lt;&#x2F;p&gt;
&lt;p&gt;Anki is minmaxed with the assumption that you &lt;em&gt;will&lt;&#x2F;em&gt; &lt;strong&gt;always&lt;&#x2F;strong&gt; be doing your daily reviews. Maximize for &lt;em&gt;that&lt;&#x2F;em&gt; as well. For &lt;em&gt;consistency&lt;&#x2F;em&gt;, &lt;strong&gt;not&lt;&#x2F;strong&gt; burst.
I consider 30 new cards per day huge, but it super depends on the content and the time and effort you&#x27;re willing to spend.&lt;&#x2F;p&gt;
&lt;p&gt;I use anki for:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;morse code&lt;&#x2F;li&gt;
&lt;li&gt;hiragana&lt;&#x2F;li&gt;
&lt;li&gt;katakana&lt;&#x2F;li&gt;
&lt;li&gt;all country flags&lt;&#x2F;li&gt;
&lt;li&gt;all country locations on a map&lt;&#x2F;li&gt;
&lt;li&gt;programming languages&lt;&#x2F;li&gt;
&lt;li&gt;APIs&lt;&#x2F;li&gt;
&lt;li&gt;hotkeys; global ones and those local to specific programs&lt;&#x2F;li&gt;
&lt;li&gt;ascii decimal and hex codes&lt;&#x2F;li&gt;
&lt;li&gt;alphabet indexes (d = 4 for example)&lt;&#x2F;li&gt;
&lt;li&gt;I shit you not, my credit card information. Don&#x27;t do this, anki isn&#x27;t meant to securely store your credit card information, lol.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I, on average, spend 20 minutes per day on reviews, with ~11 new cards per day. &lt;br &#x2F;&gt;
This is quite small workload all things considered, but the massive benefit I get is that I&#x27;m excited about doing anki every day, and it&#x27;s practically impossible for me to burn out on it.&lt;&#x2F;p&gt;
&lt;p&gt;So for the recommendation: you won&#x27;t really know how many is too many, as it&#x27;s likely you want to use anki for a different type of information than me, so set it to a reasonable amount (like 10), and feel free to change it as you continue to use anki. &lt;br &#x2F;&gt;
If you ever notice yourself feel burnt out with anki, &lt;strong&gt;the&lt;&#x2F;strong&gt; thing you should configure is the amount of daily new cards.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;maximum-reviews-day&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#maximum-reviews-day&quot; aria-label=&quot;Anchor link for: maximum-reviews-day&quot;&gt;Maximum reviews&#x2F;day&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;‼️9999 &lt;br &#x2F;&gt;
Out of every single setting in anki, this one is my strongest recommendation. Hell, this is not even a recommendation — I &lt;em&gt;&lt;strong&gt;beg&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; you to set it to 9999 and never even consider touching it. &lt;br &#x2F;&gt;
If you ever &lt;em&gt;actually&lt;&#x2F;em&gt; get to 9999 daily reviews, you&#x27;re fucked because you didn&#x27;t listen to my advice about new cards per day above; the reason to set &lt;em&gt;this&lt;&#x2F;em&gt; setting to such a high amount is mostly semantic. &lt;br &#x2F;&gt;
Anki&#x27;s algorithm is written in such a way where it&#x27;s most efficient when it&#x27;s allowed to give you cards at the precise intervals it has calculated. If it&#x27;s arbitrarily restricted by a cap of reviews, it&#x27;s simply going to spend more of your time and energy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;new-cards&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#new-cards&quot; aria-label=&quot;Anchor link for: new-cards&quot;&gt;New cards&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;learning-steps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#learning-steps&quot; aria-label=&quot;Anchor link for: learning-steps&quot;&gt;Learning steps&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Because of FSRS (we&#x27;ll get to it), this should only ever be a single step. &lt;br &#x2F;&gt;
When you press “Again” on a card, &lt;em&gt;this&lt;&#x2F;em&gt; is the time after which you&#x27;ll see it.
I have it set to &lt;code&gt;2h&lt;&#x2F;code&gt;, you may choose &lt;code&gt;30m&lt;&#x2F;code&gt; or whatever else makes the most sense for your content. &lt;br &#x2F;&gt;
❗Do not set multiple steps, just one.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;insertion-order&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#insertion-order&quot; aria-label=&quot;Anchor link for: insertion-order&quot;&gt;Insertion order&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Sequential (oldest cards first).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lapses&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#lapses&quot; aria-label=&quot;Anchor link for: lapses&quot;&gt;Lapses&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;relearning-steps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#relearning-steps&quot; aria-label=&quot;Anchor link for: relearning-steps&quot;&gt;Relearning steps&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Same as &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;how-to-anki&#x2F;#learning-steps&quot;&gt;above&lt;&#x2F;a&gt;, but for mature cards.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;leech-threshold&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#leech-threshold&quot; aria-label=&quot;Anchor link for: leech-threshold&quot;&gt;Leech threshold&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;At least 3, but then it depends. Personally I use 5.&lt;&#x2F;p&gt;
&lt;p&gt;The concept of leeching is made so that you can notice which cards you keep pressing “Again” on &lt;em&gt;repeatedly&lt;&#x2F;em&gt;.
So, once you press “Again” on the same card n times in a row, it gets the &lt;code&gt;leech&lt;&#x2F;code&gt; tag.&lt;&#x2F;p&gt;
&lt;p&gt;This by itself does absolutely nothing: it&#x27;s up to you to decide what to do with that information.
It&#x27;s your wakeup call basically, that &quot;hey! this card is really difficult! try coming up with a mnemonic for it maybe?&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Once one of my cards becomes a leech, I take some extra time to really burn it into my brain, and press &lt;kbd&gt;ctrl+alt+n&lt;&#x2F;kbd&gt; to reset it back into a new card, so that I can relearn it again, without the ease factor being fucked up.&lt;&#x2F;p&gt;
&lt;p&gt;With FSRS, it&#x27;s probably a bad idea to reset it like that, so I don&#x27;t necessarily recommend it. Just, make sure to pay extra attention to the card.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;leech-action&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#leech-action&quot; aria-label=&quot;Anchor link for: leech-action&quot;&gt;Leech action&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;‼️Tag only. &lt;br &#x2F;&gt;
I don&#x27;t get why “Suspend card” is even an option. “If the card is too hard, stop learning it” — ?????????? wtf&lt;&#x2F;p&gt;
&lt;h2 id=&quot;display-order&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#display-order&quot; aria-label=&quot;Anchor link for: display-order&quot;&gt;Display order&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here most things &lt;em&gt;can&lt;&#x2F;em&gt; work well; it depends on what you actually want. So for the most part you should click on each option title to read what it means in the built-in docs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;new-card-gather-order&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#new-card-gather-order&quot; aria-label=&quot;Anchor link for: new-card-gather-order&quot;&gt;New card gather order&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Say you have overall 100 new cards; cards you have not yet reviewed. You &quot;take in&quot; 10 new cards per day. This setting decides &lt;em&gt;which&lt;&#x2F;em&gt; 10 cards to pick out of the 100.&lt;&#x2F;p&gt;
&lt;p&gt;The 2 values you should consider is “Ascending position” and “Random cards”. &lt;br &#x2F;&gt;
The former makes it so you go through new cards in the order that you added them (oldest first). &lt;br &#x2F;&gt;
The latter just gives you random ones.&lt;&#x2F;p&gt;
&lt;p&gt;Both are good, I just want to say that “Ascending position” is better than you expect. I personally use it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;new-card-sort-order&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#new-card-sort-order&quot; aria-label=&quot;Anchor link for: new-card-sort-order&quot;&gt;New card sort order&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Sorts those 10 new cards you got after gathering them. Unless you&#x27;ve made a bad decision and there are 100 of them, this option doesn&#x27;t really matter.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;new-review-order&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#new-review-order&quot; aria-label=&quot;Anchor link for: new-review-order&quot;&gt;New&#x2F;review order&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When you have both new (blue) and not new (red and green (learning and mature)) cards to review, which to show first.&lt;&#x2F;p&gt;
&lt;p&gt;“Show before reviews” ensures that you &lt;em&gt;always&lt;&#x2F;em&gt; take in all the new cards first, and then all the reviews. &lt;br &#x2F;&gt;
I use it, but I don&#x27;t recommend it — it&#x27;s a risky choice. It is better to force yourself to go through all reviews first, before new cards (with “Show after reviews”). However, if you are &lt;em&gt;sure&lt;&#x2F;em&gt; you will complete &lt;em&gt;all&lt;&#x2F;em&gt; of your reviews, starting with the new cards is very exciting!&lt;&#x2F;p&gt;
&lt;p&gt;“Mix with reviews” is quite reasonable. Start with it if you&#x27;re not sure yet.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;interday-learning-review-order&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#interday-learning-review-order&quot; aria-label=&quot;Anchor link for: interday-learning-review-order&quot;&gt;Interday learning&#x2F;review order&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Show before reviews.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;review-sort-order&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#review-sort-order&quot; aria-label=&quot;Anchor link for: review-sort-order&quot;&gt;Review sort order&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;There&#x27;s quite a lot of options here, here are those that I would recommend:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Descending difficulty&lt;&#x2F;li&gt;
&lt;li&gt;Random&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Yep, just two! :3&lt;&#x2F;p&gt;
&lt;h2 id=&quot;burying&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#burying&quot; aria-label=&quot;Anchor link for: burying&quot;&gt;Burying&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Enable everything.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fsrs&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fsrs&quot; aria-label=&quot;Anchor link for: fsrs&quot;&gt;FSRS&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now the JUICE of the settings!! Or rather, of anki itself! FSRS!&lt;&#x2F;p&gt;
&lt;p&gt;This is the cool new algorithm that you should be using! Enable it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;desired-retention&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#desired-retention&quot; aria-label=&quot;Anchor link for: desired-retention&quot;&gt;Desired retention&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Don&#x27;t touch it for now. Come back in at least a month. I am serious.&lt;&#x2F;p&gt;
&lt;p&gt;If you read the following before having done anki for at least a month, you instantly die: you may increase or even decrease this depending on how strongly (or weakly) you want this deck to be remembered.&lt;&#x2F;p&gt;
&lt;p&gt;Alright, the 10% of readers who survived, let&#x27;s continue!&lt;&#x2F;p&gt;
&lt;p&gt;You should click the “Optimize” button once every ~1-3 months, &lt;em&gt;per&lt;&#x2F;em&gt; deck. Don&#x27;t forget to save right after, too!&lt;&#x2F;p&gt;
&lt;p&gt;‼️Do &lt;strong&gt;NOT&lt;&#x2F;strong&gt; press “Reschedule cards on change”. You may be excited to put in some extra work to make sure your cards have the perfect periods, but the tradeoff ends up making things worse.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a good chance you will instantly get a &lt;strong&gt;bunch&lt;&#x2F;strong&gt; of extra reviews at once, which you may not be able to do all at once. So their &quot;perfect periods&quot; won&#x27;t even be perfect.&lt;&#x2F;p&gt;
&lt;p&gt;But that&#x27;s misleading too: you &lt;em&gt;shouldn&#x27;t&lt;&#x2F;em&gt; do them all at once. Because if one day has a bunch of reviews at once, that will repeat on another day some time later. &lt;br &#x2F;&gt;
Your reviews that got naturally padded out throughout the days to be balanced, will &lt;em&gt;no longer&lt;&#x2F;em&gt; be balanced. &lt;br &#x2F;&gt;
So pressing “Reschedule cards on change” puts you between a rock and a hard place, it&#x27;s simply not worth it.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s been more than 2 months after I pressed Reschedule, I&#x27;m still eating shit to this day. Don&#x27;t repeat my mistake.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;advanced&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#advanced&quot; aria-label=&quot;Anchor link for: advanced&quot;&gt;Advanced&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;maximum-interval&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#maximum-interval&quot; aria-label=&quot;Anchor link for: maximum-interval&quot;&gt;Maximum interval&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;‼️DON&#x27;T set it to a reasonable value. I have it set to 100 years (36500). &lt;br &#x2F;&gt;
Trust the anki algorithm.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;deck-meta&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#deck-meta&quot; aria-label=&quot;Anchor link for: deck-meta&quot;&gt;Deck meta&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;We&#x27;re done configuring the deck!&lt;&#x2F;p&gt;
&lt;p&gt;You decided to start using anki, most likely, because you already have one or multiple things that you want to learn.&lt;&#x2F;p&gt;
&lt;p&gt;It is natural now to create a deck per each subject that you want to learn.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve been using anki for around two years, and I found that anki decks have actually quite poor UX.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s pick a list of subjects out of those that &lt;em&gt;I&lt;&#x2F;em&gt; personally learn, and split them into decks.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;morse code&lt;&#x2F;li&gt;
&lt;li&gt;ascii characters&#x27; decimal codes (from a space to &lt;code&gt;~&lt;&#x2F;code&gt;, which is from index 32 to index 126)&lt;&#x2F;li&gt;
&lt;li&gt;all countries on a map&lt;&#x2F;li&gt;
&lt;li&gt;all country flags&lt;&#x2F;li&gt;
&lt;li&gt;useful flags of terminal programs&lt;&#x2F;li&gt;
&lt;li&gt;the standard library of the programming language rust&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;deck-splitting&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#deck-splitting&quot; aria-label=&quot;Anchor link for: deck-splitting&quot;&gt;Deck splitting&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The obvious solution here is to create 6 decks. I only have 2.&lt;&#x2F;p&gt;
&lt;p&gt;Morse code is around 50 cards, ascii characters is 94, both country flags and map locations are around 250.&lt;&#x2F;p&gt;
&lt;p&gt;What unites all of them is that they&#x27;re &lt;em&gt;finite&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
You will eventually go through all of those cards; you won&#x27;t be adding more.&lt;&#x2F;p&gt;
&lt;p&gt;After a while, you&#x27;ll need to review them less and less. The decks of each one of them will become a “dead deck”: a deck with only a few reviews to do, if any, that you &lt;em&gt;still&lt;&#x2F;em&gt; have to check, travel to, open, review, and go back from.&lt;&#x2F;p&gt;
&lt;p&gt;Anki can take a lot of energy, and if you grow to say, 13 decks (I used to have around that many), you will be spending a lot of extra effort on &lt;em&gt;just&lt;&#x2F;em&gt; moving around. &lt;br &#x2F;&gt;
A lot of times, you don&#x27;t &lt;em&gt;just&lt;&#x2F;em&gt; review the mature cards — you&#x27;ll fail some of them, and have to come back to re-review them. &lt;br &#x2F;&gt;
That is a lot of travel time!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;decks-as-organisation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#decks-as-organisation&quot; aria-label=&quot;Anchor link for: decks-as-organisation&quot;&gt;Decks as organisation&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You may think that this is an okay tradeoff for the &lt;em&gt;organisation&lt;&#x2F;em&gt; that decks provide. &lt;br &#x2F;&gt;
But actually, decks are shit at organisation. I&#x27;ll expand on the &lt;em&gt;solution&lt;&#x2F;em&gt; in the &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;how-to-anki&#x2F;#note-types&quot;&gt;note types&lt;&#x2F;a&gt; section, but for now I&#x27;ll elaborate on why decks are bad at organisation.&lt;&#x2F;p&gt;
&lt;p&gt;Morse code and ascii indexes. &lt;br &#x2F;&gt;
How would you structure the question-&amp;gt;answer in those?&lt;&#x2F;p&gt;
&lt;p&gt;What I find to be most effective is &lt;em&gt;just&lt;&#x2F;em&gt; the symbol as the question, and &lt;em&gt;just&lt;&#x2F;em&gt; the sequence &#x2F; number as the answer. &lt;br &#x2F;&gt;
This way, I don&#x27;t spend extra energy on parsing useless words like &quot;what is the x character in morse code?&quot;, and instead &lt;em&gt;just&lt;&#x2F;em&gt; focus on the question at hand. &lt;br &#x2F;&gt;
Getting to the &lt;em&gt;core&lt;&#x2F;em&gt;, the &lt;em&gt;meat&lt;&#x2F;em&gt; of the question, without all the extra fluff, that &lt;em&gt;really&lt;&#x2F;em&gt; piles up, believe it or not!&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll expand on card creation in &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;how-to-anki&#x2F;#card-creation&quot;&gt;this upcoming section&lt;&#x2F;a&gt;, but for now let&#x27;s stop at the idea that cards should be very minimal.&lt;&#x2F;p&gt;
&lt;a href=&quot;#minimal&quot; id=&quot;minimal&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Great! We put ascii cards into the “Ascii” deck and morse cards into the “Morse” deck.&lt;&#x2F;p&gt;
&lt;p&gt;As you go through your thirteen billion decks, you &lt;em&gt;will&lt;&#x2F;em&gt; find yourself confused.&lt;&#x2F;p&gt;
&lt;p&gt;You open your morse code deck to do the measly two reviews, and in the rush of answering cards, seeing &lt;code&gt;x&lt;&#x2F;code&gt;, you answer &lt;code&gt;120&lt;&#x2F;code&gt;, rather than —・・—&lt;&#x2F;p&gt;
&lt;p&gt;This happens because anki does not display the title of the current deck you&#x27;re studying. There is no looming &lt;em&gt;context&lt;&#x2F;em&gt; for you to be able to check back with, and so you&#x27;ll find yourself answering the &lt;em&gt;wrong question&lt;&#x2F;em&gt; a lot of the times. &lt;br &#x2F;&gt;
You answered correctly, but to the wrong question.&lt;&#x2F;p&gt;
&lt;p&gt;What do you do in this situation? You eat sand.&lt;&#x2F;p&gt;
&lt;p&gt;You have to introduce context somehow, to not confuse cards with similarly-sounding questions. &lt;br &#x2F;&gt;
And this is why the first jump is the &quot;What is x in morse code&quot; shenanigans.&lt;&#x2F;p&gt;
&lt;p&gt;Decks don&#x27;t solve organisation, so believe it or not, I&#x27;ll recommend putting both ascii and morse code into a &lt;em&gt;single&lt;&#x2F;em&gt; deck. We will solve the confusion in the [note types] section.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;when-should-you-deck&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#when-should-you-deck&quot; aria-label=&quot;Anchor link for: when-should-you-deck&quot;&gt;When should you deck?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There are only a couple of benefits to creating a new deck. If you don&#x27;t meet any of them, I don&#x27;t recommend creating a new deck.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;news-splitting&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#news-splitting&quot; aria-label=&quot;Anchor link for: news-splitting&quot;&gt;News splitting&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We just added, like, 500 or so new cards. These are long-term — you aren&#x27;t meant to intake them all at once. So, we need to come up with a scheme to split those new cards per day in a reasonable fashion.&lt;&#x2F;p&gt;
&lt;p&gt;Say you added morse code first, then ascii indexes, then flags, then map locations.&lt;&#x2F;p&gt;
&lt;p&gt;Depending on your &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;how-to-anki&#x2F;#new-card-gather-order&quot;&gt;new card gather order&lt;&#x2F;a&gt;, you may either go through all of them in order, or through all of them randomly.&lt;&#x2F;p&gt;
&lt;p&gt;If that&#x27;s exactly what you want, blammo them all into a single deck, unless the next sections on decking positives apply.&lt;&#x2F;p&gt;
&lt;p&gt;But let&#x27;s say you want to be learning three categories at once, rather than trying to rush a single category &#x2F; randomly picking cards from all &lt;em&gt;four&lt;&#x2F;em&gt; categories.&lt;&#x2F;p&gt;
&lt;p&gt;You feel you have 3 new cards per day in you¹, and you want 1 of them to always be morse, and 2 of them to be random selections from the country flag + map location &quot;pool&quot;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;¹ pure example, I don&#x27;t actually think this is viable for the categories at hand&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;To express something like this, you &lt;em&gt;need&lt;&#x2F;em&gt; to split into two decks.&lt;&#x2F;p&gt;
&lt;a href=&quot;#two-decks&quot; id=&quot;two-decks&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;If you were okay with just doing the categories in order, with all 3 new cards being for the same category, you wouldn&#x27;t need two decks! &lt;br &#x2F;&gt;
The “Reposition” action in the card browser (&lt;kbd&gt;ctrl+shift+s&lt;&#x2F;kbd&gt;) would allow you to put all the categories&#x27; cards in the order that you want, even if you &lt;em&gt;created&lt;&#x2F;em&gt; them all in the wrong order¹.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;¹ technically speaking you can avoid having to create another deck using the Reposition action by manually positioning each and every card, but this is herculean effort compared to just creating a new deck, and then moving its cards into another deck, once you go through all of the new cards&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;But in our case, we create a deck for Morse¹ code: it will give you 1 new card per day; &lt;br &#x2F;&gt;
And a Country¹ deck that will hold country &lt;em&gt;flags&lt;&#x2F;em&gt; and country &lt;em&gt;locations&lt;&#x2F;em&gt;. Its &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;how-to-anki&#x2F;#new-card-gather-order&quot;&gt;new card gather order&lt;&#x2F;a&gt; setting will be random.&lt;&#x2F;p&gt;
&lt;p&gt;This way, you guarantee 1 new card of morse per day, and 2 &quot;country-related&quot; cards per day, totalling three. All this without touching the ascii indexes for now — you&#x27;ll get to them once you fully learn one of the three categories.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;¹ names are arbitrary, choose whatever you wish&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;ordering&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ordering&quot; aria-label=&quot;Anchor link for: ordering&quot;&gt;Ordering&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We touched on the &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;how-to-anki&#x2F;#new-card-gather-order&quot;&gt;new card gather order&lt;&#x2F;a&gt; setting — it&#x27;s quite an important one!&lt;&#x2F;p&gt;
&lt;p&gt;For some type of cards, it makes the most sense to learn them in random order. By &quot;fuzzing&quot; them like this, you avoid the issue of one card half-answering the question of the next one.&lt;&#x2F;p&gt;
&lt;p&gt;For others, where that half-answering issue doesn&#x27;t arise, it is best to go with sequential. &lt;br &#x2F;&gt;
If you keep adding cards while being served them randomly, you&#x27;ll end up having &quot;unlearned spots&quot; — some cards will slip through the cracks of how randomisation inherently works, and you might take too long to get to some crucial information to learn. &lt;br &#x2F;&gt;
If you learn sequentially, you ensure that you finish a given subject before going onto the next one.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;optimization&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#optimization&quot; aria-label=&quot;Anchor link for: optimization&quot;&gt;Optimization&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;FSRS optimization happens &lt;em&gt;per deck&lt;&#x2F;em&gt;. More precisely, per deck &lt;em&gt;preset&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It does its magic depending on how you answer the cards in the given deck. I don&#x27;t know exactly how it works, but the main idea is this: vastly different subjects will be optimized differently.&lt;&#x2F;p&gt;
&lt;p&gt;Both morse code and ascii indexes are fairly similar categories, that I&#x27;d argue are very similarly difficult to &lt;em&gt;memorize&lt;&#x2F;em&gt; and to &lt;em&gt;remember&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
Splitting them up into two decks just for the optimization I don&#x27;t think is worthwhile — you will likely respond very similarly to both, and so they could just be kept in a single deck, optimized together.&lt;&#x2F;p&gt;
&lt;p&gt;FSRS optimization makes it so you see the cards at the correcter time periods, to achieve your desired retention rate.&lt;&#x2F;p&gt;
&lt;p&gt;When the information is similar enough, you&#x27;ll lose far more time, effort, and motivation by switching a billion decks, than you would &lt;em&gt;gain&lt;&#x2F;em&gt; from slightly correcter periods.&lt;&#x2F;p&gt;
&lt;p&gt;After switching to FSRS, for &lt;em&gt;four months&lt;&#x2F;em&gt; I didn&#x27;t even know I could &quot;optimize parameters&quot; in FSRS, much less that I should be doing it monthly. And yet, I was perfectly happy with how anki was working for me. So genuinely don&#x27;t worry too much about this.&lt;&#x2F;p&gt;
&lt;p&gt;To be fair, what counts as &quot;similar enough&quot; is very personal, I don&#x27;t know if a hard rule could be worded to help you decide. So it&#x27;s not unreasonable to start with making more decks than needed, and later on merging some (if not all) together, once you get a feel for anki.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;that-s-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#that-s-it&quot; aria-label=&quot;Anchor link for: that-s-it&quot;&gt;That&#x27;s it!&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Not many reasons to make extra decks, as you can see. I hope you can keep these in mind to help you not fall into the &quot;trap&quot; of the supposed deck meta, winning you time, and saving you effort.&lt;&#x2F;p&gt;
&lt;p&gt;Now to the &lt;em&gt;really&lt;&#x2F;em&gt; fun part &amp;gt;:3c&lt;&#x2F;p&gt;
&lt;h1 id=&quot;note-types&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#note-types&quot; aria-label=&quot;Anchor link for: note-types&quot;&gt;Note Types&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You know that gif with Tony Stark dramatically hitting a helmet with a hammer? &lt;br &#x2F;&gt;
This is me with note types.&lt;&#x2F;p&gt;
&lt;p&gt;I have tried multiple approaches in using them the most effectively, and found one I believe to be perfect.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with the basics.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;default-note-types&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#default-note-types&quot; aria-label=&quot;Anchor link for: default-note-types&quot;&gt;Default note types&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In the main screen, press &lt;kbd&gt;ctrl+shift+n&lt;&#x2F;kbd&gt; to go to the list of default note types.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Basic&lt;&#x2F;li&gt;
&lt;li&gt;Basic (and reversed card)&lt;&#x2F;li&gt;
&lt;li&gt;Basic (optional reversed card)&lt;&#x2F;li&gt;
&lt;li&gt;Basic (type in the answer)&lt;&#x2F;li&gt;
&lt;li&gt;Cloze&lt;&#x2F;li&gt;
&lt;li&gt;Image occlusion&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Some of them are quite a mouthful. I&#x27;ll refer to them as this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Basic&lt;&#x2F;li&gt;
&lt;li&gt;Double basic&lt;&#x2F;li&gt;
&lt;li&gt;Basic?&lt;&#x2F;li&gt;
&lt;li&gt;Type&lt;&#x2F;li&gt;
&lt;li&gt;Cloze&lt;&#x2F;li&gt;
&lt;li&gt;Image occlusion&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If you want, you can even rename them!&lt;&#x2F;p&gt;
&lt;p&gt;Note types are going to be something you&#x27;ll keep on selecting, so having them be unique and easily typable &#x2F; searchable is very helpful. &lt;br &#x2F;&gt;
My “Basic” is just &lt;code&gt;d&lt;&#x2F;code&gt;, and “Cloze” is just &lt;code&gt;h&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The default note types showcase what anki even &lt;em&gt;allows&lt;&#x2F;em&gt; you to do in the first place, in terms of question-&amp;gt;answer organization.&lt;&#x2F;p&gt;
&lt;p&gt;A note type is a template, a constructor: you define how one creates &lt;em&gt;cards&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
You review cards created using notes. &lt;br &#x2F;&gt;
A single note can (in theory) create an infinite amount of cards.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;basic&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#basic&quot; aria-label=&quot;Anchor link for: basic&quot;&gt;Basic&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Is the most &lt;em&gt;basic&lt;&#x2F;em&gt; note type: it creates a single card.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;double-basic&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#double-basic&quot; aria-label=&quot;Anchor link for: double-basic&quot;&gt;Double basic&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Is like the above one, but here the magic starts: it creates a card for question-&amp;gt;answer AND for answer-&amp;gt;question.&lt;&#x2F;p&gt;
&lt;p&gt;It is a note type that creates TWO cards, one for each &quot;direction&quot;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;basic-1&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#basic-1&quot; aria-label=&quot;Anchor link for: basic-1&quot;&gt;Basic?&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You can probably guess now that you can use “Basic?” to &lt;em&gt;optionally&lt;&#x2F;em&gt; create the answer-&amp;gt;question card, while it doesn&#x27;t do so by default.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;type&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#type&quot; aria-label=&quot;Anchor link for: type&quot;&gt;Type&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Lets you type in the answer, rather than just recalling it in your head.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cloze&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#cloze&quot; aria-label=&quot;Anchor link for: cloze&quot;&gt;Cloze&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Omits some part, or &lt;em&gt;multiple&lt;&#x2F;em&gt; parts of the question, and you need to mentally &lt;em&gt;fill in&lt;&#x2F;em&gt; that missing part, to answer the question.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;image-occlusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#image-occlusion&quot; aria-label=&quot;Anchor link for: image-occlusion&quot;&gt;Image occlusion&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Hides some part of an &lt;em&gt;image&lt;&#x2F;em&gt;, that you need to mentally &lt;em&gt;flll in&lt;&#x2F;em&gt;. In other words, it&#x27;s “Cloze”, but for images.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;creating-your-own&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#creating-your-own&quot; aria-label=&quot;Anchor link for: creating-your-own&quot;&gt;Creating your own&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Defaults are made to be configured away, so let&#x27;s discover how you can create your &lt;em&gt;own&lt;&#x2F;em&gt; note types.&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;kbd&gt;ctrl+shift+n&lt;&#x2F;kbd&gt; screen, click on Basic and then Fields.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fields&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fields&quot; aria-label=&quot;Anchor link for: fields&quot;&gt;Fields&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A field is an inputbox, the text of which is used in some way in the note type. &lt;br &#x2F;&gt;
Here in Basic, you have 2: Front and Back.&lt;&#x2F;p&gt;
&lt;p&gt;You can add as many extra fields as you want (at least I don&#x27;t know of a limit), however they won&#x27;t &lt;em&gt;do&lt;&#x2F;em&gt; anything by default. We&#x27;ll get to how to make their text appear in your card later. &lt;br &#x2F;&gt;
For now, know that you can add multiple fields to a given note (including your own ones we&#x27;ll create later), and have them appear in the card in different ways.&lt;&#x2F;p&gt;
&lt;p&gt;Anki supports html: when adding a card, you can press &lt;kbd&gt;ctrl+shift+x&lt;&#x2F;kbd&gt; to toggle the html editor. &lt;br &#x2F;&gt;
But if you &lt;em&gt;always&lt;&#x2F;em&gt; want to edit a given field as html, here in the Fields view you can set the option below to make the field “Use HTML editor by default”. &lt;br &#x2F;&gt;
On a non-html field, the &lt;kbd&gt;ctrl+shift+x&lt;&#x2F;kbd&gt; hotkey then toggles on the non-html editor.&lt;&#x2F;p&gt;
&lt;p&gt;Go back to the previous screen by pressing &lt;kbd&gt;escape&lt;&#x2F;kbd&gt; and then click on “Cards”.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cards&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#cards&quot; aria-label=&quot;Anchor link for: cards&quot;&gt;Cards&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This screen has been confusing for a while to me. So if it feels intimidating, don&#x27;t worry — it &lt;em&gt;is&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The source of this intimidation for me is a couple of buttons and popups that we&#x27;ll get to at the end of this section, for now let&#x27;s explore the more obvious parts.&lt;&#x2F;p&gt;
&lt;p&gt;Note types are templates that decide how to create cards. Each note type can create as many cards as you want it to. &lt;br &#x2F;&gt;
Although by default, a note type creates just one card.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;front-template&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#front-template&quot; aria-label=&quot;Anchor link for: front-template&quot;&gt;Front Template&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;On the left side, you can see an edit field, with three radio buttons above. &lt;br &#x2F;&gt;
Here, you define the html template for the cards to be creates with this note type.&lt;&#x2F;p&gt;
&lt;p&gt;The main juice that actually makes note types useful at all, is &lt;code&gt;{{Front}}&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
&lt;code&gt;{{Front}}&lt;&#x2F;code&gt; is a template (that I&#x27;ll be calling a shortcode) that is replaced with the resulting html that you put in a field.&lt;&#x2F;p&gt;
&lt;p&gt;Notice the name: &lt;code&gt;Front&lt;&#x2F;code&gt;. This is a name of one of the fields of this note type. &lt;br &#x2F;&gt;
In the previous section, I mentioned that fields aren&#x27;t used automatically. &lt;br &#x2F;&gt;
&lt;em&gt;We&lt;&#x2F;em&gt; get to decide where and how they show up, by putting them in explicitly.&lt;&#x2F;p&gt;
&lt;p&gt;Say we created a field called &lt;code&gt;Extra&lt;&#x2F;code&gt;. We can now add &lt;code&gt;{{Extra}}&lt;&#x2F;code&gt; somewhere in the template for the note type, and the text (resulting html) that we put in this &lt;code&gt;Extra&lt;&#x2F;code&gt; field is going to show up there!&lt;&#x2F;p&gt;
&lt;h4 id=&quot;back-template&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#back-template&quot; aria-label=&quot;Anchor link for: back-template&quot;&gt;Back Template&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Now, click on the radio button “Back Template”. The html is a bit different now!&lt;&#x2F;p&gt;
&lt;p&gt;The real semantic of the first and second templates is the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;This is how the card looks when I&#x27;m presented the question, and haven&#x27;t yet answered the card.&lt;&#x2F;li&gt;
&lt;li&gt;This is how the card looks when I answered the question, and pressed space to see the answer.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;By default, the Front side of the card is also included in the Back side, using the special shortcode &lt;code&gt;{{FrontSide}}&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
It takes the entire Front side html, and blammoes it in the Back side template.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s nothing stopping you from removing it, though. You can simply remove it from the Back side template, and you won&#x27;t see the front of the card after pressing space. &lt;br &#x2F;&gt;
I don&#x27;t recommend doing so; you would be shooting yourself in the foot for no benefit. &lt;br &#x2F;&gt;
However I hope that showcases that templating is not that magical! &lt;br &#x2F;&gt;
How anki shows itself to you is defined clearly, and is changeable by you.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;styling&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#styling&quot; aria-label=&quot;Anchor link for: styling&quot;&gt;Styling&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Probably more changeable than you expect!&lt;&#x2F;p&gt;
&lt;p&gt;The third radio button is my favorite one: you get to define the CSS of your note type! &lt;br &#x2F;&gt;
Yes, you can make it look however you wish!&lt;&#x2F;p&gt;
&lt;p&gt;I used this to change the fonts used, the colors, and added inline and blockwise codeblocks.&lt;&#x2F;p&gt;
&lt;p&gt;You might reasonably ask how you can “Inspect Element” anki to figure out how to css it correctly. &lt;br &#x2F;&gt;
There is some plugin for it, and likely some people in the forums have figured out most things.&lt;&#x2F;p&gt;
&lt;p&gt;However, I just guessed my way throgh most of it, so I won&#x27;t give precise advice that I don&#x27;t have checked. With styling selectors you need, you&#x27;re on your own.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;card-type&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#card-type&quot; aria-label=&quot;Anchor link for: card-type&quot;&gt;Card Type&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Let&#x27;s look at the popup that scared me at first. Well, even now I never touch it (I&#x27;ll explain why later) &lt;br &#x2F;&gt;
At the top, you can see “Card Type” with something like &lt;code&gt;1: Card 1: Front -&amp;gt; Back&lt;&#x2F;code&gt; &lt;br &#x2F;&gt;
Let&#x27;s process that.&lt;&#x2F;p&gt;
&lt;p&gt;A note type can create any number of cards. That is what the &lt;code&gt;1:&lt;&#x2F;code&gt; stands for. &lt;br &#x2F;&gt;
Which one? I have no clue. At least one of them, lol. The other one of them stands for god knows what.&lt;&#x2F;p&gt;
&lt;p&gt;So, &lt;code&gt;1: Card 1: Front -&amp;gt; Back&lt;&#x2F;code&gt; means: out of potentially many, this is the first card that&#x27;s created by this note type. In this specific card, the Front side is the question, and the Back side is the answer.&lt;&#x2F;p&gt;
&lt;p&gt;Inconveniently, the fields are called the same way as another concept, making things less clear.&lt;&#x2F;p&gt;
&lt;p&gt;Anki has a concept of &quot;front side&quot; and &quot;back side&quot;. We glanced over that in the first two radio buttons. &lt;br &#x2F;&gt;
So here, the front &lt;em&gt;template&lt;&#x2F;em&gt; is used for the front side. The back template is used for the back side. &lt;br &#x2F;&gt;
As expected.&lt;&#x2F;p&gt;
&lt;p&gt;However if we looked at “Basic and reverse”, the second card that the note type makes says &lt;code&gt;Back -&amp;gt; Front&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
So, the &lt;em&gt;back&lt;&#x2F;em&gt; template is used for the front side (the question) of the card, and the &lt;em&gt;front&lt;&#x2F;em&gt; template is used for the back side (the answer) of the card.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s how that note type achieves the &quot;and reverse&quot; part — it creates two cards — one is front (question) to back (answer), and another is back (question) to front (answer).&lt;&#x2F;p&gt;
&lt;p&gt;Cool, isn&#x27;t it? &lt;br &#x2F;&gt;
However, as I mentioned, I won&#x27;t be teaching you how to make use of this, because I don&#x27;t use it.&lt;&#x2F;p&gt;
&lt;p&gt;For the most part, adding two cards per each note, just to learn the question from both sides, is a waste of effort, in my experience. &lt;br &#x2F;&gt;
I used to learn languages using anki in the past, and there the reverse thingy &lt;em&gt;was&lt;&#x2F;em&gt; helpful, but for what I use anki right now, it&#x27;s fairly useless.&lt;&#x2F;p&gt;
&lt;a href=&quot;#note-type-meta&quot; id=&quot;note-type-meta&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Viola! Now you have the necessary knowledge to learn about the card organizing meta that I&#x27;ve made for myself. I hope you&#x27;ll like it as much as I do!&lt;&#x2F;p&gt;
&lt;p&gt;Rather than using a bunch of different decks (as I mentioned, I only have 2), or a bunch of different note types per subject (used to do that, very laborious), &lt;br &#x2F;&gt;
I only have a couple of note types.&lt;&#x2F;p&gt;
&lt;p&gt;Each of those note types includes two extra fields: one is called “Header” and the other is called “Subheader”.&lt;&#x2F;p&gt;
&lt;p&gt;Because the anki browser allows you to search by each field if necessary (&lt;code&gt;header:ruby&lt;&#x2F;code&gt; for example), this works amazingly for card organization.&lt;&#x2F;p&gt;
&lt;p&gt;If I need to do bulk actions on a bunch of cards of a certain subject, I &lt;em&gt;can&lt;&#x2F;em&gt;!
Just as easily as I would with the many decks approach, and &lt;em&gt;more&lt;&#x2F;em&gt; easily than with the many note types approach.&lt;&#x2F;p&gt;
&lt;p&gt;In terms of the note types, I basically only have Basic and Cloze. Except, I split Basic into 4 different note types:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;the normal Basic one&lt;&#x2F;li&gt;
&lt;li&gt;1 but back side is a codeblock&lt;&#x2F;li&gt;
&lt;li&gt;1 but front side is a codeblock&lt;&#x2F;li&gt;
&lt;li&gt;1 but both sides are codeblocks&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I think this is niche? But I use it so much that it made sense to make a shortcut like this for myself, rather than always having to wrap things in a codeblock in the html of the card manually.&lt;&#x2F;p&gt;
&lt;p&gt;The approach is pretty simple: you come up with an element (I use &lt;code&gt;&amp;lt;cd&amp;gt;&amp;lt;&#x2F;cd&amp;gt;&lt;&#x2F;code&gt;) and make css for that element to display it as a codeblock. &lt;br &#x2F;&gt;
The note type then wraps &lt;code&gt;{{Front}}&lt;&#x2F;code&gt; in that element like &lt;code&gt;&amp;lt;cd&amp;gt;{{Front}}&amp;lt;&#x2F;cd&amp;gt;&lt;&#x2F;code&gt;. Blammo.&lt;&#x2F;p&gt;
&lt;p&gt;I will link to my html templates and css file, but be warned: I made this specifically for myself so I give no guarantees it will be a good starting point.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;anki&#x2F;card.html&quot;&gt;html templates main link&lt;&#x2F;a&gt; &lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;d21744e691c09e9980fd01b013c0daaf64a2234c&#x2F;anki&#x2F;card.html&quot;&gt;html templates backup link&lt;&#x2F;a&gt; &lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;anki&#x2F;card.css&quot;&gt;css main link&lt;&#x2F;a&gt; &lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;d21744e691c09e9980fd01b013c0daaf64a2234c&#x2F;anki&#x2F;card.css&quot;&gt;css backup link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As I alluded to prevously, this approach also solves another issue: I am never confused as to what subject I&#x27;m currently studying. It&#x27;s right there at the top! Decks simply don&#x27;t do this.&lt;&#x2F;p&gt;
&lt;p&gt;So, I get to blammo all the cards in 1-2 decks, and go through them all at once; I don&#x27;t have to experience the annoyance of jumping between 15 or so decks.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;card-creation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#card-creation&quot; aria-label=&quot;Anchor link for: card-creation&quot;&gt;Card Creation&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;First of all, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.supermemo.com&#x2F;en&#x2F;blog&#x2F;twenty-rules-of-formulating-knowledge&quot;&gt;read this&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
This blog post has massively helped me create better and more efficient cards.&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t attempt to tldr it, but here are some things that I ended up implementing into how I make cards.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-use-many-word-when-few-word-do-trick&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-use-many-word-when-few-word-do-trick&quot; aria-label=&quot;Anchor link for: why-use-many-word-when-few-word-do-trick&quot;&gt;Why use many word when few word do trick&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&quot;What was the year at which Marie Currie did x?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Is very wordy. I&#x27;m exagerating in this example, but even still you&#x27;ll find yourself making cards that use many extra useless words, kinda like the sentence above.&lt;&#x2F;p&gt;
&lt;p&gt;Ideally, you will be doing anki until you die. That is a long ass time! (Hopefully?) &lt;br &#x2F;&gt;
So all the time you spend parsing words that don&#x27;t help you arrive to the &lt;em&gt;core&lt;&#x2F;em&gt; of the question, is time wasted.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not like reading a novel: &lt;em&gt;there&lt;&#x2F;em&gt; reading 20 useless words in a row is fun (allegedly).
&lt;em&gt;Anki&lt;&#x2F;em&gt; you are doing for an exact benefit. So cutting down on non-core words is actually crucial.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Marie Currie did x when&quot;&lt;&#x2F;p&gt;
&lt;p&gt;That ↑ is all you need. Even the &lt;code&gt;?&lt;&#x2F;code&gt; at the end is bloat. You don&#x27;t need it.&lt;&#x2F;p&gt;
&lt;p&gt;Your target should be to minimize the amount of time it takes you to process the question. Sometimes adding an extra word can actually &lt;em&gt;help&lt;&#x2F;em&gt;, because it looks more natural to you that way.&lt;&#x2F;p&gt;
&lt;p&gt;So, try different approaches for debloating cards, and see what works for you. You will notice just how much faster and easier you can do reviews, because there&#x27;s much less for your brain to process.&lt;&#x2F;p&gt;
&lt;p&gt;You can then use this extra energy to do &lt;em&gt;more&lt;&#x2F;em&gt; cards, or to do the same amount of cards in less effort, to spend that effort elsewhere.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;make-use-of-headers&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#make-use-of-headers&quot; aria-label=&quot;Anchor link for: make-use-of-headers&quot;&gt;Make use of headers&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The note type approach I use helps the previous point.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;jj revset operator that gives you the intersection of two other revsets&quot;&lt;&#x2F;p&gt;
&lt;p&gt;becomes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;jj&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;revset&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;intersection operator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Header &lt;code&gt;jj&lt;&#x2F;code&gt;, subheader &lt;code&gt;revset&lt;&#x2F;code&gt;, and less wordy question. The word &lt;code&gt;operator&lt;&#x2F;code&gt; there I&#x27;d remove. &lt;br &#x2F;&gt;
Headers and subheaders let you encode a part of your question into a section above the question, that you will be able to skip over most of the time.&lt;&#x2F;p&gt;
&lt;p&gt;If you read the question and you naturally remember that the question is about jj, you won&#x27;t need to pay attention to the header &lt;em&gt;or&lt;&#x2F;em&gt; subheader.&lt;&#x2F;p&gt;
&lt;p&gt;At least for me, it&#x27;s natural to read the question first, and so header + subheader lets you move out a part of the question that otherwise, you would have to read &lt;em&gt;every&lt;&#x2F;em&gt; time. Small optimization that sums up to more than you would expect.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;one-thing-per-thing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#one-thing-per-thing&quot; aria-label=&quot;Anchor link for: one-thing-per-thing&quot;&gt;One thing per thing&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Split the question into as many cards as you reasonably can. &lt;br &#x2F;&gt;
The blog post I linked above goes into good detail on what that entails, please read it.&lt;&#x2F;p&gt;
&lt;p&gt;If you make a question and a part of it could become a whole another question, then it &lt;em&gt;should&lt;&#x2F;em&gt;.
It might look kind of ridiculous, but the amount of time you spend is actually pretty big.&lt;&#x2F;p&gt;
&lt;p&gt;❌ question: &quot;shell -&amp;gt; pueue group -&amp;gt; delete a group, moving all of its tasks to the default group&quot; &lt;br &#x2F;&gt;
❌ answer: &quot;pueue group remove&quot;&lt;&#x2F;p&gt;
&lt;p&gt;This question is worded in such a way that you hope you&#x27;ll remember some extra information in parallel. Memory doesn&#x27;t work like that, you won&#x27;t be able to &quot;brush off&quot; information in an effective manner. That part should just become its own question if you want to remember it, and be discarded if you don&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;✅ question 1: &quot;shell -&amp;gt; pueue group -&amp;gt; delete group&quot; &lt;br &#x2F;&gt;
✅ answer 1: &quot;pueue group remove&quot;&lt;&#x2F;p&gt;
&lt;p&gt;✅ question 2: &quot;shell -&amp;gt; pueue group remove -&amp;gt; what happens to the tasks when you delete a group?&quot; &lt;br &#x2F;&gt;
✅ answer 2: &quot;they get moved to default group&quot;&lt;&#x2F;p&gt;
&lt;p&gt;If each individual question is really easy to answer, all of them will quickly rank up in their intervals, and not take much of your time. So, prefer more cards to less cards, counter-intuitively.&lt;&#x2F;p&gt;
&lt;p&gt;If you make one complicated question, you will hit your head against it time and time again, and end up wasting a lot more time overall.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, if you expect yourself to give a big, multi-stage answer to a single question, you should also split it into multiple cards.&lt;&#x2F;p&gt;
&lt;a href=&quot;#thanks&quot; id=&quot;thanks&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Thanks for reading! This took me multiple months to write, lmao. Kinda burnt out on it; you might&#x27;ve noticed towards the end. Hope my experience will be useful to you!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;addendum&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#addendum&quot; aria-label=&quot;Anchor link for: addendum&quot;&gt;addendum&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;m writing this on 2025.05.19.&lt;&#x2F;p&gt;
&lt;p&gt;While most things hold up exactly as before, I&#x27;m now using a slightly different approach in terms of taking in new cards. &lt;br &#x2F;&gt;
Not entirely sure if it ends up being more or less efficient, but the consistency of it is awesome.&lt;&#x2F;p&gt;
&lt;p&gt;I learn for the love of the game, so there isn&#x27;t necessarily some deadline up until when I have to learn everything I want to. &lt;br &#x2F;&gt;
What matters far more to me, is to ensure that I never burn out on anki.&lt;&#x2F;p&gt;
&lt;p&gt;I found that for my type of cards, I can review 70 every day. I can (and did, before finding this method) in theory do more, but I know that more than 70 will end up burning me out, if prolonged.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a type of thing that you get a feel for after a while of using anki, so don&#x27;t worry if you don&#x27;t know your number yet.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I found a way to review exactly my limit of cards every day, without fucking up the algorithm too much!&lt;&#x2F;p&gt;
&lt;p&gt;First, a setting that this entire approach relies on: Deck Options -&amp;gt; Display Order -&amp;gt; New&#x2F;review order -&amp;gt; Show after reviews. &lt;br &#x2F;&gt;
Now, when we start doing our reviews for the day, we go through all the red and all the green cards first. &lt;br &#x2F;&gt;
Say I have 15 reds, and 45 greens. That&#x27;s 60 total reviews to go through. I got 10 extra in me though! And those 10 extra are for the new cards :D&lt;&#x2F;p&gt;
&lt;p&gt;So, as I review, I check every now and again:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;how many reviews (not new cards) are left&lt;&#x2F;li&gt;
&lt;li&gt;how many reviews I&#x27;ve done so far&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;After I get through all the reds and all the greens (unless they are already more than 70, I elaborate on this later), I check &lt;code&gt;70 - total_reviews&lt;&#x2F;code&gt; to figure out how many new cards to take in today. &lt;br &#x2F;&gt;
Your total reviews are shown on the main &#x2F; home screen, so that&#x27;s what I&#x27;m relying on. I wonder if there&#x27;s a plugin that would show that info &lt;em&gt;while&lt;&#x2F;em&gt; I&#x27;m reviewing! &lt;br &#x2F;&gt;
For easier math, I set the amount of daily new cards to 100. For reasons I explained in this blog post above, &lt;em&gt;obviously&lt;&#x2F;em&gt; we aren&#x27;t meant to gulp all that 100. We simply take from that 100 every day, however much we can handle (&lt;code&gt;70 - total_reviews&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Why this appproach is amazing, is that it&#x27;s quite dynamic while being consistent in terms of my effort. You have a low amount of reviews? Yipeee you get to get more new cards today! Too many reviews? No big deal, we simply take less &#x2F; no new cards.&lt;&#x2F;p&gt;
&lt;p&gt;But what happens if you have more than 70 reviews? This happens to me every time I rotate my sleep schedule, for example. Or say you miss a day for other reasons.&lt;&#x2F;p&gt;
&lt;p&gt;Generally, it&#x27;s a bad idea to gulp all the reviews at once, that you got from the previous day that you skipped. &lt;br &#x2F;&gt;
Sure, the anki algorithm works better this way, but that&#x27;s only in theory. In practice you are human. &lt;br &#x2F;&gt;
Additionally, you&#x27;re creating a fucky effect: if you get a sudden spike of reviews on a given day, this spike will repeat some days later (although it won&#x27;t be as strong).&lt;&#x2F;p&gt;
&lt;p&gt;This is why instead of gulping all reviews in a bad situation like this, I tend to instead increase my daily reviews temporarily, until the extra cards are all sorted out. This happens over the course of multiple days, and so the spike repeat is not as big of an issue. &lt;br &#x2F;&gt;
Deck Options -&amp;gt; Display Order -&amp;gt; Review Sort Order -&amp;gt; Ascending retrievability is quite important to make this as effective as it can be, to not fuck with the anki algorithm as much.&lt;&#x2F;p&gt;
&lt;p&gt;So! If you take the same strategy, my &quot;up to 70 reviews&quot; approach makes even more sense. In the general case, my reds + greens are less than 70, and I fill the rest with new cards. So when shit hits the fan, what ends up happening is that reds + greens fill up the entire 70, and I simply don&#x27;t take new cards for a couple of days. So, this approach has built in overflow protection! Although it&#x27;s not like you should want to use it :p &lt;br &#x2F;&gt;
To add, when I get an overflow, I increase my cap from 70 to 80, until it&#x27;s sorted. I consider a shitfan sorted, when to get 70 reviews, I&#x27;d have to take new cards. At &lt;em&gt;that&lt;&#x2F;em&gt; point I go back to the 70 cap, and take as many new cards as fit into the 70 cap, rather than the otherwise increased 80.&lt;&#x2F;p&gt;
&lt;p&gt;In the case where I get more than 70 reds + greens, but there &lt;em&gt;isn&#x27;t&lt;&#x2F;em&gt; an overflow from me skipping a day, the same rules apply, except I don&#x27;t touch the cap. So, I basically allow the remaining reds + greens go to the next day, and let them get sorted out automatically via me taking in less new cards. Quite dynamic!&lt;&#x2F;p&gt;
&lt;p&gt;Aside from the overflow protection, what I love most about this approach, is that I never get &quot;unlucky&quot;. &lt;br &#x2F;&gt;
I never get too many reviews on a day where I&#x27;m exhausted. &lt;br &#x2F;&gt;
I never get too little reviews on a day where I&#x27;m extra energetic. &lt;br &#x2F;&gt;
It&#x27;s always the same exact number of reviews :D&lt;&#x2F;p&gt;
&lt;p&gt;And what&#x27;s fun about this, is that it lets you more clearly tell what your cap is. If you do exactly 70 (or your other number) reviews &lt;em&gt;every single day&lt;&#x2F;em&gt;, you will realize sooner, whether it&#x27;s too much or too little. &lt;br &#x2F;&gt;
My cap used to be 65, but over time I noticed that I wanted to do more, and so I increased my cap to 70. I want to increase it again, but I&#x27;m intentionally waiting for a while to make sure that would be the correct move. &lt;br &#x2F;&gt;
Don&#x27;t rush when changing your cap, and change it by small amounts.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>rust for... scripting?</title>
          <pubDate>Sat, 04 Jan 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/rust-scripting/</link>
          <guid>https://axlefublr.github.io/rust-scripting/</guid>
          <description xml:base="https://axlefublr.github.io/rust-scripting/">&lt;p&gt;If the title of this blog post is a genuine question you have, and you want to just skip to the most reasonable solution: &lt;spoiler&gt;use cargo-script&lt;&#x2F;spoiler&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;why&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why&quot; aria-label=&quot;Anchor link for: why&quot;&gt;why&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I recently realized that the two languages I like using, fish shell and rust, are ridiculously far apart. &lt;br &#x2F;&gt;
I wanted to find myself a language I could use for scripting that is non-viable to do in fish shell, but too annoying in rust.&lt;&#x2F;p&gt;
&lt;p&gt;Turns out, there are not really any languages that fit all of my criteria!&lt;&#x2F;p&gt;
&lt;p&gt;Python, Ruby, Crystal, Ocaml, Nim, Julia, Go, Nushell — these are the languages I tried, or considered going for.&lt;&#x2F;p&gt;
&lt;p&gt;I actually wrote the majority of the blog post on my adventure looking for a good programming language, but found what I wrote kinda boring and soulless, so I won&#x27;t get into why each of those languages didn&#x27;t fit me. &lt;br &#x2F;&gt;
Once I&#x27;m &quot;over&quot; something, it becomes incredibly boring for me to talk about it, and so I missed the train of writing a blog post on that, lol.&lt;&#x2F;p&gt;
&lt;p&gt;The TLDR is that I came back to rust, reinvigorated to use it more!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;on-rust&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#on-rust&quot; aria-label=&quot;Anchor link for: on-rust&quot;&gt;on rust&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Rust has always felt really &lt;em&gt;solid&lt;&#x2F;em&gt; to me. But like a cock, it is sometimes too hard to work with.&lt;&#x2F;p&gt;
&lt;p&gt;After trying out so many other programming languages, and spending the most time and effort on Ruby, I re-started to appreciate that solidity of rust, and changed my approach to the language a bit.&lt;&#x2F;p&gt;
&lt;p&gt;Inlay hints turned out to be visual clutter I came to accept. Removing them by default, and only toggling them when I &lt;em&gt;need&lt;&#x2F;em&gt; them, has helped immensely to look at rust more &lt;em&gt;calmly&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Diagnostics in rust are very helpful, but sometimes overwhelming. Similarly, once I see a bit too many diagnostics, I disable them. Once I need the extra advice, I enable them back.&lt;&#x2F;p&gt;
&lt;p&gt;I was constantly &lt;em&gt;fighting&lt;&#x2F;em&gt; rust, getting annoyed at how I&#x27;m meant to do seemingly simple things. &lt;br &#x2F;&gt;
Getting the modification time of a file is kinda cumbersome in terms of the syntax, &lt;br &#x2F;&gt;
working with files is often way too involved, calling external commands is boilerplaty; especially so once you literally just need the stdout as a string.&lt;&#x2F;p&gt;
&lt;p&gt;Often times it felt like rust overcomplicates things. For good reason, mind you, I just happen to not care. &lt;br &#x2F;&gt;
I&#x27;m a very selfish programmer, I don&#x27;t need cases I won&#x27;t come across to need to be solved.&lt;&#x2F;p&gt;
&lt;p&gt;But, it is the language that rust is, and some code &lt;em&gt;will&lt;&#x2F;em&gt; look boilerplaty &#x2F; ugly. &lt;br &#x2F;&gt;
I&#x27;ve come to &lt;em&gt;accept&lt;&#x2F;em&gt; that, instead of being annoyed that my code isn&#x27;t syntactically perfect. &lt;br &#x2F;&gt;
Now I&#x27;m more okay with some parts being kinda hard to look at — I will simply skill solution my way into being used to it.&lt;&#x2F;p&gt;
&lt;p&gt;And lastly, rust has always felt like &lt;em&gt;responsibility&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Making plugins for neovim in lua had the nice benefit of that I &lt;em&gt;didn&#x27;t have to&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
I could just have some code in my own config for a couple of months, completely working. &lt;br &#x2F;&gt;
And then, once I&#x27;m ready to, I could package it all nice and prettily.&lt;&#x2F;p&gt;
&lt;p&gt;Fish is even more amazing than that, because you can have a lot of callable executables in single files, thanks to a technique I use and will probably talk about in the future. So, the pressure of writing something new in fish is also really really small.&lt;&#x2F;p&gt;
&lt;p&gt;Starting up a new CSS extension with stylus is &lt;em&gt;slightly&lt;&#x2F;em&gt; a process, but it&#x27;s straightforward and fast enough where it&#x27;s not that big of a commitment. If I want to, I can easily shrink the ridiculously large sidebar with css for some stupid website, without it breaking my flow particularly much.&lt;&#x2F;p&gt;
&lt;p&gt;Rust is in a completely different league. &lt;br &#x2F;&gt;
I have always wanted to &lt;em&gt;avoid&lt;&#x2F;em&gt; using rust because of the sheer pressure I put on myself.&lt;&#x2F;p&gt;
&lt;p&gt;First, I need to come up with a name for a project, and create a new repository and directory for it. &lt;br &#x2F;&gt;
Nope, you already lost me!&lt;&#x2F;p&gt;
&lt;p&gt;Coming up with a project name and being happy with it are really fucking difficult, and are not something I want to do for a on-a-whim script that probably only I will use.&lt;&#x2F;p&gt;
&lt;p&gt;Then, setting up rustfmt config, github action for auto-making releases, keeping track of the version and the versioning tags, remembering to push them, writing DOCUMENTATION in both the readme and source code with &lt;code&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;code&gt;, picking apart which information should be in which side of the documentation...&lt;&#x2F;p&gt;
&lt;p&gt;IT&#x27;S TOO MUCH!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;but-not-anymore&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#but-not-anymore&quot; aria-label=&quot;Anchor link for: but-not-anymore&quot;&gt;but not anymore&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I created myself a new system that allows me to use rust for scripting in a pretty fast and straightforward way.
No more various bullshit to take care of for the 0 users I&#x27;ll have — sheer selfish programming!&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start where I started, to figure out why I ended up creating my own system.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;igor-petruk&#x2F;scriptisto&quot;&gt;scriptisto&lt;&#x2F;a&gt; is a really neat program that I used for the various languages I have tried. It allows you to use a compiled language for scripting, conveniently!&lt;&#x2F;p&gt;
&lt;p&gt;You can run that script just like it&#x27;s written in an interpreted language, because scriptisto can be used as a shebang.&lt;&#x2F;p&gt;
&lt;p&gt;So, something like &lt;code&gt;.&#x2F;script.rs&lt;&#x2F;code&gt; is possible. The first time you run that script, scriptisto compiles it. On the following runs, it simply resolves to the compiled binary and runs that, without needing to recompile.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve had an amazing experience with scriptisto, and would heavily recommend it. However, it was strangely slow with rust!&lt;&#x2F;p&gt;
&lt;p&gt;After the first run, the following runs &lt;em&gt;still&lt;&#x2F;em&gt; had awful startup time. Around 3 times slower than ruby! And ruby has a pretty shit startup time already.&lt;&#x2F;p&gt;
&lt;p&gt;When you can tell the startup speed by an eye test, that means it&#x27;s &lt;em&gt;really&lt;&#x2F;em&gt; bad. So, I decided to try using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;DanielKeep&#x2F;cargo-script&quot;&gt;cargo-script&lt;&#x2F;a&gt; instead, and it indeed didn&#x27;t have that issue! The following runs were definitely fast!&lt;&#x2F;p&gt;
&lt;a href=&quot;#definitely-not-foreshadowing&quot; id=&quot;definitely-not-foreshadowing&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;&lt;em&gt;Until they weren&#x27;t...&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;One of the first programs I wrote is called &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;eli&#x2F;velvidek.rs&quot;&gt;&lt;code&gt;velvidek.rs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
I don&#x27;t use the number row; instead, right meta key + fdsrewvcxa are my numbers (1234567890). &lt;br &#x2F;&gt;
Velvidek takes those letters, and replaces them with their appropriate digit. Using this program, I can shim in support for my number layer, without requiring me to press the right meta key. &lt;br &#x2F;&gt;
Now instead of having to do &lt;code&gt;fg %2&lt;&#x2F;code&gt;, I can just do &lt;code&gt;f d&lt;&#x2F;code&gt;, thanks to the fish function I made that made use of velvidek. Very helpful and important addition to my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;suspend&#x2F;&quot;&gt;suspend-based workflow&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I was pressing &lt;code&gt;f&lt;&#x2F;code&gt; to go back to the suspended process, and noticed the operation be slower than I expected. &lt;br &#x2F;&gt;
I use fish shell&#x27;s &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fishshell.com&#x2F;docs&#x2F;current&#x2F;cmds&#x2F;time.html&quot;&gt;&lt;code&gt;time&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to check how long it takes for velvidek to execute, and see ~70ms.&lt;&#x2F;p&gt;
&lt;p&gt;Well holy shit, that is entirely too slow! For a program as modular, small, and fast as this, this is ridiculously long.&lt;&#x2F;p&gt;
&lt;p&gt;I was running velvidek as a script through cargo-script, so, using the shebang &lt;code&gt;#!&#x2F;usr&#x2F;bin&#x2F;env run-cargo-script&lt;&#x2F;code&gt;. I decided to check how long &lt;code&gt;env&lt;&#x2F;code&gt; takes to figure out the path to the binary. 3ms. So, env is not the problem here.&lt;&#x2F;p&gt;
&lt;p&gt;It turns out that cargo-script is wasting a lot of time doing &lt;em&gt;something&lt;&#x2F;em&gt;. Well this is concerning.&lt;&#x2F;p&gt;
&lt;p&gt;But interestingly, a fish &lt;em&gt;script&lt;&#x2F;em&gt; takes around the same time! ~80ms for a roughly equivalent functionality script I tested. So, at least cargo-script is faster, or on par with a shebanged script in a different language; that&#x27;s good news.&lt;&#x2F;p&gt;
&lt;p&gt;The bad news is that it &lt;em&gt;is&lt;&#x2F;em&gt; too slow regardless. When you write a fish &lt;em&gt;function&lt;&#x2F;em&gt;, the time it takes to execute it is in the nanoseconds. When you turn it into a script, it gains these extra ~80ms of startup time, apparently, and so does a shebanged rust script.&lt;&#x2F;p&gt;
&lt;p&gt;cargo-script caches compiled binaries as I mentioned, so I decide to time how long it takes to execute, if I call the compiled binary directly. 3ms. &lt;br &#x2F;&gt;
It seems like it takes around 3ms to start a process on my computer, considering that both &lt;code&gt;env&lt;&#x2F;code&gt; and a random rust binary take around the same time.&lt;&#x2F;p&gt;
&lt;p&gt;So, in other words, the binary itself is not slow; cargo-script is simply wasting time.&lt;&#x2F;p&gt;
&lt;p&gt;My guess was the following: cargo-script tries too hard to not recompile, massively slowing down the general case.
So, if I make that process stupider, I&#x27;ll gain a faster general case, while probably having to recompile unecessarily more often.
A tradeoff I&#x27;m absolutely willing to make.&lt;&#x2F;p&gt;
&lt;p&gt;My idea is to compare the modification times of the script and the compiled binary.
If the binary is older than the script, let cargo-script continue like normal, to recompile it. &lt;br &#x2F;&gt;
If it is not older, run the binary directly, and forgo asking cargo-script for its opinion.&lt;&#x2F;p&gt;
&lt;p&gt;This sounds like such an obvious solution, that it&#x27;s weird they are apparently not using it. &lt;br &#x2F;&gt;
When you feel smarter than a developer who&#x27;s more impressive than you, you are &lt;em&gt;probably&lt;&#x2F;em&gt; wrong, and that&#x27;s what I assumed as well.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m trying my best to not reinvent the wheel though, and this pre-step possibly working would allow me to continue using most of the functionality of cargo-script, without having to recreate it for myself, to allow for optimization.&lt;&#x2F;p&gt;
&lt;p&gt;Alright, first run! &lt;br &#x2F;&gt;
The binary is older than the script, and the execution gets forwarded to cargo-script. Fair enough. &lt;br &#x2F;&gt;
And right about now, it should recompile. Right? Right???&lt;&#x2F;p&gt;
&lt;p&gt;It does not. And so my pre-step just infinitely transfers control to cargo-script, infinitely having that ~70ms startup time.&lt;&#x2F;p&gt;
&lt;p&gt;Worse yet, the time difference between the binary and the script is ~5 seconds. Not &lt;em&gt;milliseconds&lt;&#x2F;em&gt;. So, at which point do I consider the binary &quot;old enough&quot; or not?&lt;&#x2F;p&gt;
&lt;p&gt;Going in this direction seems fruitless. And I forgot to mention something: when using cargo-script, rust-analyzer does not help you. It requires there to be a Cargo.toml to give you lsp capabilities; if you don&#x27;t have it, it gives up and does nothing.&lt;&#x2F;p&gt;
&lt;p&gt;So, for a good developer experience, you kinda need to have a directory where you write the scripts to begin with, and then something that would compile that source code into a cargo-script compatible single-file script.&lt;&#x2F;p&gt;
&lt;p&gt;Considering that I &lt;em&gt;already&lt;&#x2F;em&gt; had a &quot;workspace&quot; directory, I thought &quot;fuck it&quot; and went ahead to fully forgo using cargo-script, in favor of making my own system. It will be less convenient, but far faster to start up.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;my-system&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-system&quot; aria-label=&quot;Anchor link for: my-system&quot;&gt;my system&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;A &quot;workspace&quot; directory named &lt;code&gt;wks&lt;&#x2F;code&gt;. I use this place to write the scripts for the first time. &lt;br &#x2F;&gt;
There&#x27;s &lt;code&gt;src&#x2F;main.rs&lt;&#x2F;code&gt; and &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;. Just what is needed to make rust-analyzer work.&lt;&#x2F;p&gt;
&lt;p&gt;Once I finish writing a rust script, it&#x27;s now time to export it. &lt;br &#x2F;&gt;
I have a (rust) script that takes main.rs and Cargo.toml, and joins them into a single file. &lt;br &#x2F;&gt;
The path to the target file I want to write to, I specify as the first line in main.rs, in a comment. &lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;eli&#x2F;scriptister&#x2F;export-rust-script.rs&quot;&gt;Primary link&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;777ec42abaaa0313bf89e6bae0810de058e84f6c&#x2F;scripts&#x2F;scriptister&#x2F;export-rust-script.rs&quot;&gt;backup link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;While writing this export step, I started thinking about how I&#x27;d make a script executable. I would probably write another script, that would act as the program in the shebang. But I found something more elegant!&lt;&#x2F;p&gt;
&lt;p&gt;What I want, effectively, is to:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;not pollute where the scripts are, with their compiled binaries&lt;&#x2F;li&gt;
&lt;li&gt;to execute a script, you simply use the script name (for example, &lt;code&gt;velvidek.rs&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;To achieve that, I can make use of &lt;code&gt;$PATH&lt;&#x2F;code&gt;! Once I compile a script, I will rename the resulting binary to the name of a the file, and put that binary somewhere on the &lt;code&gt;PATH&lt;&#x2F;code&gt;. This way, I&#x27;m typing in a name of a script to execute, but sneakily I&#x27;m actually executing the compiled binary stored somewhere else.&lt;&#x2F;p&gt;
&lt;p&gt;This is where the second script comes in. This one is in fish though: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;eli&#x2F;scriptister&#x2F;compile-rust-script.fish&quot;&gt;primary link&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;777ec42abaaa0313bf89e6bae0810de058e84f6c&#x2F;scripts&#x2F;scriptister&#x2F;compile-rust-script.fish&quot;&gt;backup link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;While the export script just writes to the target script file, &lt;em&gt;this&lt;&#x2F;em&gt; is the compilation script. It compiles the project, and copies the resulting binary somewhere on the PATH.&lt;&#x2F;p&gt;
&lt;p&gt;While one ensures my work is &lt;em&gt;backed up&lt;&#x2F;em&gt; (as a single file &quot;script&quot; in my dotfiles repository), the other one actually makes sure it&#x27;s executable, by providing a binary with the exact same name, that I can call.&lt;&#x2F;p&gt;
&lt;p&gt;A very sneaky and elegant solution, I&#x27;d say! :3&amp;lt;&lt;&#x2F;p&gt;
&lt;p&gt;In the future, if I need to &lt;em&gt;edit&lt;&#x2F;em&gt; some rust script, that&#x27;s where the &lt;em&gt;import&lt;&#x2F;em&gt; script comes into play. &lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;main&#x2F;eli&#x2F;scriptister&#x2F;import-rust-script.rs&quot;&gt;Primary link&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dotfiles&#x2F;blob&#x2F;777ec42abaaa0313bf89e6bae0810de058e84f6c&#x2F;scripts&#x2F;scriptister&#x2F;import-rust-script.rs&quot;&gt;backup link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It takes a path to a rust script that I exported into previously, splits it into main.rs and Cargo.toml, and writes those files in the workspace directory &lt;code&gt;wks&lt;&#x2F;code&gt;. After I import, I&#x27;m ready to edit the script in my workspace, to then export it back again.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;helix fork&lt;&#x2F;a&gt;&#x27;s command harps, running all of these scripts is really easy, and this has become a way nicer workflow than I expected!&lt;&#x2F;p&gt;
&lt;p&gt;Now that rust is so fast to get running, I&#x27;m way more excited to write it, and I already am rewriting some things as rust scripts, when they were written in fish before. It&#x27;s super nice!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>stray from defaults</title>
          <pubDate>Thu, 02 Jan 2025 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/stray-from-defaults/</link>
          <guid>https://axlefublr.github.io/stray-from-defaults/</guid>
          <description xml:base="https://axlefublr.github.io/stray-from-defaults/">&lt;p&gt;Vim has made a stupid design decision, and we&#x27;re still eating shit many years later.&lt;&#x2F;p&gt;
&lt;p&gt;It prioritised mnemonics, rather than ergonomics.&lt;&#x2F;p&gt;
&lt;p&gt;The issue is pretty apparent: mnemonics are helpful for the first, like, &lt;em&gt;week&lt;&#x2F;em&gt; while you&#x27;re learning vim for the first time. &lt;br &#x2F;&gt;
And then many &lt;em&gt;years&lt;&#x2F;em&gt; later you still end up using the same non-optimal mappings.&lt;&#x2F;p&gt;
&lt;a href=&quot;#the-mappings&quot; id=&quot;the-mappings&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;One of the most frequent things you do in a text editor, is copy. &lt;br &#x2F;&gt;
And yet it&#x27;s mapped to one of the most annoying keys to press: &lt;kbd&gt;y&lt;&#x2F;kbd&gt;. While powered by a big stretch of a mnemonic that we just came to accept: &quot;yank&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;And yet &lt;kbd&gt;s&lt;&#x2F;kbd&gt; sits there undisturbed, in one of the most prime finger positions on the home row, doing what &lt;code&gt;cl&lt;&#x2F;code&gt; can also do.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Don&#x27;t get me wrong: I loved using &lt;kbd&gt;s&lt;&#x2F;kbd&gt;, but it is too convenient of a placement.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I hate pressing &lt;kbd&gt;p&lt;&#x2F;kbd&gt; almost as much as pressing &lt;kbd&gt;y&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
It is another example of an 😩 key used for one of the most common actions. Except, pasting is probably more common than copying.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;o&lt;&#x2F;kbd&gt; is one of the &lt;em&gt;nicest&lt;&#x2F;em&gt; to press keys, yet it&#x27;s there for a fairly niche action: creating a new line.&lt;&#x2F;p&gt;
&lt;p&gt;What I find myself doing the most after creating a new line, is to create &lt;em&gt;another&lt;&#x2F;em&gt; line. &lt;br &#x2F;&gt;
Because &lt;kbd&gt;o&lt;&#x2F;kbd&gt; puts you into insert mode, the natural way to create another line is by pressing enter. &lt;br &#x2F;&gt;
Yet, the hand motion of switching from &lt;kbd&gt;o&lt;&#x2F;kbd&gt; to &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt; is pretty cumbersome.&lt;&#x2F;p&gt;
&lt;p&gt;What is the most common usecase for &lt;kbd&gt;A&lt;&#x2F;kbd&gt;? &lt;br &#x2F;&gt;
In my experience, it&#x27;s to add in a &lt;code&gt;;&lt;&#x2F;code&gt; or a &lt;code&gt;,&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
However, if you correctly use both shifts, the hand movement to do an action like this is a bit too ridiculous: for such a &lt;em&gt;common&lt;&#x2F;em&gt; usecase, having to move your pinky &lt;em&gt;aaaaallllll&lt;&#x2F;em&gt; the way from the right shift to &lt;code&gt;;&lt;&#x2F;code&gt; ends up compiling into an annoyance.&lt;&#x2F;p&gt;
&lt;p&gt;The choice of &lt;kbd&gt;a&lt;&#x2F;kbd&gt; is also strange in a different way. &lt;br &#x2F;&gt;
To insert at the &lt;em&gt;left&lt;&#x2F;em&gt; of the cursor, you press the &lt;em&gt;right&lt;&#x2F;em&gt; key (&lt;kbd&gt;i&lt;&#x2F;kbd&gt;). To insert at the &lt;em&gt;right&lt;&#x2F;em&gt; of the cursor, you press the &lt;em&gt;left&lt;&#x2F;em&gt; key (&lt;kbd&gt;a&lt;&#x2F;kbd&gt;). &lt;br &#x2F;&gt;
???&lt;&#x2F;p&gt;
&lt;h1 id=&quot;you-can-stop-eating-shit&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#you-can-stop-eating-shit&quot; aria-label=&quot;Anchor link for: you-can-stop-eating-shit&quot;&gt;you can stop eating shit&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Defaults are made to be CHANGED from. &lt;br &#x2F;&gt;
It&#x27;s great when they are good to begin with, but that&#x27;s not always the case. &lt;br &#x2F;&gt;
Do not be afraid of &lt;em&gt;change&lt;&#x2F;em&gt; when it can provide you a much nicer experience.&lt;&#x2F;p&gt;
&lt;p&gt;My copy key is now &lt;kbd&gt;s&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
What&#x27;s the mnemonic? &quot;Steal&quot;? &lt;br &#x2F;&gt;
Wrong question. I don&#x27;t &lt;em&gt;need&lt;&#x2F;em&gt; a mnemonic! If the mapping &lt;em&gt;feels&lt;&#x2F;em&gt; right, your muscle memory adjusts pretty quick!&lt;&#x2F;p&gt;
&lt;p&gt;Now I don&#x27;t have to travel across the Alps just to copy something: the key is on my home row.&lt;&#x2F;p&gt;
&lt;p&gt;My paste key is &lt;kbd&gt;o&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
&lt;em&gt;Much&lt;&#x2F;em&gt; nicer to press than &lt;kbd&gt;p&lt;&#x2F;kbd&gt;! And in addition, something like &lt;code&gt;yyp&lt;&#x2F;code&gt; is now &lt;code&gt;sso&lt;&#x2F;code&gt;, which I find to simply be much more enjoyable.&lt;&#x2F;p&gt;
&lt;p&gt;Insert new line is now on &lt;kbd&gt;a&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
Now when I insert a new line, the motion of my right hand to reach &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt; is much smoother! &lt;br &#x2F;&gt;
Smoother even if I do &quot;insert new line above&quot; (&lt;kbd&gt;A&lt;&#x2F;kbd&gt;) first; all I need to do is slightly move the right pinky from right shift to &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Insert &lt;em&gt;after&lt;&#x2F;em&gt; the cursor is on &lt;kbd&gt;p&lt;&#x2F;kbd&gt;. &lt;br &#x2F;&gt;
This was risky in my head, because I don&#x27;t &lt;em&gt;like&lt;&#x2F;em&gt; pressing &lt;kbd&gt;p&lt;&#x2F;kbd&gt;. But very quickly I realized just how much nicer it is than &lt;kbd&gt;a&lt;&#x2F;kbd&gt; for the purpose.&lt;&#x2F;p&gt;
&lt;p&gt;First of all, it &lt;em&gt;is&lt;&#x2F;em&gt; on the right side of &lt;kbd&gt;i&lt;&#x2F;kbd&gt;! So, &lt;kbd&gt;i&lt;&#x2F;kbd&gt; and &lt;kbd&gt;p&lt;&#x2F;kbd&gt; now play along with a consistent semantic of &quot;this one is on the left, this means &lt;em&gt;before&lt;&#x2F;em&gt;&quot; and &quot;this one is on the right, this means &lt;em&gt;after&lt;&#x2F;em&gt;&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;But even better than that, appending is AMAZING now! &lt;br &#x2F;&gt;
The hand movement to append a &lt;code&gt;;&lt;&#x2F;code&gt; or &lt;code&gt;,&lt;&#x2F;code&gt; at the end of the line is way smaller now, and feels really comfortable. &lt;br &#x2F;&gt;
Also generally, pressing right shift is more difficult than pressing &lt;em&gt;left&lt;&#x2F;em&gt; shift anyway; so overall there&#x27;s less hand movement for something that I do really frequently, especially while writing a blog post for example.&lt;&#x2F;p&gt;
&lt;a href=&quot;#conclusion&quot; id=&quot;conclusion&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;After changing these, it took me &lt;em&gt;maybe&lt;&#x2F;em&gt; two days to get used to the new mappings. This is simply because of how much more &lt;em&gt;fitting&lt;&#x2F;em&gt; they feel in my head, and to my fingers.&lt;&#x2F;p&gt;
&lt;p&gt;You will have your own gripes that you will solve differently than me, but I wanted to shed light on that it &lt;em&gt;can&lt;&#x2F;em&gt; be &lt;strong&gt;really&lt;&#x2F;strong&gt; beneficial to change defaults, even when they are as strong-rooted as the ones I listed.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s true: a lot of &lt;em&gt;other&lt;&#x2F;em&gt; programs will replicate vim, and have semantically fitting &lt;code&gt;hjkl&lt;&#x2F;code&gt;, &lt;code&gt;y&lt;&#x2F;code&gt;, &lt;code&gt;p&lt;&#x2F;code&gt;, etc mappings. &lt;br &#x2F;&gt;
What do you do about that?&lt;&#x2F;p&gt;
&lt;p&gt;Personally, I just context switch, or reconfigure the mappings.
This may seem like a lot of effort, or a non-ideal solution, but look at it from a different lens: why &lt;em&gt;would&lt;&#x2F;em&gt; you sacrifice your experience in the place where you spend most of your time (your editor), just for some &lt;em&gt;other&lt;&#x2F;em&gt; program to feel consistent?&lt;&#x2F;p&gt;
&lt;p&gt;I do agree, context switching is annoying, but can be learned: if you have a strong thought of &quot;this is a different program&quot;, you can eventually stop caring that its mappings are inconsistent with what you remapped.
Or, you know, remap them in that program as well.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>suspend is actually neat</title>
          <pubDate>Tue, 31 Dec 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/suspend/</link>
          <guid>https://axlefublr.github.io/suspend/</guid>
          <description xml:base="https://axlefublr.github.io/suspend/">&lt;p&gt;Part of why &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;why-i-hate-kitty&#x2F;&quot;&gt;I still use kitty&lt;&#x2F;a&gt; is because its window manipulation is goated. &lt;br &#x2F;&gt;
You can create windows (panes), tabs, overlay windows (panes) and os windows using hotkeys. &lt;br &#x2F;&gt;
That&#x27;s cool enough on its own, but you can do all of that from a &lt;em&gt;script&lt;&#x2F;em&gt; too!
This lets you integrate window manipulation into a bunch of places, so it&#x27;s quite workflow-building.&lt;&#x2F;p&gt;
&lt;p&gt;Say I&#x27;m in helix, and want to run some shell command.
I can of course use &lt;code&gt;:sh&lt;&#x2F;code&gt;, but it&#x27;s pretty cumbersome, so I&#x27;d rather use my actual terminal.&lt;&#x2F;p&gt;
&lt;p&gt;Not only can I &lt;em&gt;just&lt;&#x2F;em&gt; create a new pane, I can create it in the same cwd as the current one, or as the same cwd as &lt;em&gt;helix&lt;&#x2F;em&gt; is in (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;my helix fork&lt;&#x2F;a&gt; exclusive feature), or in the parent directory of the current helix buffer (helix fork specific also).&lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t a post on why kitty is amazing, because as I expressed in the past, I &lt;em&gt;hate&lt;&#x2F;em&gt; kitty.
I more so want to shed light on that my window manipulating workflow is super solid, so there was never a need to look into the shell feature called &quot;suspending&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Plus, it&#x27;s kind of confusing and last time I tried it, it felt wonky.&lt;&#x2F;p&gt;
&lt;a href=&quot;#yoink&quot; id=&quot;yoink&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I happened to be reading a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;jvns.ca&#x2F;blog&#x2F;2024&#x2F;07&#x2F;03&#x2F;reasons-to-use-job-control&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt; by Julia Evans some time ago, and it goes on to explain the benefits of actually using job control. &lt;br &#x2F;&gt;
(It was a great read but) at this point I don&#x27;t really remember a single point; all I remember is that &quot;job control &lt;em&gt;can&lt;&#x2F;em&gt; be kinda wonky but it&#x27;s also super neat&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;I decided to give it another try. &lt;br &#x2F;&gt;
While in helix for example, instead of opening another pane to run a shell command (only to close the pane right after), I would instead &lt;em&gt;suspend&lt;&#x2F;em&gt; helix and execute the command in the shell that I already had open.&lt;&#x2F;p&gt;
&lt;p&gt;Very very quickly I realized that I absolutely love it!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;command-output&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#command-output&quot; aria-label=&quot;Anchor link for: command-output&quot;&gt;command output&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;When I create a new pane to run a shell command, I&#x27;ll probably close it right after. &lt;br &#x2F;&gt;
Having windows I forgot about &lt;em&gt;open&lt;&#x2F;em&gt; feels messy, after all.&lt;&#x2F;p&gt;
&lt;p&gt;But when I close a pane, naturally I lose all the output of the commands that I ran previously.&lt;&#x2F;p&gt;
&lt;p&gt;This doesn&#x27;t happen with a suspending workflow!
The output of previous commands actually &lt;em&gt;stays&lt;&#x2F;em&gt; and I can look at it again as many times as I want to.&lt;&#x2F;p&gt;
&lt;p&gt;Better yet, I can switch back and forth between helix and the shell output very quickly — as fast as I would be switching between multiple (fullscreened) windows.
(But with the benefit of not needing to clean anything up)&lt;&#x2F;p&gt;
&lt;p&gt;This factor really started to shine once I was fucking around with colors using &lt;code&gt;pastel&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I couldn&#x27;t quite get the correct lightness factor on some color, and so I was going back and forth between helix and my shell, using the previous color (displayed in the output) as the input to a new &lt;code&gt;pastel darken 0.01&lt;&#x2F;code&gt; command; then, going back to helix to try out where I was actually using the color.&lt;&#x2F;p&gt;
&lt;p&gt;This worked so amazingly for me because I never felt like I needed to clean up a pane after I&#x27;m &quot;done&quot;. &lt;br &#x2F;&gt;
With a pane, I might&#x27;ve closed it early and lost output that I then would realize I need, a couple of seconds later. &lt;br &#x2F;&gt;
And in the same fashion, keeping multiple windows open feels quite bloaty, and I see it disrupt my worklow in a way that suspending simply doesn&#x27;t.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;toggle-hotkey&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#toggle-hotkey&quot; aria-label=&quot;Anchor link for: toggle-hotkey&quot;&gt;toggle hotkey&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Another thing that helps a lot in the workflow, is how natural it is to make a hotkey for it.&lt;&#x2F;p&gt;
&lt;p&gt;With a pane, you need a hotkey to &lt;em&gt;create&lt;&#x2F;em&gt; a window, and a different hotkey to switch between windows.
Then maybe even another hotkey to switch windows &lt;em&gt;backwards&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t need that with suspend! &lt;br &#x2F;&gt;
The hotkey is simply &lt;kbd&gt;ctrl+z&lt;&#x2F;kbd&gt; to suspend; and I made a hotkey in my &lt;em&gt;shell&lt;&#x2F;em&gt; to run &lt;code&gt;fg&lt;&#x2F;code&gt; — that puts the latest job into the foreground.&lt;&#x2F;p&gt;
&lt;p&gt;I do something in helix and realize I need to run a command.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;kbd&gt;ctrl+z&lt;&#x2F;kbd&gt;&lt;&#x2F;li&gt;
&lt;li&gt;run command&lt;&#x2F;li&gt;
&lt;li&gt;&lt;kbd&gt;ctrl+z&lt;&#x2F;kbd&gt; &lt;em&gt;again&lt;&#x2F;em&gt;, now to go back to helix&lt;&#x2F;li&gt;
&lt;li&gt;FIN&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Rather than:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;hotkey 1 to create a new pane&lt;&#x2F;li&gt;
&lt;li&gt;run command&lt;&#x2F;li&gt;
&lt;li&gt;hotkey 2 to close it&lt;&#x2F;li&gt;
&lt;li&gt;FIN?&lt;&#x2F;li&gt;
&lt;li&gt;oh fACK I needed that output, now I have to repeat this process to get it back&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;a href=&quot;#strong&quot; id=&quot;strong&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Neither of these are particularly &lt;em&gt;that&lt;&#x2F;em&gt; strong of arguments; ultimately this suspending workflow simply felt &lt;em&gt;neat&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
So try it out, maybe you&#x27;re be as overjoyed as I am!&lt;&#x2F;p&gt;
&lt;p&gt;However, I was still missing a part of my windowing workflow power. &lt;br &#x2F;&gt;
As I mentioned, I can do something like &quot;create pane in the working directory of &lt;em&gt;helix&lt;&#x2F;em&gt;&quot; or &quot;... in the parent directory of the current helix buffer&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;The pane creating hotkeys know about this info because I explicitly pass it; how would suspend know about it?&lt;&#x2F;p&gt;
&lt;p&gt;By me &lt;em&gt;forcing&lt;&#x2F;em&gt; it to know! 😈&lt;&#x2F;p&gt;
&lt;a href=&quot;#force&quot; id=&quot;force&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;In my helix fork, I made the suspend action write the current buffer&#x27;s parent directory to a path, and the current helix cwd to a different path. &lt;br &#x2F;&gt;
Then for yazi, I wrote a small plugin that writes the current directory path to both of those files every time I change directory.&lt;&#x2F;p&gt;
&lt;p&gt;Now, I have a hotkey in my shell on &lt;kbd&gt;ctrl+y&lt;&#x2F;kbd&gt; that toggles between the two paths listed in those two files.&lt;&#x2F;p&gt;
&lt;p&gt;So now, instead of needing to create a new pane in some specific directory with dedicated mappings, I can &lt;em&gt;retroactively&lt;&#x2F;em&gt; cd into the directory from which I want to execute the command.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m working on a new script in helix, and want to run it. &lt;br &#x2F;&gt;
I suspend helix, and press &lt;kbd&gt;ctrl+y&lt;&#x2F;kbd&gt; to switch to the parent directory of that script, and simply do &lt;code&gt;.&#x2F;script.fish&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I press &lt;kbd&gt;ctrl+y&lt;&#x2F;kbd&gt; only once, assuming that my shell&#x27;s cwd and &lt;em&gt;helix&lt;&#x2F;em&gt;&#x27;s cwd match up; &lt;br &#x2F;&gt;
if they didn&#x27;t, I&#x27;d have to press &lt;kbd&gt;ctrl+y&lt;&#x2F;kbd&gt; twice.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that my &lt;kbd&gt;ctrl+z&lt;&#x2F;kbd&gt; is actually on &lt;kbd&gt;capslock+w&lt;&#x2F;kbd&gt; and &lt;kbd&gt;ctrl+y&lt;&#x2F;kbd&gt; is on &lt;kbd&gt;capslock+e&lt;&#x2F;kbd&gt; &lt;br &#x2F;&gt;
So these two hotkeys are actually way more ergonomic to press than the &lt;em&gt;real&lt;&#x2F;em&gt; &lt;kbd&gt;ctrl+z&lt;&#x2F;kbd&gt; and &lt;kbd&gt;ctrl+y&lt;&#x2F;kbd&gt; would be&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Me storing helix&#x27;s cwd solves the other part of of the windowing workflow — &quot;create pane in the cwd of &lt;em&gt;helix&lt;&#x2F;em&gt;&quot;. &lt;br &#x2F;&gt;
Except, it does it &lt;em&gt;better&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;With the windowing workflow, I need to proactively think about how to create my new window. &lt;br &#x2F;&gt;
&quot;Which cwd do I need?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Even if I just default to helix&#x27;s cwd, I&#x27;m bound to have to use a different mapping to open windows from helix, than I usually would anywhere else. &lt;br &#x2F;&gt;
And even then, I still need to proactively think about creating windows in the parent directory of a buffer.&lt;&#x2F;p&gt;
&lt;p&gt;The suspend workflow wins here yet again, because I &lt;em&gt;fix&lt;&#x2F;em&gt; my current working directory, instead of having to &lt;em&gt;prepare&lt;&#x2F;em&gt; it.&lt;&#x2F;p&gt;
&lt;p&gt;The thought process in this workflow is way simpler.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I need to execute a command&lt;&#x2F;li&gt;
&lt;li&gt;suspend&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;starts writing command&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;oh right I need to execute it from the parent directory of that buffer&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;presses &lt;kbd&gt;ctrl+y&lt;&#x2F;kbd&gt;&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;continues writing command and executes it&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I don&#x27;t even need to &lt;em&gt;delete&lt;&#x2F;em&gt; the command and then re-write it; the cwd fix is on a hotkey! &lt;br &#x2F;&gt;
So this process is &lt;em&gt;incredibly&lt;&#x2F;em&gt; smooth 😋&lt;&#x2F;p&gt;
&lt;a href=&quot;#hope&quot; id=&quot;hope&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I hope I was able to show you how a suspend-driven workflow can work really well! &lt;br &#x2F;&gt;
Try out using job control more, maybe you will discover that you love it too!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>safety razors slap</title>
          <pubDate>Mon, 30 Dec 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/safety-razor/</link>
          <guid>https://axlefublr.github.io/safety-razor/</guid>
          <description xml:base="https://axlefublr.github.io/safety-razor/">&lt;p&gt;Shaving is a massive hassle. Because I&#x27;m trans, it&#x27;s even hassler for me than to the average person.&lt;&#x2F;p&gt;
&lt;p&gt;Elecric shavers are pretty low effort, but they also don&#x27;t cut that close to the skin, so it&#x27;s a good strategy to use when you have a lot of hair, but pretty ass if you don&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;To &lt;em&gt;get&lt;&#x2F;em&gt; a pretty ass though, you need the power of an actual razor.
But those have their own plethora of issues: they may cut you, &quot;dribble&quot; on the skin, introduce ingrown hairs, overall feel too rough and damage your skin. &lt;br &#x2F;&gt;
You can pick your razor to have more blades to mitigate some of these issues, but then the problem is the sheer price.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m broke as hell! I can&#x27;t replace the blade as often as it&#x27;s recommended, so I end up with a shitty razor for most of the time. If I go for a cheaper blade, I just &lt;em&gt;start&lt;&#x2F;em&gt; with a shitty one, lol.&lt;&#x2F;p&gt;
&lt;p&gt;Shaving sucks, doesn&#x27;t it!&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s the thought that I accepted for the longest time. But just recently, my friend recommended me something that made me &lt;em&gt;want&lt;&#x2F;em&gt; to shave again. Over the past couple of days, I shaved my entire body. This barely ever happens! It&#x27;s so fun now!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;safety-razors&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#safety-razors&quot; aria-label=&quot;Anchor link for: safety-razors&quot;&gt;safety razors&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;This product name sounded strangely vague to me!&lt;&#x2F;p&gt;
&lt;p&gt;A safety razor (image 1) is basically a holder for the classic razor blades (image 2). I had no clue what they were used for before!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;safety-razor&#x2F;.&#x2F;safety-razor.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;safety-razor&#x2F;.&#x2F;razor-blade.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So, a safety razor takes a razor blade, and bends it at the perfect angle to give you two bladed sides that you can use to shave with, making the razors &lt;em&gt;safe to use&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
Interestingly, in russian, &quot;razor blade&quot; is sometimes literally called &quot;dangerous razor&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;I was warned that you need to be &lt;em&gt;&lt;strong&gt;really&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; careful when shaving with a safety razor — unlike your usual razor, you don&#x27;t have the spinny bit that will follow the shape of the skin that you&#x27;re shaving — you need to uphold that invariant yourself, otherwise you will get cut.&lt;&#x2F;p&gt;
&lt;p&gt;The friend that suggested a safety razor to me said she cut herself 6 times! Naturally I got anxious about that, and thought &quot;nah I&#x27;d win and only get cut 2-3 times&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Eventually the safety razor arrived and I got to shaving. &lt;br &#x2F;&gt;
Turns out the name &lt;em&gt;wasn&#x27;t&lt;&#x2F;em&gt; a lie! It &lt;em&gt;is&lt;&#x2F;em&gt; indeed safe!&lt;&#x2F;p&gt;
&lt;p&gt;Because of how sharp the razors are, I don&#x27;t need to apply any pressure — I basically just let the handle dramatically fall against my skin... and it just works??
In the end I didn&#x27;t get cut a single time, so I guess I &lt;em&gt;did&lt;&#x2F;em&gt; win!&lt;&#x2F;p&gt;
&lt;p&gt;The process of shaving is pretty similar to a normal razor, but you &lt;em&gt;do&lt;&#x2F;em&gt; need to be more careful and slow. &lt;br &#x2F;&gt;
Because it&#x27;s just a single razor rather than 2-5, you can&#x27;t just force the razor to do everything in one go — it is pretty important to first shave with the grain, and then against the grain.&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t forget to apply shaving cream both times!&lt;&#x2F;p&gt;
&lt;p&gt;A normal razor has this colored line that somehow relaxes your skin after shaving across it; a safety razor doesn&#x27;t have that.
And so you have to do the job of this colored line yourself by making sure you use shaving cream &#x2F; gel more thoroughly.&lt;&#x2F;p&gt;
&lt;p&gt;Another tip which I&#x27;ve been using prior but not as conciously: warm up the area you plan to shave. Most straghtforward way is to apply some very warm water to the area.
This allegedly makes your hair softer, making it easier to shave off.&lt;&#x2F;p&gt;
&lt;a href=&quot;#first-time&quot; id=&quot;first-time&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;So, I finish shaving with a safety razor for the first time, and wow! &lt;br &#x2F;&gt;
My skin feels FAR less damaged than it usually is with a normal razor. &lt;br &#x2F;&gt;
The experience itself is actually kinda... fun?
When was the last time shaving actually felt fun!&lt;&#x2F;p&gt;
&lt;p&gt;As I mentioned, over the last couple of days I went ahead and shaved my entire body. &lt;br &#x2F;&gt;
It&#x27;s usually a massive chore, but for once I feel &lt;em&gt;excited&lt;&#x2F;em&gt; to shave, because my razor actually does its job as advertised! &lt;br &#x2F;&gt;
Nay, &lt;em&gt;better&lt;&#x2F;em&gt; than advertised!&lt;&#x2F;p&gt;
&lt;p&gt;And best of all, it is now &lt;em&gt;cheap&lt;&#x2F;em&gt;. REALLY fucking cheap. &lt;br &#x2F;&gt;
The replacement blade for my previous go-to razor cost me around 6$. &lt;br &#x2F;&gt;
More precisely, I could at minimum buy 2 at a time, costing me 12$.&lt;&#x2F;p&gt;
&lt;p&gt;I will remind you: I am very poor, and so I couldn&#x27;t pay that price often enough to get the best performance out of the razor.&lt;&#x2F;p&gt;
&lt;p&gt;Now, for that same 6$, I can get a HUNDRED replacement razors. &lt;br &#x2F;&gt;
They are dirt cheap, &lt;strong&gt;and&lt;&#x2F;strong&gt; perform better than &quot;peak&quot; normal-razor-blades. &lt;br &#x2F;&gt;
Better shaves, less damaged skin, cheaper, more enjoyable.&lt;&#x2F;p&gt;
&lt;p&gt;Safety razors are amazing! Try one out if you haven&#x27;t before!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>best find &amp; replace tool I found</title>
          <pubDate>Mon, 23 Dec 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/repgrep/</link>
          <guid>https://axlefublr.github.io/repgrep/</guid>
          <description xml:base="https://axlefublr.github.io/repgrep/">&lt;p&gt;I used to do magic with the quickfix list back in neovim, that gave me a pretty good find &amp;amp; replace experience.&lt;&#x2F;p&gt;
&lt;p&gt;However as you may know, I switched to helix. It can be very barebones at times, compared to the shenanigans I wrote for myself in neovim. &lt;br &#x2F;&gt;
My find and replace now is mostly just the “find” part — I use helix&#x27;s searcher, and then visit each place individually to modify it how I want. It&#x27;s as laborious as it sounds.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;About time to change this&quot; I decided, and went to look for an interactive find &amp;amp; replace tool.&lt;&#x2F;p&gt;
&lt;p&gt;First thing I found is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yassinebridi&#x2F;serpl&quot;&gt;&lt;code&gt;serpl&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &lt;br &#x2F;&gt;
It was quite precisely what I wanted! &lt;br &#x2F;&gt;
However, I quickly noticed &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yassinebridi&#x2F;serpl&#x2F;issues&#x2F;39&quot;&gt;a bug&lt;&#x2F;a&gt; that literally disintegrated the UI over time. Non-0 chance I could fix it in my fork like I tend to do (apparently), but I&#x27;m not in love with the software enough to bother.&lt;&#x2F;p&gt;
&lt;p&gt;For what it&#x27;s worth, it would be strange for a bug as big as this to exist for everyone. &lt;br &#x2F;&gt;
If you&#x27;re interested in a TUI find &amp;amp; replace tool, serpl might still be for you! &lt;br &#x2F;&gt;
Maybe the stars align and the bug doesn&#x27;t happen for you ✨&lt;&#x2F;p&gt;
&lt;p&gt;Conveniently though, serpl mentions another similar tool at the end of the readme. Honestly it&#x27;s almost too nice, because it is just directly better for the most part! (if we exclude the bug I experienced)&lt;&#x2F;p&gt;
&lt;p&gt;The awkward name of this tool is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;acheronfail&#x2F;repgrep&quot;&gt;&lt;code&gt;repgrep&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Nope, I didn&#x27;t misspell &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BurntSushi&#x2F;ripgrep&quot;&gt;&lt;code&gt;ripgrep&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;Seems like the idea for the name is “ripgrep, but r&lt;em&gt;&lt;strong&gt;e&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;place”.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly to ripgrep, the binary you will be using is not that wordy: &lt;code&gt;rgr&lt;&#x2F;code&gt;. Once again, the semantic of “rg, but &lt;em&gt;&lt;strong&gt;r&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;eplace”.&lt;&#x2F;p&gt;
&lt;p&gt;The beauty of repgrep for me, is that it &lt;em&gt;just&lt;&#x2F;em&gt; uses ripgrep under the hood. &lt;br &#x2F;&gt;
Because of this, you won&#x27;t need to learn any new arguments &#x2F; flags to use repgrep — it &lt;em&gt;just&lt;&#x2F;em&gt; passes along the arguments to &lt;code&gt;rg&lt;&#x2F;code&gt;! &lt;br &#x2F;&gt;
So if you know &lt;code&gt;rg&lt;&#x2F;code&gt; flags, you automatically know &lt;code&gt;rgr&lt;&#x2F;code&gt; flags :D&lt;&#x2F;p&gt;
&lt;p&gt;You start repgrep by specifying the arguments to ripgrep, mainly the search pattern:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;rgr&lt;&#x2F;span&gt;&lt;span&gt; maximi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And find yourself in the TUI:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;repgrep&#x2F;.&#x2F;maximi.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s as natural as it looks, so I won&#x27;t spend time explaining all the hotkeys. You can look at them by pressing &lt;kbd&gt;?&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;repgrep&#x2F;.&#x2F;help.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s have a look at replace mode, that you get to by pressing &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt; or &lt;kbd&gt;r&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;repgrep&#x2F;.&#x2F;replace.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The interesting part of the design decisions, is that while entering your pattern, &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt; doesn&#x27;t confirm! &lt;br &#x2F;&gt;
Instead, it inserts a newline:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;repgrep&#x2F;.&#x2F;enter.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You accept by pressing the awkward hotkey &lt;kbd&gt;ctrl+s&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Strange decision, but I respect the thinking behind it. Letting the user insert newlines just like that is pretty helpful, considering that neither &lt;code&gt;\n&lt;&#x2F;code&gt; nor &lt;code&gt;\r&lt;&#x2F;code&gt; work.&lt;&#x2F;p&gt;
&lt;p&gt;However still, accepting happens way more frequently than inserting a newline. Unfortunately, there is no configuration, so I couldn&#x27;t change it in a normal way.&lt;&#x2F;p&gt;
&lt;p&gt;I maintain a helix fork already, what&#x27;s one more? Especially not scary considering how long ago the most recent commit was. So, I forked repgrep to change the behavior of enter. &lt;br &#x2F;&gt;
Now &lt;kbd&gt;enter&lt;&#x2F;kbd&gt; accepts, &lt;kbd&gt;alt+enter&lt;&#x2F;kbd&gt; inserts a newline.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s how I finally have a nice find &amp;amp; replace tool!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>helix is ridiculously consistent</title>
          <pubDate>Fri, 13 Dec 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/consistentc/</link>
          <guid>https://axlefublr.github.io/consistentc/</guid>
          <description xml:base="https://axlefublr.github.io/consistentc/">&lt;p&gt;In helix, these two actions exist:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;copy_selection_on_next_line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;copy_selection_on_prev_line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The default hotkeys for both of them are &lt;kbd&gt;shift+c&lt;&#x2F;kbd&gt; and &lt;kbd&gt;shift+alt+c&lt;&#x2F;kbd&gt;, respectively.&lt;&#x2F;p&gt;
&lt;p&gt;From the name I instantly assumed: &quot;ah, it&#x27;s the usual &quot;add multicursor on the next line&quot; and &quot;add multicursor on the previous line&quot;&quot;, like practically every multicursor implementation has.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve talked about the elegant consistency of helix in &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;why-even-helix&#x2F;&quot;&gt;this blog post&lt;&#x2F;a&gt;; &lt;br &#x2F;&gt;
turns out the idea of &quot;selections matter, not your cursor&quot; applies here as well!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;showcase&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#showcase&quot; aria-label=&quot;Anchor link for: showcase&quot;&gt;showcase&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;video controls&gt;
  &lt;source src=&quot;lines.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;You create a new cursor below the current &lt;em&gt;selection&lt;&#x2F;em&gt;, &lt;strong&gt;not&lt;&#x2F;strong&gt; the current line!&lt;&#x2F;p&gt;
&lt;p&gt;So you could possibly make use of this by selecting two lines, and then effectively make cursors on every other line.&lt;&#x2F;p&gt;
&lt;p&gt;The usecase that comes in mind immediately is some long &lt;code&gt;if&lt;&#x2F;code&gt; chain, where the bodies are all a single line, &lt;br &#x2F;&gt;
and you want to change something in all (or some) of the conditions &#x2F; bodies.&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;something-else.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;To be fair, I have yet to use this for anything, but found the consistency really cool. &lt;br &#x2F;&gt;
Being able to express editing desires in such an elegant way is part of why I switched to helix!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>newest helix master features</title>
          <pubDate>Tue, 10 Dec 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/recent-helix-burst/</link>
          <guid>https://axlefublr.github.io/recent-helix-burst/</guid>
          <description xml:base="https://axlefublr.github.io/recent-helix-burst/">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;helix-master-vs-stable&#x2F;&quot;&gt;As you may know&lt;&#x2F;a&gt;, I maintain my own &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;helix fork&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
Recently I noticed a huuuuuuuge burst of new commits, and here&#x27;s what new features I found!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;cd-improvement&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#cd-improvement&quot; aria-label=&quot;Anchor link for: cd-improvement&quot;&gt;cd improvement&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The &lt;code&gt;:change-current-directory&lt;&#x2F;code&gt; (&lt;code&gt;:cd&lt;&#x2F;code&gt;) command now more closely mimics the useful behavior of &lt;code&gt;cd&lt;&#x2F;code&gt; in the shell: &lt;br &#x2F;&gt;
With no arguments (&lt;code&gt;:cd&lt;&#x2F;code&gt;), it now changes directory to &lt;code&gt;~&lt;&#x2F;code&gt; (&lt;code&gt;$HOME&lt;&#x2F;code&gt;). &lt;br &#x2F;&gt;
&lt;code&gt;:cd -&lt;&#x2F;code&gt; changes directory to the most recent one. So, if you &lt;code&gt;:cd ~&#x2F;Documents&lt;&#x2F;code&gt; and then &lt;code&gt;:cd ~&#x2F;Downloads&lt;&#x2F;code&gt;, &lt;code&gt;:cd -&lt;&#x2F;code&gt; will put you back into &lt;code&gt;~&#x2F;Documents&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;auto-trim-trailing-whitespace-with-a-caveat&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#auto-trim-trailing-whitespace-with-a-caveat&quot; aria-label=&quot;Anchor link for: auto-trim-trailing-whitespace-with-a-caveat&quot;&gt;auto-trim trailing whitespace with a caveat&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The &lt;code&gt;insert_newline&lt;&#x2F;code&gt; action now trims that line&#x27;s trailing whitespace.&lt;&#x2F;p&gt;
&lt;p&gt;So if you make custom mappings for &lt;code&gt;insert_newline&lt;&#x2F;code&gt;, or far more likely when you press &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt; in insert mode, that line&#x27;s trailing whitespace is automatically removed.&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;trim-trailing-whitespace.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;While this is cool to have and will fix most trailing whitespace moving forward, the issue is the &lt;em&gt;moving forward&lt;&#x2F;em&gt; part. &lt;br &#x2F;&gt;
Somehow we still don&#x27;t have a &lt;code&gt;:trim&lt;&#x2F;code&gt; command or on-write hooks that would trim for us, so this on-newline behavior won&#x27;t help you clean up a codebase — only to not mess up (as much) when writing a new one.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;auto-continue-line-comments&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#auto-continue-line-comments&quot; aria-label=&quot;Anchor link for: auto-continue-line-comments&quot;&gt;auto-continue line comments&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Our second on-newline feature! Although this one doesn&#x27;t depend on the &lt;code&gt;insert_newline&lt;&#x2F;code&gt; action, and will happen even if you use something like &lt;kbd&gt;o&lt;&#x2F;kbd&gt; &#x2F; &lt;kbd&gt;O&lt;&#x2F;kbd&gt;&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;extending-comments.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;This feature has actually been in core for about a month I think, but I didn&#x27;t rush to rebase to get it because honestly I didn&#x27;t want the feature. &lt;br &#x2F;&gt;
I used it back in neovim, and I found it to annoy me more often than help me. An extra &lt;code&gt;&#x2F;&#x2F; &lt;&#x2F;code&gt; &#x2F; &lt;code&gt;# &lt;&#x2F;code&gt; &#x2F; etc to type in is not as much effort as possibly having to &lt;em&gt;fix&lt;&#x2F;em&gt; them. &lt;br &#x2F;&gt;
Additionally, in neovim the operation felt very wonky visually.&lt;&#x2F;p&gt;
&lt;p&gt;The wonkiness is not an issue in helix, as this is a &lt;em&gt;core&lt;&#x2F;em&gt; feature, not something that was tacked on, so that&#x27;s crossed out. &lt;br &#x2F;&gt;
However the &quot;annoying&quot; part may still remain, as after ~1 minute of fiddling with it, I found a bug¹ when you try to extend a comment upwards, when you&#x27;re at the first line in the file:&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;weird-bug.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Interestingly, there is no option to disable this auto-comment-extending behavior.&lt;&#x2F;p&gt;
&lt;p&gt;¹ Around two days after publishing this blog post, the bug is fixed! &lt;br &#x2F;&gt;
This is surprisingly fast response speed for helix — generally things move reeeeeaaaally slowly. &lt;br &#x2F;&gt;
This fills me with determination!&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, there &lt;em&gt;is&lt;&#x2F;em&gt; now an option to disable this behavior 🥳 &lt;br &#x2F;&gt;
Set &lt;code&gt;continue-comments&lt;&#x2F;code&gt; in the &lt;code&gt;[editor]&lt;&#x2F;code&gt; section to &lt;code&gt;false&lt;&#x2F;code&gt;, if you want to.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;path-completions&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#path-completions&quot; aria-label=&quot;Anchor link for: path-completions&quot;&gt;path completions&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Now you get autocomplete for filepaths! :D&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;filepath-completions.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;If you were using my fork prior, you already had these! &lt;br &#x2F;&gt;
I&#x27;ve been following the PR that implements this feature for a month or two, and I had it merged into my fork. &lt;br &#x2F;&gt;
I&#x27;m quite surprised to see it get merged into core! So now that&#x27;s one less responsibility on my fork.&lt;&#x2F;p&gt;
&lt;p&gt;But also, before this point, there was a bug where you could only complete a single filepath on a given line. If you tried to complete another path, the completions wouldn&#x27;t show up. &lt;br &#x2F;&gt;
This is no longer an issue!&lt;&#x2F;p&gt;
&lt;p&gt;This feature is enabled by default, but if you wanted to disable it, set the &lt;code&gt;path-completion&lt;&#x2F;code&gt; option in the &lt;code&gt;[editor]&lt;&#x2F;code&gt; section to false.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;default-comment-token&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#default-comment-token&quot; aria-label=&quot;Anchor link for: default-comment-token&quot;&gt;default comment token&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;For unrecognized languages (if you just open a file with no extension and no inferrable text, for example), the comment token used to be &lt;code&gt;&#x2F;&#x2F;&lt;&#x2F;code&gt;. Now it is &lt;code&gt;#&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Makes sense, considering that more often than not, an unrecognized file is a config file that &lt;em&gt;probably&lt;&#x2F;em&gt; uses &lt;code&gt;#&lt;&#x2F;code&gt; for comments (if it even supports them).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conf-language&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conf-language&quot; aria-label=&quot;Anchor link for: conf-language&quot;&gt;conf &quot;language&quot;&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You might notice that the syntax highlighting for random &lt;code&gt;.conf&lt;&#x2F;code&gt; files is now gone. &lt;br &#x2F;&gt;
This happened because of a commit that (as it says in the commit message) “Fix language configuration for .conf files”. &lt;br &#x2F;&gt;
“Fix” my ass.&lt;&#x2F;p&gt;
&lt;p&gt;Put this in your languages.toml to bring it back:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[[language]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;hocon&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;file-types&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;  &amp;quot;conf&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  { glob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;**&#x2F;src&#x2F;*&#x2F;resources&#x2F;**&#x2F;*.conf&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  { glob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;*scalafmt*.conf&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  { glob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;*scalafix*.conf&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;safer-paste&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#safer-paste&quot; aria-label=&quot;Anchor link for: safer-paste&quot;&gt;safer paste&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;If you use &lt;code&gt;paste&lt;&#x2F;code&gt; in insert mode, that makes an undo &quot;checkpoint&quot;:&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;paste-checkpoint.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;I needed to press &lt;kbd&gt;u&lt;&#x2F;kbd&gt; three times there, to undo the second line. &lt;br &#x2F;&gt;
Previously, a single &lt;kbd&gt;u&lt;&#x2F;kbd&gt; would undo the whole line.&lt;&#x2F;p&gt;
&lt;p&gt;This is pretty great! It&#x27;s somewhat often that I start typing in a line and then paste from my system clipboard, only to realize I pasted in the wrong thing. Now after I undo, I &lt;em&gt;don&#x27;t&lt;&#x2F;em&gt; lose the extra text I typed in before the paste.&lt;&#x2F;p&gt;
&lt;p&gt;About clipboards...&lt;&#x2F;p&gt;
&lt;h1 id=&quot;configurable-clipboard-providers&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#configurable-clipboard-providers&quot; aria-label=&quot;Anchor link for: configurable-clipboard-providers&quot;&gt;configurable clipboard providers&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Previously, helix figured them out automatically. &lt;br &#x2F;&gt;
Now, you have an option to set them explicitly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bit-from-the-docs&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#bit-from-the-docs&quot; aria-label=&quot;Anchor link for: bit-from-the-docs&quot;&gt;bit from the docs:&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;clipboard-provider&lt;&#x2F;code&gt; — Which API to use for clipboard interaction. &lt;br &#x2F;&gt;
One of &lt;code&gt;pasteboard&lt;&#x2F;code&gt; (MacOS), &lt;code&gt;wayland&lt;&#x2F;code&gt;, &lt;code&gt;x-clip&lt;&#x2F;code&gt;, &lt;code&gt;x-sel&lt;&#x2F;code&gt;, &lt;code&gt;win-32-yank&lt;&#x2F;code&gt;, &lt;code&gt;termux&lt;&#x2F;code&gt;, &lt;code&gt;tmux&lt;&#x2F;code&gt;, &lt;code&gt;windows&lt;&#x2F;code&gt;, &lt;code&gt;termcode&lt;&#x2F;code&gt;, &lt;code&gt;none&lt;&#x2F;code&gt;, or a custom command set.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;editor-clipboard-provider-section&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#editor-clipboard-provider-section&quot; aria-label=&quot;Anchor link for: editor-clipboard-provider-section&quot;&gt;&lt;code&gt;[editor.clipboard-provider]&lt;&#x2F;code&gt; Section&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Helix can be configured wither to use a builtin clipboard configuration or to use a provided command. &lt;br &#x2F;&gt;
For instance, setting it to use OSC 52 termcodes, the configuration would be:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[editor]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;clipboard-provider&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;termcode&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Alternatively, Helix can be configured to use arbitary commands for clipboard integration:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[editor.clipboard-provider.custom]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;yank&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { command&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;cat&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,  args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;test.txt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;paste&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { command&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;tee&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,  args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;test.txt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;primary-yank&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { command&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;cat&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,  args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;test-primary.txt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #928374;&quot;&gt; # optional&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;primary-paste&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { command&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;quot;tee&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,  args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;quot;test-primary.txt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #928374;&quot;&gt; # optional&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For custom commands the contents of the yank&#x2F;paste is communicated over stdin&#x2F;stdout.&lt;&#x2F;p&gt;
&lt;a href=&quot;#wither&quot; id=&quot;wither&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;blockquote&gt;
&lt;p&gt;Yes it really said “wither”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is of course cool for the (I think unlikely?) situation if your clipboard provider didn&#x27;t work, but what I find more interesting is the &lt;em&gt;custom&lt;&#x2F;em&gt; clipboard provider. &lt;br &#x2F;&gt;
As you see in the example they specify, you can straight up just use a random file. &lt;br &#x2F;&gt;
Interestingly, that&#x27;s a hack to get your latest register to stay across helix sessions (unless helix deletes the file on exit, which would be mean).&lt;&#x2F;p&gt;
&lt;p&gt;If you use my fork though, you don&#x27;t need to bother doing that, as I merge in a PR that adds persistence to various things, including your default register.&lt;&#x2F;p&gt;
&lt;p&gt;However: the &quot;primary selection&quot; (register &lt;code&gt;*&lt;&#x2F;code&gt;) is something that I never use, so I could potentially change it to give me fairly arbitrary behavior. &lt;br &#x2F;&gt;
I could easily write a script that would act as my &lt;code&gt;*&lt;&#x2F;code&gt; register, and do different things on paste &#x2F; yank.&lt;&#x2F;p&gt;
&lt;p&gt;For the most part, actions like &lt;code&gt;shell_pipe&lt;&#x2F;code&gt;, &lt;code&gt;insert_output&lt;&#x2F;code&gt;, &lt;code&gt;append_ouput&lt;&#x2F;code&gt; along with command harps (my fork&#x27;s feature) already provide you this &quot;easily accessible script&quot; behavior, but maybe you can come up with a strong enough contender that would make sense to put directly as the &lt;code&gt;*&lt;&#x2F;code&gt; register.&lt;&#x2F;p&gt;
&lt;p&gt;Share your ideas with me on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;bsky.app&#x2F;profile&#x2F;axlefublr.bsky.social&quot;&gt;bluesky&lt;&#x2F;a&gt; or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;discord.gg&#x2F;bgVSg362dK&quot;&gt;discord&lt;&#x2F;a&gt;, I would love to hear them.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;configurable-default-register&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#configurable-default-register&quot; aria-label=&quot;Anchor link for: configurable-default-register&quot;&gt;configurable default register&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The default register used to be just &lt;code&gt;&quot;&lt;&#x2F;code&gt;. Used when you don&#x27;t explicitly specify any other register.&lt;&#x2F;p&gt;
&lt;p&gt;But &lt;em&gt;now&lt;&#x2F;em&gt;, there&#x27;s an option in the &lt;code&gt;[editor]&lt;&#x2F;code&gt; section called &lt;code&gt;default-yank-register&lt;&#x2F;code&gt; that you can set to override that.&lt;&#x2F;p&gt;
&lt;p&gt;Aside from path completion, I feel this is the biggest &quot;fuck yes finally!&quot; recent feature.&lt;&#x2F;p&gt;
&lt;p&gt;In neovim, there was some option (don&#x27;t remember lol) to let you use your system clipboard as your default register. So if you set it, you could just &lt;code&gt;y&lt;&#x2F;code&gt; directly into the clipboard and &lt;code&gt;p&lt;&#x2F;code&gt; directly from the clipboard.&lt;&#x2F;p&gt;
&lt;p&gt;I used it, actually! And I loved it. &lt;br &#x2F;&gt;
And now, helix has it too 🥳&lt;&#x2F;p&gt;
&lt;p&gt;However, unsurprisingly, it&#x27;s &lt;em&gt;better&lt;&#x2F;em&gt; — you aren&#x27;t restricted to just set the &lt;code&gt;+&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;*&lt;&#x2F;code&gt; registers as your default ones, you can use whichever you want! &lt;br &#x2F;&gt;
It could be just &lt;code&gt;a&lt;&#x2F;code&gt;, or even the &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; register, terrifyingly: that would give you the behavior that all yanks set your current search.&lt;&#x2F;p&gt;
&lt;p&gt;Or remember that custom clipboard provider feature from the last section? Nobody is stopping you from combining these two features, and setting your default register to behave differently somehow. &lt;br &#x2F;&gt;
Default register set to &lt;code&gt;*&lt;&#x2F;code&gt;, and default provider for &lt;code&gt;*&lt;&#x2F;code&gt; is your custom script. ??? -&amp;gt; profit.&lt;&#x2F;p&gt;
&lt;p&gt;Currently, &lt;kbd&gt;y&lt;&#x2F;kbd&gt;¹ yanks to default register for me, and &lt;kbd&gt;Y&lt;&#x2F;kbd&gt; to the system clipboard. It was more of a workaround than preferred solution, since now I&#x27;ll just set &lt;code&gt;default-yank-register&lt;&#x2F;code&gt; to &lt;code&gt;+&lt;&#x2F;code&gt; to sync it to my clipboard, and I&#x27;ll never need to worry about it again 🥳&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;¹ this is technically a lie, because it&#x27;s &lt;kbd&gt;s&lt;&#x2F;kbd&gt; and &lt;kbd&gt;S&lt;&#x2F;kbd&gt; that are my yanking hotkeys (I hate pressing &lt;kbd&gt;y&lt;&#x2F;kbd&gt;), &lt;br &#x2F;&gt;
but the example would be less clear if I said it to begin with&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Keep in mind, the default register using your clipboard directly &lt;em&gt;may introduce overhead&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
Meaning: some operations, especially when you yank &#x2F; paste in bulk, may slow down; sometimes considerably. &lt;br &#x2F;&gt;
But I&#x27;m saying this from experience in &lt;em&gt;neovim&lt;&#x2F;em&gt;, and even then it was only noticeable in the most obscene of situations. &lt;br &#x2F;&gt;
So, it&#x27;s something to consider, but not something to particularly worry about.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;word-bounded-autosearch&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#word-bounded-autosearch&quot; aria-label=&quot;Anchor link for: word-bounded-autosearch&quot;&gt;word-bounded autosearch&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;kbd&gt;*&lt;&#x2F;kbd&gt; lets you search for your selection. But it slightly changed!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Now&lt;&#x2F;em&gt; it places &lt;code&gt;\b&lt;&#x2F;code&gt; around the selection to only match it word-bounded. In other words, if you &lt;kbd&gt;*&lt;&#x2F;kbd&gt; on &lt;code&gt;word&lt;&#x2F;code&gt;, you will no longer match &lt;code&gt;wordword&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The default behavior of &lt;kbd&gt;*&lt;&#x2F;kbd&gt; changed to the new action called &lt;code&gt;search_selection_detect_word_boundaries&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
The &lt;em&gt;old&lt;&#x2F;em&gt; behavior is in the action called &lt;code&gt;search_selection&lt;&#x2F;code&gt; and can be accessed by pressing &lt;kbd&gt;alt+*&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Arrest me: I was &lt;em&gt;just&lt;&#x2F;em&gt; booting up to complain that I don&#x27;t like this new default behavior because &lt;code&gt;\b&lt;&#x2F;code&gt; doesn&#x27;t work for non-word characters... &lt;br &#x2F;&gt;
But they thought of this!&lt;&#x2F;p&gt;
&lt;p&gt;If you select &lt;code&gt;*just*&lt;&#x2F;code&gt; and press &lt;kbd&gt;*&lt;&#x2F;kbd&gt;, it will search for &lt;code&gt;*just*&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
If you select &lt;code&gt;just&lt;&#x2F;code&gt; and press &lt;kbd&gt;*&lt;&#x2F;kbd&gt;, it will search for &lt;code&gt;\bjust\b&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So it&#x27;s actually being smart about word boundaries, and only applies them when they would &lt;em&gt;work&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
Bravo, Vince.&lt;&#x2F;p&gt;
&lt;a href=&quot;#bravo&quot; id=&quot;bravo&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;All of these new features are now also available in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;my fork&lt;&#x2F;a&gt; 🥳&lt;&#x2F;p&gt;
&lt;p&gt;I liked writing this blog post, so I might continue making these &quot;recent new helix features&quot; blog posts in the future.&lt;&#x2F;p&gt;
&lt;p&gt;Want to make sure to not miss them? Add &lt;a href=&quot;&#x2F;rss.xml&quot;&gt;this link&lt;&#x2F;a&gt; to your RSS reader!&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t have an RSS reader? I recommend &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;guyfedwards&#x2F;nom&quot;&gt;nom&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>my usb drive experience</title>
          <pubDate>Fri, 15 Nov 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/my-usb-drive-experience/</link>
          <guid>https://axlefublr.github.io/my-usb-drive-experience/</guid>
          <description xml:base="https://axlefublr.github.io/my-usb-drive-experience/">&lt;p&gt;I hate buffering, so I download practically every youtube video I watch using yt-dlp. &lt;br &#x2F;&gt;
That&#x27;s all fun and great, however my 256gb laptop is slowly running out of space! &lt;br &#x2F;&gt;
Well... that&#x27;s a bit of an overestimation: I have hours upon hours of content downloaded and am still at only 71% usage, but that number freaks me out regardless!&lt;&#x2F;p&gt;
&lt;p&gt;You may reasonably suggest to upgrade my SSD to something like 1 terabytes. &lt;br &#x2F;&gt;
However, I find it boring! Often times when I solve some issue, I do it with a completely different agenda in mind.&lt;&#x2F;p&gt;
&lt;a href=&quot;#suboptimal&quot; id=&quot;suboptimal&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;If I upgrade the SSD, I just end up never having to worry about storage again (I keep everything pretty clean, so 1tb is more than enough) and learn &lt;em&gt;nothing&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
But if I try to solve the issue with a &lt;em&gt;usb drive&lt;&#x2F;em&gt;, now &lt;em&gt;that&#x27;s&lt;&#x2F;em&gt; interesting.&lt;&#x2F;p&gt;
&lt;p&gt;I know Linux&#x27;s mechanics for mounting a drive, but mostly on paper — I&#x27;ve done them before, but they aren&#x27;t something that I do often enough to put deeply into my workflow. If I &lt;em&gt;have to&lt;&#x2F;em&gt; use a usb drive, I&#x27;ll learn about all the steps surrounding it more deeply, so I get a &quot;learning benefit&quot; by trading in effectiveness of the solution, lol.&lt;&#x2F;p&gt;
&lt;a href=&quot;#simple-parts&quot; id=&quot;simple-parts&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;As I&#x27;ve made clear, I don&#x27;t have deep knowledge, but let&#x27;s go through the simple parts that you may want to know, if you didn&#x27;t already!&lt;&#x2F;p&gt;
&lt;p&gt;On windows, new drives appear separately, as new drives. With their own letter and everything. If you get beyond drive &lt;code&gt;Z&lt;&#x2F;code&gt;, your computer explodes. Simple stuff.&lt;&#x2F;p&gt;
&lt;p&gt;Linux does this differently! You don&#x27;t get another &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; or anything like that — &lt;em&gt;you&lt;&#x2F;em&gt; get to decide where the (usb) drive lives by &lt;em&gt;mounting&lt;&#x2F;em&gt; it. You say to the filesystem: &quot;hey, act like this usb drive is located here&quot;.&lt;&#x2F;p&gt;
&lt;a href=&quot;#mounting&quot; id=&quot;mounting&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; mount &#x2F;dev&#x2F;sda1 &#x2F;mnt&#x2F;usb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looks like a pretty simple command! What was most non-obvious to me in it, is the &lt;em&gt;directories&lt;&#x2F;em&gt; passed.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;What in the living and dying hell is &lt;code&gt;&#x2F;dev&#x2F;sda1&lt;&#x2F;code&gt;?&quot; — that is our usb drive! Well... saying that is a bit misleading. That name is not at all guaranteed and might be different for you, and that&#x27;s if the drive got recognized to begin with!&lt;&#x2F;p&gt;
&lt;a href=&quot;#lsblk&quot; id=&quot;lsblk&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;So, let&#x27;s call &lt;code&gt;lsblk&lt;&#x2F;code&gt; in our terminal and look at the output to try to find our drive:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sda           8:0    1 230.5G  0 disk &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└─sda1        8:1    1 230.5G  0 part &#x2F;mnt&#x2F;usb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;nvme0n1     259:0    0 238.5G  0 disk &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├─nvme0n1p1 259:1    0  1000M  0 part &#x2F;efi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└─nvme0n1p2 259:2    0 237.5G  0 part &#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Don&#x27;t worry, it&#x27;s confusing to me too! -1 clue what &lt;code&gt;MAJ:MIN&lt;&#x2F;code&gt; means, and &lt;code&gt;RM&lt;&#x2F;code&gt; is a wonder to me as well. Forget about &lt;code&gt;RO&lt;&#x2F;code&gt;. Anyway, I&#x27;m going to focus on the part that&#x27;s going to be useful to you first.&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;code&gt;NAME&lt;&#x2F;code&gt; column, thingies are shown in a tree structure. &lt;br &#x2F;&gt;
&lt;code&gt;nvme0n1&lt;&#x2F;code&gt; is the name of my SSD drive! and &lt;code&gt;sda&lt;&#x2F;code&gt; is the name of the usb disk. Yipee 🥳&lt;&#x2F;p&gt;
&lt;a href=&quot;#tree-structure&quot; id=&quot;tree-structure&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;However, there&#x27;s still this tree structure. This confused me, but now I finally realize what&#x27;s happening: the items that are branches (with the &lt;code&gt;└&lt;&#x2F;code&gt; before them) are &lt;em&gt;partitions&lt;&#x2F;em&gt; of the above drive. &lt;em&gt;These&lt;&#x2F;em&gt; are what you should be pointing at when trying to specify a drive somewhere, &lt;em&gt;not&lt;&#x2F;em&gt; that parent item.&lt;&#x2F;p&gt;
&lt;p&gt;So, what we did so far is the following: inserted the usb drive into some port, executed &lt;code&gt;lsblk&lt;&#x2F;code&gt; and found a drive that isn&#x27;t our SSD. Then looked at all the partitions (branches) it has (may have more than 1 potentially) and took &lt;em&gt;that&lt;&#x2F;em&gt; as the thing that we&#x27;ll be calling our usb drive.&lt;&#x2F;p&gt;
&lt;a href=&quot;#arbitrary-mount-point&quot; id=&quot;arbitrary-mount-point&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;That &lt;code&gt;&#x2F;mnt&#x2F;usb&lt;&#x2F;code&gt; directory is actually pretty arbitrary! The &lt;code&gt;&#x2F;mnt&lt;&#x2F;code&gt; directory is a conventional place where you can &lt;strong&gt;m&lt;&#x2F;strong&gt;ou&lt;strong&gt;nt&lt;&#x2F;strong&gt; your various drives. &lt;br &#x2F;&gt;
It is not the only place however, I &lt;em&gt;believe&lt;&#x2F;em&gt; ext4 (the linux filesystem you&#x27;re probably using) allows you to mount things anywhere.&lt;&#x2F;p&gt;
&lt;p&gt;So, in the &lt;code&gt;&#x2F;mnt&lt;&#x2F;code&gt; directory I created a directory called &lt;code&gt;usb&lt;&#x2F;code&gt;. Just makes sense to name it that way, you can name it whatever you want!&lt;&#x2F;p&gt;
&lt;p&gt;Keep in mind that &lt;code&gt;&#x2F;mnt&lt;&#x2F;code&gt; is restricted, so you&#x27;ll have to create &lt;code&gt;usb&#x2F;&lt;&#x2F;code&gt; with elevated privileges:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; mkdir &#x2F;mnt&#x2F;usb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;a href=&quot;#restriction&quot; id=&quot;restriction&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Because &lt;code&gt;&#x2F;mnt&lt;&#x2F;code&gt; is restricted, &lt;code&gt;&#x2F;mnt&#x2F;usb&#x2F;&lt;&#x2F;code&gt; is going to be restricted too. Considering that this our lovely personal usb drive, it makes sense to &lt;em&gt;own&lt;&#x2F;em&gt; it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; chown username:username &#x2F;mnt&#x2F;usb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Viola, now the directory is actually ours 🥰. I sure hope you replaced &lt;code&gt;username&lt;&#x2F;code&gt; with your &lt;em&gt;actual&lt;&#x2F;em&gt; username!&lt;&#x2F;p&gt;
&lt;a href=&quot;#we-can-start-now&quot; id=&quot;we-can-start-now&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;After explaining what the directories mean, now &lt;code&gt;sudo mount &#x2F;dev&#x2F;sda1 &#x2F;mnt&#x2F;usb&lt;&#x2F;code&gt; makes a bit more sense. &lt;br &#x2F;&gt;
We finally can start actually using our usb drive, as if it&#x27;s just a normal directory on our filesystem!&lt;&#x2F;p&gt;
&lt;a href=&quot;#massive&quot; id=&quot;massive&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The 61 gigabytes of content I had downloaded, I now started moving to my shiny new drive.&lt;&#x2F;p&gt;
&lt;p&gt;Quickly issues started to arise, and my mirror rolled its eyes 🙄 when I said &quot;I told you this would be a learning experience!&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Sixty one gigabytes of data is quite a lot! Understandable that it would take some time to move. But it was getting ridiculous! &lt;br &#x2F;&gt;
In my very rough count, it took TWO whole minutes to move a single gigabyte. The drive I bought is usb 3.1 so I was flabbergasted, but brushed it off as &quot;damn I guess usbs are that slow still&quot;. &lt;br &#x2F;&gt;
The last time I needed to use a usb drive &lt;em&gt;not&lt;&#x2F;em&gt; to install linux was back on windows, so I had no recollection of a good transfer speed. &lt;br &#x2F;&gt;
However, in an interesting turn of events, this turned out to be a chehov&#x27;s gun. Yes I am making a cliffhanger in a blog post, what about it &amp;gt;:D&lt;&#x2F;p&gt;
&lt;a href=&quot;#fine&quot; id=&quot;fine&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I don&#x27;t need to move a whole ass 61gb of data often, if at all, so this slow transfer speed seemed to be an okay-ish tradeoff for the extra space I now get. &lt;br &#x2F;&gt;
My internet speed will be the bigger bottleneck anyway.&lt;&#x2F;p&gt;
&lt;p&gt;After ~4 hours (or so it felt), the moving &lt;em&gt;finally&lt;&#x2F;em&gt; finished. I excitedly went ahead to download more youtube videos, now to the &lt;em&gt;usb drive&lt;&#x2F;em&gt;, rather than my SSD.&lt;&#x2F;p&gt;
&lt;p&gt;Exciting! &lt;br &#x2F;&gt;
As I download the new videos, I decide to watch one I already have downloaded, at the same time. &lt;br &#x2F;&gt;
After a while, I notice a &lt;em&gt;horrifying fact&lt;&#x2F;em&gt;... There&#x27;s buffering now! &lt;br &#x2F;&gt;
What the fuck? The whole reason I download all youtube videos I watch is to &lt;em&gt;avoid&lt;&#x2F;em&gt; buffering.&lt;&#x2F;p&gt;
&lt;a href=&quot;#fucked&quot; id=&quot;fucked&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;So I guess write speed is a bottleneck in the place that matters more: my watching experience... 😭&lt;&#x2F;p&gt;
&lt;p&gt;Well, let&#x27;s think about this: currently I have 6 videos downloading. All of them are written to the usb. &lt;br &#x2F;&gt;
I&#x27;m not sure how read vs write conflict, but I&#x27;m sure writing that much introduces some congestion. &lt;br &#x2F;&gt;
I guess I just have to download videos while not watching them at the same time! &lt;br &#x2F;&gt;
That&#x27;s kinda bad, but I can easily get used to it, no big deal.&lt;&#x2F;p&gt;
&lt;p&gt;After my downloads all finished, I decided to test by watching another downloaded youtube video. Surely now the buffering is gone; there&#x27;s no writes coming into the usb! &lt;br &#x2F;&gt;
Oh my god... I am horrified to discover that I &lt;em&gt;still&lt;&#x2F;em&gt; have buffering... It&#x27;s &lt;em&gt;maybe&lt;&#x2F;em&gt; not as bad, but this thought may just be powered entirely by bias.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start another chehov&#x27;s gun here, and talk about something that &lt;em&gt;seems&lt;&#x2F;em&gt; unrelated.&lt;&#x2F;p&gt;
&lt;a href=&quot;#lights&quot; id=&quot;lights&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I despise when hardware, like my laptop, earphones, headphones, speakers, power switches, phones, have some lights on them. &lt;br &#x2F;&gt;
The reason for them to exist is to tell you information, like the charge percentage, connection state, on &#x2F; off position. &lt;br &#x2F;&gt;
However, I&#x27;m autistic! Those random lights can be a real bother when I&#x27;m trying to sleep, and yet my room lights up.&lt;&#x2F;p&gt;
&lt;p&gt;When I first inserted my new usb drive, I was horrified to find out that it has a light on it too... &lt;br &#x2F;&gt;
I guess I should&#x27;ve checked for that, but the design of the usb drive had nothing to suggest a light; &lt;br &#x2F;&gt;
matter of fact, the light is &lt;em&gt;inside&lt;&#x2F;em&gt; of the usb, in a sorta awkward fashion.&lt;&#x2F;p&gt;
&lt;p&gt;I would never expect that I would not only &lt;em&gt;like&lt;&#x2F;em&gt; this light, but also find it useful.&lt;&#x2F;p&gt;
&lt;p&gt;I eventually naturally noticed that it stays solid some times, and blinks other times. &lt;br &#x2F;&gt;
This &lt;em&gt;has to&lt;&#x2F;em&gt; mean something, right? Turns out that if it&#x27;s blinking, some io operations are being done with the usb drive; if it&#x27;s solid, none are happening.&lt;&#x2F;p&gt;
&lt;p&gt;Nope, surprisingly enough I didn&#x27;t read the manual on the usb drive (&lt;code&gt;HS-USB-M220P&#x2F;256G&#x2F;U3&lt;&#x2F;code&gt;); I discovered this behavior via another way:&lt;&#x2F;p&gt;
&lt;p&gt;I remembered the &lt;code&gt;sync&lt;&#x2F;code&gt; command on linux. It flushes the read&#x2F;write data to make sure it reaches its destination, &lt;em&gt;finalizing&lt;&#x2F;em&gt; all the read-write caches.&lt;&#x2F;p&gt;
&lt;p&gt;As I was watching that youtube video I downloaded, with no other downloads happening at the moment, the light &lt;em&gt;was&lt;&#x2F;em&gt; flashing. &lt;br &#x2F;&gt;
Fair enough, it&#x27;s reading from the drive to let me watch the current video. So I close it, but still see it flashing even after waiting for a couple of seconds. &lt;br &#x2F;&gt;
I do &lt;code&gt;sync&lt;&#x2F;code&gt; and eventually the flashing goes away 🤯 &lt;br &#x2F;&gt;
So &lt;em&gt;maybe&lt;&#x2F;em&gt;, the weird buffering issue happened because of write caches staying for too long?&lt;&#x2F;p&gt;
&lt;p&gt;Nope. Cool guess though.&lt;&#x2F;p&gt;
&lt;p&gt;We handled chehov&#x27;s gun #2, but didn&#x27;t actually move to the solution.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s check up on chehov&#x27;s gun #1! What about those super slow write speeds anyway?&lt;&#x2F;p&gt;
&lt;a href=&quot;#specs&quot; id=&quot;specs&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;After not being to fix this buffering issue, it made me think: &lt;br &#x2F;&gt;
I bought my laptop 2-3 years ago, for a pretty solid price, &lt;em&gt;new&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
How the fuck would it only have usb 2.0 ports? &lt;br &#x2F;&gt;
That sure sounds unlikely!&lt;&#x2F;p&gt;
&lt;p&gt;So this time I &lt;em&gt;do&lt;&#x2F;em&gt; google the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.asus.com&#x2F;laptops&#x2F;for-home&#x2F;everyday-use&#x2F;asus-m515-amd-ryzen-5000-series&#x2F;techspec&#x2F;&quot;&gt;specs of my laptop&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
Europe! I &lt;em&gt;do&lt;&#x2F;em&gt; have a usb 3.x port!&lt;&#x2F;p&gt;
&lt;p&gt;You might reasonably ask &quot;how the hell do you not know that already?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Good question!&lt;&#x2F;p&gt;
&lt;p&gt;I noticed a long time ago that usb 3.x ports are colored blue, to make them easy to tell apart from usb 2.0. &lt;br &#x2F;&gt;
This seemed so consistent, that I simply ignored one of my ports as a possible solution.&lt;&#x2F;p&gt;
&lt;p&gt;I have nothing to lose by trying to prove myself wrong, so I insert the usb into the one port I haven&#x27;t tried, mount it, and try moving a big ass video file, that would usually take 2+ minutes to move.&lt;&#x2F;p&gt;
&lt;p&gt;Well holy shit! It&#x27;s moving &lt;em&gt;waaayyy&lt;&#x2F;em&gt; faster! Yes! This is definitely a 3.x port! &lt;br &#x2F;&gt;
(however it is still massively slower than what I expected out of 3.x).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;aha-chehov-s-gun-1-solved-everything&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#aha-chehov-s-gun-1-solved-everything&quot; aria-label=&quot;Anchor link for: aha-chehov-s-gun-1-solved-everything&quot;&gt;aha! chehov&#x27;s gun #1 solved everything!&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Right?..&lt;&#x2F;p&gt;
&lt;p&gt;Wrong 😭&lt;&#x2F;p&gt;
&lt;p&gt;Sure, moving stuff is now way faster, and I got a sense of regret due to the 4 hours of useless extra waiting, &lt;br &#x2F;&gt;
but fascinatingly enough, I &lt;em&gt;still&lt;&#x2F;em&gt; had weird pauses in mpv.&lt;&#x2F;p&gt;
&lt;p&gt;And as always, A™ Configuration™ Option™ saved the day.&lt;&#x2F;p&gt;
&lt;p&gt;Turns out if you set &lt;code&gt;cache=yes&lt;&#x2F;code&gt; in your mpv config file, it will automatically prefetch the video you&#x27;re watching wayyyy forwards, completely eliminating the pauses (that I call buffering), &lt;em&gt;&lt;strong&gt;even&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; if you&#x27;re also downloading like 6 videos at the same time. &lt;br &#x2F;&gt;
God I love mpv 😩 &#x2F;srs&lt;&#x2F;p&gt;
&lt;p&gt;Yipee 🥳&lt;&#x2F;p&gt;
&lt;h1 id=&quot;would-be-better-to-know-about-this-prior-wouldn-t-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#would-be-better-to-know-about-this-prior-wouldn-t-it&quot; aria-label=&quot;Anchor link for: would-be-better-to-know-about-this-prior-wouldn-t-it&quot;&gt;would be better to know about this prior, wouldn&#x27;t it?&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Nope, not really!&lt;&#x2F;p&gt;
&lt;p&gt;I decided to buy a usb drive specifically to run myself into issues like all of these, and &lt;em&gt;learn&lt;&#x2F;em&gt; things by solving them. &lt;br &#x2F;&gt;
I succeeded in that exact goal SPECTACULARLY. The decision went &lt;em&gt;exactly&lt;&#x2F;em&gt; according to plan.&lt;&#x2F;p&gt;
&lt;p&gt;First, I now know that I have a usb 3.x port, and that the other two are usb 2.0.&lt;&#x2F;p&gt;
&lt;p&gt;Then, for once I like a light in my hardware! &lt;br &#x2F;&gt;
Thankfully, it turns off when the laptop goes to sleep (thank god). &lt;br &#x2F;&gt;
I like it now because of how nice it feels to &lt;em&gt;have&lt;&#x2F;em&gt; the information of io operations given to me at all times. &lt;br &#x2F;&gt;
If I notice the light blinking at a time where I don&#x27;t expect, it&#x27;s something that I can look into &#x2F; investigate, rather than not know at all. &lt;br &#x2F;&gt;
If you saw my window manager bar, you&#x27;d say &quot;yep checks out&quot;. (I have like a billion widgets)&lt;&#x2F;p&gt;
&lt;p&gt;Knowing the io operation information also made me &lt;em&gt;accept&lt;&#x2F;em&gt; a lesson I always thought to be unecessary bullshit.&lt;&#x2F;p&gt;
&lt;p&gt;Since childhood, back on windows, people around me always said to right click the usb drive and click &quot;safe remove&quot;. &lt;br &#x2F;&gt;
I did it at first, of course, but after a while I noticed that it&#x27;s just completely useless. Does seemingly nothing.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Now&lt;&#x2F;em&gt; that I actually see the io operations by the light, I won&#x27;t just pull out the usb all willy-nilly: it&#x27;s &lt;em&gt;clear&lt;&#x2F;em&gt; that I would be fucking over &lt;em&gt;something&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So what I now do is first &lt;code&gt;sync&lt;&#x2F;code&gt;, and then &lt;code&gt;sudo umount &#x2F;mnt&#x2F;usb&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
For a shortcut that does &lt;em&gt;both&lt;&#x2F;em&gt; at the same time: &lt;code&gt;sudo eject &#x2F;mnt&#x2F;usb&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I sure learnt a lot! And still have the opportunity to learn more: experimenting with the drive&#x27;s filesystem, figuring out an auto-mounting solution (requiring sudo every time will, I&#x27;m sure, get annoying), or maybe another problem I don&#x27;t yet realize I have!&lt;&#x2F;p&gt;
&lt;p&gt;And all these reasons are why it&#x27;s sometimes reasonable to go for the worse solution, if you feel that it will lead you to something more important! :3&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>magazines</title>
          <pubDate>Sun, 03 Nov 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/magazines/</link>
          <guid>https://axlefublr.github.io/magazines/</guid>
          <description xml:base="https://axlefublr.github.io/magazines/">&lt;p&gt;I came up with a concept that completely revolutionized a &lt;em&gt;lot&lt;&#x2F;em&gt; of my workflow.&lt;&#x2F;p&gt;
&lt;p&gt;I introduce to you: magazines™!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-basics&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-basics&quot; aria-label=&quot;Anchor link for: the-basics&quot;&gt;the basics&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Each magazine is just a normal file that has a one letter file name, from a to z, from A to Z, and from 1 to 9. &lt;br &#x2F;&gt;
All magazines are located in a single directory called &lt;code&gt;magazines&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The name doesn&#x27;t really have meaning, I just happened to be obsessed with guns at the time of coming up the concept&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I have different &lt;em&gt;actions&lt;&#x2F;em&gt; I can do on any magazine. An &quot;action&quot; is just some shell function that interacts with a file in some way.&lt;&#x2F;p&gt;
&lt;p&gt;And finally, I have chord mappings that make me pick an action, and then a magazine to act on. &lt;br &#x2F;&gt;
All the magazines use either a letter or a digit for their filenames, to mimic the hotkeys I use to choose them.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;actions&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#actions&quot; aria-label=&quot;Anchor link for: actions&quot;&gt;actions&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;All action picking hotkeys use &lt;em&gt;left&lt;&#x2F;em&gt; shift + a &lt;em&gt;left&lt;&#x2F;em&gt; side key. This is because when typing, I will always use the right shift for left side keys, so I get to have very accessible hotkeys specifically for magazine actions. &lt;br &#x2F;&gt;
After I press the action hotkey, I press a letter (or digit) key, to pick the magazine I want to execute the action on.&lt;&#x2F;p&gt;
&lt;p&gt;This is a pretty simple concept! But it&#x27;s so flexible &lt;em&gt;specifically&lt;&#x2F;em&gt; because it&#x27;s so simple.&lt;&#x2F;p&gt;
&lt;p&gt;Considering that all actions &lt;em&gt;just&lt;&#x2F;em&gt; act on some filepath, let&#x27;s go over the actions I can do!&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;use &lt;code&gt;rofi&lt;&#x2F;code&gt; to type in a line of text, and overwrite a file with that text (&lt;kbd&gt;lshift+alt+s&lt;&#x2F;kbd&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;1, but append the line rather than overwrite with it (&lt;kbd&gt;lshift+s&lt;&#x2F;kbd&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;copy the text in a file to my clipboard (&lt;kbd&gt;lshift+c&lt;&#x2F;kbd&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;truncate the file (remove its contents, but don&#x27;t delete the actual file) (&lt;kbd&gt;lshift+r&lt;&#x2F;kbd&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;3 + 4 — this is basically a &quot;cut&quot; action (&lt;kbd&gt;lshift+alt+c&lt;&#x2F;kbd&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;take the contents of my clipboard, and overwrite a file with them (&lt;kbd&gt;lshift+alt+v&lt;&#x2F;kbd&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;6, but append the contents rather than overwrite with them (&lt;kbd&gt;lshift+v&lt;&#x2F;kbd&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;use &lt;code&gt;rofi&lt;&#x2F;code&gt; to pick &lt;em&gt;a line&lt;&#x2F;em&gt; from a file to &lt;em&gt;remove&lt;&#x2F;em&gt; and copy to my clipboard (or, to &lt;em&gt;cut&lt;&#x2F;em&gt; to my clipboard basically) (&lt;kbd&gt;lshift+f&lt;&#x2F;kbd&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;use &lt;code&gt;rofi&lt;&#x2F;code&gt; to pick &lt;em&gt;a line&lt;&#x2F;em&gt; from a file to copy to my clipboard (like 8, but doesn&#x27;t remove the line) (&lt;kbd&gt;lshift+alt+f&lt;&#x2F;kbd&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;open a floating terminal, in which the file is opened in helix, to get the full power of my editor in a fast way (&lt;kbd&gt;lshift+d&lt;&#x2F;kbd&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Further in the gist I&#x27;ll refer to actions by their shortened name, with a superscript number next to it, that specifies the index in this list.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;autocommitting&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#autocommitting&quot; aria-label=&quot;Anchor link for: autocommitting&quot;&gt;autocommitting&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;All actions that modify a file, also &lt;em&gt;commit&lt;&#x2F;em&gt; it with git — the &lt;code&gt;magazines&lt;&#x2F;code&gt; directory is a git repo. &lt;br &#x2F;&gt;
This way, I have a &lt;em&gt;very&lt;&#x2F;em&gt; easily traversable history, that doubles as a backup. &lt;br &#x2F;&gt;
As long as something &lt;em&gt;has been&lt;&#x2F;em&gt; in a magazine, I will be able to restore it if necessary.&lt;&#x2F;p&gt;
&lt;p&gt;Commits are done automatically by all actions that modify a file; however I can still modify magazines elsehow. &lt;br &#x2F;&gt;
I have hotkeys in helix to open each magazine in the already existing editor session (different from the 10th action, because I&#x27;m not opening a new floating terminal window). &lt;br &#x2F;&gt;
When editing the magazines like this, it&#x27;s not an action so can&#x27;t be a convenient trigger for an autocommit. &lt;br &#x2F;&gt;
That&#x27;s why there&#x27;s an 11th action that &lt;em&gt;just&lt;&#x2F;em&gt; commits a magazine.&lt;&#x2F;p&gt;
&lt;p&gt;All the leftover changes that &lt;em&gt;still&lt;&#x2F;em&gt; didn&#x27;t get committed, are collected together into a single commit, daily. &lt;br &#x2F;&gt;
So at the absolute worst, I have a day old backup for all magazines.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;most-important-magazines&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#most-important-magazines&quot; aria-label=&quot;Anchor link for: most-important-magazines&quot;&gt;most important magazines&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Let me go through some of my actively used magazines and their purpose, to explain how this system helps me keep track of things in an easy way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;magazine-r&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#magazine-r&quot; aria-label=&quot;Anchor link for: magazine-r&quot;&gt;magazine r&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;...stores all things I want to read. &quot;read&quot; is used pretty loosely here, as the file contains a bunch of different stuff I basically want to &lt;em&gt;get to&lt;&#x2F;em&gt;, while not necessarily being a &quot;task&quot; that I can &lt;em&gt;do&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s part of what it contains currently:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;!# gh cli (gh-issue-develop)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;!&amp;amp; Hugo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# pandoc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# string-replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ loago-based workflow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ magazines&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;% how to remove background in krita&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;% can you &amp;quot;close all other windows&amp;quot; to close the main window from an overlay window in kitty?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;amp; qalculate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;amp; zbarimg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pcre or whatever regex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;the sliding window technique&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:&#x2F;&#x2F;matklad.github.io&#x2F;2021&#x2F;07&#x2F;09&#x2F;inline-in-rust.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:&#x2F;&#x2F;www.howtogeek.com&#x2F;how-to-see-beautiful-git-project-stats-in-your-terminal&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This seems like a hotpot but it&#x27;s pretty intentional. &lt;br &#x2F;&gt;
&lt;code&gt;#&lt;&#x2F;code&gt; marks &lt;em&gt;docs&lt;&#x2F;em&gt; that I want to read (with the part I left off on written down in &lt;code&gt;()&lt;&#x2F;code&gt;), &lt;br &#x2F;&gt;
&lt;code&gt;$&lt;&#x2F;code&gt; is gists &#x2F; blog posts that I want to write (&lt;code&gt;magazines&lt;&#x2F;code&gt; is this one!!), &lt;br &#x2F;&gt;
&lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; is for &lt;em&gt;programs&lt;&#x2F;em&gt; that I want to discover, &lt;br &#x2F;&gt;
&lt;code&gt;%&lt;&#x2F;code&gt; is for questions I want to discover, figure out, or take in.&lt;&#x2F;p&gt;
&lt;a href=&quot;#seemingly-simple&quot; id=&quot;seemingly-simple&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The two questions I have there seem simple, but they may stay there for a while because they&#x27;re more loaded questions than they seem. &lt;br &#x2F;&gt;
I&#x27;m sure there&#x27;s more than a single way to remove the background in krita, with each being useful in a different situation — I&#x27;d want to focus on learning this properly. &lt;br &#x2F;&gt;
Even more the case with &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;why-i-hate-kitty&#x2F;&quot;&gt;kitty&lt;&#x2F;a&gt; — trying to solve this question might move me to come up with a different window managing concept that I&#x27;ll then spend three more hours on. &lt;br &#x2F;&gt;
Never underestimate a question, especially if you&#x27;re autistic like me.&lt;&#x2F;p&gt;
&lt;a href=&quot;#vimium-c&quot; id=&quot;vimium-c&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I usually use the append² action for this magazine.&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gdh1995&#x2F;vimium-c&quot;&gt;vimium c&lt;&#x2F;a&gt;, I can copy links I see on the screen to my clipboard, using my keyboard. &lt;br &#x2F;&gt;
The various rogue links you see without a section header are usually added by copying a link that way, and using the append clipboard⁷ action.&lt;&#x2F;p&gt;
&lt;p&gt;Sectioning things is pretty nice, but has an additional benefit that I haven&#x27;t yet made clear. &lt;br &#x2F;&gt;
The commit¹¹ action has extra functionality to it: I can pick filepaths that are automatically &lt;em&gt;sorted&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
The section headers intentionally use ascii symbols that go before letters, so that they would appear first in the file after it gets automtically sorted.&lt;&#x2F;p&gt;
&lt;p&gt;Going in and editing the code for the commit action every time I want to autosort another magazine would go against my principles. &lt;br &#x2F;&gt;
This is why I use &lt;em&gt;another&lt;&#x2F;em&gt; magazine to solve this!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;magazine-o&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#magazine-o&quot; aria-label=&quot;Anchor link for: magazine-o&quot;&gt;magazine O&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;...contains all the filepaths that I want to automatically sort:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;~&#x2F;.local&#x2F;share&#x2F;magazine&#x2F;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;~&#x2F;.local&#x2F;share&#x2F;magazine&#x2F;r&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So if I decide to autosort another magazine on commit, I can just add its filepath there! :D&lt;&#x2F;p&gt;
&lt;p&gt;This autosort behavior explains the reasoning behind &lt;code&gt;!&lt;&#x2F;code&gt; before some section headers: &lt;code&gt;!&lt;&#x2F;code&gt; is the first printable character in ascii, excepting space, with its decimal index being 33. So it&#x27;s guaranteed to come first. &lt;br &#x2F;&gt;
I use it for reading tasks that I want to get to &lt;em&gt;first&lt;&#x2F;em&gt;, before any other ones.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;magazine-p&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#magazine-p&quot; aria-label=&quot;Anchor link for: magazine-p&quot;&gt;magazine P&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;...is similar in concept to &lt;code&gt;O&lt;&#x2F;code&gt;: filepaths listed in magazine &lt;code&gt;P&lt;&#x2F;code&gt; are automatically made &lt;em&gt;unique&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
If a magazine path is listed in magazine &lt;code&gt;P&lt;&#x2F;code&gt;, there will never be duplicate lines in the former.&lt;&#x2F;p&gt;
&lt;p&gt;I could opt to join &lt;code&gt;O&lt;&#x2F;code&gt; and &lt;code&gt;P&lt;&#x2F;code&gt;, but I might want to sort a file without deduplicating lines, and may want to deduplicate lines without sorting (which you can achieve with this monstrosity: &lt;code&gt;awk &#x27;!seen[$0]++&#x27;&lt;&#x2F;code&gt;), so I keep them separate.&lt;&#x2F;p&gt;
&lt;a href=&quot;#dynamic&quot; id=&quot;dynamic&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The above examples are magazines that are fairly dynamic and moving, but there&#x27;s use in magazines that are fairly static, and are made mostly to access the information faster, than necessarily change it often.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;magazine-u&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#magazine-u&quot; aria-label=&quot;Anchor link for: magazine-u&quot;&gt;magazine u&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;...contains a bunch of cool looking special symbols and nerd font symbols, that I may use in the future. Here&#x27;s a small chunk of it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;󱞭 󱞯 󱞱 󱞳 󱞵 󱞷 󱞹 󱞻 &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;󱞡 󱞣 󱞥 󱞧 󱞩 󱞫 󱞽 &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    󰁕  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ⮌ ⮍ ⮎ ⮏  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;← 󰹹  󰒟 &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;󰚪 󰘲 󰕍 󰓦  ↪ ➜ &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;󰒊 ▶ &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The only action I may conceivably do with this one, is to edit¹⁰ it. And even then, usually from an already existing helix instance. The benefit is yet still huge, as it&#x27;s very easy to get to this file to add another cool unicode symbol.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;magazine-o-1&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#magazine-o-1&quot; aria-label=&quot;Anchor link for: magazine-o-1&quot;&gt;magazine o&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;...is the opposite of static — it stores the command output of the last command I ran in my rofi command runner.&lt;&#x2F;p&gt;
&lt;p&gt;Usually, the output of my rofi command runner is shown in a notification that stays for 3 seconds. That&#x27;s plenty of time for the vast majority of usecases, but I &lt;em&gt;may&lt;&#x2F;em&gt; want to look at it for longer. Blammo — edit¹⁰ action.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s fairly convenient as is already, but the real power lies in the copy³ action. Any time I execute a command, I can &lt;em&gt;choose&lt;&#x2F;em&gt; to copy its output, if I need it. &lt;br &#x2F;&gt;
So, I don&#x27;t have to preemtively plan to pipe the output into &lt;code&gt;xclip&lt;&#x2F;code&gt;, and don&#x27;t have to rerun the command once I realize I want to pipe it into &lt;code&gt;xclip&lt;&#x2F;code&gt;. I &lt;em&gt;just&lt;&#x2F;em&gt; use the copy³ action.&lt;&#x2F;p&gt;
&lt;a href=&quot;#free-power&quot; id=&quot;free-power&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Another power I get for free, is that I can choose a line to copy⁹ from the command output.&lt;&#x2F;p&gt;
&lt;p&gt;I didn&#x27;t consider this as something I&#x27;d want to do with command output — it wasn&#x27;t forethought. &lt;br &#x2F;&gt;
It just so happened I needed this action for something else (magazine &lt;code&gt;F&lt;&#x2F;code&gt; that stores cool fonts) and now the action is integrated into the &lt;em&gt;magazine framework&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
So with magazine &lt;code&gt;o&lt;&#x2F;code&gt;, and many other ones, I end up having editing flexibility that I didn&#x27;t plan for that magazine specifically. It&#x27;s a big part for why this system has been so successful for me.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;special-casing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#special-casing&quot; aria-label=&quot;Anchor link for: special-casing&quot;&gt;special-casing&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I create all the hotkeys for all the actions, and all magazines, myself. There are like 900 or so lines of yaml to make them all using xremap. &lt;br &#x2F;&gt;
Because I don&#x27;t have some complicated system to make the mappings, nothing is stopping me from making some action for some magazine behave slightly differently, to be more useful for that magazine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;magazine-l&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#magazine-l&quot; aria-label=&quot;Anchor link for: magazine-l&quot;&gt;magazine l&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;...is my &quot;linker&quot;. It contains all the links I want to store in this format:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;!general my youtube channel — https:&#x2F;&#x2F;www.youtube.com&#x2F;@Axlefublr&#x2F;streams&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;blog reasons I still love fish shell — https:&#x2F;&#x2F;jvns.ca&#x2F;blog&#x2F;2024&#x2F;09&#x2F;12&#x2F;reasons-i--still--love-fish&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;doc ankiconnect — https:&#x2F;&#x2F;foosoft.net&#x2F;projects&#x2F;anki-connect&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;general phind — https:&#x2F;&#x2F;www.phind.com&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gist why I hate kitty — https:&#x2F;&#x2F;gist.github.com&#x2F;Axlefublr&#x2F;260f653c25c34c3ed6147a6638fc6512&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mat gun sounds — https:&#x2F;&#x2F;samplefocus.com&#x2F;tag&#x2F;gun&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;meme I have done nothing but teleport bread for three days. — https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=NE1-dKc6R_I&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;music hatchetsaw, hauntgat, fleshwound — country side massacre — https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=H4Hw-ARuEa4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;plug nvim harp-nvim — https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;harp-nvim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;proj Axlefublr&#x2F;helix — https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First goes a &quot;header&quot;: &lt;code&gt;general&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;blog&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;music&lt;&#x2F;code&gt; &#x2F; etc. Then the title of the link. Then a &lt;code&gt;—&lt;&#x2F;code&gt; (long dash, U+2014). Then the actual link.&lt;&#x2F;p&gt;
&lt;p&gt;I used to use the append² action for this in the past, but found it annoying to have to put in a long dash &lt;em&gt;and&lt;&#x2F;em&gt; paste in the link every time, considering that it&#x27;s the &lt;em&gt;only&lt;&#x2F;em&gt; thing I&#x27;d want to do anyway.&lt;&#x2F;p&gt;
&lt;p&gt;I created a &quot;subaction&quot; meant to be the append² action replacement, but &lt;em&gt;only&lt;&#x2F;em&gt; for magazine &lt;code&gt;l&lt;&#x2F;code&gt;. The only difference, is that after I type in the input (link title), it appends a &lt;code&gt;—&lt;&#x2F;code&gt; to it and the link (which is in my clipboard), and &lt;em&gt;then&lt;&#x2F;em&gt; adds it into the file.&lt;&#x2F;p&gt;
&lt;p&gt;That makes it really non-laborious to add in new links! &lt;br &#x2F;&gt;
As well as showcase how flexible magazines are, considering that I was able to make a custom action for something like this.&lt;&#x2F;p&gt;
&lt;a href=&quot;#reasoning&quot; id=&quot;reasoning&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Now, there&#x27;s a reason I want a specific format here to begin with. I don&#x27;t actually open this file directly that often. Magazine &lt;code&gt;l&lt;&#x2F;code&gt; is used as a &quot;data file&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;All the links are stored in it because I have a global hotkey that &lt;em&gt;parses&lt;&#x2F;em&gt; through them all, lets me search by title, and then either opens the link or copies it to my clipboard.&lt;&#x2F;p&gt;
&lt;p&gt;So, sometimes magazines &lt;em&gt;are&lt;&#x2F;em&gt; the behavior, other times they&#x27;re an &lt;em&gt;interface&lt;&#x2F;em&gt; to interact with a data file conveniently, so that it could be used by something else.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;magazine-e&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#magazine-e&quot; aria-label=&quot;Anchor link for: magazine-e&quot;&gt;magazine e&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&#x27;s idea is basically the exact same:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;¡ a1 reversed exclamation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;⁷ 2077 top superscript 7 seven&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;↕ 2195 arrow down &amp;amp; up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;🐄 1f404 cow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;🔇 1f507 muted speaker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;🤢 1f922 vomit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Easier automatic adder, that takes the symbol from my clipboard, figures out each character&#x27;s unicode (try &lt;code&gt;printf %x \&#x27;🐄&lt;&#x2F;code&gt;), and asks me for a title. Then a hotkey that lets me search by all of that, to copy just the symbol to my clipboard, so I could paste it wherever I need.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s about it when it comes to the explanation of the idea! Hope you got motivated to implement something like this, or better yet — something that makes even more sense for &lt;em&gt;you&lt;&#x2F;em&gt;. Right now I&#x27;m going to continue explaining a bunch of my other magazines and what I use them for, to maybe help you get ideas.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;etc-etc&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#etc-etc&quot; aria-label=&quot;Anchor link for: etc-etc&quot;&gt;etc etc&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Out of these magazines: &lt;code&gt;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[];&#x27;,.&#x2F;{}:&quot;&amp;lt;&amp;gt;?&lt;&#x2F;code&gt;, &lt;br &#x2F;&gt;
I&#x27;m actively using these: &lt;code&gt;acdefijklmopqrsuvwxACDEFHIJKLOPQRSTUVWXYZ134[];:&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, really, that many! I&#x27;m thinking of possibly adding hotkeys with &lt;kbd&gt;alt&lt;&#x2F;kbd&gt; in the future, once I run out of magazines. Then &lt;kbd&gt;ctrl&lt;&#x2F;kbd&gt;, then &lt;kbd&gt;shift+alt&lt;&#x2F;kbd&gt;, then... etc. That would in theory increase those ~900 lines of yaml to be like, three million! Oh well :&amp;gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;a&lt;&#x2F;kbd&gt; stores &quot;all the possible things I can do&quot; — helpful to take a step back, breathe, and calmly decide what next to do, rather than hurrily and anxiously jump around in my mind.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;c&lt;&#x2F;kbd&gt; stores copypastas I want to be easily accessible. Here&#x27;s one of them: «when making australia God said &quot;only a spiderful&quot; but then pulled out a comically large spider».&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;d&lt;&#x2F;kbd&gt; diary that gets automatically emptied every day. Because all remaining changes get automatically committed at the end of the day, I have access to all of my past&#x27;s diaries, without it cluttering up in one ginormous file. I don&#x27;t really ever read my diaries from that past, that&#x27;s why.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;f&lt;&#x2F;kbd&gt; similar to &lt;kbd&gt;a&lt;&#x2F;kbd&gt;, but I store &lt;em&gt;specifically&lt;&#x2F;em&gt; the &quot;next&quot; things I want to do. Here&#x27;s what it has now:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ff: !&amp;#39; is ctrl+l, +!&amp;#39; focuses page by probably clicking&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;c&amp;gt;, cda, cdb, cdab, codeblock, code, anki in not subheaders&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;qalculate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;life drain anki plugin https:&#x2F;&#x2F;ankiweb.net&#x2F;shared&#x2F;info&#x2F;715575551&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;css flex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;blog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:&#x2F;&#x2F;ankiweb.net&#x2F;shared&#x2F;info&#x2F;206062158&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;anki searching&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Very helpful with keeping me on track!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;k&lt;&#x2F;kbd&gt; stores links to youtube videos I want to download, &lt;kbd&gt;K&lt;&#x2F;kbd&gt; to &lt;em&gt;longform&lt;&#x2F;em&gt; videos, &lt;kbd&gt;i&lt;&#x2F;kbd&gt; to asmr videos. I have a script that takes a couple (dynamically settable) links from one of these three files, and starts downloading them, removing them from the magazine.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;j&lt;&#x2F;kbd&gt; is special-cased to instead be &lt;code&gt;~&#x2F;prog&#x2F;dotfiles&#x2F;project.txt&lt;&#x2F;code&gt;. &lt;code&gt;project.txt&lt;&#x2F;code&gt; is a file that gets automatically created for all of my projects, and I use it to organize thoughts of what I want to do in a given project. &lt;br &#x2F;&gt;
&lt;kbd&gt;J&lt;&#x2F;kbd&gt; is special-cased to let me &lt;em&gt;choose&lt;&#x2F;em&gt; a &lt;code&gt;project.txt&lt;&#x2F;code&gt; to act on. Reason why &lt;kbd&gt;j&lt;&#x2F;kbd&gt; is made more accessible, is that I &lt;em&gt;really&lt;&#x2F;em&gt; like to configure so I interact with the dotfiles project file the most frequently.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;m&lt;&#x2F;kbd&gt; stores long-term project ideas that I&#x27;ll definitely do Eventually™.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;p&lt;&#x2F;kbd&gt; my proxy&#x27;s information. I can quickly go in and copy the address, for example.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;q&lt;&#x2F;kbd&gt; my hardware specs. Even includes the specs of my physical body, lol.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;v&lt;&#x2F;kbd&gt; important events that I want to be reminded of yearly. I have a script that runs every day to check this file, and tells me stuff like &quot;3 years ago: started programming&quot;. Here&#x27;s the format:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;21.09.01 — started programming&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;22.09.24 — started using vim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;23.08.06 — installed EndeavorOS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;24.02.21 — she&#x2F;they&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;24.08.18 — switched to helix&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;kbd&gt;V&lt;&#x2F;kbd&gt; is the same thing with the same format, except it&#x27;s &lt;em&gt;not&lt;&#x2F;em&gt; checked daily; it&#x27;s for event dates I want to have access to, but don&#x27;t care to be reminded of.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;23.07.26 - installed Debian&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;24.02.22 - switched to pure neovim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;24.03.11 - 16gb ram&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;kbd&gt;Q&lt;&#x2F;kbd&gt; is also similar to &lt;kbd&gt;v&lt;&#x2F;kbd&gt;, but doesn&#x27;t specify a year — mostly for storing birthdays and getting reminders of them.&lt;&#x2F;p&gt;
&lt;p&gt;For reminders of things that will happen once, or monthly, or yearly (mostly payments and meetings), I made a python script that parses &lt;kbd&gt;T&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;w&lt;&#x2F;kbd&gt; is the short-term shopping list, and &lt;kbd&gt;W&lt;&#x2F;kbd&gt; is the long-term shopping list. &lt;br &#x2F;&gt;
These make more sense once you realize I have a telegram bot that lets me easily interact with magazines from my phone.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;x&lt;&#x2F;kbd&gt; contains today&#x27;s &quot;habit tasks&quot;. My daily tasks alternate: one side is stored in &lt;kbd&gt;[&lt;&#x2F;kbd&gt; and the other in &lt;kbd&gt;]&lt;&#x2F;kbd&gt;; each of them happens every other day.&lt;&#x2F;p&gt;
&lt;p&gt;One thing I have in &lt;kbd&gt;[&lt;&#x2F;kbd&gt; is to read through &lt;kbd&gt;D&lt;&#x2F;kbd&gt;, which stores words &#x2F; mindsets that I want to implement into myself, and so repeat every two days:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;split the scary into &amp;quot;not very&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;laborious&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stellar&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:o&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:O&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;・&amp;gt;・&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;kbd&gt;Z&lt;&#x2F;kbd&gt; contains package names I installed with &lt;code&gt;pacman&lt;&#x2F;code&gt; (meaning, from one of the arch repos), &lt;br &#x2F;&gt;
&lt;kbd&gt;X&lt;&#x2F;kbd&gt; for those installed from the AUR.&lt;&#x2F;p&gt;
&lt;p&gt;In my system setup script, both of these magazines are used to install all packages I want.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;C&lt;&#x2F;kbd&gt; stores packages that I want to be deleted the next time I update. This makes more sense to exist once you realize the workflow of filtering⁸ &lt;kbd&gt;Z&lt;&#x2F;kbd&gt; or &lt;kbd&gt;X&lt;&#x2F;kbd&gt;, and then appending the clipboard⁷ to &lt;kbd&gt;C&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;E&lt;&#x2F;kbd&gt; is actually a big ass list of all unicodes for my other, slower but more complete unicode symbol picker.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;L&lt;&#x2F;kbd&gt; contains commands to always be in my rofi command runner history, &lt;kbd&gt;H&lt;&#x2F;kbd&gt; for the dynamically generated history.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;R&lt;&#x2F;kbd&gt; repository paths, that should be automatically &lt;code&gt;git push&lt;&#x2F;code&gt;ed daily.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;U&lt;&#x2F;kbd&gt; a big ass list of words I use for &lt;code&gt;ttyper&lt;&#x2F;code&gt;, to practice touch typing. Which I never do anymore, but still.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;Y&lt;&#x2F;kbd&gt; my youtube channel subscriptions, because I don&#x27;t trust google to keep that information.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;1&lt;&#x2F;kbd&gt; consistently used as &quot;store something short-term&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;3&lt;&#x2F;kbd&gt; a bunch of things make &quot;notifications&quot; into here, like my various event notifiers, for example.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;4&lt;&#x2F;kbd&gt; github notifications go here.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;;&lt;&#x2F;kbd&gt; by the time I finished writing this gist, the &lt;code&gt;$&lt;&#x2F;code&gt; writing tasks from &lt;kbd&gt;r&lt;&#x2F;kbd&gt; moved here.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;kbd&gt;:&lt;&#x2F;kbd&gt; similarly, &lt;code&gt;%&lt;&#x2F;code&gt; &quot;processing&quot; tasks from &lt;kbd&gt;r&lt;&#x2F;kbd&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>elegant fish shell booleans</title>
          <pubDate>Thu, 24 Oct 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/elegant-fish-shell-booleans/</link>
          <guid>https://axlefublr.github.io/elegant-fish-shell-booleans/</guid>
          <description xml:base="https://axlefublr.github.io/elegant-fish-shell-booleans/">&lt;p&gt;I recently &lt;em&gt;finally&lt;&#x2F;em&gt; figured out how booleans work in fish shell, and turns out they&#x27;re very elegant!&lt;&#x2F;p&gt;
&lt;p&gt;You can use &lt;code&gt;set&lt;&#x2F;code&gt; to set variables to values; you can set them to &lt;code&gt;true&lt;&#x2F;code&gt; or &lt;code&gt;false&lt;&#x2F;code&gt; too. &lt;br &#x2F;&gt;
If your editor supports fish shell as a language, it will probably highlight them as booleans.&lt;&#x2F;p&gt;
&lt;p&gt;What are they? Some special types, or special syntax introduced by the shell?&lt;&#x2F;p&gt;
&lt;p&gt;Not at all actually, they&#x27;re &lt;em&gt;just&lt;&#x2F;em&gt; strings, like &lt;code&gt;asdf&lt;&#x2F;code&gt; and &lt;code&gt;the&lt;&#x2F;code&gt; would be.&lt;&#x2F;p&gt;
&lt;a href=&quot;#test&quot; id=&quot;test&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;You usually use &lt;code&gt;test&lt;&#x2F;code&gt; to check for various common equality comparisons, in shell scripting.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;var = &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;#39;thingy&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;   echo&lt;&#x2F;span&gt;&lt;span&gt; yeppies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If the string in variable &lt;code&gt;var&lt;&#x2F;code&gt; is equal to &lt;code&gt;thingy&lt;&#x2F;code&gt;, output &lt;code&gt;yeppies&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;a href=&quot;#if-semantics&quot; id=&quot;if-semantics&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Let&#x27;s examine more closely &lt;em&gt;why&lt;&#x2F;em&gt; we need &lt;code&gt;test&lt;&#x2F;code&gt; here to begin with.&lt;&#x2F;p&gt;
&lt;p&gt;What &lt;code&gt;if&lt;&#x2F;code&gt; does, is take in arguments, call those arguments as a command, and execute the inner block of code if the command&#x27;s exitcode is 0.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;test $var = &#x27;thingy&#x27;&lt;&#x2F;code&gt; are the arguments to the &lt;code&gt;if&lt;&#x2F;code&gt; command. &lt;br &#x2F;&gt;
If &lt;code&gt;test&lt;&#x2F;code&gt; executes successfully (meaning &lt;code&gt;$status&lt;&#x2F;code&gt; is 0 after it exits), &lt;code&gt;if&lt;&#x2F;code&gt; will execute the code block, which is &lt;code&gt;echo yeppies&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;What this means is that both &lt;code&gt;test&lt;&#x2F;code&gt; and &lt;code&gt;if&lt;&#x2F;code&gt; are not that special. They&#x27;re just commands doing command stuff. &lt;br &#x2F;&gt;
So you can use &lt;em&gt;any&lt;&#x2F;em&gt; command in an &lt;code&gt;if&lt;&#x2F;code&gt;, to check for its exitcode:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; rg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39;struct&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; args.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;   echo&lt;&#x2F;span&gt;&lt;span&gt; yeppies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If there is the word &lt;code&gt;struct&lt;&#x2F;code&gt; in the file &lt;code&gt;args.rs&lt;&#x2F;code&gt;, output &lt;code&gt;yeppies&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I&#x27;m saying all this to highlight: &lt;code&gt;if&lt;&#x2F;code&gt; &lt;em&gt;just&lt;&#x2F;em&gt; wants to execute a command as its condition, that&#x27;s it.&lt;&#x2F;p&gt;
&lt;a href=&quot;#command&quot; id=&quot;command&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;You can even store the command in a variable:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt; -l command rg &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;#39;struct&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; args.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;   echo&lt;&#x2F;span&gt;&lt;span&gt; yeppies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The variable &lt;code&gt;$command&lt;&#x2F;code&gt;, will expand to be &lt;code&gt;rg &#x27;struct&#x27; args.rs&lt;&#x2F;code&gt;, so this is basically equivalent to the codeblock above, where we &lt;em&gt;don&#x27;t&lt;&#x2F;em&gt; use a variable.&lt;&#x2F;p&gt;
&lt;a href=&quot;#booleans&quot; id=&quot;booleans&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Coming back to booleans:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt; -l var1 true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt; -l var2 false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;var1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;   echo&lt;&#x2F;span&gt;&lt;span&gt; yeppies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;var2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;   echo&lt;&#x2F;span&gt;&lt;span&gt; yeppies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Despite &lt;code&gt;true&lt;&#x2F;code&gt; and &lt;code&gt;false&lt;&#x2F;code&gt; looking colorful, and therefore seeming &quot;special&quot;, in your editor, &lt;br &#x2F;&gt;
they are actually both &lt;em&gt;just&lt;&#x2F;em&gt; strings, so both if statements here will execute their codeblock.&lt;&#x2F;p&gt;
&lt;a href=&quot;#false&quot; id=&quot;false&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I always thought, for some reason, that &lt;code&gt;false&lt;&#x2F;code&gt; will evaluate to, well, &lt;em&gt;false&lt;&#x2F;em&gt; in &lt;code&gt;test&lt;&#x2F;code&gt;, but now that I think about it, why would it?&lt;&#x2F;p&gt;
&lt;p&gt;The real gold lies in something interesting: both &lt;code&gt;true&lt;&#x2F;code&gt; and &lt;code&gt;false&lt;&#x2F;code&gt; are also &lt;em&gt;commands&lt;&#x2F;em&gt;. Fish shell built in commands. &lt;br &#x2F;&gt;
&lt;code&gt;true&lt;&#x2F;code&gt; always returns with exitcode 0, &lt;code&gt;false&lt;&#x2F;code&gt; always returns with exitcode 1.&lt;&#x2F;p&gt;
&lt;p&gt;So by setting variables to (completely normal strings) &lt;code&gt;true&lt;&#x2F;code&gt; or &lt;code&gt;false&lt;&#x2F;code&gt;, you also happen to set those variables to commands that can be executed in &lt;code&gt;if&lt;&#x2F;code&gt; conditionals.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt; -l condition true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;condition&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;   echo&lt;&#x2F;span&gt;&lt;span&gt; yeppies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt; condition false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B58CC6;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt;condition&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;   echo&lt;&#x2F;span&gt;&lt;span&gt; yeppies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Will essentially expand to:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;   echo&lt;&#x2F;span&gt;&lt;span&gt; yeppies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;   echo&lt;&#x2F;span&gt;&lt;span&gt; yeppies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s much more clear this way, why &lt;code&gt;true&lt;&#x2F;code&gt; and &lt;code&gt;false&lt;&#x2F;code&gt; seem special! &lt;br &#x2F;&gt;
It&#x27;s entirely &lt;em&gt;just&lt;&#x2F;em&gt; because they also happen to be commands that you can call to get your wanted exitcode, &lt;br &#x2F;&gt;
&lt;strong&gt;not&lt;&#x2F;strong&gt; because fish shell uses them as special syntax.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>why even helix?</title>
          <pubDate>Mon, 21 Oct 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/why-even-helix/</link>
          <guid>https://axlefublr.github.io/why-even-helix/</guid>
          <description xml:base="https://axlefublr.github.io/why-even-helix/">&lt;p&gt;I&#x27;ve been using neovim for around two years. &lt;br &#x2F;&gt;
I&#x27;ve rewritten my config three times: for the first time, when I switched to astronvim, and when I switched back from astronvim. At the most recent point, my config was 5000 lines long. &lt;br &#x2F;&gt;
I&#x27;ve gotten into the habit of reading nvim help pages in their entirety, for fun. &lt;br &#x2F;&gt;
I have also written &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;edister.nvim&quot;&gt;s&lt;&#x2F;a&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;harp-nvim&quot;&gt;e&lt;&#x2F;a&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;qfetter.nvim&quot;&gt;v&lt;&#x2F;a&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;lupa.nvim&quot;&gt;e&lt;&#x2F;a&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;selabel.nvim&quot;&gt;n&lt;&#x2F;a&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;dress.nvim&quot;&gt;!&lt;&#x2F;a&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;wife.nvim&quot;&gt;!&lt;&#x2F;a&gt; plugins. &lt;br &#x2F;&gt;
And usually spent multiple hours every day configuring nvim.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m glazing myself here to point out: I have obviously given nvim a good try; matter of fact the try was unreasonably good! &lt;br &#x2F;&gt;
And the reason why I switched off nvim is not due to the lack of knowledge about nvim.&lt;&#x2F;p&gt;
&lt;a href=&quot;#brighter-future&quot; id=&quot;brighter-future&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Considering my &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;why-i-hate-lua&#x2F;&quot;&gt;two&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;why-i-hate-kitty&#x2F;&quot;&gt;other&lt;&#x2F;a&gt; blog posts, this one should be called &quot;why I hate nvim&quot;, but I don&#x27;t actually hate it! &lt;br &#x2F;&gt;
I just realize that helix is simply the better option.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve been wanting a brighter future than nvim, for a long time. And while I did look at helix, there was something that stopped me from considering actually switching to it. &lt;br &#x2F;&gt;
I&#x27;m sure you&#x27;ve heard of this stance, or even maybe have it yourself: &quot;helix has no plugins, so I&#x27;ll just wait for it to get them, and then I&#x27;ll switch&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Fair enough! That was my idea too! &lt;br &#x2F;&gt;
However, I&#x27;m autistic, so switching to things is a whole ordeal, usually taking me multiple consecutive days, and taking a lot of time, effort, and energy. &lt;br &#x2F;&gt;
Doesn&#x27;t really make sense to wait for the plugin system, to then overwhelm myself all at once, does it? &lt;br &#x2F;&gt;
So I decided to do it the smart way.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-plan&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-plan&quot; aria-label=&quot;Anchor link for: the-plan&quot;&gt;the plan&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;First, I go on and fully discover helix. Learn the editing model, the bindings; configure it to be fairly usable, go through the entire &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.helix-editor.com&#x2F;master&quot;&gt;documentation&lt;&#x2F;a&gt; to not miss anyting. &lt;br &#x2F;&gt;
With &lt;em&gt;this&lt;&#x2F;em&gt; basis, I effectively split the overwhelm into two parts, making it more manageable. &lt;br &#x2F;&gt;
So that when the plugin system comes, I can &lt;em&gt;actually&lt;&#x2F;em&gt; switch. &lt;br &#x2F;&gt;
Yes! My idea was to stick with nvim still, but think about the future in this way.&lt;&#x2F;p&gt;
&lt;p&gt;I failed spectacularly... Or did helix succeed that much? &lt;br &#x2F;&gt;
Let me elaborate on why I switched to helix so soon, despite intending not to!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-editing-model&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-editing-model&quot; aria-label=&quot;Anchor link for: the-editing-model&quot;&gt;the editing model&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Helix&#x27;s &quot;selection-&amp;gt;action&quot; model is ultimately the biggest reason for why I switched. &lt;br &#x2F;&gt;
Despite being so used to vim&#x27;s &quot;action-&amp;gt;selection&quot; model, it took me 1-3 days to get used to helix&#x27;s one. &lt;br &#x2F;&gt;
I believe it&#x27;s because it feels &lt;em&gt;that&lt;&#x2F;em&gt; natural!&lt;&#x2F;p&gt;
&lt;p&gt;The way my brain works is something like this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&quot;uhhhh right so this piece of text&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;uhhhhh facken let&#x27;s do this&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;rather than:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&quot;uhhhhh soooo let&#x27;s do this ig&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;with uhhhhh this text&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;a href=&quot;#pausing&quot; id=&quot;pausing&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;It&#x27;s fairly often that I know &lt;em&gt;subconsciously&lt;&#x2F;em&gt; what I wanna do, and actively &quot;discover&quot; what that something actually is. &lt;br &#x2F;&gt;
Because of that, I may take ridiculously long pauses between my keystrokes to think.&lt;&#x2F;p&gt;
&lt;p&gt;Nvim has this incredibly annoying default, where your action+selection key sequences are quick time events. I&#x27;m serious! &lt;br &#x2F;&gt;
You have to execute the whole action in some amount of time after pressing the &quot;operator&quot; — otherwise it will time out.&lt;&#x2F;p&gt;
&lt;p&gt;You can of course disable this (via &lt;code&gt;:h &#x27;timeoutlen&#x27;&lt;&#x2F;code&gt;), but this is just the start of the pattern of bad defaults in nvim. For now I will just state that since this is a default, other nvim functionality (as well as plugins), will often be designed having this behavior in mind. In short, nvim penalizes pauses.&lt;&#x2F;p&gt;
&lt;a href=&quot;#an-even-better-point&quot; id=&quot;an-even-better-point&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Coming back to the example above, nvim makes you decide on an action first, and the selection second; right after you just decided on an action, not encouraging pauses, it makes you decide the selection too.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;That&#x27;s kinda rough when you put it that way, but it&#x27;s not that bad, right?&quot; — I&#x27;ll make my argument less strawmanny and still showcase how it&#x27;s actually really terrible.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s do this very very common thing in nvim and fix a default: we will disable the key timeout. &lt;br &#x2F;&gt;
We&#x27;ll claim that &quot;well yes OBVIOUSLY you change that&quot; and transform an individual named Bob into the brother of our parent.&lt;&#x2F;p&gt;
&lt;p&gt;We still have a pretty glaring issue with the editing model as a whole, even with key timeout not being an issue.&lt;&#x2F;p&gt;
&lt;p&gt;Whether or not we&#x27;ll even be able to make the selection is not a guarantee! &lt;br &#x2F;&gt;
&quot;First you select an action to do and then the area of text it acts on&quot; is not the full story at all.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vim-s-actual-editing-model&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#vim-s-actual-editing-model&quot; aria-label=&quot;Anchor link for: vim-s-actual-editing-model&quot;&gt;vim&#x27;s &lt;em&gt;actual&lt;&#x2F;em&gt; editing model&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Especially without plugins to &lt;em&gt;help&lt;&#x2F;em&gt; (notice, not &lt;em&gt;solve&lt;&#x2F;em&gt;), you will often times &lt;strong&gt;not&lt;&#x2F;strong&gt; be able to select the text area that you &lt;em&gt;actually&lt;&#x2F;em&gt; want. &lt;br &#x2F;&gt;
The more realistic model of vim is:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Place your cursor in a position from which you&#x27;ll be able to make the selection motion later&lt;&#x2F;li&gt;
&lt;li&gt;Decide on what you want to do&lt;&#x2F;li&gt;
&lt;li&gt;Think about the selection &lt;em&gt;again&lt;&#x2F;em&gt;, now actually making it&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;It&#x27;s a lie to say that vim has an action-&amp;gt;selection model, because you first need to figure out if your selection will even work! &lt;br &#x2F;&gt;
And because of things like dot repeat, and efficiency (generally doing an action via action-&amp;gt;selection is less keystrokes than the visual mode (selection-&amp;gt;action) equivalent, in nvim), actively picking to always use visual mode first is a known anti-pattern! &lt;br &#x2F;&gt;
Think of any vim tutorial: things like &quot;you should use &lt;code&gt;ciw&lt;&#x2F;code&gt; instead of &lt;code&gt;viwc&lt;&#x2F;code&gt; 🤓&quot; are always (validly) pointed out.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;core-philosophy-as-a-solution&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#core-philosophy-as-a-solution&quot; aria-label=&quot;Anchor link for: core-philosophy-as-a-solution&quot;&gt;core philosophy as a solution&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;In helix, half the time you don&#x27;t even need to think about how to make the selection, because you already made it just by naturally moving around.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;w&lt;&#x2F;code&gt;, &lt;code&gt;e&lt;&#x2F;code&gt;, &lt;code&gt;b&lt;&#x2F;code&gt; word motions that you already know and love now also &lt;em&gt;select&lt;&#x2F;em&gt; the word. This is useful because in helix, you &lt;em&gt;always&lt;&#x2F;em&gt; operate on a selection. Matter of fact, your cursor is just a 1 column wide selection!&lt;&#x2F;p&gt;
&lt;p&gt;As I&#x27;ve been writing this blog post, I&#x27;ve been moving around using the word motions — they&#x27;re pretty natural for moving around in literal text. &lt;br &#x2F;&gt;
Another thing that&#x27;s very natural to want to do in literal text is to delete &#x2F; change words. &lt;br &#x2F;&gt;
This combines nicely: I move to some word, and it also &lt;em&gt;happens&lt;&#x2F;em&gt; to become my target. Often times, I only need to press a single key to do the action that I decide to do.&lt;&#x2F;p&gt;
&lt;p&gt;The reason why you&#x27;d usually want to use &lt;code&gt;ciw&lt;&#x2F;code&gt; rather than &lt;code&gt;ce&lt;&#x2F;code&gt; in vim, is due to precision. With the former, you can act on a word no matter what, and so by spending an extra keypress, you can allow yourself to spend less mental effort. Interesting tradeoff! &lt;br &#x2F;&gt;
It only really makes sense because to &lt;em&gt;see&lt;&#x2F;em&gt; what you&#x27;re going to capture with a motion, you need to actively think. What if your editor thought for you?&lt;&#x2F;p&gt;
&lt;a href=&quot;#visuality&quot; id=&quot;visuality&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;This is effectively the greatest strength of helix: rather than having to spend mental cpu cycles to figure out what you&#x27;d match with a certain motion, you &lt;em&gt;already&lt;&#x2F;em&gt; can clearly see what you&#x27;d match, &lt;em&gt;always&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
Rather than thinking &quot;hmmmm how do I change this word?&quot;, you think &quot;I want to act on &lt;em&gt;this&lt;&#x2F;em&gt; area... oh wait! it&#x27;s already selected! I guess I just &lt;code&gt;c&lt;&#x2F;code&gt; then!&quot;. &lt;br &#x2F;&gt;
This seemingly small difference ends up merging together to form a &lt;em&gt;much&lt;&#x2F;em&gt; nicer editor experience, especially considering that the entire editor is designed around it.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;normal-semantics&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#normal-semantics&quot; aria-label=&quot;Anchor link for: normal-semantics&quot;&gt;&quot;normal&quot; semantics&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Something that took me a bit to &lt;em&gt;get&lt;&#x2F;em&gt;, is the semantic of normal mode in helix. &lt;br &#x2F;&gt;
I can put it to words most precisely like this: &lt;br &#x2F;&gt;
In normal mode, as you move, you &lt;em&gt;replace&lt;&#x2F;em&gt; your selection by every next motion. &lt;br &#x2F;&gt;
In &lt;em&gt;select&lt;&#x2F;em&gt; mode, you &lt;em&gt;extend&lt;&#x2F;em&gt; your selection by every next motion.&lt;&#x2F;p&gt;
&lt;p&gt;Pretty straightforward, isn&#x27;t it! Might take some time to get used to, but ultimately it&#x27;s really nice.&lt;&#x2F;p&gt;
&lt;p&gt;Let me present another example of how this model aids you, without you needing to put in extra effort for extra benefit.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;f&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;F&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;t&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;T&lt;&#x2F;code&gt; motions replace your selection too! When you &lt;code&gt;f&lt;&#x2F;code&gt; towards something, you make a selection from your current cursor position to the character that you aimed for. &lt;br &#x2F;&gt;
You may use &lt;code&gt;f&lt;&#x2F;code&gt; just to move and ignore the selection it makes, &lt;br &#x2F;&gt;
or you can use &lt;code&gt;f&lt;&#x2F;code&gt; to &lt;em&gt;select&lt;&#x2F;em&gt; towards something to then delete it, for example. &lt;br &#x2F;&gt;
Regardless of which action you decide to do, you can make the motion in the exact same way.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;built-in-plugins&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#built-in-plugins&quot; aria-label=&quot;Anchor link for: built-in-plugins&quot;&gt;built in &quot;plugins&quot;&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Helix has the equivalents of &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nvim-telescope&#x2F;telescope.nvim&quot;&gt;telescope&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kylechui&#x2F;nvim-surround&quot;&gt;nvim-surround&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;folke&#x2F;which-key.nvim&quot;&gt;whichkey&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;nvim-lspconfig&quot;&gt;lspconfig&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;easymotion&#x2F;vim-easymotion&quot;&gt;easymotion&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bkad&#x2F;CamelCaseMotion&quot;&gt;CamelCaseMotion&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;stevearc&#x2F;conform.nvim&quot;&gt;conform.nvim&lt;&#x2F;a&gt; built in.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s pretty nice! But ultimately things being built in is just nice, not really an argument towards an editor. After all, all of the above are really known plugins in the nvim community, so it&#x27;s very likely a nvim user uses some, or all of them. &lt;br &#x2F;&gt;
Right?&lt;&#x2F;p&gt;
&lt;p&gt;That point of view misses something.&lt;&#x2F;p&gt;
&lt;p&gt;Neovim plugins are inherently limited by the nvim API. They can only be as good as nvim allows them to be. &lt;br &#x2F;&gt;
Some of them may employ some hacks, or less than pretty implementation details that end up making a plugin feel &lt;em&gt;like a plugin&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
Something that was tacked onto a foundation that didn&#x27;t think ahead to work nicely with that plugin&#x27;s behavior. &lt;br &#x2F;&gt;
As someone who made 7 plugins, I encountered this fact very closely.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;telescope&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#telescope&quot; aria-label=&quot;Anchor link for: telescope&quot;&gt;telescope&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;An amazing plugin, fwiw. Very extendable, configurable, powerful. &lt;br &#x2F;&gt;
&lt;em&gt;However&lt;&#x2F;em&gt;, it does so much while built &lt;em&gt;on top&lt;&#x2F;em&gt; of neovim, that it&#x27;s noticeable in usage. &lt;br &#x2F;&gt;
When I launch telescope, I can distinctly see two rendering stages: first, the window appears. Second, it&#x27;s filled with text.&lt;&#x2F;p&gt;
&lt;p&gt;The two stages happen slowly enough where I can clearly notice them, and it&#x27;s always been jarring to me. I&#x27;ve since tried to switch off telescope, by discovering &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ibhagwan&#x2F;fzf-lua&quot;&gt;fzf-lua&lt;&#x2F;a&gt;, but turns out it&#x27;s even slower in terms of the UI updates (because it uses terminal mode).&lt;&#x2F;p&gt;
&lt;p&gt;On the opposite hand, &lt;em&gt;helix&lt;&#x2F;em&gt;&#x27;s &quot;telescope&quot; is built in, and when you press the hotkey to open it, all of the UI happens &lt;em&gt;at once&lt;&#x2F;em&gt;. It &lt;em&gt;opens&lt;&#x2F;em&gt;, rather than &lt;em&gt;loads in&lt;&#x2F;em&gt;, is how I can describe it. And god does that feel incredible!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;whichkey&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#whichkey&quot; aria-label=&quot;Anchor link for: whichkey&quot;&gt;whichkey&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Neovim&#x27;s whichkey uses key timeout to reveal itself, which I&#x27;ve already explained being quite uncomfortable to use. But without key timeout, you get no whichkey. &lt;br &#x2F;&gt;
This is not a point against &lt;code&gt;folke&lt;&#x2F;code&gt;, it&#x27;s a point against a plugin that is better served by being built in. &lt;br &#x2F;&gt;
And omg, it sure is, in helix!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Immediately&lt;&#x2F;em&gt; as you press a key that has submappings, you get shown a whichkey menu, on the right side of the screen. &lt;br &#x2F;&gt;
Because there&#x27;s no key timeout, you can look at it for as long as you want to! This is how I was able to &lt;em&gt;discover&lt;&#x2F;em&gt; a large part of helix. &lt;br &#x2F;&gt;
Generally I use &lt;code&gt;anki&lt;&#x2F;code&gt; to memorize all keybinds, but with a nice interface to teach me, there was far less need to do so.&lt;&#x2F;p&gt;
&lt;p&gt;Because the mapping system is designed having this menu in mind, you create all of your mappings in a hierarchical fashion. &lt;br &#x2F;&gt;
So, rather than mapping &lt;code&gt;mf&lt;&#x2F;code&gt; to something, you map &lt;code&gt;f&lt;&#x2F;code&gt; in section &lt;code&gt;m&lt;&#x2F;code&gt; to something. &lt;br &#x2F;&gt;
Nvim&#x27;s whichkey had to create this system for itself.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nicer-registers&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nicer-registers&quot; aria-label=&quot;Anchor link for: nicer-registers&quot;&gt;nicer registers&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Another neat thing it does, that completely solves an issue nvim otherwise has, is that when you access a register (via &lt;code&gt;&quot;&lt;&#x2F;code&gt; by default), it &lt;em&gt;shows you&lt;&#x2F;em&gt; the contents of filled registers in that same whichkey menu!&lt;&#x2F;p&gt;
&lt;p&gt;In nvim, you use &lt;code&gt;:reg&lt;&#x2F;code&gt; to look at a register&#x27;s contents. But you only ever need to look at a register&#x27;s contents &lt;em&gt;right&lt;&#x2F;em&gt; before using it in some way, and so helix does exactly that!&lt;&#x2F;p&gt;
&lt;p&gt;I was never a fan of the whichkey idea overall, but helix&#x27;s implementation was very helpful and improved my opinion a bit :3 &lt;br &#x2F;&gt;
Ultimately still, it&#x27;s a bit too much UI for me to see jump around, so I removed it once I memorized every mapping. &lt;br &#x2F;&gt;
In &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;my fork&lt;&#x2F;a&gt;, I added an option to disable the whichkey menu, but keep it for registers, so that&#x27;s what I&#x27;ve been using.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;surround&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#surround&quot; aria-label=&quot;Anchor link for: surround&quot;&gt;surround&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Because nvim text objects are actually just visual selections in disguise, using text objects is often jumpy and hard to look at. &lt;br &#x2F;&gt;
When you combine that with nvim-surround, which uses even &lt;em&gt;more&lt;&#x2F;em&gt; janky movement + change approaches, the experience ends up looking very &quot;pluginy&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;The helix built-in surrounding mechanism doesn&#x27;t have to work within such restrictive rules, as it&#x27;s built into the system to begin with. &lt;br &#x2F;&gt;
There&#x27;s something really elegant and powerful it lets you do, thanks to that!&lt;&#x2F;p&gt;
&lt;p&gt;Say you&#x27;re writing markdown, and want to make a word &lt;strong&gt;bold&lt;&#x2F;strong&gt;, retroactively. &lt;br &#x2F;&gt;
In nvim, you would do &lt;code&gt;ysiw*ysiw*&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
You &lt;em&gt;almost&lt;&#x2F;em&gt; could &lt;code&gt;ysiw*.&lt;&#x2F;code&gt;, but I believe it moves your cursor onto one of the &lt;code&gt;*&lt;&#x2F;code&gt;, making you first move before being able to dot repeat. &lt;br &#x2F;&gt;
So basically, that&#x27;s kinda cumbersome. And that&#x27;s just a situation where you &lt;em&gt;can&lt;&#x2F;em&gt; use the same motion twice; that&#x27;s not always the case.&lt;&#x2F;p&gt;
&lt;p&gt;For example, it isn&#x27;t the case if you wanted to surround a &lt;code&gt;word&lt;&#x2F;code&gt; in such a way, that you would get: &lt;code&gt;{ [&#x27;word&#x27;] }&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
In nvim, this is kind of a pain, because you keep needing to use a different text object every time: &lt;code&gt;ysiw&#x27;ysa&#x27;]ysa] ysa }&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Even if we assume you use a plugin that makes that last &lt;code&gt;ysa] ysa }&lt;&#x2F;code&gt; into a &lt;code&gt;ysa]{&lt;&#x2F;code&gt; (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;wellle&#x2F;targets.vim&quot;&gt;targets.vim&lt;&#x2F;a&gt;, I think?), we still get left with: &lt;code&gt;ysiw&#x27;ysa&#x27;]ysa]{&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;First, it&#x27;s an obscene amount of characters to press. &lt;br &#x2F;&gt;
But more importantly, you use THREE different text objects here, and one of them uses &lt;code&gt;i&lt;&#x2F;code&gt; rather than &lt;code&gt;a&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Doing this has always been quite a pain for me, as you need to think about what you&#x27;re doing with considerable amount of focus.&lt;&#x2F;p&gt;
&lt;a href=&quot;#consistency&quot; id=&quot;consistency&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;How does this work in helix? Remember that &quot;motions replace your selection&quot; thing? What if I told you surrounding did this too? &lt;br &#x2F;&gt;
Genious! Of course it would! &lt;br &#x2F;&gt;
Due to this convenient consistency, executing the two examples I just gave is very simple.&lt;&#x2F;p&gt;
&lt;p&gt;The first one, considering that you already selected the word, is: &lt;code&gt;ms*ms*&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
After the first surround, your selection updates to &lt;em&gt;contain&lt;&#x2F;em&gt; the new characters you just added. So you don&#x27;t need to &quot;fix&quot; your selection or anything! &lt;br &#x2F;&gt;
You unfortunately can&#x27;t dot repeat that second &lt;code&gt;ms*&lt;&#x2F;code&gt; in helix yet, which is quite annoying :c &lt;br &#x2F;&gt;
In nvim it wasn&#x27;t that big of a deal because you had to fix your position anyway, but it would be way nicer to have in helix because you &lt;strong&gt;don&#x27;t&lt;&#x2F;strong&gt; need to fix the selection.&lt;&#x2F;p&gt;
&lt;p&gt;The second example is just fantastic, especially in comparison: &lt;code&gt;ms&#x27;ms[ms ms{&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
All you need to do is &lt;em&gt;just&lt;&#x2F;em&gt; keep saying what you want to surround with. &lt;br &#x2F;&gt;
Not having to fix your position, or use a different text object, REALLY helps here! &lt;br &#x2F;&gt;
I can do this blindly without really needing to focus much, so it&#x27;s quite a big win.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;autopairs&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#autopairs&quot; aria-label=&quot;Anchor link for: autopairs&quot;&gt;autopairs&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Not much to say about this one, it just works! &lt;br &#x2F;&gt;
You can define what your autopairs are globally, and then also define them per-language, in a very obvious configuration format. &lt;br &#x2F;&gt;
Very possible that I just picked a wrong plugin, out of the million that exist, but in neovim adding an autopair was a chore, that also ended up working differently from all the other autopairs already enabled by default, in a jarring way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lsp&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#lsp&quot; aria-label=&quot;Anchor link for: lsp&quot;&gt;lsp&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Oh my FUCKING god do I despise neovim&#x27;s lsp integration. &lt;br &#x2F;&gt;
Somehow despite all of my experience and knowledge, when it comes to the editor, I still see lsp configuration as half magic. &lt;br &#x2F;&gt;
Fucking 5 or so different plugins doing god knows what in magicky ways, requiring you to do a lot of guesswork to configure in any non-standard way (that lsps sometimes require (rust-analyzer)). &lt;br &#x2F;&gt;
With this structure, hanging on by a thread, it still takes up like 50 or so milliseconds off your startup time, which is pretty horrendous. You then may spend a lot of effort on optimizing that startup time, too. Which is a craft of its own...&lt;&#x2F;p&gt;
&lt;p&gt;I forgot to mention this, but helix starts instantly. If you get all the neovim plugins that &quot;exist&quot; in helix, and lazy load them properly, neovim will still take longer to put you into a buffer, than helix will. You get everything, while not sacrificing speed.&lt;&#x2F;p&gt;
&lt;p&gt;And the lsp integration is &lt;em&gt;really&lt;&#x2F;em&gt; simple and lovely. In your &lt;code&gt;languages.toml&lt;&#x2F;code&gt;, you define which lsps you want to use (you can just specify multiple of them per-language if you want!) and what arguments they should be given to start properly. &lt;br &#x2F;&gt;
That&#x27;s in theory, at least. In practice it&#x27;s probably already done for you by helix contributors. So all you need to do is install the lsp so it&#x27;s in your &lt;code&gt;$PATH&lt;&#x2F;code&gt;, and blammo — the lsp just works. I&#x27;ll repeat that: in the general case, to get an lsp to work, you &lt;em&gt;just&lt;&#x2F;em&gt; install it. Often times you won&#x27;t even really need to configure it.&lt;&#x2F;p&gt;
&lt;p&gt;Formatting is similarly simple: you define how to call it (if it&#x27;s not already done for you), and then can use &lt;code&gt;:fmt&lt;&#x2F;code&gt; or the auto-format option (configured globally &lt;em&gt;and&lt;&#x2F;em&gt; per language, also).&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s no non-lsp diagnostic sources like in none-ls or nvim-lint, unfortunately. But it&#x27;s a tradeoff I&#x27;m willing to make, because I only lost fish shell diagnostics, which aren&#x27;t that important to me anyway. I&#x27;m sure it&#x27;ll get added in eventually, though!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;registers-part-2&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#registers-part-2&quot; aria-label=&quot;Anchor link for: registers-part-2&quot;&gt;registers part 2&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s go back to registers for a bit. The way that helix handles them is what initially made me &lt;em&gt;consider&lt;&#x2F;em&gt; switching to begin with.&lt;&#x2F;p&gt;
&lt;p&gt;In nvim, when you yank into a named (&lt;code&gt;[a-z]&lt;&#x2F;code&gt;) register, you &lt;em&gt;also&lt;&#x2F;em&gt; yank into the default register (&lt;code&gt;&quot;&lt;&#x2F;code&gt;). I always found this annoying! &lt;br &#x2F;&gt;
Imagine a situation where you yanked something, and are travelling through the file to paste it elsewhere. &lt;br &#x2F;&gt;
As you travel, you notice another piece of text that you want to &lt;em&gt;also&lt;&#x2F;em&gt; take with you.&lt;&#x2F;p&gt;
&lt;p&gt;What do you do in this situation? Correct, you eat sand and annoyingly come back for it later. Or use my plugin that I didn&#x27;t publish.&lt;&#x2F;p&gt;
&lt;p&gt;You might present uppercase registers (&lt;code&gt;[A-Z]&lt;&#x2F;code&gt;) as a solution, but appending, rather than overwriting a register doesn&#x27;t necessarily solve the problem. &lt;br &#x2F;&gt;
If the important yank you made is a characterwise yank, appending to it most likely isn&#x27;t what you want at all. &lt;br &#x2F;&gt;
Even if both the important yank 1 and important yank 2 are linewise, there&#x27;s no guarantee that they are related; you might want to paste them separately. &lt;br &#x2F;&gt;
Separating them after the fact seems like an annoying workaround.&lt;&#x2F;p&gt;
&lt;p&gt;And let&#x27;s not forget: you yanked to the &lt;em&gt;default&lt;&#x2F;em&gt; register. So you can&#x27;t even append to it anyway. &lt;br &#x2F;&gt;
And you can&#x27;t retroactively move it into another register, without coming back and reyanking, or without using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;edister.nvim&quot;&gt;my plugin&lt;&#x2F;a&gt; that I did publish.&lt;&#x2F;p&gt;
&lt;p&gt;All of this hassle because yanking, even to a named register, still touches your default register. A non-unfuckable situation that I ran into often (enough to have made to plugins to work around it). &lt;br &#x2F;&gt;
In helix, it &lt;em&gt;obviously&lt;&#x2F;em&gt; just yanks to the register you specified. Duh! You specified a register, that register should be used. Pretty straightforward!&lt;&#x2F;p&gt;
&lt;p&gt;Now that same situation is colored in a different light: &lt;br &#x2F;&gt;
You yank something important, then find &lt;em&gt;another&lt;&#x2F;em&gt; thing you want to yank. &lt;br &#x2F;&gt;
You just select a register and continue on! :D &lt;br &#x2F;&gt;
And as you collect these important yanks, when you access yet another register, helix will tell you which registers you&#x27;re already using, implying what the free ones are. &lt;br &#x2F;&gt;
So (if you pay attention) you won&#x27;t even accidentally overwrite an important yank!&lt;&#x2F;p&gt;
&lt;a href=&quot;#price-of-mistakes&quot; id=&quot;price-of-mistakes&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Using registers is always an &lt;em&gt;active&lt;&#x2F;em&gt; decision for me. Because of this, it&#x27;s common that I yank something, and then think &quot;wait nevermind, I actually want this in register &lt;code&gt;x&lt;&#x2F;code&gt;&quot;. This &quot;nevermind&quot; thing happens most commonly when my current default register contents &lt;em&gt;aren&#x27;t&lt;&#x2F;em&gt; important.&lt;&#x2F;p&gt;
&lt;p&gt;In neovim, if you &quot;misyank&quot; something, you then need to re-specify the area you targeted. &lt;br &#x2F;&gt;
&lt;code&gt;yiw&lt;&#x2F;code&gt; then &quot;whoops&quot; then &lt;code&gt;&quot;xyiw&lt;&#x2F;code&gt;. Get more and more annoying, the more complex text objects you use.&lt;&#x2F;p&gt;
&lt;p&gt;Even if you used visual mode for your selection, you can&#x27;t &lt;em&gt;just&lt;&#x2F;em&gt; reyank: the selection is gone, and you have to press &lt;code&gt;gv&lt;&#x2F;code&gt; to restore it.&lt;&#x2F;p&gt;
&lt;p&gt;In helix, after you yank something, you can re-yank without any such hassle. &lt;code&gt;y&lt;&#x2F;code&gt; &quot;whoops&quot; &lt;code&gt;&quot;xy&lt;&#x2F;code&gt;. That&#x27;s it.&lt;&#x2F;p&gt;
&lt;p&gt;The selection actually staying like that is a common &quot;omg that&#x27;s so nice&quot; exclaim I do to myself, about helix. &lt;br &#x2F;&gt;
But there are places where, at least at first, it&#x27;s just really weird!&lt;&#x2F;p&gt;
&lt;a href=&quot;#strange-consistency&quot; id=&quot;strange-consistency&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Remember how your cursor is just a single-width selection? Helix stays consistent to the idea of selections mattering more than your cursor in this interesting way: &lt;br &#x2F;&gt;
By default, &lt;code&gt;a&lt;&#x2F;code&gt; appends after your selection, and &lt;code&gt;i&lt;&#x2F;code&gt; prepends before your selection.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, really! &lt;em&gt;Not&lt;&#x2F;em&gt; your cursor!&lt;&#x2F;p&gt;
&lt;p&gt;This means that if you have &lt;code&gt;word&lt;&#x2F;code&gt; selected, and your cursor is at &lt;code&gt;wor█&lt;&#x2F;code&gt;, &lt;br &#x2F;&gt;
when you press &lt;code&gt;i&lt;&#x2F;code&gt;, you will start inserting here: &lt;code&gt;|word&lt;&#x2F;code&gt;, &lt;br &#x2F;&gt;
rather than here: &lt;code&gt;wor|d&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Same case with &lt;code&gt;a&lt;&#x2F;code&gt;, just in the opposite direction.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Ok that&#x27;s just ridiculous&quot; you might say, and at first I agreed with you! &lt;br &#x2F;&gt;
While I did, I remapped &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;i&lt;&#x2F;code&gt; to get the behavior we both expect:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;#39;collapse_selection&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39;append_mode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt;&amp;#39;collapse_selection&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D3AD5C;&quot;&gt; &amp;#39;insert_mode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But after using helix for some time, I actually removed these bindings! &lt;br &#x2F;&gt;
Helix is &lt;em&gt;very&lt;&#x2F;em&gt; consistent with acting on selections specifically, and when you want to act on a &lt;em&gt;cursor&lt;&#x2F;em&gt;, it expects you to press &lt;code&gt;;&lt;&#x2F;code&gt; first, to collapse selections. &lt;br &#x2F;&gt;
Having &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;i&lt;&#x2F;code&gt; fall out of this rule became annoying, rather than helpful, as I got used to pressing &lt;code&gt;;&lt;&#x2F;code&gt; when I need to.&lt;&#x2F;p&gt;
&lt;p&gt;But aside from consistency, turns out it&#x27;s just kinda nice!&lt;&#x2F;p&gt;
&lt;a href=&quot;#ai&quot; id=&quot;ai&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Say you&#x27;re writing a sentence, and as you move through it, you got some word selected. &lt;br &#x2F;&gt;
You can pick whether you want to insert before &lt;em&gt;or&lt;&#x2F;em&gt; after the word, without having to adjust your position! &lt;br &#x2F;&gt;
It&#x27;s just &lt;code&gt;a&lt;&#x2F;code&gt; or &lt;code&gt;i&lt;&#x2F;code&gt;, depending on where you want to end up :D&lt;&#x2F;p&gt;
&lt;p&gt;Even more powerfully, this behavior of &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;i&lt;&#x2F;code&gt; makes &lt;em&gt;surrounding&lt;&#x2F;em&gt; things really easy. First you press &lt;code&gt;i&lt;&#x2F;code&gt; and type the left delimiter in, then &lt;code&gt;a&lt;&#x2F;code&gt; to type in the right one. &lt;br &#x2F;&gt;
I remember there was a very hyperspecific feature in nvim-surround to let you do exactly this; here it&#x27;s just part of the editing model, which is fascinating!&lt;&#x2F;p&gt;
&lt;p&gt;However, I half-think that this &lt;code&gt;a&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;i&lt;&#x2F;code&gt; behavior is more of a side effect than intended behavior — your selection is updated when typing in with &lt;code&gt;a&lt;&#x2F;code&gt;, but isn&#x27;t with &lt;code&gt;i&lt;&#x2F;code&gt;. So far that hasn&#x27;t given me problems, but it &lt;em&gt;does&lt;&#x2F;em&gt; feel like a bug. Maybe will get fixed someday!&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll admit, all this selection business takes a while to get used to, but actually now I prefer it. Even in my fish shell &quot;helix mode&quot;, I re-made this behavior, that&#x27;s how much I like it!&lt;&#x2F;p&gt;
&lt;a href=&quot;#pasting&quot; id=&quot;pasting&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Another example is &lt;code&gt;p&lt;&#x2F;code&gt; and &lt;code&gt;P&lt;&#x2F;code&gt;. Yep, they also paste after and before the &lt;em&gt;selection&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
With them though, the behavior isn&#x27;t particularly mind-boggling, and just ends up feeling correct immediately.&lt;&#x2F;p&gt;
&lt;p&gt;Say you have &lt;code&gt;word&lt;&#x2F;code&gt; selected, with your cursor on &lt;code&gt;█ord&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
After you yank, to multiply &lt;code&gt;word&lt;&#x2F;code&gt;, you just press &lt;code&gt;pp&lt;&#x2F;code&gt; as many times as you need. &lt;br &#x2F;&gt;
If you tried doing that in vim (same cursor position, after you yank with &lt;code&gt;yiw&lt;&#x2F;code&gt;), you&#x27;d end up with &lt;code&gt;wwordwordord&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
I massively prefer &lt;em&gt;just&lt;&#x2F;em&gt; pressing &lt;code&gt;p&lt;&#x2F;code&gt; mindlessly, rather than having to first move to the end of the word, or press &lt;code&gt;Pppp&lt;&#x2F;code&gt; instead. &lt;br &#x2F;&gt;
And if I wanted to multiply backwards in vim, &lt;code&gt;word&lt;&#x2F;code&gt; vores itself in an even more horrifying way: &lt;code&gt;worworwordddword&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;aha-the-perfect-editor&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#aha-the-perfect-editor&quot; aria-label=&quot;Anchor link for: aha-the-perfect-editor&quot;&gt;aha! the perfect editor!&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;After all this glazing you might rightfully think &quot;helix must be perfect!&quot;. &lt;br &#x2F;&gt;
Is that the case? FUCK NO!&lt;&#x2F;p&gt;
&lt;p&gt;The big downside of helix is its lack of maturity and slowness of development. &lt;br &#x2F;&gt;
First of all, it doesn&#x27;t have a plugin system. &lt;br &#x2F;&gt;
Yep, not at all! &lt;br &#x2F;&gt;
Even something like kakoune, which design is &lt;em&gt;against&lt;&#x2F;em&gt; the idea of plugins, &lt;em&gt;does&lt;&#x2F;em&gt; have a plugin system. &lt;br &#x2F;&gt;
Your &lt;em&gt;shell&lt;&#x2F;em&gt; has a plugin system. That itty bitty program that you click clack commands in. &lt;br &#x2F;&gt;
Your fridge probably has a plugin system. &lt;br &#x2F;&gt;
Helix doesn&#x27;t!&lt;&#x2F;p&gt;
&lt;p&gt;And because of this, you&#x27;re bound to encounter problems that are currently unsolvable, as generally a plugin for that behavior would already exist, or you&#x27;d write your own to get it. &lt;br &#x2F;&gt;
This state of affairs makes it infuriating to use helix sometimes, because the &lt;code&gt;:trim&lt;&#x2F;code&gt; command has been bikeshed for over a year, and some seemingly basic lsp methods are not implemented, leading to some lsps literally not working!&lt;&#x2F;p&gt;
&lt;p&gt;The example I&#x27;m immediately thinking of, is the Scala lsp not working because it can&#x27;t show its startup message. This may be niche, but papercuts do pile up!&lt;&#x2F;p&gt;
&lt;p&gt;Have I already mentioned that you can&#x27;t complete words from the document in helix &lt;del&gt;stable&lt;&#x2F;del&gt; master? Yeah... &lt;br &#x2F;&gt;
This feature is completely working and finished, &lt;em&gt;but&lt;&#x2F;em&gt; is floating around as a PR for seemingly no reason at all. &lt;br &#x2F;&gt;
As I like to say: “if we consider all the unmerged completely finished and working PRs, we have a functioning editor!”. &lt;br &#x2F;&gt;
On one hand, we already have way more than enough features to have a really fucking good editor. &lt;br &#x2F;&gt;
Because it&#x27;s designed so well, you tend to be able to work around the missing parts not too difficultly. &lt;br &#x2F;&gt;
But still, the more I learn about helix and its decisions, the more I think it holds itself back just to reach unecessary perfection; never trading &quot;perfect&quot; for &quot;done&quot;. &lt;br &#x2F;&gt;
And basic editor features are so important, that I&#x27;d rather see them get merged asap, and then evolve over time into becoming perfect. But maybe that&#x27;s unrealistic?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;is-this-a-worthy-tradeoff&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#is-this-a-worthy-tradeoff&quot; aria-label=&quot;Anchor link for: is-this-a-worthy-tradeoff&quot;&gt;is this a worthy tradeoff?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;But consider all the elegance of the editor I&#x27;ve discussed so far — was the slowness of development a necessary evil to achieve it? Is it the reason I even switched to helix in the first place? It&#x27;s a difficult spot to be in emotionally, as I really do care deeply about this editor now 🥺.&lt;&#x2F;p&gt;
&lt;p&gt;Regardless, the issues that come from not having a plugin system is why many people, including me, decide to make a personal &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;helix fork&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Editing the source code of a text editor to get the missing features sounds, truthfully, insane. And like a lot of effort. That&#x27;s what I thought, at least!&lt;&#x2F;p&gt;
&lt;p&gt;Turns out, the developmental slowness has made the helix codebase &lt;em&gt;really&lt;&#x2F;em&gt; good. &lt;br &#x2F;&gt;
I don&#x27;t think I&#x27;m &lt;em&gt;that&lt;&#x2F;em&gt; good at rust, however I keep getting surprised at how &lt;em&gt;easy&lt;&#x2F;em&gt; it is to add new features in.&lt;&#x2F;p&gt;
&lt;p&gt;Especially coming from a &lt;em&gt;lot&lt;&#x2F;em&gt; of neovim configuration, I expect to go on a whole adventure to try to make something work, and then get surprised when my endeavor cost me 5 minutes at most.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-happy-dev-adventure&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-happy-dev-adventure&quot; aria-label=&quot;Anchor link for: a-happy-dev-adventure&quot;&gt;a happy dev adventure&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;One feature I have in my fork (all features are listed in the readme) is that you can remove the statusline.&lt;&#x2F;p&gt;
&lt;p&gt;Vaguely remembering how the statusline works in nvim, if you were to remove it, it would be unreasonable to think to enable it back on at runtime, without reloading neovim as a whole. &lt;br &#x2F;&gt;
I kept this assumption with helix — I put in only slight effort, &lt;em&gt;just&lt;&#x2F;em&gt; to be able to disable the statusline using a config option, not caring enough to implement the ability to switch it back on dynamically. &lt;br &#x2F;&gt;
After finishing the feature, I wanted to see &lt;em&gt;how much&lt;&#x2F;em&gt; things break if I try to &lt;code&gt;:toggle should-statusline&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Imagine my surprise when nothing broke 🤯 &lt;br &#x2F;&gt;
Matter of fact, the statusline showed up with all the information up-to-date, no less!&lt;&#x2F;p&gt;
&lt;p&gt;This flabbergastment of mine never stops: with every new feature I try to add, it generally goes far better than I expect. Traumatized by neovim configuration I guess! &lt;br &#x2F;&gt;
But it &lt;em&gt;makes sense&lt;&#x2F;em&gt;. Of &lt;em&gt;course&lt;&#x2F;em&gt; an editor that feels clean and consistent is also written in a clean and consistent way.&lt;&#x2F;p&gt;
&lt;p&gt;This is all to say that if you decide against using my fork for whatever reason, consider forking it yourself anyway. You&#x27;ll be pleased to see the features you want be easily addable, and considering how slow helix development moves, you won&#x27;t need to rebase on upstream that often. Because of this ease though, you&#x27;ll gain a habit of screaming &quot;WHY ISN&#x27;T THIS IN CORE ALREADY&quot;, like I did :&amp;gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>helix master vs stable</title>
          <pubDate>Fri, 11 Oct 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/helix-master-vs-stable/</link>
          <guid>https://axlefublr.github.io/helix-master-vs-stable/</guid>
          <description xml:base="https://axlefublr.github.io/helix-master-vs-stable/">&lt;p&gt;When considering switching to helix master, I went through all the commits after stable. &lt;br &#x2F;&gt;
Here are the new features I discovered.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;pickers&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#pickers&quot; aria-label=&quot;Anchor link for: pickers&quot;&gt;pickers&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;columns&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#columns&quot; aria-label=&quot;Anchor link for: columns&quot;&gt;columns&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There&#x27;s a picker refactor: most pickers now have columns, that you can search directly. &lt;br &#x2F;&gt;
Here&#x27;s how the bindings picker looks like now:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;helix-master-vs-stable&#x2F;.&#x2F;picker.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;shorthands&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#shorthands&quot; aria-label=&quot;Anchor link for: shorthands&quot;&gt;shorthands&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;And thanks to columns, it&#x27;s much nicer to use! &lt;br &#x2F;&gt;
You can type in &lt;code&gt;%column_name&lt;&#x2F;code&gt; to start searching in that column. &lt;br &#x2F;&gt;
So you can search by &lt;em&gt;specifically&lt;&#x2F;em&gt; documentation by using &lt;code&gt;%doc&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;helix-master-vs-stable&#x2F;.&#x2F;picker-column-search.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;a href=&quot;#shorter-hander&quot; id=&quot;shorter-hander&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Or just &lt;code&gt;%d&lt;&#x2F;code&gt;! The column matcher just needs to be unique, from the start of the column name; you don&#x27;t have to use the full name.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;helix-master-vs-stable&#x2F;.&#x2F;picker-shorter-column-search.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;a href=&quot;#dual-wielding&quot; id=&quot;dual-wielding&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;You can combine a normal search with a column search:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;helix-master-vs-stable&#x2F;.&#x2F;picker-combination.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And even multiple:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;helix-master-vs-stable&#x2F;.&#x2F;picker-combined.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;global-search&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#global-search&quot; aria-label=&quot;Anchor link for: global-search&quot;&gt;global_search&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The &lt;code&gt;global_search&lt;&#x2F;code&gt; action used to prompt you for the search in the commandline area, and then show the results at once. Now it is an interactive picker, and shows results as you type in the regex pattern:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;helix-master-vs-stable&#x2F;.&#x2F;global-search.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;a href=&quot;#also-column&quot; id=&quot;also-column&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Also has a column you can additionally filter by:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;helix-master-vs-stable&#x2F;.&#x2F;global-search-column.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;inline-diagnostics&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#inline-diagnostics&quot; aria-label=&quot;Anchor link for: inline-diagnostics&quot;&gt;inline diagnostics&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;There&#x27;s now an &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.helix-editor.com&#x2F;master&#x2F;editor.html#editorinline-diagnostics-section&quot;&gt;&lt;code&gt;inline-diagnostics&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; option in the &lt;code&gt;[editor]&lt;&#x2F;code&gt; section, that lets you have &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ErichDonGubler&#x2F;lsp_lines.nvim&quot;&gt;lsp-lines&lt;&#x2F;a&gt;-like diagnostics (without being super buggy, like that nvim plugin is).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;helix-master-vs-stable&#x2F;.&#x2F;lsp-lines.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;snippets&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#snippets&quot; aria-label=&quot;Anchor link for: snippets&quot;&gt;“snippets”&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Lsp snippets: when lsps complete extra text (default parameters for example), it now actually appears in the completed suggestion. It used to strangely dissapear. &lt;br &#x2F;&gt;
This snippet implementation is not full; you still can&#x27;t go to the previous &#x2F; next node in the snippet, for example.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;suggestions&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#suggestions&quot; aria-label=&quot;Anchor link for: suggestions&quot;&gt;suggestions&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Extra information for suggestions now appears at the top &#x2F; bottom of the screen, rather than being squished to the side of the suggestion box. So generally you get to look at it a bit more normally.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;helix-master-vs-stable&#x2F;.&#x2F;suggestion-information.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;macro-mappings&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#macro-mappings&quot; aria-label=&quot;Anchor link for: macro-mappings&quot;&gt;macro mappings&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;In mappings, you can now use @ to bind to literal keypresses. For example &lt;code&gt;&#x27;mw&#x27; = &#x27;@miw&#x27;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;camel-case-motion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#camel-case-motion&quot; aria-label=&quot;Anchor link for: camel-case-motion&quot;&gt;camel case motion&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Subword movement actions. Search for them with &lt;code&gt;sub_word&lt;&#x2F;code&gt; in the keybind picker. I went with using &lt;code&gt;gw&lt;&#x2F;code&gt;, &lt;code&gt;ge&lt;&#x2F;code&gt;, &lt;code&gt;gb&lt;&#x2F;code&gt; (the first two are mapped by default, I moved those default mappings elsewhere).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;various-fixes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#various-fixes&quot; aria-label=&quot;Anchor link for: various-fixes&quot;&gt;various fix&lt;del&gt;es&lt;&#x2F;del&gt;&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Hardlinks were broken: if you wrote to a hardlink, it wouldn&#x27;t update the other file. This was fixed in master.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>why I hate kitty</title>
          <pubDate>Fri, 13 Sep 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/why-i-hate-kitty/</link>
          <guid>https://axlefublr.github.io/why-i-hate-kitty/</guid>
          <description xml:base="https://axlefublr.github.io/why-i-hate-kitty/">&lt;p&gt;I say &quot;god I hate kitty&quot; a lot, but I usually can&#x27;t think of examples for &lt;em&gt;why&lt;&#x2F;em&gt; on the spot. &lt;br &#x2F;&gt;
I just encountered yet another &quot;god I hate&quot; about kitty, so I&#x27;m gonna write it down while it&#x27;s hot to transfer why I hate this terminal emulator so much.&lt;&#x2F;p&gt;
&lt;a href=&quot;#desire&quot; id=&quot;desire&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I wanted a certain feature: in the tab bar, usually I want tabs to just have their number displayed, and nothing else. But optionally, I should be able to add a title to an individual tab.&lt;&#x2F;p&gt;
&lt;p&gt;You might reasonably think &quot;oh that sure sounds like a job for a plugin&quot; and in any other app, something this specific would require a plugin, yes. &lt;br &#x2F;&gt;
Kitty, however, picks to be between a rock and a hard place.&lt;&#x2F;p&gt;
&lt;a href=&quot;#tab-title-template&quot; id=&quot;tab-title-template&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Usually when configuring things, ideas come to mind because I already have a very vague idea of how to do it &#x2F; assume it&#x27;s doable. &lt;br &#x2F;&gt;
It was the case here too: there&#x27;s an option called &lt;code&gt;tab_title_template&lt;&#x2F;code&gt; that lets you define the text displayed in each individual tab in the tab bar.&lt;&#x2F;p&gt;
&lt;p&gt;Aside from feeling a bit wonky (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sw.kovidgoyal.net&#x2F;kitty&#x2F;conf&#x2F;index.html#opt-kitty.tab_title_template&quot;&gt;have a look&lt;&#x2F;a&gt;), I actually quite like it because it&#x27;s pretty flexible for a config-based terminal emulator (rather than one that uses a programming language directly, like wezterm).&lt;&#x2F;p&gt;
&lt;p&gt;So I put in the title there and went on to configure.&lt;&#x2F;p&gt;
&lt;a href=&quot;#fish&quot; id=&quot;fish&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;A lot of terminal applications change the shell title (or window title you would usually call it?), so once I configured them to not, I was able to get to &lt;code&gt;fish_title&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;fish_title&lt;&#x2F;code&gt; is fish shell&#x27;s mechanism for setting the shell title, and it&#x27;s really cool!
You can use arbitrary fish shell logic to print the exact title that you want. &lt;br &#x2F;&gt;
I used to use it a long time ago, but found the concept of changing shell title more distracting than useful, so I removed it.&lt;&#x2F;p&gt;
&lt;p&gt;I came back to it now to try to make it more useful: usually the title would be some reasonable default I define in &lt;code&gt;fish_title&lt;&#x2F;code&gt;, but I could also override it to be something else instead. &lt;br &#x2F;&gt;
I used an arbitrary variable called &lt;code&gt;title&lt;&#x2F;code&gt; that I could set to do that overriding, all in my shell.&lt;&#x2F;p&gt;
&lt;p&gt;That sounds like a finished job, doesn&#x27;t it? But here comes in kitty, trying to be useful in the most annoying way.&lt;&#x2F;p&gt;
&lt;a href=&quot;#title-reporting&quot; id=&quot;title-reporting&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;&lt;code&gt;fish_title&lt;&#x2F;code&gt; runs before and after making your shell prompt, and there &lt;em&gt;can&lt;&#x2F;em&gt; be times where fish doesn&#x27;t report its title, or sets it to a blank string, before setting it again.&lt;&#x2F;p&gt;
&lt;p&gt;In actual usage what ended up happening, is sometimes my kitty tab title changed to &lt;code&gt;fish&lt;&#x2F;code&gt; for a flash, and then got back to the title defined in &lt;code&gt;fish_title&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
So I thought &quot;huh, maybe fish is reporting some &lt;code&gt;fish -c&lt;&#x2F;code&gt; action and so is setting the title to that?&quot; — my logic for making the title was pretty solid, but I assumed it allowed something like that to happen. &lt;br &#x2F;&gt;
My solution for this was to stop trying to make the title useful, and disable it completely. I set &lt;code&gt;fish_title&lt;&#x2F;code&gt; to be a blank function the echoes nothing.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine my horror when after doing so, I still see &lt;code&gt;fish&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
??? wtf the title is supposed to be blank now? &lt;br &#x2F;&gt;
And &lt;em&gt;now&lt;&#x2F;em&gt; I realize that fish was doing its work perfectly fine, and there was no issue there to begin with — it was &lt;em&gt;kitty&lt;&#x2F;em&gt;&#x27;s default messing things up.&lt;&#x2F;p&gt;
&lt;a href=&quot;#kitty-default&quot; id=&quot;kitty-default&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;So &lt;em&gt;turns out&lt;&#x2F;em&gt; (I don&#x27;t think it&#x27;s documented, at least I wasn&#x27;t able to come across this in the documentation) in kitty, if your shell hasn&#x27;t got the shell title set, it will default to whatever the current app running is. &lt;br &#x2F;&gt;
That &lt;code&gt;fish&lt;&#x2F;code&gt; was kitty saying &quot;hey! you&#x27;re running fish!&quot; because I was just looking at my shell.&lt;&#x2F;p&gt;
&lt;p&gt;I have some kitty mappings that open programs directly in overlay windows (which are REALLY cool btw), and once I opened &lt;code&gt;yazi&lt;&#x2F;code&gt; like that, I saw &lt;code&gt;yazi&lt;&#x2F;code&gt; in the window title.&lt;&#x2F;p&gt;
&lt;p&gt;Eureka! 🥳&lt;&#x2F;p&gt;
&lt;p&gt;You know what this means now? The fish shell titling mechanism is effectively useless, because kitty will interrupt and set a default intermittently with fish, so the tab title will jump jarringly and is therefore not worth using.&lt;&#x2F;p&gt;
&lt;a href=&quot;#set-tab-title&quot; id=&quot;set-tab-title&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I set the &lt;code&gt;shell_integration&lt;&#x2F;code&gt; kitty option to &lt;code&gt;no-title&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
While we disabled &lt;code&gt;fish_title&lt;&#x2F;code&gt;, some programs can still set the shell title themselves, and that option ensures that it&#x27;s ignored. Now only kitty has the capability to set its own tab titles.&lt;&#x2F;p&gt;
&lt;p&gt;Now practically every tab has &lt;code&gt;fish&lt;&#x2F;code&gt; in its title, that sometimes turns into &lt;code&gt;yazi&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;lazygit&lt;&#x2F;code&gt;. The latter is kinda cool, but having &lt;code&gt;fish&lt;&#x2F;code&gt; in every title is pretty jarringly useless.&lt;&#x2F;p&gt;
&lt;p&gt;The other piece of the puzzle, &lt;code&gt;set_tab_title&lt;&#x2F;code&gt;, is a kitty action you can map to, that will let you interactively change the tab title. &lt;br &#x2F;&gt;
With it, I have a solution: I could rename every tab I use to make more sense, rather than being just &lt;code&gt;fish&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
But also, that&#x27;s pretty unreasonable to ask of myself — I create and close tabs all the time, very quickly, and in reality I&#x27;ll just end up seeing a lot of 🐟es in my tab titles, and &lt;em&gt;sometimes&lt;&#x2F;em&gt; see my &lt;em&gt;actual&lt;&#x2F;em&gt; titles. &lt;br &#x2F;&gt;
All that plus I&#x27;ll feel more pressured to title tabs that I don&#x27;t actually care to have titles.&lt;&#x2F;p&gt;
&lt;p&gt;Between a rock and a hard place.&lt;&#x2F;p&gt;
&lt;a href=&quot;#disable&quot; id=&quot;disable&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;A VERY obvious solution that you might&#x27;ve just thought about is to just disable this default kitty functionality that sets the titles to begin with. Very reasonable! I thought about it too, but you can&#x27;t disable it, as far as I&#x27;m aware 💀&lt;&#x2F;p&gt;
&lt;p&gt;You might now think &quot;well surely that&#x27;s a bug! you should open an issue about this&quot; which is once again reasonable, but I already got burned on that with kitty.&lt;&#x2F;p&gt;
&lt;a href=&quot;#infamous-dev&quot; id=&quot;infamous-dev&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Kitty is infamous, first and foremost, for its unbearable dev. He instantly closes issues (which in itself is not an issue (lol)), rudely disregarding often times &lt;em&gt;reasonable&lt;&#x2F;em&gt; concerns.&lt;&#x2F;p&gt;
&lt;p&gt;My story: &lt;br &#x2F;&gt;
You can set the shape of the cursor in kitty with the &lt;code&gt;cursor_shape&lt;&#x2F;code&gt; option. It can be one of &lt;code&gt;block&lt;&#x2F;code&gt;, &lt;code&gt;beam&lt;&#x2F;code&gt;, &lt;code&gt;underline&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
There is also a &lt;code&gt;cursor_shape_unfocused&lt;&#x2F;code&gt; option. Does the same thing, but for when kitty is not in focus. &lt;em&gt;Except&lt;&#x2F;em&gt;, it can &lt;em&gt;also&lt;&#x2F;em&gt; be &lt;code&gt;hollow&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, you cannot set &lt;code&gt;cursor_shape&lt;&#x2F;code&gt; to &lt;code&gt;hollow&lt;&#x2F;code&gt;, but can set it for &lt;code&gt;cursor_shape_unfocused&lt;&#x2F;code&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;That seemed like an obvious misstep but I&#x27;ve been taught by others that sometimes even &quot;obvious&quot; things should be reported in issues and worked on in PRs, so I created a PR adding &lt;code&gt;hollow&lt;&#x2F;code&gt; to &lt;code&gt;cursor_shape&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;...Instantly rejected with something along the lines of &quot;this is stupid, the &lt;code&gt;hollow&lt;&#x2F;code&gt; shape shows that kitty is unfocused&quot;. &lt;br &#x2F;&gt;
This is awful on multiple levels.&lt;&#x2F;p&gt;
&lt;a href=&quot;#the-user-knows-better&quot; id=&quot;the-user-knows-better&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Sure, &lt;code&gt;cursor_shape&lt;&#x2F;code&gt; being &lt;code&gt;hollow&lt;&#x2F;code&gt; by default would be stupid, but there &lt;em&gt;should&lt;&#x2F;em&gt; be an option to set it, because it&#x27;s up to the &lt;em&gt;USER&lt;&#x2F;em&gt; to decide that for themselves. &lt;br &#x2F;&gt;
You &lt;strong&gt;never&lt;&#x2F;strong&gt; fully know the usecase of each user, and should allow them to be &quot;stupid&quot; if that&#x27;s what they actually want. &lt;br &#x2F;&gt;
The argument also doesn&#x27;t hold up because you can set set both &lt;code&gt;cursor_shape&lt;&#x2F;code&gt; and &lt;code&gt;cursor_shape_unfocused&lt;&#x2F;code&gt; to block and continue to &quot;not know if kitty is focused or not&quot;, so why should you be unable to set them both to &lt;code&gt;hollow&lt;&#x2F;code&gt;??&lt;&#x2F;p&gt;
&lt;p&gt;If your window manager and kitty window borders already make things clear, it&#x27;s not unreasonable to not care about the cursor shape, especially considering that the hollow cursor looks really cool! &lt;br &#x2F;&gt;
I would 30% understand if I opened an &lt;em&gt;issue&lt;&#x2F;em&gt;, but I opened a &lt;em&gt;PR&lt;&#x2F;em&gt; that just adds that, so all you have to do is press accept and blammo! The change is literally two lines, one of which is the docs, so even the maintenance argument doesn&#x27;t hold weight here.&lt;&#x2F;p&gt;
&lt;p&gt;This same exact feature request I opened as an &lt;em&gt;issue&lt;&#x2F;em&gt; in ghostty, the dev said &quot;huh I don&#x27;t see why not&quot; and implemented it a couple of days later. Night and day.&lt;&#x2F;p&gt;
&lt;p&gt;If this was my &lt;em&gt;only&lt;&#x2F;em&gt; interaction with the kitty dev, I would give him the benefit of the doubt (although would still be annoyed), but all I hear about the kitty dev from people is mostly stories like mine.&lt;&#x2F;p&gt;
&lt;a href=&quot;#that is why&quot; id=&quot;that is why&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Coming back to shell titles: this is why it&#x27;s not worth the effort to open an issue to make the default kitty titling behavior disableable.&lt;&#x2F;p&gt;
&lt;p&gt;I could potentially change it in source code and compile my own kitty, but I have no clue how to compile kitty — it feels like a big mishmash of everything that I really wouldn&#x27;t want to work with, even though I &lt;em&gt;do&lt;&#x2F;em&gt; keep a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Axlefublr&#x2F;helix&quot;&gt;helix fork&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;a href=&quot;#session&quot; id=&quot;session&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Next I came across &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sw.kovidgoyal.net&#x2F;kitty&#x2F;overview&#x2F;#sessions&quot;&gt;session files&lt;&#x2F;a&gt;. &lt;br &#x2F;&gt;
&quot;Surely the bee&#x27;s knees&quot; I thought — they allow you to specify a bunch of kitty commands to execute on startup. &lt;br &#x2F;&gt;
Buuuut on startup of the &lt;em&gt;instance&lt;&#x2F;em&gt;, so they won&#x27;t control each individual window &#x2F; tab, which is what I would need. &lt;br &#x2F;&gt;
Even calling &lt;code&gt;set_tab_title&lt;&#x2F;code&gt; in the session file didn&#x27;t do anything for even the first window (which I don&#x27;t exactly get).&lt;&#x2F;p&gt;
&lt;a href=&quot;#watchers&quot; id=&quot;watchers&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The final possibility is &quot;watchers&quot;. Python scripts that listen on kitty events and execute kitty code on them. That&#x27;s what I&#x27;m guessing they are anyway, because I dismissed them instantly out of this thought process: &lt;br &#x2F;&gt;
Oppositely from session files, the watcher would run on... when exactly? Let&#x27;s say I&#x27;m lucky and there&#x27;s a &quot;title changed&quot; event. &lt;br &#x2F;&gt;
Will that event run on &lt;em&gt;startup&lt;&#x2F;em&gt;? This is only based on my overall experience using kitty, but I assumed it would for some reason &lt;em&gt;not&lt;&#x2F;em&gt;, specialcasing when you first launch kitty, and working normally all the following windows. &lt;br &#x2F;&gt;
I have no reason to think this except kitty being similarly horrible to me like 20 other times, so this isn&#x27;t really a &quot;point&quot;. &lt;br &#x2F;&gt;
For all I know, watchers might be the bee&#x27;s knees but at this point I was tired and making a python script to work around yet another &quot;nice&quot; kitty behavior didn&#x27;t seem worth it.&lt;&#x2F;p&gt;
&lt;a href=&quot;#giving-up&quot; id=&quot;giving-up&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;So I give up. I get hyperfocused on things like this often and that can put me in a spiral. I went and did some house chores, until I got another idea...&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;tab_title_template&lt;&#x2F;code&gt;, this is offhandedly mentioned:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that formatting is done by Python’s string formatting machinery&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I mostly diregarded this because what in the living and dying hell is &quot;string formatting machinery&quot;.
The limits of how it actually works are not well defined in the docs, so that&#x27;s why I went on to try other options that &lt;em&gt;felt&lt;&#x2F;em&gt; viable, before coming to this one.&lt;&#x2F;p&gt;
&lt;a href=&quot;#possibility&quot; id=&quot;possibility&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;In the docs, we get this example: &lt;code&gt;{layout_name[:2].upper()}&lt;&#x2F;code&gt; &lt;br &#x2F;&gt;
I realize that I can at least slice strings and call methods on them. &lt;br &#x2F;&gt;
This by itself is not strong enough for what I&#x27;m trying to do, so I decided to take a gamble: what if &quot;string formatting machinery&quot; is actually &quot;python expression&quot;?&lt;&#x2F;p&gt;
&lt;p&gt;To reiterate the behavior that I want: usually the tab titles are &lt;code&gt;1&lt;&#x2F;code&gt;, where 1 is the amount of windows on that tab. I should also use my mapping for &lt;code&gt;set_tab_title&lt;&#x2F;code&gt; to append some text to it like &lt;code&gt;1 asdf&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So I need to somehow filter &lt;em&gt;all&lt;&#x2F;em&gt; titles that kitty might automatically set (i.e. any possible name for a program). I also need to handle the space after the number and before the title, and the rightmost space, to keep to correct padding.&lt;&#x2F;p&gt;
&lt;a href=&quot;#viola&quot; id=&quot;viola&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Behold: yet another kitty wack solution that does what I want, through a hack:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot; {fmt.fg.pink}{bell_symbol}{activity_symbol}{fmt.fg.tab}{num_windows}{title[0] == &amp;#39; &amp;#39; and title or &amp;#39;&amp;#39;} &amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;or, simplified,&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot; {num_windows}{title[0] == &amp;#39; &amp;#39; and title or &amp;#39;&amp;#39;} &amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It turned out that &quot;python string formatting machinery&quot; &lt;em&gt;does&lt;&#x2F;em&gt; just mean &quot;python expression&quot;. Amazing docs as always kitty, very clear &#x2F;s &lt;br &#x2F;&gt;
Using a python expression, I can use a ternary (the &lt;code&gt;and or&lt;&#x2F;code&gt; there) to filter out titles set by kitty.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m hoping and coping that no title set by kitty will start with a space (I would still be only slightly surprised, though, it&#x27;s kitty after all), &lt;br &#x2F;&gt;
and because I need a space between the number and the title, &lt;br &#x2F;&gt;
if I always start my tab titles with a space, I get to solve two issues in one approach!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;axlefublr.github.io&#x2F;why-i-hate-kitty&#x2F;.&#x2F;kitty-tab-title.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Press my &lt;code&gt;set_tab_title&lt;&#x2F;code&gt; hotkey&lt;&#x2F;li&gt;
&lt;li&gt;Type in &lt;code&gt; gist&lt;&#x2F;code&gt; (with a space before)&lt;&#x2F;li&gt;
&lt;li&gt;Bob becomes the brother of your parent&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;a href=&quot;#overcooked&quot; id=&quot;overcooked&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;So while I have my desired behavior, I&#x27;m obviously unhappy about it. It&#x27;s a hack as clear as day.&lt;&#x2F;p&gt;
&lt;p&gt;The real issue with kitty that makes me so mad at it, is that it shines gold coins at you all over the place, suggesting that making some feature you assume is obvious is going to be easy. &lt;br &#x2F;&gt;
It shows you multiple different approaches through its functionality, and so you think &quot;with so many options, surely this is trivial&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;And yet, time and time again, I come across poorly worded &#x2F; explained documentation, strange &quot;useful&quot; default behavior I have to work around, a very unhelpful dev that I can simply ignore trying to contact for better behavior, a messy project structure where it&#x27;s not viable (at least for me) to keep a personal fork, a billion features, all of which are somehow &lt;em&gt;just&lt;&#x2F;em&gt; not enough for the functionality I want, but enough to make me excited to try implementing it, and an autistic brain that makes me want to configure my tools in ways that &lt;em&gt;apparently&lt;&#x2F;em&gt; no one else has wanted. Somehow.&lt;&#x2F;p&gt;
&lt;p&gt;Sounds awful, doesn&#x27;t it? &lt;br &#x2F;&gt;
If you were as into configuring your terminal, I&#x27;m sure you would hate kitty too.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;All of these are reasons for why I use kitty but can&#x27;t recommend it. I &lt;em&gt;can&lt;&#x2F;em&gt; easily recommend alacritty, though.&lt;&#x2F;p&gt;
&lt;p&gt;Alacritty can&#x27;t do shit but doesn&#x27;t claim it can, so you have to just deal with it. Helix can&#x27;t do shit and doesn&#x27;t claim you can, so you have to just deal with it (you can draw the same connection between neovim and helix as I am drawing with kitty and alacritty).&lt;&#x2F;p&gt;
&lt;p&gt;I hope that draws a clear enough picture for my hatred towards this feline terminal emulator 🐈. I gave two examples here but you should subconsciously multiply them by at least 7. &lt;br &#x2F;&gt;
This is not my first or last kitty configuring adventure that goes in me hating it more, this is just the first time I caught it and decided to write it down.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-kitty-then&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-kitty-then&quot; aria-label=&quot;Anchor link for: why-kitty-then&quot;&gt;why kitty then?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The worst part about all of this is that I now have yet another cool and useful feature that is either hard or impossible to recreate in another terminal emulator, so I&#x27;m bound to use a terminal I despise.&lt;&#x2F;p&gt;
&lt;p&gt;Kitty has better looking and faster rendering than anything else (except &lt;em&gt;maybe&lt;&#x2F;em&gt; ghostty, although ime ghostty was slower, and I was &lt;em&gt;trying&lt;&#x2F;em&gt; to like ghostty so I doubt it was bias). &lt;br &#x2F;&gt;
It slightly boldens fonts which is REALLY weird for it to do but now I really love it and can&#x27;t live without. &lt;br &#x2F;&gt;
It doesn&#x27;t make ANY gui-like elements, which I hate especially in terminals: even the tab bar looks like it&#x27;s from a tui application. &lt;br &#x2F;&gt;
The remote window manipulation is super powerful, and I make a lot of use from windows, tabs, layouts, overlays (omg the overlays 😩) (yet another painful config adventure). &lt;br &#x2F;&gt;
Kitty can work as a &quot;server&quot; for kitty, letting you create new os windows practically instantly (ghostty can do this too but in a different way and slower) (this adventure was especially painful). &lt;br &#x2F;&gt;
The binding system is really powerful and lets me use chord mappings.&lt;&#x2F;p&gt;
&lt;p&gt;The supposed &quot;new best terminal&quot; ghostty has some of these features, but they often times are not as good, or just equal; some things are missing or work worse so I don&#x27;t feel encouraged to switch off kitty, and I am...&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;between a rock and a hard place&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</description>
      </item>
      <item>
          <title>a neat helix multicursor trick</title>
          <pubDate>Sun, 01 Sep 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/columnar-multicursors/</link>
          <guid>https://axlefublr.github.io/columnar-multicursors/</guid>
          <description xml:base="https://axlefublr.github.io/columnar-multicursors/">&lt;p&gt;You may sometimes want to set a bunch of multicursors on a lot of lines, where just holding &lt;code&gt;C&lt;&#x2F;code&gt; and letting key repeat do the job is a bit bothersome. &lt;br &#x2F;&gt;
So you &lt;code&gt;mip&lt;&#x2F;code&gt; to select inside paragraph, and use &lt;code&gt;s&lt;&#x2F;code&gt; to set cursors how you usually would with &lt;code&gt;C&lt;&#x2F;code&gt;, but with far less keystrokes&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;regex-column-showcase.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Doing this feels illegal fwiw, but it&#x27;s actually super valid for this usecase, where you want to act on a certain column, rather than anything that you can regex match by text. &lt;br &#x2F;&gt;
If you know exactly how many columns you need to match, you could also just &lt;code&gt;^.{30}&lt;&#x2F;code&gt; or something, but I generally don&#x27;t know. &lt;br &#x2F;&gt;
Regex is really powerful in theory, really fun to learn how to use it more creatively.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>why I hate lua</title>
          <pubDate>Fri, 05 Jul 2024 00:00:00 +0000</pubDate>
          <author>Axlefublr</author>
          <link>https://axlefublr.github.io/why-i-hate-lua/</link>
          <guid>https://axlefublr.github.io/why-i-hate-lua/</guid>
          <description xml:base="https://axlefublr.github.io/why-i-hate-lua/">&lt;p&gt;What I value most in a language is &lt;em&gt;functionality&lt;&#x2F;em&gt; — what and how easily the language lets me do things. &lt;br &#x2F;&gt;
No wonder! That&#x27;s what programming is kinda for: &lt;em&gt;doing cool things more easily&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
And here&#x27;s lua, that doesn&#x27;t even have an abstraction over something as simple as &lt;code&gt;.split()&lt;&#x2F;code&gt;. Ridiculous.&lt;&#x2F;p&gt;
&lt;a href=&quot;#std&quot; id=&quot;std&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Lua has a very weak standard library. You&#x27;ll find yourself reimplementing functionality that you&#x27;ll be flabbergasted isn&#x27;t there to begin with. &lt;br &#x2F;&gt;
Sure, some of that functionality might be simple to implement, but it shouldn&#x27;t be my job. &lt;br &#x2F;&gt;
Imagine doing the equivalent of implementing the &lt;code&gt;print&lt;&#x2F;code&gt; function in every new project you create. It&#x27;s disheartening.&lt;&#x2F;p&gt;
&lt;p&gt;Not only is the standard library weak, but it&#x27;s also not ergonomic. &lt;br &#x2F;&gt;
Whenever you want to push a value into an array (more precisely a list &#x2F; vector), the way that you&#x27;re used to doing so in basically every language on earth is this: &lt;code&gt;my_array.push(value)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Well duh! Right? Right...&lt;&#x2F;p&gt;
&lt;a href=&quot;#tables&quot; id=&quot;tables&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The way you do that in lua is &lt;code&gt;table.insert(my_table, value)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Oh it sure looks like the expanded version of the method syntax, so you can just do &lt;code&gt;my_table:insert(value)&lt;&#x2F;code&gt; and it&#x27;ll work surely&quot; — yeah that&#x27;s what I wished too. &lt;br &#x2F;&gt;
What is sometimes an implementation detail in some languages, is actually &lt;em&gt;the&lt;&#x2F;em&gt; way you&#x27;re supposed to call, what should be by all accounts, a &lt;em&gt;method&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Insert is not a method for any table, which is the obvious thing that you want, no. It&#x27;s a &lt;em&gt;function&lt;&#x2F;em&gt; that just happens to be in the &lt;code&gt;table&lt;&#x2F;code&gt; module. &lt;br &#x2F;&gt;
This kind of idea repeats with stuff like &lt;code&gt;math.abs()&lt;&#x2F;code&gt;, but math being stored in &lt;del&gt;the balls&lt;&#x2F;del&gt; a module is a pretty common thing across languages, and not too insulting. &lt;br &#x2F;&gt;
An &lt;em&gt;action&lt;&#x2F;em&gt; you&#x27;re doing on an &lt;em&gt;object&lt;&#x2F;em&gt; being a function is &lt;strong&gt;very&lt;&#x2F;strong&gt; insulting.&lt;&#x2F;p&gt;
&lt;a href=&quot;#symbol-soup&quot; id=&quot;symbol-soup&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;You know how you can fix this though? With inscrutable symbol soup!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;local&lt;&#x2F;span&gt;&lt;span&gt; my_table&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; setmetatable&lt;&#x2F;span&gt;&lt;span&gt;({}, { __index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; table })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And now you can do:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;my_table:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(value)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yipee 🥳 right? &lt;br &#x2F;&gt;
Yeah fuck no! Why is this bullshit not the default? It is not reasonable at all to insert that symbol soup every time you want to make a table, just to get slightly better syntax. &lt;br &#x2F;&gt;
The confusion you&#x27;ll get from (most) people is simply not worth it. &lt;br &#x2F;&gt;
So I&#x27;m stuck between a rock and a hard place.&lt;&#x2F;p&gt;
&lt;p&gt;You could I guess make this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;local function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; get_reasonable_table&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;   return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; setmetatable&lt;&#x2F;span&gt;&lt;span&gt;({}, { __index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; table })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But even with this, this is a bit stupid. &lt;br &#x2F;&gt;
Remember, we&#x27;re not doing this to inherit some table in our designed app, we&#x27;re doing this &lt;em&gt;just&lt;&#x2F;em&gt; to have slightly better syntax. &lt;br &#x2F;&gt;
So I once again argue that it&#x27;s not worth it.&lt;&#x2F;p&gt;
&lt;a href=&quot;#local&quot; id=&quot;local&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Notice how both that variable and function use the &lt;code&gt;local&lt;&#x2F;code&gt; keyword? &lt;br &#x2F;&gt;
Yeah that&#x27;s because both of those would otherwise be &lt;em&gt;global&lt;&#x2F;em&gt; by default. Because that&#x27;s a very good idea for a default &#x2F;s&lt;&#x2F;p&gt;
&lt;p&gt;To reiterate: why in living and dying hell are those not &lt;em&gt;local&lt;&#x2F;em&gt; by default? &lt;br &#x2F;&gt;
And then you&#x27;d maybe opt into globality via &lt;code&gt;global&lt;&#x2F;code&gt;?? Autohotkey does it and it&#x27;s great there! A bunch of other languages make globality more annoying to use, which is overall a good idea hehehe :3&lt;&#x2F;p&gt;
&lt;p&gt;Or perhaps they use the concept of &lt;code&gt;const&lt;&#x2F;code&gt;, which covers a lot of the cases for wanting globality anyway.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally confusingly, you need the &lt;code&gt;local&lt;&#x2F;code&gt; keyword even if you&#x27;re not in a block &#x2F; function. &lt;br &#x2F;&gt;
Because without it, the variable won&#x27;t just be global in the file you&#x27;re working on, nope — it&#x27;s going to be global to &lt;em&gt;everywhere&lt;&#x2F;em&gt;. &lt;br &#x2F;&gt;
So you put the &lt;code&gt;local&lt;&#x2F;code&gt; keyword to make the variable &quot;local to the module&quot;. This language is a god&#x27;s mistake.&lt;&#x2F;p&gt;
&lt;a href=&quot;#casing&quot; id=&quot;casing&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;But we continue on: if a feature exists, makes sense to use it. &lt;br &#x2F;&gt;
Even &lt;code&gt;goto&lt;&#x2F;code&gt;s have their use, I&#x27;m sure. &lt;br &#x2F;&gt;
(While writing I mentioned &lt;code&gt;goto&lt;&#x2F;code&gt;s as a joke, only to then realize they actually exist in lua... Yes, &lt;code&gt;goto&lt;&#x2F;code&gt;s, but &lt;strong&gt;not&lt;&#x2F;strong&gt; the FUCKING CONTINUE STATEMENT. Yes, really. I&#x27;m way ahead of you and I &lt;em&gt;have&lt;&#x2F;em&gt; been crying about it, don&#x27;t worry.)&lt;&#x2F;p&gt;
&lt;p&gt;The convention for variables and functions in lua seems to be using &lt;code&gt;snake_case&lt;&#x2F;code&gt;. Alrightie then.&lt;&#x2F;p&gt;
&lt;p&gt;Another convention, suggested by the lua language server, is to make at least the first letter of global variables uppercase.&lt;&#x2F;p&gt;
&lt;p&gt;What I think is suggests is &lt;code&gt;SCREAMING_SNAKE_CASE&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
This of course makes a lot of sense for global variables that are meant to be &lt;code&gt;const&lt;&#x2F;code&gt;s. &lt;br &#x2F;&gt;
(&quot;pinky promise &lt;code&gt;const&lt;&#x2F;code&gt;s&quot;, because the concept of actual &lt;code&gt;const&lt;&#x2F;code&gt; in lua doesn&#x27;t exist, and all variables are mutable) &lt;br &#x2F;&gt;
But not all global variables are meant to be &lt;code&gt;const&lt;&#x2F;code&gt;s, many of them will be global just so that they can be accessed from anywhere conveniently. So we can&#x27;t just lie and use that upper case, because it &lt;em&gt;will&lt;&#x2F;em&gt; confuse programmers looking at our code, when we modify (after instantiation) what looks like an immutable variable.&lt;&#x2F;p&gt;
&lt;p&gt;What other choice do we have? &lt;code&gt;PascalCase&lt;&#x2F;code&gt;? No!! That&#x27;s obscene. The convention is &lt;em&gt;still&lt;&#x2F;em&gt; &quot;variables use underscores to separate subwords&quot;, so why would we suddenly change that because of &lt;em&gt;globality&lt;&#x2F;em&gt;? It makes no sense.&lt;&#x2F;p&gt;
&lt;p&gt;And, I can understand a pascal case function, cause that does appear in some languages (like C#). A pascal case variable is really out of the blue, considering it&#x27;s not the usual case in lua, or any other language I&#x27;ve worked with.&lt;&#x2F;p&gt;
&lt;p&gt;So what am I left with? &lt;code&gt;This_stupid_bullshit&lt;&#x2F;code&gt;. To satisfy both conventions, I have to do something as ridiculous as that. I will shoot anyone that argues for this absolute strawman of a casing convention.&lt;&#x2F;p&gt;
&lt;p&gt;If we bring it back to using &lt;code&gt;SCREAMING_SNAKE_CASE&lt;&#x2F;code&gt; disregarding the &lt;code&gt;const&lt;&#x2F;code&gt;-related confusion, then we&#x27;d have to name &lt;em&gt;functions&lt;&#x2F;em&gt; in that case too. Which is a whole another level of cursed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D4BE98; background-color: #00000000;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA6962;&quot;&gt;local&lt;&#x2F;span&gt;&lt;span&gt; thingy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E49641;font-weight: bold;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A9B665;&quot;&gt; YEP_JUST_A_GLOBAL_FUNCTION&lt;&#x2F;span&gt;&lt;span&gt;(params)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What the fuck.&lt;&#x2F;p&gt;
&lt;a href=&quot;#ignore&quot; id=&quot;ignore&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;You might say &quot;well you could just ignore the suggestion by the language server&quot; — I wholeheartedly reject that notion. &lt;br &#x2F;&gt;
The lua language server will be used by the overwhelming majority of people that program in lua. &lt;br &#x2F;&gt;
The majority sets a standard, and a good programmer follows standards (yes, even if they&#x27;re stupid!). So I can&#x27;t just ignore it.&lt;&#x2F;p&gt;
&lt;p&gt;I haven&#x27;t looked at much lua code aside from that I wrote (cause remember, I fucking despise the language!), but it seems like the convention is to just never use global variables lol. Which is, like, fair.&lt;&#x2F;p&gt;
&lt;a href=&quot;#functions&quot; id=&quot;functions&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Lua uses the concept of &quot;first level citizen functions&quot;. Or however that concept is properly worded. &lt;br &#x2F;&gt;
Basically, functions are just values that you can assign to variables, and store in tables. &lt;br &#x2F;&gt;
That kind of behavior is actually pretty cool, and makes sense for the language. The problem I have with them is the syntax.&lt;&#x2F;p&gt;
&lt;p&gt;Think of basically any language that uses the concept of closures. &lt;br &#x2F;&gt;
Rust&#x27;s &lt;code&gt;|x|&lt;&#x2F;code&gt; (stupid but consise), python&#x27;s &lt;code&gt;lambda&lt;&#x2F;code&gt;, javascript&#x27;s &lt;code&gt;(x) =&amp;gt; {}&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
All three differentiate functions and closures, fwiw, so they might not be good examples, but my point is that you can make syntax for closures that is nice and consise. &lt;br &#x2F;&gt;
If you wanted to interpret functions and closures in the same way, using &lt;code&gt;fn&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;def&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;fun&lt;&#x2F;code&gt; &#x2F; etc works just as well.&lt;&#x2F;p&gt;
&lt;p&gt;Then why in living and dying hell does it &lt;em&gt;have to&lt;&#x2F;em&gt; be &lt;code&gt;function&lt;&#x2F;code&gt;. Bitch, you might as well write an entire poem just to define an anonymous closure in lua by that point. God am I mad at this in specific. &lt;br &#x2F;&gt;
Because of how &lt;em&gt;neat&lt;&#x2F;em&gt; the concept of &quot;functions are also closures&quot; is in lua, it&#x27;s very very commonly used. &lt;br &#x2F;&gt;
And any time you need to pass some closure as an argument, you have to boilerplate it with typing out &lt;code&gt;function&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
Just &lt;code&gt;fun&lt;&#x2F;code&gt;, &lt;code&gt;def&lt;&#x2F;code&gt;, &lt;code&gt;fn&lt;&#x2F;code&gt;, &lt;code&gt;func&lt;&#x2F;code&gt; would all work! I&#x27;m sure you might have a distaste for some of them, but you&#x27;ll probably see at least one to be &quot;alright as a closure starter&quot;. So yeah, it genuinely doesn&#x27;t need to be that long.&lt;&#x2F;p&gt;
&lt;a href=&quot;#newbies&quot; id=&quot;newbies&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Oh, lua is made to be readable and approachable to newbie programmers!&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;That&#x27;s a good benefit! &lt;br &#x2F;&gt;
There are for sure some things that make sense to change to make them more approachable to newbies. &lt;br &#x2F;&gt;
An example of that could be &lt;code&gt;{}&lt;&#x2F;code&gt; vs indentation in python. &lt;br &#x2F;&gt;
I have genuinely heard &lt;code&gt;{}&lt;&#x2F;code&gt; confusing people, and making it harder for people to read code. &lt;br &#x2F;&gt;
This is not the case for me anymore, but I do remember the time when I was just starting out, where that definitely &lt;em&gt;was&lt;&#x2F;em&gt; the case. &lt;code&gt;{}&lt;&#x2F;code&gt; were harder to visually parse.&lt;&#x2F;p&gt;
&lt;p&gt;You &lt;em&gt;&lt;strong&gt;cannot&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; make this same argument for &lt;code&gt;function&lt;&#x2F;code&gt; vs &lt;code&gt;func&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
The latter is just as visible as the former, and just as obvious &lt;em&gt;literally&lt;&#x2F;em&gt; as soon as you define your first function in lua. &lt;br &#x2F;&gt;
Your second function forward, you now have to &lt;em&gt;deal with&lt;&#x2F;em&gt; typing out the entirety of &lt;code&gt;function&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;a href=&quot;#lsp&quot; id=&quot;lsp&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Oh just autocomplete it&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yeah no. Most (lua) programmers are on vscode, and that editor will generally not be fast enough to make it worth it to complete &lt;code&gt;function&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
By the time the suggestion window appears and you pick the correct thing (cause also remember, most people don&#x27;t realize they can fuzzy search their suggestions), you would have already typed in &lt;code&gt;function&lt;&#x2F;code&gt;. &lt;br &#x2F;&gt;
So the result is you always just typing in &lt;code&gt;function&lt;&#x2F;code&gt; yourself. &lt;code&gt;func&lt;&#x2F;code&gt; would reduce that by &lt;strong&gt;half&lt;&#x2F;strong&gt;, and would be quite ergonomic.&lt;&#x2F;p&gt;
&lt;a href=&quot;#patterns&quot; id=&quot;patterns&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Actually, forget that &quot;approachable to newbies&quot; point, cause it&#x27;s obscene in its own sense. Let&#x27;s talk about lua &lt;em&gt;patterns&lt;&#x2F;em&gt;. Do you know how they work? I sure don&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of implementing regex, lua has its own flavor of pattern matching with its &lt;code&gt;gsub&lt;&#x2F;code&gt;s and the like. In those, you have to use lua patterns. &lt;br &#x2F;&gt;
They &lt;em&gt;sometimes&lt;&#x2F;em&gt; resemble regex, but for some odd reason don&#x27;t try to fully emulate it. &lt;br &#x2F;&gt;
And let me also mention that you can&#x27;t just &lt;code&gt;my_str:contains(literal_string)&lt;&#x2F;code&gt; — you&#x27;d have to use &lt;code&gt;gmatch&lt;&#x2F;code&gt; I believe, and that has to use lua patterns, meaning you can&#x27;t just conveniently raw compare a substring. &lt;br &#x2F;&gt;
What a travesty.&lt;&#x2F;p&gt;
&lt;p&gt;The main point behind not implementing regex is that it would double the size of the lua binary. &lt;br &#x2F;&gt;
I personally couldn&#x27;t give two shits, but I can see it as an important concern, so I don&#x27;t have much against that point.&lt;&#x2F;p&gt;
&lt;p&gt;So, what I&#x27;d expect is for lua to match the syntax of regex, but just have a bunch of missing features. &lt;br &#x2F;&gt;
If that was the case, there wouldn&#x27;t be a &quot;patterns&quot; section in this rant. &lt;br &#x2F;&gt;
But no, lua decides to use its own syntax, that you now have to learn, even if you&#x27;re familiar with regex.&lt;&#x2F;p&gt;
&lt;p&gt;Why do I then not complain about rust not having regex? &lt;br &#x2F;&gt;
That&#x27;s because it has enough features to make it very viable to not use it — you have other ways of achieving the same text parsing objective. And you have the obvious &lt;code&gt;.contains()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;a href=&quot;#then&quot; id=&quot;then&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Coming back to syntax: why does &lt;code&gt;then&lt;&#x2F;code&gt; need to exist? &lt;br &#x2F;&gt;
It&#x27;s used in &lt;code&gt;if&lt;&#x2F;code&gt; statements for example. Statements that only take a single expression as a condition anyway. &lt;br &#x2F;&gt;
So it&#x27;s already as clear as day where that condition ends! Because it&#x27;s required to end after a single expression! &lt;br &#x2F;&gt;
And so, everything else should be considered the body of the &lt;code&gt;if&lt;&#x2F;code&gt; statement, and there&#x27;s no confusion. &lt;br &#x2F;&gt;
And yet we stil have &lt;code&gt;then&lt;&#x2F;code&gt; for some odd reason. Fish shell very comfortably doesn&#x27;t!&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t like the &lt;code&gt;end&lt;&#x2F;code&gt;-type &quot;bracket keywords&quot; in programming languages, but I can see how it&#x27;s needed in something like fish shell. &lt;br &#x2F;&gt;
It does not need to be so in a &quot;proper programming language&quot; which I expected lua to be.&lt;&#x2F;p&gt;
&lt;a href=&quot;#why&quot; id=&quot;why&quot; class=&quot;anchorina&quot;&gt;
  &lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Worst thing about lua is the fact that every goddamn configurable thingy in existence seems to immediately go for this piece of shit language, resulting in both my window manager and text editor to be configured in it. &lt;br &#x2F;&gt;
Lua is unfortunately my most used programming language, however mad I am at this fact being the truth.&lt;&#x2F;p&gt;
&lt;p&gt;Other languages that I&#x27;ve seen people dislike are lisp and haskell. &lt;br &#x2F;&gt;
I haven&#x27;t tried either of them, maybe I would like them maybe not, but regardless, I retain my possibility of avoiding them if I so desire. Lua is fucking inescapable.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Oh you might like Fennel then!&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;(yes every possible argument made towards me by the reader will start with &quot;Oh&quot;)&lt;&#x2F;p&gt;
&lt;p&gt;Good suggestion! I honestly might. &lt;br &#x2F;&gt;
But having to use a language to fix another is just another proof of lua being a shit language. Kinda like the javascript vs typescript situation.&lt;&#x2F;p&gt;
&lt;p&gt;What I use lua for is configuration. If I want &lt;em&gt;functionality&lt;&#x2F;em&gt;, I&#x27;ll pick fish shell any day over lua. &lt;br &#x2F;&gt;
So creating a level of abstraction over my configuration-based lua is just an extra complexity that I&#x27;ll have to &lt;em&gt;deal&lt;&#x2F;em&gt; with. Making it not worth it conceptually. &lt;br &#x2F;&gt;
This is the reason why I haven&#x27;t rewritten my neovim config in rust (which you can supposedly do, as it turns out).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;p-s&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#p-s&quot; aria-label=&quot;Anchor link for: p-s&quot;&gt;P.S.&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Everything I&#x27;ve learnt about lua was against my will, so if I&#x27;m wrong on some points in this rant, don&#x27;t be surprised. &lt;br &#x2F;&gt;
I&#x27;m not interested in giving a language I hate more time than I already do, to learn how to circumvent its annoyances. &lt;br &#x2F;&gt;
This rant is also against &lt;em&gt;lua&lt;&#x2F;em&gt;, not against &lt;em&gt;lua likers&lt;&#x2F;em&gt;. I believe it&#x27;s (almost) always better to like something than to not, so if you enjoy the language, you&#x27;re better off than me!&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
