<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>OddKnight&apos;s Space</title><link>https://oddknight.space/</link><description>OddKnight&apos;s personal webpage. Thanks for stopping by!</description><language>en</language><atom:link href="https://oddknight.space/rss.xml" rel="self" type="application/rss+xml"/><item><title>Switch Tab with Ctrl+Number</title><link>https://oddknight.space/blog/switch-tab-ctrl-number</link><guid isPermaLink="true">https://oddknight.space/blog/switch-tab-ctrl-number</guid><description>My tiny Firefox extension that brings Ctrl+1..9 tab switching to Linux</description><content:encoded><![CDATA[<p>I made a tiny Firefox extension.</p>
<p>On Windows and macOS, Firefox lets you jump to tabs with <code>Ctrl+1</code> … <code>Ctrl+8</code>, and <code>Ctrl+9</code> jumps to the last tab. On Linux? Nope. That bugged me enough that I just fixed it myself.</p>
<p>So this extension does exactly one thing:</p>
<ul>
<li><code>Ctrl+1</code> … <code>Ctrl+8</code> switch to tab 1-8</li>
<li><code>Ctrl+9</code> switch to the last tab</li>
</ul>
<p>No toolbar button, no settings page, no tracking. It just listens for those shortcuts and activates the right tab in the current window.</p>
<h2 id="download" tabindex="-1">Download</h2>
<p><a href="https://oddknight.space/downloads/switch-tab-ctrl-number-1.0.0.xpi" download>Download switch-tab-ctrl-number-1.0.0.xpi (v1.0.0, Firefox 109+)</a></p>
<h2 id="install" tabindex="-1">Install</h2>
<p>Firefox doesn't let you install random <code>.xpi</code> files with one click from a personal site, so:</p>
<ol>
<li>Download the file above.</li>
<li>Go to <code>about:addons</code> in Firefox.</li>
<li>Click the gear icon → <strong>Install Add-on From File…</strong></li>
<li>Pick the downloaded <code>.xpi</code> and confirm.</li>
</ol>
<p>Or drag-and-drop the <code>.xpi</code> file onto a Firefox window.</p>
<p>After that, just press <code>Ctrl+1</code> … <code>Ctrl+9</code> and enjoy Windows-style tab switching on Linux.</p>
<h2 id="source-code" tabindex="-1">Source code</h2>
<p>The whole thing is two files. That's it.</p>
<p><code>background.js</code>:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> switchToTab</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">slot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> tabs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> browser.tabs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">query</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({ currentWindow: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> });</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (tabs.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> ordered</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tabs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">slice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">b</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a.index </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> b.index);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> slot </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 9</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ?</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ordered[ordered.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ordered[slot </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">];</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (target) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> browser.tabs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(target.id, { active: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">browser.commands.onCommand.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">addListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> match</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">^</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF">switch-to-tab-(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">[1-9]</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">exec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">match) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  switchToTab</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">parseInt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(match[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">});</span></span>
<span class="line"></span></code></pre>
<p><code>manifest.json</code>:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "manifest_version"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch Tab with Ctrl+Number"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "version"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1.0.0"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch tabs with Ctrl+1..8 (and Ctrl+9 for last tab) on Linux Firefox, matching the Windows/macOS behavior."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "browser_specific_settings"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "gecko"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "id"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"switch-tab-ctrl-number@dmitryside"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "strict_min_version"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"109.0"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "data_collection_permissions"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "required"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">          "none"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "background"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "scripts"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      "background.js"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "commands"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "switch-to-tab-1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "suggested_key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "default"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Ctrl+1"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch to tab 1"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "switch-to-tab-2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "suggested_key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "default"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Ctrl+2"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch to tab 2"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "switch-to-tab-3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "suggested_key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "default"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Ctrl+3"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch to tab 3"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "switch-to-tab-4"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "suggested_key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "default"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Ctrl+4"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch to tab 4"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "switch-to-tab-5"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "suggested_key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "default"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Ctrl+5"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch to tab 5"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "switch-to-tab-6"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "suggested_key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "default"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Ctrl+6"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch to tab 6"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "switch-to-tab-7"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "suggested_key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "default"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Ctrl+7"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch to tab 7"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "switch-to-tab-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "suggested_key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "default"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Ctrl+8"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch to tab 8"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "switch-to-tab-9"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "suggested_key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "default"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Ctrl+9"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      "description"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Switch to last tab"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span></code></pre>
<p>No bundlers, no minified blob, no network requests. It queries the tabs in the current window, picks the one at the requested index (or the last one for <code>Ctrl+9</code>), and activates it.</p>
<h2 id="check-it-yourself" tabindex="-1">Check it yourself</h2>
<p>An <code>.xpi</code> is just a <code>.zip</code>. You don't have to trust the code block above. Inspect the exact file you're installing:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 1. Download it, then list what's inside</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unzip</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -l</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> switch-tab-ctrl-number-1.0.0.xpi</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 2. Unpack it somewhere</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">mkdir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ext-src</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;&#x26; </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unzip</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> switch-tab-ctrl-number-1.0.0.xpi</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ext-src</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ls</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -R</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ext-src</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 3. Read the actual code</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">cat</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ext-src/manifest.json</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">cat</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ext-src/background.js</span></span>
<span class="line"></span></code></pre>
<p>You'll see <code>background.js</code>, <code>manifest.json</code>, plus a <code>META-INF/</code> folder. That folder (<code>cose.sig</code>, <code>mozilla.rsa</code>, etc.) is Mozilla's signature — it's what lets Firefox install the file without complaining about it being unsigned. You can ignore it for review purposes; the executable part is only the two files above.</p>
<p>Optional, verify the download wasn't corrupted/tampered with in transit:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sha256sum</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> switch-tab-ctrl-number-1.0.0.xpi</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># expected: 239813cbb50b615608527fd364bab75ea6c1e853b6266cc58e6ab5b579e4e90c</span></span>
<span class="line"></span></code></pre>
<p>If the hash matches and the two source files match what's posted here, you're running exactly what I wrote.</p>
]]></content:encoded><pubDate>Sun, 13 Sep 2026 00:00:00 GMT</pubDate></item><item><title>My Blog</title><link>https://oddknight.space/blog/my-blog</link><guid isPermaLink="true">https://oddknight.space/blog/my-blog</guid><description>Thoughts on my blog</description><content:encoded><![CDATA[<p>Still thinking about it</p>
<p><img src="https://oddknight.space/img/my-blog/post.jpg" alt="post" loading="lazy" decoding="async"></p>
]]></content:encoded><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Top Text</title><link>https://oddknight.space/blog/top-text</link><guid isPermaLink="true">https://oddknight.space/blog/top-text</guid><description>Top Text</description><content:encoded><![CDATA[<p>Top Text</p>
<p><img src="https://oddknight.space/img/top-text/top-text.jpg" alt="top text" loading="lazy" decoding="async"></p>
]]></content:encoded><pubDate>Thu, 05 Jun 2025 00:00:00 GMT</pubDate></item><item><title>So...</title><link>https://oddknight.space/blog/so</link><guid isPermaLink="true">https://oddknight.space/blog/so</guid><description>It&apos;s been a while</description><content:encoded><![CDATA[<p>Okay, it's been a while since I posted the last time. I have a lot of things going on right now (not many frankly) and I couldn't quite find the time and/or urge to sit down and write a goddamn post for my bloody website.</p>
<p>So originally I was going to write a review for a book and I even got a couple of paragraphs done, but now reading the draft I realize it's completely irrelevant and lacks consistency. In other words, I'm not going to post it anytime soon, at least until I rewrite the whole draft to my liking.</p>
<p>As for the older posts, I'm sure I'll get rid of them eventually. They feel like placeholders, and for some reason, I now find them embarrassing. But I don't want the blog page to be completely empty, so I guess I'll leave it as it is until I write one or two more posts.</p>
<p>So yeah. Every post I've written is cringe and will be removed (except for the sheep).</p>
<p>Stay tuned</p>
]]></content:encoded><pubDate>Sat, 16 Nov 2024 00:00:00 GMT</pubDate></item><item><title>My first blender model</title><link>https://oddknight.space/blog/my-first-blender-model</link><guid isPermaLink="true">https://oddknight.space/blog/my-first-blender-model</guid><description>My hideous first time modeling experience</description><content:encoded><![CDATA[<p>So here it is. I made this sheep back in 2017.</p>
<p><img src="https://oddknight.space/img/my-first-blender-model/sheep.webp" alt="sheep" loading="lazy" decoding="async"></p>
<p>I have no idea why I'm sharing this. Yes, I know it's disgusting.</p>
]]></content:encoded><pubDate>Sat, 06 Apr 2024 00:00:00 GMT</pubDate></item><item><title>Comic Sans</title><link>https://oddknight.space/blog/comic-sans</link><guid isPermaLink="true">https://oddknight.space/blog/comic-sans</guid><description>About the most beautiful font in the world</description><content:encoded><![CDATA[<h2 id="the-true-beauty" tabindex="-1">The true beauty</h2>
<p>You heard me right. I freakin' love <strong>Comic Sans</strong>.</p>
<p>In the world of typography, Comic Sans gets a bad rap. It's always made fun of by design snobs and relegated to children's birthday party flyers or poor promos. But I'm here to argue that this playful font is deeply underrated. Sure, <strong>Comic Sans</strong> might not be the most sophisticated choice for a legal document or a scientific paper. But for what it's designed to do – add a touch of whimsy and informality –  Comic Sans excels.</p>
<p>Think about it. This font is perfect for capturing a sense of fun and friendliness. It's inviting and approachable, a quality that many fonts lack. Here's the thing: not everything needs to be taken so seriously. Sometimes, you just want a font that <em>slaps</em>. Comic Sans does that perfectly.</p>
<p>So get your dirty hands off my beloved font!</p>
<h3 id="upd" tabindex="-1">UPD</h3>
<p>I like this font so much I even started using it on this site. Well, not Comic Sans exactly — I switched everything over to <a href="https://github.com/dtinth/comic-mono-font">Comic Mono</a> instead. Same energy, just monospace.</p>
]]></content:encoded><pubDate>Wed, 03 Apr 2024 00:00:00 GMT</pubDate></item><item><title>Productivity, I guess?</title><link>https://oddknight.space/blog/productivity-i-guess</link><guid isPermaLink="true">https://oddknight.space/blog/productivity-i-guess</guid><description>Some notes on my laziness</description><content:encoded><![CDATA[<p>I'm starting to take some notes. Let's see how it goes.</p>
<p><em>NOTE: It was made long time ago</em></p>
<h2 id="my-productivity" tabindex="-1">My productivity</h2>
<p><em>Near zero</em>. Lately, I've fallen into a procrastination trap. I wait for the mythical <em>&quot;perfect moment&quot;</em> to focus on work, but it never arrives. Even though I have uninterrupted time throughout the day, the excuse of needing complete silence keeps circling in my head. (Right now, I'm writing this instead of working on my Django project for uni – classic procrastination!)</p>
<p>The struggle is real – tasks can feel uninspiring, and on the flip side, I haven't discovered any hobbies that truly excite me. During free time after exams, I fill the void with activities like endless Twitter scrolling or mindless gaming, but this &quot;rest&quot; feels hollow. It's a vicious cycle: I wake up with the intention to be productive, but the &quot;later&quot; monster whispers in my ear, and procrastination wins again.</p>
<p>I really want to break free from this cycle and find a way to use my free time productively and discover activities that bring me genuine joy.</p>
]]></content:encoded><pubDate>Thu, 28 Mar 2024 00:00:00 GMT</pubDate></item><item><title>My favorite things</title><link>https://oddknight.space/blog/my-favorite-things</link><guid isPermaLink="true">https://oddknight.space/blog/my-favorite-things</guid><description>List of things that OddKnight (me) likes</description><content:encoded><![CDATA[<p>Here's a small list of things that I like (<em>might be updated later</em>)</p>
<blockquote>
<p><em><strong>Quick note: The numbers in the list do not indicate significance or quality.</strong></em></p>
</blockquote>
<h2 id="movies" tabindex="-1">Movies</h2>
<ol>
<li><strong>Whiplash</strong></li>
<li>Any film with <strong>Ryan Gosling</strong> 🥰</li>
<li><strong>Inside Llewyn Davis</strong></li>
<li>Any film by <strong>Denis Villeneuve</strong></li>
</ol>
<h2 id="books" tabindex="-1">Books</h2>
<ol>
<li><strong>Martin Eden</strong> by Jack London</li>
<li><strong>The Witcher</strong>  series by Andrzej Sapkowski</li>
<li><strong>The Dark Tower</strong> series by Stephen King</li>
</ol>
<h2 id="games" tabindex="-1">Games</h2>
<ol>
<li><strong>Disco Elysium</strong></li>
<li><strong>Cyberpunk 2077</strong></li>
<li><strong>Risk of Rain 2</strong></li>
<li><strong>Dead by Daylight</strong></li>
<li><strong>The Witcher 3: Wild Hunt</strong></li>
</ol>
]]></content:encoded><pubDate>Sat, 02 Mar 2024 00:00:00 GMT</pubDate></item></channel></rss>