<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oliver Burn</title>
    <description>The latest articles on DEV Community by Oliver Burn (@oliverburn).</description>
    <link>https://dev.to/oliverburn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F105162%2Fef9ebc78-62f0-41b6-b5a4-ce89d3e78631.png</url>
      <title>DEV Community: Oliver Burn</title>
      <link>https://dev.to/oliverburn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oliverburn"/>
    <language>en</language>
    <item>
      <title>Emacs 2024 Changes</title>
      <dc:creator>Oliver Burn</dc:creator>
      <pubDate>Wed, 01 Jan 2025 09:16:08 +0000</pubDate>
      <link>https://dev.to/oliverburn/emacs-2024-changes-4n0p</link>
      <guid>https://dev.to/oliverburn/emacs-2024-changes-4n0p</guid>
      <description>&lt;p&gt;Wow, it has been nearly two years since I have blogged - time to see if I can still do it. Let's blog about how my Emacs configuration has changed over the last year (2024).&lt;/p&gt;

&lt;p&gt;I have now been using Emacs for over thirty years. It used to be the main IDE I wrote code with, but I have long since moved to a dedicated IDE, these days being IntelliJ and VSCode. But, I still using Emacs heavily into two contexts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Work - I use &lt;a href="https://orgmode.org/" rel="noopener noreferrer"&gt;org-mode&lt;/a&gt; &lt;strong&gt;heavily&lt;/strong&gt; for my personal project management and note keeping.&lt;/li&gt;
&lt;li&gt;Home - I use &lt;a href="https://github.com/ledger/ledger-mode" rel="noopener noreferrer"&gt;ledger-mode&lt;/a&gt; for managing my personal finances.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Across both contexts, I lean heavily on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.gnu.org/s/emacs/manual/html_node/emacs/Dired.html" rel="noopener noreferrer"&gt;Dired&lt;/a&gt; as a cross-platform file manager. I used to use &lt;a href="https://midnight-commander.org/" rel="noopener noreferrer"&gt;Midnight Commander&lt;/a&gt; but I found it buggy in the end (on MacOS). Since investing time in learning &lt;code&gt;dired&lt;/code&gt; it's &lt;em&gt;good enough&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://magit.vc/" rel="noopener noreferrer"&gt;Magit&lt;/a&gt; for using Git - I would be lost without this.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As a &lt;a href="https://www.linkedin.com/in/robbieg8s/" rel="noopener noreferrer"&gt;friend of mine&lt;/a&gt; said when I asked why he kept working on his &lt;code&gt;zsh&lt;/code&gt; configuration, &lt;em&gt;"it's my version of golf!"&lt;/em&gt;. Similarly I am often looking to improve my Emacs configuration. I keep up to date by tracking the blogs of &lt;a href="https://sachachua.com/blog/" rel="noopener noreferrer"&gt;Sacha Chua&lt;/a&gt; and &lt;a href="https://irreal.org/blog/" rel="noopener noreferrer"&gt;Irreal&lt;/a&gt;, and seeing what takes my fancy.&lt;/p&gt;

&lt;p&gt;In the last year I did 25 commits to my &lt;code&gt;.emacs&lt;/code&gt; file (yes, it's under Git source control). Here are the major changes I made over the last year:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For my templating needs, I moved to &lt;a href="https://github.com/minad/tempel" rel="noopener noreferrer"&gt;tempel&lt;/a&gt; (from &lt;a href="https://github.com/joaotavora/yasnippet" rel="noopener noreferrer"&gt;yasnippet&lt;/a&gt;). I have found it to be way more powerful and grok-able.&lt;/li&gt;
&lt;li&gt;For completions, I finally embraced using &lt;a href="https://github.com/minad/corfu" rel="noopener noreferrer"&gt;corfu&lt;/a&gt;, which is nice (especially the integration with &lt;code&gt;tempel&lt;/code&gt;). I almost gave up until I realised that I needed to also install &lt;a href="https://github.com/minad/cape" rel="noopener noreferrer"&gt;cape&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I gave up on trying to use a terminal emulator in Emacs, and instead now use &lt;a href="https://github.com/davidshepherd7/terminal-here" rel="noopener noreferrer"&gt;terminal-here&lt;/a&gt; to open a &lt;em&gt;proper&lt;/em&gt; terminal in the current working directory. This approach works much better for me.&lt;/li&gt;
&lt;li&gt;I improved my &lt;code&gt;dired&lt;/code&gt; setup by installing &lt;a href="https://codeberg.org/amano.kenji/dired-single" rel="noopener noreferrer"&gt;dired-single&lt;/a&gt;, &lt;a href="https://github.com/Fuco1/dired-hacks#dired-collapse" rel="noopener noreferrer"&gt;dired-collapse&lt;/a&gt; and &lt;a href="https://github.com/Fuco1/dired-hacks#dired-subtree" rel="noopener noreferrer"&gt;dired-subtree&lt;/a&gt;. I also learned about &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Wdired.html" rel="noopener noreferrer"&gt;wdired-mode&lt;/a&gt; which makes the &lt;code&gt;dired&lt;/code&gt; buffer editable (a game changer). 🤯&lt;/li&gt;
&lt;li&gt;I use &lt;a href="https://asdf-vm.com/" rel="noopener noreferrer"&gt;asdf&lt;/a&gt; and &lt;a href="https://direnv.net/" rel="noopener noreferrer"&gt;direnv&lt;/a&gt; to manage my toolchain at the project level, so to improve the integration with Emacs I installed &lt;a href="https://github.com/purcell/envrc" rel="noopener noreferrer"&gt;envrc&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This blogpost was originally posted at &lt;a href="https://puppycrawl.com/blog/2024/01/01/emacs-changes.html" rel="noopener noreferrer"&gt;https://puppycrawl.com/blog/2024/01/01/emacs-changes.html&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>emacs</category>
      <category>configuration</category>
      <category>2024</category>
    </item>
    <item>
      <title>Using asdf to manage my development tools</title>
      <dc:creator>Oliver Burn</dc:creator>
      <pubDate>Thu, 12 Jan 2023 06:39:47 +0000</pubDate>
      <link>https://dev.to/oliverburn/using-asdf-to-manage-my-development-tools-9hm</link>
      <guid>https://dev.to/oliverburn/using-asdf-to-manage-my-development-tools-9hm</guid>
      <description>&lt;p&gt;Today I was reminded again of the tool &lt;a href="https://asdf-vm.com"&gt;asdf&lt;/a&gt; which can &lt;em&gt;manage multiple runtime versions with a single CLI tool&lt;/em&gt;. I have been a long-time user of &lt;a href="https://sdkman.io"&gt;Sdkman&lt;/a&gt; for managing my JVM related tool chain (JDK, Kotlin, Gradle, etc), but then I use &lt;a href="https://brew.sh"&gt;Homebrew&lt;/a&gt; for managing Nodejs, Python, Poetry.&lt;/p&gt;

&lt;p&gt;I don't like that this approach as it is not cross-platform (by which I mean Linux and MacOS), and uses a combination of tools - &lt;code&gt;asdf&lt;/code&gt; and &lt;code&gt;homebrew&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So I have decided to try out &lt;code&gt;asdf&lt;/code&gt; in anger. It's quite easy to get started following the documentation, but the main things to annoy me are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;By default it does not respect existing files like &lt;code&gt;.nvmrc&lt;/code&gt; when picking a version of a tool. You need to add &lt;code&gt;legacy_version_file = yes&lt;/code&gt; to the file &lt;code&gt;~.asdfrc&lt;/code&gt; to enable this behaviour.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When installing a new tool, it does not immediately register it as the global default. For example, installing &lt;code&gt;gradle&lt;/code&gt; requires two commands: &lt;code&gt;asdf install gradle latest&lt;/code&gt; and &lt;code&gt;asdf global gradle latest&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It does not handle JDK distributions as well as &lt;code&gt;sdkman&lt;/code&gt;, which is hardly a surprise. The support for upgrading multiple versions (11 and 17) is clunky.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I have written the following script that works around these limitations, and can be used to boostrap and update my &lt;code&gt;asdf&lt;/code&gt; installation. Sharing in case it's useful for others.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env zsh&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Updates my asdf install. Very basic for now.&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Fail quickly&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="c"&gt;# Ensure sensible configuration file&lt;/span&gt;
&lt;span class="nv"&gt;rcfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.asdfrc
&lt;span class="nb"&gt;echo &lt;/span&gt;Checking &lt;span class="nv"&gt;$rcfile&lt;/span&gt;...
&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$rcfile&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="nv"&gt;$rcfile&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; legacy_version_file &lt;span class="nv"&gt;$rcfile&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; ...adding &lt;span class="s1"&gt;'legacy_version_file = yes'&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'legacy_version_file = yes'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$rcfile&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Update installed plugins&lt;/span&gt;
&lt;span class="nb"&gt;echo &lt;/span&gt;Updating installed plugins...
asdf plugin-update &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null

&lt;span class="c"&gt;# Ensure all the plugins are installed&lt;/span&gt;
&lt;span class="nb"&gt;echo &lt;/span&gt;Checking plugins are installed...
&lt;span class="k"&gt;for &lt;/span&gt;n &lt;span class="k"&gt;in &lt;/span&gt;java kotlin gradle python poetry nodejs&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    if &lt;/span&gt;asdf plugin-list | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-cq&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="c"&gt;# Already installed&lt;/span&gt;
    &lt;span class="k"&gt;else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; ...installing &lt;span class="nv"&gt;$n&lt;/span&gt;
        &lt;span class="nb"&gt;echo &lt;/span&gt;asdf plugin-add &lt;span class="nv"&gt;$n&lt;/span&gt;
    &lt;span class="k"&gt;fi
done

&lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;Updating versions...
&lt;span class="c"&gt;# Special Java logic&lt;/span&gt;
asdf &lt;span class="nb"&gt;install &lt;/span&gt;java latest:temurin-11
asdf &lt;span class="nb"&gt;install &lt;/span&gt;java latest:corretto-17
asdf global java latest:corretto-17

&lt;span class="c"&gt;# Special Nodejs logic&lt;/span&gt;
asdf &lt;span class="nb"&gt;install &lt;/span&gt;nodejs lts
asdf global nodejs lts

&lt;span class="c"&gt;# The nice ones&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;n &lt;span class="k"&gt;in &lt;/span&gt;gradle kotlin python poetry&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;asdf &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; latest
    asdf global &lt;span class="nv"&gt;$n&lt;/span&gt; latest
&lt;span class="k"&gt;done

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; ...done
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-------------&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Need to run `asdf uninstall &amp;lt;tool&amp;gt; &amp;lt;old-version&amp;gt;` as necessary'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This blogpost was originally posted at &lt;a href="https://puppycrawl.com/blog/2023/01/12/asdf.html"&gt;https://puppycrawl.com/blog/2023/01/12/asdf.html&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>asdf</category>
      <category>sdkman</category>
      <category>toolchain</category>
    </item>
    <item>
      <title>Using Finicky to handle URLs</title>
      <dc:creator>Oliver Burn</dc:creator>
      <pubDate>Tue, 03 Jan 2023 09:00:12 +0000</pubDate>
      <link>https://dev.to/oliverburn/using-finicky-to-handle-urls-8bo</link>
      <guid>https://dev.to/oliverburn/using-finicky-to-handle-urls-8bo</guid>
      <description>&lt;h1&gt;
  
  
  Context
&lt;/h1&gt;

&lt;p&gt;Let me share the biggest productivity hack I made in 2022. For a while I have been frustrated at the handling of opening URLs on both my work and personal MacBook laptops. I want the ability to open certain URLs in different applications.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zoom/Miro/Spotify links in the corresponding native applications.&lt;/li&gt;
&lt;li&gt;Specific URLs, like news websites, in the Chrome browser under my personal profile.&lt;/li&gt;
&lt;li&gt;Open all URLs in the &lt;a href="https://signal.org/en/download/macos/"&gt;Signal Desktop&lt;/a&gt; using the Chrome browser under my personal profile.&lt;/li&gt;
&lt;li&gt;Everything else using my default browser, which is &lt;a href="https://vivaldi.com"&gt;Vivaldi&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Enter Finicky
&lt;/h2&gt;

&lt;p&gt;Enter &lt;a href="https://github.com/johnste/finicky"&gt;Finicky&lt;/a&gt; which provides a way to programmatically (in JavaScript) describe how URLs are to be handled. It works by being registered as the default URL handler on MacOS. When it is invoked, it consults the file &lt;code&gt;~/.finicky.js&lt;/code&gt; to determine which application will handle the URL.&lt;/p&gt;

&lt;p&gt;The following diagram gives an overview of how the flow works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iEWA5Ojr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://puppycrawl.com/images/2023/20230103-overview.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iEWA5Ojr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://puppycrawl.com/images/2023/20230103-overview.png" alt="Overview" width="880" height="713"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I installed Finicky using &lt;code&gt;brew install --cask finicky&lt;/code&gt;, and found the documentation to be excellent. I will now describe my current configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining a default handler
&lt;/h2&gt;

&lt;p&gt;Since I use Vivaldi as my default browser, the following snippet defines how a URL will be handled by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;defaultBrowser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Vivaldi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining specific native handlers
&lt;/h2&gt;

&lt;p&gt;The following snippet shows how to define handlers for different native applications.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;open.spotify.com/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Spotify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sr"&gt;/miro.com&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;app&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;board&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;com.electron.realtimeboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sr"&gt;/zoom.us&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;j&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us.zoom.xos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sr"&gt;/https:&lt;/span&gt;&lt;span class="se"&gt;\/\/&lt;/span&gt;&lt;span class="sr"&gt;atlassian.slack.com&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;archives&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Slack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Opening specific URLs in Chrome
&lt;/h2&gt;

&lt;p&gt;The following snippet shows how to open specific URLs in my Google Chrome browser, using my personal profile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;finicky&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchHostnames&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
          &lt;span class="sr"&gt;/abc.net.au$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="sr"&gt;/news.com.au$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="sr"&gt;/smh.com.au$/&lt;/span&gt;
        &lt;span class="p"&gt;]),&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Google Chrome&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Profile 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Opening all URLs from Signal Desktop
&lt;/h2&gt;

&lt;p&gt;Since I use the Signal Desktop for personal use only, I want to open all URLs from Signal using the Chrome browser under my personal profile. The following snippet shows how to achieve this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;opener&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;opener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bundleId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;org.whispersystems.signal-desktop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Google Chrome&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Profile 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complete configuration
&lt;/h2&gt;

&lt;p&gt;Here is what my &lt;code&gt;~/.finicky.js&lt;/code&gt; configuration looks like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// See https://github.com/johnste/finicky&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;defaultBrowser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Vivaldi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;opener&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;opener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bundleId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;org.whispersystems.signal-desktop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Google Chrome&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Profile 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;open.spotify.com/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Spotify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sr"&gt;/miro.com&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;app&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;board&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;com.electron.realtimeboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sr"&gt;/zoom.us&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;j&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us.zoom.xos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sr"&gt;/https:&lt;/span&gt;&lt;span class="se"&gt;\/\/&lt;/span&gt;&lt;span class="sr"&gt;atlassian.slack.com&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;archives&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Slack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;finicky&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchHostnames&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
          &lt;span class="sr"&gt;/abc.net.au$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="sr"&gt;/news.com.au$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="sr"&gt;/smh.com.au$/&lt;/span&gt;
        &lt;span class="p"&gt;]),&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Google Chrome&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Profile 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Footnote
&lt;/h1&gt;

&lt;p&gt;This blog was originally posted on my &lt;a href="https://www.puppycrawl.com/blog"&gt;personal blog&lt;/a&gt;. I have decided to start writing my non-work blog posts here and then cross posting to either my work or &lt;a href="https://dev.to/oliverburn"&gt;dev.to&lt;/a&gt; blogs. &lt;/p&gt;

&lt;p&gt;Since I joined Atlassian I have publicly stopped blogging, but in reality I have been blogging more than ever. In 2023 I am experimenting with making certain blogs more widely visible.&lt;/p&gt;

</description>
      <category>finicky</category>
    </item>
    <item>
      <title>Advent of Code and Dash API Browser</title>
      <dc:creator>Oliver Burn</dc:creator>
      <pubDate>Tue, 06 Dec 2022 23:44:37 +0000</pubDate>
      <link>https://dev.to/oliverburn/advent-of-code-and-dash-api-browser-4kgd</link>
      <guid>https://dev.to/oliverburn/advent-of-code-and-dash-api-browser-4kgd</guid>
      <description>&lt;p&gt;Each year when I do the &lt;a href="https://adventofcode.com/" rel="noopener noreferrer"&gt;Advent of Code challenge&lt;/a&gt; I use it as an opportunity to learn a new language or tool chain. This year I am writing in Java 17 (I have not used Java since Java 8), along with &lt;a href="https://www.eclipse.org/collections/" rel="noopener noreferrer"&gt;Eclipse Collections&lt;/a&gt;, and using VS Code as my IDE.&lt;/p&gt;

&lt;p&gt;Since I have never used Eclipse Collections before, I have installed the API documentation into &lt;a href="https://kapeli.com/dash" rel="noopener noreferrer"&gt;Dash for macOS&lt;/a&gt;, which is an API Documentation Browser and Code Snippet Manager. I have used Dash for a long time, and love the integration with Alfred to quickly lookup documentation for a method/class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75oesnookloi833eljlg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75oesnookloi833eljlg.gif" alt="Basic Alfred Search" width="798" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Despite using Dash for years, I only just discovered the &lt;a href="https://kapeli.com/dash_guide#searchProfiles" rel="noopener noreferrer"&gt;search profiles feature&lt;/a&gt;, which allows you to define a custom collection of docsets search, rather than all documentation. Very handy when wanting to filter down and ignore other large docsets like Spring or Kotlin. The custom docset can be triggered by multiple things like a keyword, or the fact that an application like VS Code is open.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2bx0x391d1qrpvr3im3d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2bx0x391d1qrpvr3im3d.gif" alt="Access Search Profiles" width="798" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another nice touch is that the keyword is integrated into Alfred.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fchg93mg1hlvb10qwxi2d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fchg93mg1hlvb10qwxi2d.gif" alt="AOC Alfred Search" width="798" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only frustration I have with Dash is that it does not understand inherited methods for Java types. So for a while there I was struggling to understand the true power of Eclipse Collections, as I could not see all the available methods on a type. The only workaround I have is search on the page to find "Methods Inherited". It is rather sub-optimal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyo4jlhh7fp11oyi6z517.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyo4jlhh7fp11oyi6z517.gif" alt="Find Methods Inherited" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;eom.&lt;/p&gt;

</description>
      <category>dash</category>
    </item>
    <item>
      <title>My toolchain changes in 2020</title>
      <dc:creator>Oliver Burn</dc:creator>
      <pubDate>Sun, 20 Dec 2020 03:08:11 +0000</pubDate>
      <link>https://dev.to/oliverburn/my-toolchain-changes-in-2020-45hm</link>
      <guid>https://dev.to/oliverburn/my-toolchain-changes-in-2020-45hm</guid>
      <description>&lt;p&gt;This page describes the changes I made to my toolchain in the last year. True to my writing style, this will be short and (hopefully) sweet.&lt;/p&gt;

&lt;p&gt;The changes in (roughly) decreasing significance:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Switched to using &lt;a href="https://www.zsh.org"&gt;Zsh&lt;/a&gt; along with the &lt;a href="https://ohmyz.sh/"&gt;Oh My Zsh framework&lt;/a&gt;. I have used Bash for about 30 years, so this was not done lightly. The killer plugin is &lt;a href="https://github.com/zsh-users/zsh-autosuggestions"&gt;zsh-autosuggestions&lt;/a&gt;, which provides Fish-like suggestions. Very addictive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moved away from Firefox to the &lt;a href="https://vivaldi.com/"&gt;Vivaldi Browser&lt;/a&gt;. It took a bit of getting used to, but it seems to come with almost all the plugins/extensions that I require built in. The &lt;a href="https://help.vivaldi.com/tutorials/quick-commands-for-beginners/"&gt;Quick Commands&lt;/a&gt; capability is excellent. I feel a bit sad as I realise that this is just Google Chrome re-skinned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For my personal machine, I switched to running &lt;a href="https://getfedora.org/"&gt;Fedora Linux&lt;/a&gt;, as I have a love/hate relationship with Ubuntu. So far I am coping just fine, and it feels more developer friendly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I learnt to use the Org Capture extension for &lt;a href="https://chrome.google.com/webstore/detail/org-capture/kkkjlfejijcjgjllecmnejhogpbcigdc"&gt;Vivaldi/Chrome&lt;/a&gt; and Firefox. This was a game changer for me at work, as I can use it to track what web pages I need to review. I use &lt;a href="https://orgmode.org/"&gt;Org Mode&lt;/a&gt; to run my work life.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I switched to &lt;a href="https://github.com/abo-abo/swiper#counsel"&gt;Counsel&lt;/a&gt; from &lt;a href="https://emacs-helm.github.io/helm/"&gt;Helm&lt;/a&gt;. I was motivated when Helm was discontinued for a short period of time, and I found that Counsel &lt;em&gt;felt faster&lt;/em&gt; and worked for my use-cases. Note, I have not found a replacement for &lt;a href="https://github.com/alphapapa/org-rifle#helm-org-rifle"&gt;helm-org-rifle&lt;/a&gt; to search my Org files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I learn to use the &lt;a href="https://github.com/abo-abo/hydra"&gt;Hydra&lt;/a&gt; package to create my own contextual menus in Emacs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I use &lt;a href="https://github.com/ledger/ledger"&gt;Ledger&lt;/a&gt; for tracking my finances. This year I embraced using the reporting capabilities in &lt;a href="https://github.com/ledger/ledger-mode#ledger-mode"&gt;ledger-mode&lt;/a&gt;, which dramatically improved my work-flow.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it.&lt;/p&gt;

</description>
      <category>2020</category>
      <category>toolchain</category>
    </item>
    <item>
      <title>My Firefox Add-ons in 2019</title>
      <dc:creator>Oliver Burn</dc:creator>
      <pubDate>Wed, 09 Jan 2019 04:40:27 +0000</pubDate>
      <link>https://dev.to/oliverburn/my-firefox-add-ons-in-2019-130o</link>
      <guid>https://dev.to/oliverburn/my-firefox-add-ons-in-2019-130o</guid>
      <description>

&lt;p&gt;This is the current list of Firefox Add-ons that I am using at work. Sharing here out of (possible?) interest (and so I can have a backup). They are all available via &lt;a href="https://addons.mozilla.org/en-US/firefox/"&gt;https://addons.mozilla.org/en-US/firefox/&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/auto-tab-discard/"&gt;Auto Tab Discard&lt;/a&gt; - Automatically discard inactive tabs to free up resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/gesturefy/"&gt;Gesturefy&lt;/a&gt; - Mouse gesture addon, which supports over 60 different commands and additional features like rocker and wheel gestures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/https-everywhere/"&gt;HTTPS Everywhere&lt;/a&gt; - encrypts your communications with many major websites, making your browsing more secure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/privacy-badger17/"&gt;Privacy Badger&lt;/a&gt; - automatically learns to block invisible trackers. &lt;strong&gt;Be warned - it's good at breaking sites!&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/shorten_me/"&gt;Shorten me - URL Shortener&lt;/a&gt; - shortens links and current tab's url using goo.gl service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/tree-style-tab/"&gt;Tree Style Tab&lt;/a&gt; - provides tree-style tab bar, like a folder tree of Windows Explorer. New tabs opened from links (or etc.) are automatically attached to the parent tab. If you often use many many tabs, it will help your web browsing because you can understand relations of tabs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/"&gt;uBlock Origin&lt;/a&gt; - an efficient blocker. Easy on CPU and memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/youtube-high-definition/"&gt;YouTube High Definition&lt;/a&gt; - let's you play all YouTube videos in HD and change video player size automatically.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


</description>
      <category>firefoxaddons</category>
    </item>
    <item>
      <title>fzf is my tool discovery of 2018</title>
      <dc:creator>Oliver Burn</dc:creator>
      <pubDate>Sat, 29 Dec 2018 12:08:22 +0000</pubDate>
      <link>https://dev.to/oliverburn/fzf-is-my-tool-discovery-of-2018-4gb6</link>
      <guid>https://dev.to/oliverburn/fzf-is-my-tool-discovery-of-2018-4gb6</guid>
      <description>

&lt;p&gt;This year I discovered the command-line tool &lt;a href="https://github.com/junegunn/fzf"&gt;fzf&lt;/a&gt; by accident while experimenting with Vim plugins (long story).&lt;/p&gt;

&lt;p&gt;In the words of the website:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's an interactive Unix filter for command-line that can be used with any list; files, command history, processes, hostnames, bookmarks, git commits, etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It very quickly become an indispensable tool that I use on Linux and macOS. Examples of how I use it are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Search my command history.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Combined with &lt;a href="https://github.com/junegunn/fzf/wiki/examples#z"&gt;z&lt;/a&gt; it makes it trivial to navigate around previous directories.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I use the following script to select an account from the file &lt;code&gt;accounts.ledger&lt;/code&gt; before running &lt;a href="https://www.ledger-cli.org/"&gt;ledger&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;account&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/^account //'&lt;/span&gt; accounts.ledger | fzf&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$account&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;ledger reg &lt;span class="nv"&gt;$account&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;




</description>
      <category>fzftiptool</category>
    </item>
  </channel>
</rss>
