<?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: Kevin Cui</title>
    <description>The latest articles on DEV Community by Kevin Cui (@kevcui).</description>
    <link>https://dev.to/kevcui</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%2F99326%2F71543d82-bc69-47c6-8241-a9b690c05946.jpg</url>
      <title>DEV Community: Kevin Cui</title>
      <link>https://dev.to/kevcui</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kevcui"/>
    <language>en</language>
    <item>
      <title>Use Burp Suite Community Edition Like A Pro</title>
      <dc:creator>Kevin Cui</dc:creator>
      <pubDate>Sun, 01 May 2022 11:44:59 +0000</pubDate>
      <link>https://dev.to/kevcui/use-burp-suite-community-edition-like-a-pro-1kak</link>
      <guid>https://dev.to/kevcui/use-burp-suite-community-edition-like-a-pro-1kak</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j_kzwIVB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/burp-suite-community-to-pro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j_kzwIVB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/burp-suite-community-to-pro.png" alt="cover_image" width="880" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should have noticed the pun in this post title 😉. That's right, some powerful Burp Suite extensions can make the free community edition as good as the Burp Pro version. Knowing how to use those extensions will make you feel like a pro.&lt;/p&gt;

&lt;h3&gt;
  
  
  Turbo Intruder
&lt;/h3&gt;

&lt;p&gt;Let's start with &lt;a href="https://github.com/PortSwigger/turbo-intruder"&gt;Turbo Intruder&lt;/a&gt;. It's one of the most (if not the most) popular Burp extensions. Basically, anyone who knew Burp extensions should have heard the name of Turbo Intruder.&lt;/p&gt;

&lt;p&gt;The Burp Suite community edition comes with a "lite" version of Burp Intruder. The first impression of this community edition Intruder is: It has really low RPS (Request Per Second). The time you waited for finishing a 1000-request brute-forcing attack can make you grow out some gray hair, slow and anxious. Meanwhile, the Burp Pro version provides a decent speed Burp Intruder, which is suitable for daily usage.&lt;/p&gt;

&lt;p&gt;However, Turbo Intruder is a beast on another level. It's fast and furious. To be honest, I never hit once its full speed and I don't know how fast it can truly go...&lt;/p&gt;

&lt;p&gt;Another highlight of the Turbo Intruder is the customization. It supports Python scripts, which makes it flexible. You could modify any parameters as you want or add additional steps in the script to fit your needs. Personally, I find it's pretty handy for testing race conditions.&lt;/p&gt;

&lt;p&gt;Turbo Intruder will let you forget about the Burp Intruder in the Burp Pro version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logger++
&lt;/h3&gt;

&lt;p&gt;After a session of testing, you may already have collected hundreds of requests and responses in Logger or HTTP history. Sometimes, you need to search for a specific request with a certain parameter in the request URI path or a specific request with a certain value in the response... It's clearly not an option to go through all the requests and check them one by one. Missing the search function is a big deal in the Burp Suite community edition.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nccgroup/LoggerPlusPlus"&gt;Logger++&lt;/a&gt; provides enhanced search functionality. Among all the features in Logger++, I find its grep tool is the most useful feature. As the name suggested, you could "grep" logs with matched patterns:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BAV-UAXd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nccgroup/LoggerPlusPlus/master/images/grep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BAV-UAXd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nccgroup/LoggerPlusPlus/master/images/grep.png" alt="logger++ grep values" width="880" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are using Logger++ already, I'm pretty sure you won't open Burp Logger anymore, and you won't mind using the search functionality in the Burp Pro version either.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactsh Collaborator
&lt;/h3&gt;

&lt;p&gt;The Burp Collaborator is a killer tool in the Burp Pro version. It's valuable for testing OOB (Out-of-band), or generating temporary email addresses...&lt;/p&gt;

&lt;p&gt;Don't be sad yet if you cannot use Collaborator in the community edition. Because if you know &lt;a href="https://github.com/wdahlenburg/interactsh-collaborator"&gt;interactsh-collaborator&lt;/a&gt; extension, you won't miss a thing.&lt;/p&gt;

&lt;p&gt;Interactsh Collaborator provides a good alternative, based on &lt;a href="https://github.com/projectdiscovery/interactsh/"&gt;interactsh-client&lt;/a&gt;. It offers the same functionalities as the Burp Collaborator does:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CGQEDb9L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/4451504/131763193-7f0c32f3-1683-4166-9c9d-1a948ea04fd4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CGQEDb9L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/4451504/131763193-7f0c32f3-1683-4166-9c9d-1a948ea04fd4.gif" alt="Interactsh Collaborator" width="880" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  LazyCSRF
&lt;/h3&gt;

&lt;p&gt;Last but not least, another feature in Burp Pro you may need is "Generate CSRF PoC". &lt;a href="https://github.com/tkmru/lazyCSRF"&gt;LazyCSRF&lt;/a&gt; is an extension to fulfill this purpose with some additional enhancements:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--doATZ-2x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/tkmru/lazyCSRF/main/img/display-japanese.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--doATZ-2x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/tkmru/lazyCSRF/main/img/display-japanese.png" alt="LazyCSRF" width="880" height="571"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The purpose of this post is not to demotivate you from purchasing the Burp Pro license. Contrarily, if you love Burp Suite and you're able to pay for the Pro license, then please own it properly like a pro.&lt;/p&gt;

&lt;p&gt;Here is a list of the mentioned extensions in the post and their GitHub repositories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Turbo Intruder: &lt;a href="https://github.com/PortSwigger/turbo-intruder"&gt;https://github.com/PortSwigger/turbo-intruder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Logger++: &lt;a href="https://github.com/nccgroup/LoggerPlusPlus"&gt;https://github.com/nccgroup/LoggerPlusPlus&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Interactsh-collaborator: &lt;a href="https://github.com/wdahlenburg/interactsh-collaborator"&gt;https://github.com/wdahlenburg/interactsh-collaborator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;LazyCSRF: &lt;a href="https://github.com/tkmru/lazyCSRF"&gt;https://github.com/tkmru/lazyCSRF&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>burpsuite</category>
      <category>pentesting</category>
      <category>tips</category>
    </item>
    <item>
      <title>Three jq Tips You May Need to Know</title>
      <dc:creator>Kevin Cui</dc:creator>
      <pubDate>Tue, 03 Nov 2020 13:50:55 +0000</pubDate>
      <link>https://dev.to/kevcui/three-jq-tips-you-may-need-to-know-5bf5</link>
      <guid>https://dev.to/kevcui/three-jq-tips-you-may-need-to-know-5bf5</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CcdCZYeW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1000/1%2AZb1Sf4nO9QqCcREfy4vfdA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CcdCZYeW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1000/1%2AZb1Sf4nO9QqCcREfy4vfdA.png" alt="jq"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stedolan.github.io/jq/manual/"&gt;jq&lt;/a&gt; is famously known as a powerful command-line JSON parser. Besides performing as a parser, jq has many other handy usages as well. Here, I'd like to share 3 jq tips you may need to know.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON Prettier
&lt;/h3&gt;

&lt;p&gt;When we &lt;code&gt;curl&lt;/code&gt; API to fetch JSON response with raw data. It certainly looks messy:&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="nv"&gt;$ &lt;/span&gt;curl https://api.spacexdata.com/v4/launches/latest
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"fairings"&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"reused"&lt;/span&gt;:false,&lt;span class="s2"&gt;"recovery_attempt"&lt;/span&gt;:true,&lt;span class="s2"&gt;"recovered"&lt;/span&gt;:null,&lt;span class="s2"&gt;"ships"&lt;/span&gt;:[&lt;span class="s2"&gt;"5ea6ed2e080df4000697c907"&lt;/span&gt;,&lt;span class="s2"&gt;"5ea6ed2e080df4000697c908"&lt;/span&gt;&lt;span class="o"&gt;]}&lt;/span&gt;,...&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="s2"&gt;"5ef6a2e70059c33cee4a8293"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's toss raw data into &lt;code&gt;jq&lt;/code&gt; and make it look prettier:&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="nv"&gt;$ &lt;/span&gt;curl https://api.spacexdata.com/v4/launches/latest | jq
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"fairings"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"reused"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
    &lt;span class="s2"&gt;"recovery_attempt"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
    &lt;span class="s2"&gt;"recovered"&lt;/span&gt;: null,
    &lt;span class="s2"&gt;"ships"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"5ea6ed2e080df4000697c907"&lt;/span&gt;,
      &lt;span class="s2"&gt;"5ea6ed2e080df4000697c908"&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;,
  ...
  &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"5ef6a2e70059c33cee4a8293"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the opposite way, when we got some pretty-printed JSON data and want to concatenate them to a one-line string, using &lt;code&gt;jq -c&lt;/code&gt;:&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="nv"&gt;$ &lt;/span&gt;curl https://api.spacexdata.com/v4/launches/latest | jq &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; example.json

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;example.json
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"fairings"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"reused"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
    &lt;span class="s2"&gt;"recovery_attempt"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
    &lt;span class="s2"&gt;"recovered"&lt;/span&gt;: null,
    &lt;span class="s2"&gt;"ships"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"5ea6ed2e080df4000697c907"&lt;/span&gt;,
      &lt;span class="s2"&gt;"5ea6ed2e080df4000697c908"&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;,
  ...
  &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"5ef6a2e70059c33cee4a8293"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;example.json | jq &lt;span class="nt"&gt;-c&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"fairings"&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"reused"&lt;/span&gt;:false,&lt;span class="s2"&gt;"recovery_attempt"&lt;/span&gt;:true,&lt;span class="s2"&gt;"recovered"&lt;/span&gt;:null,&lt;span class="s2"&gt;"ships"&lt;/span&gt;:[&lt;span class="s2"&gt;"5ea6ed2e080df4000697c907"&lt;/span&gt;,&lt;span class="s2"&gt;"5ea6ed2e080df4000697c908"&lt;/span&gt;&lt;span class="o"&gt;]}&lt;/span&gt;,...&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="s2"&gt;"5ef6a2e70059c33cee4a8293"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  JSON Validator
&lt;/h3&gt;

&lt;p&gt;jq can be served as a simple JSON validator, for instance:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'{"fairings":{"reused":false,, "recovery_attempt":true}}'&lt;/span&gt; | jq
parse error: Expected value before &lt;span class="s1"&gt;','&lt;/span&gt; at line 1, column 29
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because its output doesn't give much information to pinpoint directly the error in an obvious way, it's better to use a proper validator for some complex cases. But for some quick checks to validate JSON data, jq can be considered as a suitable choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON Pathfinder
&lt;/h3&gt;

&lt;p&gt;Analyzing JSON files and finding the correct path syntax to a certain value sometimes can be troublesome. Many times, I was punched hard by the frustration of trial and error. Until one day, this magic jq command line brings me the light: &lt;code&gt;jq -r 'paths(scalars) as $p | "." + ([([$p[] | tostring] | join(".")), (getpath($p) | tojson)] | join(": "))'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's use the same &lt;code&gt;curl&lt;/code&gt; data from the previous example, in this case, I want to get the path syntax of &lt;code&gt;ships&lt;/code&gt; ids:&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="nv"&gt;$ &lt;/span&gt;curl https://api.spacexdata.com/v4/launches/latest &lt;span class="se"&gt;\&lt;/span&gt;
| jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'paths(scalars) as $p | "." + ([([$p[] | tostring] | join(".")), (getpath($p) | tojson)] | join(": "))'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
| &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'.ships'&lt;/span&gt;
.fairings.ships.0: &lt;span class="s2"&gt;"5ea6ed2e080df4000697c907"&lt;/span&gt;
.fairings.ships.1: &lt;span class="s2"&gt;"5ea6ed2e080df4000697c908"&lt;/span&gt;
.ships.0: &lt;span class="s2"&gt;"5ea6ed2f080df4000697c910"&lt;/span&gt;
.ships.1: &lt;span class="s2"&gt;"5ea6ed2f080df4000697c90b"&lt;/span&gt;
.ships.2: &lt;span class="s2"&gt;"5ea6ed2e080df4000697c907"&lt;/span&gt;
.ships.3: &lt;span class="s2"&gt;"5ea6ed2e080df4000697c908"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the output, now I know the right path syntax is &lt;code&gt;.ships[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As you can see from this example, this magic jq command line will print each path and value pair from the input JSON. Combing with &lt;code&gt;grep&lt;/code&gt; command, it's sufficient to be used as a handy JSON pathfinder.&lt;/p&gt;




&lt;p&gt;If you do know other hot jq tips, do not hesitate to share them with me.&lt;/p&gt;

</description>
      <category>jq</category>
      <category>cli</category>
      <category>json</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Git Alias -- Did You Git It?</title>
      <dc:creator>Kevin Cui</dc:creator>
      <pubDate>Sat, 04 Jul 2020 07:02:36 +0000</pubDate>
      <link>https://dev.to/kevcui/git-alias-did-you-git-it-53h4</link>
      <guid>https://dev.to/kevcui/git-alias-did-you-git-it-53h4</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NWcPWwcV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a5ugygs5gu7m2fip76k1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NWcPWwcV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a5ugygs5gu7m2fip76k1.png" alt="git"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Git alias is powerful and yet simple to set up. I'd like to share my journey in configuring git alias for my personal use. Now let's dig it and git it!&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 1: Why git alias?
&lt;/h3&gt;

&lt;p&gt;I was using &lt;a href="https://github.com/jonas/tig"&gt;Tig&lt;/a&gt; for some time. It's good but not great. The problems I got during the time:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It takes time to memorize &lt;a href="https://jonas.github.io/tig/doc/manual.html"&gt;the default key bindings&lt;/a&gt;. Since I'm using &lt;a href="https://dev.to/2019/04/18/twenty-months-with-colemak/"&gt;Colemak&lt;/a&gt; keyboard layout, obviously, the default navigation key bindings need to be adjusted accordingly. Therefore, it takes me more time to customize them.&lt;/li&gt;
&lt;li&gt;Tig doesn't support customized diff formatter, like my current favorite &lt;a href="https://github.com/dandavison/delta"&gt;delta&lt;/a&gt;. &lt;a href="https://github.com/jonas/tig/issues/542"&gt;An open issue from 2016&lt;/a&gt; gives me the fearful feeling that Tig wouldn't officially support this feature in the foreseeable future.&lt;/li&gt;
&lt;li&gt;Switching between different views in Tig makes the workflow complex and slow. For example, to add an untracked file: run tig, press &lt;code&gt;s&lt;/code&gt; to switch to status view, move up and down to select an untracked file, press &lt;code&gt;u&lt;/code&gt; to add it. Well, in this case, why using Tig instead of simply typing &lt;code&gt;git add &amp;lt;untracked_file&amp;gt;&lt;/code&gt;?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At some point, I decided to drop Tig and tried to search for other tools to assist my git workflow.&lt;/p&gt;

&lt;p&gt;Don't get me wrong. Tig is a decent tool. However, my needs are just picky and I'm just too lazy 🤷.&lt;/p&gt;

&lt;p&gt;After trying &lt;a href="https://git-scm.com/downloads/guis/"&gt;this and that&lt;/a&gt;, surprisingly, I find out that git alias is one ideal solution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Git alias is supported by default, no need to install any 3rd-party dependencies.&lt;/li&gt;
&lt;li&gt;Git alias is relatively easy to customize. Knowing git command and put an alias for it, that's all about.&lt;/li&gt;
&lt;li&gt;Git alias is illegally powerful once you know how to use &lt;code&gt;!&lt;/code&gt; to run the external command! Yes, its existence is a crime.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Day 2: start with [alias]
&lt;/h3&gt;

&lt;p&gt;The official way to add git alias is to edit &lt;code&gt;~/.gitconfig&lt;/code&gt; file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;code&gt;~/.gitconfig&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;[alias]&lt;/code&gt; section&lt;/li&gt;
&lt;li&gt;Put a bunch of aliases&lt;/li&gt;
&lt;li&gt;Save and close file, done!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After this change, my alias setup looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[alias]
  a = add
  c = commit
  ca = commit --amend
  ci = commit -m
  cm = commit -m
  co = checkout
  di = diff
  p = push origin
  pl = pull
  rsthrd = reset --hard origin/master
  s = status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those aliases cover all my basic needs of git workflow. For example, to add an untracked file, now I can type: &lt;code&gt;git a &amp;lt;untracked_file&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By using one letter alias for most commonly used git commands saves my time and gives me pleasures. Yeah, you know that typing fewer letters feels amazing!&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 3: go external !
&lt;/h3&gt;

&lt;p&gt;As you may know, &lt;a href="https://github.com/junegunn/fzf"&gt;fzf&lt;/a&gt; is an extremely powerful tool (yep, it should be illegal as well). Imagine that git alias x fzf, what a dream team-up!&lt;/p&gt;

&lt;p&gt;By using &lt;code&gt;!&lt;/code&gt; symbol can make this dream come true. &lt;code&gt;!&lt;/code&gt; allows running external commands with the alias, including &lt;code&gt;git&lt;/code&gt; command itself. So many possibilities can be achieved by combining external commands.&lt;/p&gt;

&lt;p&gt;For example, I add an alias &lt;code&gt;ac&lt;/code&gt;, known as &lt;code&gt;add modified files&lt;/code&gt;, to add modified file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[alias]
  ...
  ac = ! git add $(git diff --name-only --diff-filter=M | fzf -m --bind "ctrl-a:select-all")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Video: &lt;a href="https://kevcui.github.io/videos/git-alias-ac.mp4"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The steps in this video are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git s&lt;/code&gt; to show unstaged changes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git ac&lt;/code&gt; to list modified files in fzf, &lt;code&gt;ctrl-a&lt;/code&gt; to select all and &lt;code&gt;enter&lt;/code&gt; to add them&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git s&lt;/code&gt; to show the result that all modified files are added and staged&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Day 4: go smooth
&lt;/h3&gt;

&lt;p&gt;To smooth git workflow, I tweak fzf key binding to configure command execution when selection is made in fzf.&lt;/p&gt;

&lt;p&gt;For example, I create an alias &lt;code&gt;ds&lt;/code&gt;, known as &lt;code&gt;diff staged files&lt;/code&gt;, to show changes in staged files and after pressing &lt;code&gt;enter&lt;/code&gt;, it goes to commit process directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[alias]
  ...
  ds = ! git diff --name-only --cached | fzf --preview "git diff --cached -- {} | delta" --bind "enter:abort+execute(git commit)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Video: &lt;a href="https://kevcui.github.io/videos/git-alias-ds.mp4"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The steps in this video are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git ds&lt;/code&gt; to show all staged files&lt;/li&gt;
&lt;li&gt;Check changes by switching files listed in fzf preview screen&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;enter&lt;/code&gt; to go to commit&lt;/li&gt;
&lt;li&gt;Type commit message and save it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you may also notice in the &lt;code&gt;ds&lt;/code&gt; alias, I'm now able to use &lt;code&gt;delta&lt;/code&gt; to format git diff in fzf preview screen, by piping diff to it.&lt;/p&gt;

&lt;p&gt;Until now, all the main problems I have with Tig are solved by git alias. I'd be happier than ever.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 5: go dynamic
&lt;/h3&gt;

&lt;p&gt;For some reason, I'd like to pass the file name as an argument to a git command bound with an alias.&lt;/p&gt;

&lt;p&gt;For example, I'd like to see certain change in a file, when and who made it, and all related changes in the same commit. It involves &lt;code&gt;git blame&lt;/code&gt; command with the file name as an argument. Without doubt, it's possible to accomplish it with git alias by using &lt;code&gt;sh -c&lt;/code&gt; to pass arguments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[alias]
  ...
  b = ! sh -c \"git blame $1 | fzf --bind 'enter:abort+execute(git diff-tree -p {1} | delta)'\"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Video: &lt;a href="https://kevcui.github.io/videos/git-alias-b.mp4"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚠️ Pay attention to escape single quotes &lt;code&gt;'&lt;/code&gt; or/and double quotes &lt;code&gt;"&lt;/code&gt; inside &lt;code&gt;sh -c&lt;/code&gt; if needed.&lt;/p&gt;

&lt;p&gt;An alternative and more complex method is to bind a function, like &lt;code&gt;! f() {...}; f&lt;/code&gt;. Once you dig deeper in this way, you will certainly find the answers for all your needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 6: go flexible
&lt;/h3&gt;

&lt;p&gt;Pursuing the ambition of customizing as many aliases as possible to perfectly suit my needs, the aliases are getting complicated with many duplicated and redundant codes. It's hard to maintain in the configuration file like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[alias]
  ac = ! git add $(git diff --name-only --diff-filter=M | fzf -0 -m --reverse --height=40% --bind tab:down,btab:up,ctrl-j:up,ctrl-k:down,change:top,alt-space:toggle,ctrl-a:select-all,ctrl-u:deselect-all --cycle)
  b = ! sh -c \"git blame $1 | fzf -0 --ansi --bind tab:down,btab:up,ctrl-j:up,ctrl-k:down,change:top,alt-space:toggle,ctrl-a:select-all,ctrl-u:deselect-all --bind 'enter:abort+execute(git diff-tree -p {1} | delta --theme=iceberg)' --cycle\"
  ds = ! git diff --name-only --cached | fzf -0 --ansi --preview-window=right:80:wrap --preview 'git diff --cached -- {} | delta --theme=iceberg' --bind tab:down,btab:up,ctrl-j:up,ctrl-k:down,change:top,alt-space:toggle,ctrl-a:select-all,ctrl-u:deselect-all --bind alt-k:preview-down,alt-j:preview-up,alt-h:preview-page-down,alt-l:preview-page-up --bind 'enter:abort+execute(git commit)' --cycle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For instance, if I want to update fzf preview screen key bindings for all aliases, I have to edit all aliases one by one. It's a bummer.&lt;/p&gt;

&lt;p&gt;Luckily, git alias can be edited via command line:&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="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.&amp;lt;alias_name&amp;gt; &amp;lt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates the possibility to let Bash script handle flexibly the alias modifications. I can define some variables for the common parts in the aliases, which permits that the modifications in one location will affect all aliases at once.&lt;/p&gt;

&lt;p&gt;Here is a sample of Bash script:&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 bash&lt;/span&gt;
&lt;span class="c"&gt;# remove all aliases&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="nt"&gt;--remove-section&lt;/span&gt; &lt;span class="nb"&gt;alias&lt;/span&gt;

&lt;span class="c"&gt;# set variables&lt;/span&gt;
&lt;span class="nv"&gt;FZF_KEYBINDING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"tab:down,btab:up,ctrl-j:up,ctrl-k:down,change:top,alt-space:toggle,ctrl-a:select-all,ctrl-u:deselect-all"&lt;/span&gt;
&lt;span class="nv"&gt;FZF_PREVIEW_KEYBINDING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"alt-k:preview-down,alt-j:preview-up,alt-h:preview-page-down,alt-l:preview-page-up"&lt;/span&gt;
&lt;span class="nv"&gt;DIFF_CMD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"delta --theme=iceberg"&lt;/span&gt;
&lt;span class="nv"&gt;GIT_DIFF_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git diff --name-only"&lt;/span&gt;
&lt;span class="nv"&gt;GIT_DIFF_NAME_CACHED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GIT_DIFF_NAME&lt;/span&gt;&lt;span class="s2"&gt; --cached"&lt;/span&gt;
&lt;span class="nv"&gt;GIT_DIFF_TREE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git diff-tree -p {1}"&lt;/span&gt;

&lt;span class="c"&gt;# define alias&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.ac &lt;span class="s2"&gt;"! git add &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$GIT_DIFF_NAME&lt;/span&gt;&lt;span class="s2"&gt; --diff-filter=M | fzf -0 -m --reverse --height=40% --bind &lt;/span&gt;&lt;span class="nv"&gt;$FZF_KEYBINDING&lt;/span&gt;&lt;span class="s2"&gt; --cycle)"&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.b &lt;span class="s1"&gt;'! sh -c "git blame $1 | fzf -0 --ansi --bind '&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FZF_KEYBINDING&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s1"&gt;' --bind '&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;'enter:abort+execute('&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GIT_DIFF_TREE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s1"&gt;' | '&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DIFF_CMD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s1"&gt;')'&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;' --cycle"'&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.ds &lt;span class="s2"&gt;"! &lt;/span&gt;&lt;span class="nv"&gt;$GIT_DIFF_NAME_CACHED&lt;/span&gt;&lt;span class="s2"&gt; | fzf -0 --ansi --preview-window=right:80:wrap --preview 'git diff --cached -- {} | &lt;/span&gt;&lt;span class="nv"&gt;$DIFF_CMD&lt;/span&gt;&lt;span class="s2"&gt;' --bind &lt;/span&gt;&lt;span class="nv"&gt;$FZF_KEYBINDING&lt;/span&gt;&lt;span class="s2"&gt; --bind &lt;/span&gt;&lt;span class="nv"&gt;$FZF_PREVIEW_KEYBINDING&lt;/span&gt;&lt;span class="s2"&gt; --bind 'enter:abort+execute(git commit)' --cycle"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ Pay attention to escape &lt;code&gt;$&lt;/code&gt; symbol by &lt;code&gt;\$&lt;/code&gt;, in case &lt;code&gt;$&lt;/code&gt; symbol indicates the variable used in alias.&lt;/p&gt;

&lt;p&gt;In the example above, if I want to add more key bindings for fzf preview screen, I'll modify &lt;code&gt;FZF_PREVIEW_KEYBINDING&lt;/code&gt; then run the Bash script. All aliases will be updated accordingly and beautifully.&lt;/p&gt;

&lt;p&gt;For more details and examples, go checkout &lt;a href="https://github.com/KevCui/dotfiles/blob/master/git/addalias.sh"&gt;addalias.sh&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 7: go extreme
&lt;/h3&gt;

&lt;p&gt;After 6 days hands-on of git alias configuration, it's time to lay down holding a beer and enjoy the efficiency brought by git alias? Wait a minute here, I still have some small problems with the current setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Certain alias is conflicted with default git command. For example, &lt;code&gt;git am&lt;/code&gt; is already used by &lt;a href="https://git-scm.com/docs/git-am"&gt;git-am&lt;/a&gt;, and &lt;a href="https://stackoverflow.com/a/3538791"&gt;it's impossible to overwrite git command by git alias&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Typing 3-letter &lt;code&gt;git&lt;/code&gt; to initial git command every time is fatigue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's time to push the limit and go extreme. To solve those problems, the idea is to create a function in &lt;code&gt;~/.zshrc&lt;/code&gt;, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
g () {
    if [[ "$1" == "am" ]]; then
        git ac
    else
        git "$@"
    fi
}
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I'm able to use &lt;code&gt;am&lt;/code&gt; as &lt;code&gt;add modified files&lt;/code&gt;, way easier to remember than &lt;code&gt;ac&lt;/code&gt;. If on a rare occasion I want to use &lt;code&gt;git-am&lt;/code&gt;, I'll just simply type &lt;code&gt;git am&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Meanwhile, using &lt;code&gt;g&lt;/code&gt; instead of &lt;code&gt;git&lt;/code&gt; reduces the time of typing 2 letters. What a pleasure for a lazy person like me!&lt;/p&gt;

&lt;h3&gt;
  
  
  Sum-up
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Git alias is amazing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git alias with &lt;code&gt;!&lt;/code&gt; to execute external command is powerful.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git alias combined with other commands like &lt;code&gt;fzf&lt;/code&gt; and &lt;code&gt;sh -c&lt;/code&gt; is matchless.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git alias created by Bash script is flexible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shell alias/function gives wings to git alias.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Did you git alias as well? What's your favorite git alias? Share it with me and let me learn from you.&lt;/p&gt;

</description>
      <category>git</category>
      <category>cli</category>
      <category>script</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Twenty Months With Colemak</title>
      <dc:creator>Kevin Cui</dc:creator>
      <pubDate>Fri, 19 Apr 2019 08:51:23 +0000</pubDate>
      <link>https://dev.to/kevcui/twenty-months-with-colemak-1ln6</link>
      <guid>https://dev.to/kevcui/twenty-months-with-colemak-1ln6</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AhcY3Bk8YY_1keCJW_b70Vw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AhcY3Bk8YY_1keCJW_b70Vw.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time truly flies. It has been 20 months since &lt;a href="https://dev.to/kevcui/why-i-switch-to-colemak-keyboard-layout-24h4"&gt;I switched from QWERTY to Colemak keyboard layout&lt;/a&gt;. Am I now able to type on the Colemak keyboard as fast as the time flies? Certainly not. My typing speed 20 months ago was 75 WPM on average with QWERTY, now it's 85 WPM on average with Colemak. I can feel the improvement and that's why I never look back to QWERTY again.&lt;/p&gt;

&lt;p&gt;Besides things mentioned in &lt;a href="https://dev.to/kevcui/one-week-with-colemak-489k"&gt;One Week with Colemak&lt;/a&gt;, are there somethings special happened during these 20 months?&lt;/p&gt;

&lt;h3&gt;
  
  
  Remap Caps Lock as...?
&lt;/h3&gt;

&lt;p&gt;Caps Lock key is a huge waste on the standard keyboard. It locates in such important position but with less functional benefit. Some remap it as Escape key; some remap it as BackSpace key...&lt;/p&gt;

&lt;p&gt;My favorite remapping solution is: Press Caps Lock once, it sends "Escape" key event; Hold Caps Lock, it sends "Control" key event. So, one Caps Lock key can act as Escape and Control combined together.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to achieve this key binding on Linux?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Act as &lt;strong&gt;Control&lt;/strong&gt; when press and hold: HHKB keyboard by default puts Control key on the usual Caps Lock position, which is great for me, so no tweak is needed. For other keyboards, I usually use &lt;code&gt;xmodmap&lt;/code&gt; to map Caps Lock key as Left Control key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Act as &lt;strong&gt;Escape&lt;/strong&gt; when single press: &lt;a href="https://github.com/alols/xcape" rel="noopener noreferrer"&gt;xcape&lt;/a&gt; can configure one key to act as other key when pressed and released:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xcape -t 300 -e 'Control_L=Escape'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  How to achieve this key binding on macOS?
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/tekezo/Karabiner-Elements" rel="noopener noreferrer"&gt;Karabiner&lt;/a&gt; is a great tool to archive the same key binding conception on macOS. Karabiner supports customized json configuration file. Here is &lt;a href="https://github.com/KevCui/dotfiles/blob/master/karabiner/capslock.json" rel="noopener noreferrer"&gt;my configuration file&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
"from": {
    "key_code": "caps_lock",
    "modifiers": {
        "optional": [ "any" ]
    }
},
"to": [{
    "key_code": "right_control"
}],
"to_if_alone": [{
    "key_code": "escape"
}],
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Some small troubles in the real world
&lt;/h3&gt;

&lt;p&gt;When you use some uncommon tools in the real world, you know you have to prepare some small troubles that may come to you every day:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;QWERTY is literally everywhere: Accept the reality and enforce the muscle memory of QWERTY layout as well. Otherwise, like me, I'm extremely clumsy when typing on QWERTY.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pair programming or testing on my machine: Remember to switch keyboard and key binding settings on the fly, depending on the person.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"This guy is a weirdo.": So what?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Overall, I'm super happy with Colemak for now. I have no plan to learn another keyboard layout. I guess I will stick with Colemak for years. Maybe after some years, I'll write another recap post about Colemak. I shall call it "Twenty Years With Colemak". 😉&lt;/p&gt;

</description>
      <category>colemak</category>
      <category>keyboard</category>
      <category>productivity</category>
      <category>lifestyle</category>
    </item>
    <item>
      <title>Build A Killer Note-taking System</title>
      <dc:creator>Kevin Cui</dc:creator>
      <pubDate>Sun, 07 Apr 2019 15:26:05 +0000</pubDate>
      <link>https://dev.to/kevcui/build-a-killer-note-taking-system-2b5n</link>
      <guid>https://dev.to/kevcui/build-a-killer-note-taking-system-2b5n</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fk9g5yk2nsb7vfgz12msc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fk9g5yk2nsb7vfgz12msc.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The proverb says, "The palest ink is better than the best memory". Note-taking is certainly an essential part of knowledge learning, information collecting and retaining. In the fast-changing digital era, pen, ink and paper may not be able to fulfill the important job of note-taking anymore. So, what's a killer note-taking system nowadays?&lt;/p&gt;

&lt;h3&gt;
  
  
  My requirements?
&lt;/h3&gt;

&lt;p&gt;My dream system must be &lt;em&gt;Easy&lt;/em&gt;, &lt;em&gt;Efficient&lt;/em&gt; and &lt;em&gt;Flexible&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know where &amp;amp; how to write notes easily without hesitations&lt;/li&gt;
&lt;li&gt;Find right notes &amp;amp; roll back to old changes efficiently without hassles&lt;/li&gt;
&lt;li&gt;Convert notes to other formats and share them flexibly without troubles&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Build it!
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Note format
&lt;/h4&gt;

&lt;p&gt;I love taking notes with markdown. Why markdown?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's clean for writing and reading&lt;/li&gt;
&lt;li&gt;It's efficient, almost like writing plain texts&lt;/li&gt;
&lt;li&gt;It's flexible to convert to any other formats&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Note taking &amp;amp; organization app
&lt;/h4&gt;

&lt;p&gt;I like doing everything in the terminal, so naturally, Vim is the best note-taking editor for me.&lt;/p&gt;

&lt;p&gt;For organizing notes, in the beginning, I set up different folders for different notes. But it's not quite close to what I want. Especially, searching note is not a straightforward task, it needs to &lt;code&gt;find&lt;/code&gt; or &lt;code&gt;grep&lt;/code&gt; for a while. Then I wrote a handy script &lt;a href="https://github.com/KevCui/pynote" rel="noopener noreferrer"&gt;pynote&lt;/a&gt; for helping note organization, it worked and only at "it works" level... Recently, I switched to the amazing &lt;a href="https://github.com/alok/notational-fzf-vim" rel="noopener noreferrer"&gt;Notational Velocity for Vim&lt;/a&gt;, a plugin to port famous &lt;a href="http://notational.net/" rel="noopener noreferrer"&gt;Notational Velocity&lt;/a&gt; into Vim. The whole note-taking experience never becomes so smooth! 💆&lt;/p&gt;

&lt;h4&gt;
  
  
  Note version-control system
&lt;/h4&gt;

&lt;p&gt;It's easy. Git is the only reasonable option I can think of. &lt;code&gt;¯\_(ツ)_/¯&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git init&lt;/code&gt;, make note changes, &lt;code&gt;git add&lt;/code&gt;, &lt;code&gt;git commit&lt;/code&gt; or &lt;code&gt;git revert&lt;/code&gt;... All the fancy version control things are already familiar under my hands.&lt;/p&gt;

&lt;h4&gt;
  
  
  Note auto backup system
&lt;/h4&gt;

&lt;p&gt;Google Drive? OneDrive? Dropbox? Nah, they are not really Git-compatible by default. However, I got inspired by &lt;a href="https://github.com/hbons/SparkleShare" rel="noopener noreferrer"&gt;SparkleShare&lt;/a&gt;, an open-source file sync app powered by Git, it adds file changes and pushes them to Github or GitLab automatically.&lt;/p&gt;

&lt;p&gt;I may achieve the same functionality by using a simple script. The idea is to run &lt;a href="https://github.com/emcrisostomo/fswatch" rel="noopener noreferrer"&gt;fswatch&lt;/a&gt; in the background and keep monitoring file changes. When file changes are happening, fswatch will trigger Git commands to add and push changes automatically.&lt;/p&gt;

&lt;p&gt;Here is a snippet of Bash script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env bash
...
function notesync() {
  fswatch -r -0 -d "$1" -e '\.git' -m "inotify_monitor" --event=Created --event=Updated --event=Removed | xargs -0 -n 1 zsh -c "source ~/.zshrc; cd $1; git add -A; git commit -m 'Update file'; git push" &amp;amp;
}
notesync "&amp;lt;folder_path&amp;gt;"
notesync "&amp;lt;another_folder_path&amp;gt;"
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;fswatch part&lt;/strong&gt; is to monitor file changes, filter out correct file change events and send the signal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fswatch -r -0 -d "$1" -e '\.git' -m "inotify_monitor" --event=Created --event=Updated --event=Removed | ... &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;-r: watch subdirectories recursively&lt;/li&gt;
&lt;li&gt;-0: pass NUL as delimiter (no idea why it's need.....)&lt;/li&gt;
&lt;li&gt;-d: directory to monitor, the target folder full of notes&lt;/li&gt;
&lt;li&gt;-e: exude paths matching regex, here I don't want to trigger Git commands when any changes are happening in &lt;code&gt;.git&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;-m: monitor, type &lt;code&gt;fswatch -M&lt;/code&gt; to see available monitors, more details of all available monitors: &lt;a href="https://emcrisostomo.github.io/fswatch/doc/1.14.0/fswatch.html/Monitors.html#Available-Monitors" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;--event: filter event by event flag, mainly using events related to file changes, all available events: &lt;a href="https://emcrisostomo.github.io/fswatch/doc/1.14.0/fswatch.html/Invoking-fswatch.html#Event-Flags-1" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&amp;amp;: last but not least, don't forget it at the end, because it provides the ability to run fswatch command in background and detach the process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;xargs part&lt;/strong&gt; is to get signal from fswatch and execute specific commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... | xargs -0 -n 1 ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;-0: input items are terminated by null, not whitespace (no idea why it's needed...)&lt;/li&gt;
&lt;li&gt;-n: maximum argument, &lt;code&gt;1&lt;/code&gt; it is&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;zsh command part&lt;/strong&gt; is to run Git commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... zsh -c "source ~/.zshrc; cd $1; git add -A; git commit -m 'Update file'; git push" ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;zsh -c: execute following commands in &lt;code&gt;zsh&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;source ~/.zshrc: all my SSH keys are declared in &lt;code&gt;.zshrc&lt;/code&gt; file, this command will load configurations from &lt;code&gt;.zshrc&lt;/code&gt; file. Otherwise, push to remove Git repository may get permission denied&lt;/li&gt;
&lt;li&gt;git add -A...: Git commands to add changes and push to remote repository. Some optimization ideas: 1) &lt;code&gt;git pull&lt;/code&gt; first, in case it's a shared repository; 2) Put some specific texts in commit messages, maybe also including file names&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Sumup
&lt;/h4&gt;

&lt;p&gt;This is my killer note-taking system. It's easy, efficient and flexible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Note format: Markdown
Note taking &amp;amp; organization app: Vim + Notational Velocity for Vim
Note version-control system: Git
Note auto backup system: fswatch + GitHub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far I'm quite happy with this system. I enjoy using it not only for taking some private notes with my dirty secrets, but also for sharing notes with colleagues in my day-to-day work, like notes for &lt;a href="https://kevcui.github.io/2017/04/17/how-i-do-exploratory-testing/" rel="noopener noreferrer"&gt;exploratory testing&lt;/a&gt;. Oh, I almost forget, guess what I'm using now for wring this blog post?&lt;/p&gt;

&lt;p&gt;How does your note-taking system look like? Share with me your awesome ideas?&lt;/p&gt;

</description>
      <category>notetaking</category>
      <category>script</category>
      <category>cli</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Replace 8 Frequently Used Linux Commands!?</title>
      <dc:creator>Kevin Cui</dc:creator>
      <pubDate>Sun, 02 Sep 2018 15:21:08 +0000</pubDate>
      <link>https://dev.to/kevcui/replace-8-frequently-used-linux-commands-p2f</link>
      <guid>https://dev.to/kevcui/replace-8-frequently-used-linux-commands-p2f</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qaY5Vx-c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1000/1%2AhcY3Bk8YY_1keCJW_b70Vw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qaY5Vx-c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1000/1%2AhcY3Bk8YY_1keCJW_b70Vw.jpeg" alt="coverimage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Almost a decade ago, I started to touch the command-line interface (CLI). I’m now a nerdy CLI lover and I’m so obsessed by its efficiency. Therefore, I’m always trying out new command-line commands. From time to time, some commands are replaced by other improved ones in my daily workflow. Especially for some frequently used commands, it’s worth to find better alternatives.&lt;/p&gt;

&lt;p&gt;Here is a list of improved commands I’d like to share with you:&lt;/p&gt;

&lt;h3&gt;
  
  
  cd? z, up and fzf!
&lt;/h3&gt;

&lt;h4&gt;
  
  
  z
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/rupa/z"&gt;z&lt;/a&gt; is a very popular alternative command for jumping around. &lt;code&gt;z&lt;/code&gt; doesn’t require any additional configurations. Although it works out of the box, you need just a little bit of patience. Because &lt;code&gt;z&lt;/code&gt; has a “magic” algorithm based on “frequency” which can learn from the frequent vested directories after your &lt;code&gt;cd&lt;/code&gt; around for a while.&lt;/p&gt;

&lt;p&gt;An easy and quick example how to &lt;code&gt;z&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~$ pwd
/home/foo/bar/one/two/three

~$ z tw
~$ pwd
/home/foo/bar/one/two

~$ z foo
~$ pwd
/home/foo

~$ z th
~$ pwd
/home/foo/bar/one/two/three
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want to know how “frequency” score looks like for all directories? Simply run command &lt;code&gt;z -l&lt;/code&gt; will give you a list.&lt;/p&gt;

&lt;p&gt;Want to clean some/all saved directories? Simply modify &lt;code&gt;$HOME/.z&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  up
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/shannonmoeller/up"&gt;up&lt;/a&gt; is an interesting command to replace &lt;code&gt;cd ..&lt;/code&gt; and this ridicules one &lt;code&gt;cd ../../../../&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~$ pwd
/home/foo/bar/one/two/three

~$ up
~$ pwd
/home/foo/bar/one/two

~$ up 2
~$ pwd
/home/foo/bar

~$ up h
~$ pwd
/home
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  fzf
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/junegunn/fzf"&gt;fzf&lt;/a&gt; is a versatile command, which can be combined in other commands. With the help of its amazing searchability, it can be used to &lt;a href="https://github.com/junegunn/fzf/blob/master/shell/key-bindings.zsh"&gt;“cd into the selected directory”&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kevcui.github.io/videos/fzf-example.svg"&gt;fzf example&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ls? exa!
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/ogham/exa"&gt;exa&lt;/a&gt; aims to be the modem replacement for &lt;code&gt;ls&lt;/code&gt;. In my opinion, it did it. exa is really easy to use. Its options are straightforward:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f2MELheO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/exa-example.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f2MELheO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/exa-example.jpg" alt="exa-example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are my aliases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias ls='exa -s mod --git'
alias ll='exa -l -s mod --git --time-style=long-iso'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More options to tweak exa: &lt;a href="https://the.exa.website/docs/command-line-options"&gt;exa options&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  cat? bat!
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/sharkdp/bat"&gt;bat&lt;/a&gt; is a &lt;code&gt;cat&lt;/code&gt; clone with syntax highlighting, line numbers and automatic paging (using &lt;code&gt;less&lt;/code&gt; as the default pager). To display the contents of a file using &lt;code&gt;bat&lt;/code&gt; looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e8cscuGf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/bat-example.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e8cscuGf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/bat-example.jpg" alt="bat-example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s possible to customize the theme of syntax highlighting. It supports Sublime Text syntax format. Check these default themes to have some inspirations: &lt;a href="https://github.com/sharkdp/bat/tree/master/assets/themes"&gt;bat themes&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  grep? rg!
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/BurntSushi/ripgrep"&gt;rg&lt;/a&gt;, ripgrep, is fast &amp;amp; furious. It has almost the same parameters of &lt;code&gt;grep&lt;/code&gt; command, with improved output style and speed.&lt;/p&gt;

&lt;p&gt;One main usage of &lt;code&gt;grep&lt;/code&gt; for me is to find out which files contain some specific contents. An example to compare &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;ripgrep&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ysEzlymt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/grep-example.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ysEzlymt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/grep-example.jpg" alt="grep-example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_DP-zWiK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/ripgrep-example.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_DP-zWiK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/ripgrep-example.jpg" alt="ripgrep-example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re interested in how fast &lt;code&gt;rg&lt;/code&gt; can be? Check this comparison: &lt;a href="https://github.com/BurntSushi/ripgrep#quick-examples-comparing-tools"&gt;rg vs. grep vs. ag. vs. ack…&lt;/a&gt; Not sure if it’s still the case now. But overall, ripgrep is fast enough for my daily use.&lt;/p&gt;

&lt;h3&gt;
  
  
  find? fd and fzf!
&lt;/h3&gt;

&lt;h4&gt;
  
  
  fd
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/sharkdp/fd"&gt;fd&lt;/a&gt; is a replacement for &lt;code&gt;find&lt;/code&gt; focusing on user-friendly, with simplifying options of &lt;code&gt;find&lt;/code&gt;. For example, I want to edit a file but I don’t remember what’s its full path actually is. Usually, I need to find its full path first and then edit it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~$ find . -ipath "*how*exp*" -name "index.html"
./2017/04/17/how-i-do-exploratory-testing/index.html
~$ vi ./2017/04/17/how-i-do-exploratory-testing/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since I know the result will be only one file found, I can combine &lt;code&gt;vi&lt;/code&gt; inside &lt;code&gt;find&lt;/code&gt; command as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~$ find . -ipath "*how*exp*" -name "index.html" -exec vi {} \;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;fd&lt;/code&gt;, the command is more readable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~$ fd -p 'how.*exp.*/index'
2017/04/17/how-i-do-exploratory-testing/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  fzf
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/junegunn/fzf"&gt;fzf&lt;/a&gt; has an extremely powerful fuzzy searchability. It can nest finding steps directly with another command. I bind the key &lt;a href="https://github.com/junegunn/fzf/blob/master/shell/key-bindings.zsh"&gt;&lt;code&gt;ctrl-t&lt;/code&gt; to enable fzf&lt;/a&gt;. As the same example as above, but with &lt;code&gt;fzf&lt;/code&gt;, it’s a completely different story:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~$ vi (press ctrl-t)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://kevcui.github.io/videos/fzf-example2.svg"&gt;Another fzf example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An alias to combine &lt;code&gt;vim&lt;/code&gt; and &lt;code&gt;fzf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias vif='vim $(fzf)'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  kill? fkill!
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/sindresorhus/fkill"&gt;fkill&lt;/a&gt;, its &lt;strong&gt;f&lt;/strong&gt; stands for “fabulously” (It’s definitely not the word I’m thinking in my mind 😉). Sometimes, &lt;code&gt;kill&lt;/code&gt; some zombie processes is necessary. &lt;code&gt;fkill&lt;/code&gt; can search a process and kill it interactively. It makes killing stylish:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kevcui.github.io/videos/fkill-example.svg"&gt;fkill example&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  watch? loop!
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;“UNIX’s missing loop command.”&lt;/em&gt; &lt;a href="https://github.com/Miserlou/Loop"&gt;loop&lt;/a&gt; is designed to fill the gap. It works well to replace &lt;code&gt;watch&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# monitor current directory and print file list every 6 seconds

# watch
~$ watch -n 6 ls -l

# loop
~$ loop -e 6s 'ls -l'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moreover, &lt;code&gt;loop&lt;/code&gt; has some awesome options to determine when to stop watching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
-c, --until-contains &amp;lt;until_contains&amp;gt; Keep going until the output contains this string
-r, --until-error &amp;lt;until_error&amp;gt; Keep going until the command exit status is non-zero, or the value given
-m, --until-match &amp;lt;until_match&amp;gt; Keep going until the output matches this regular expression
-t, --until-time &amp;lt;until_time&amp;gt; Keep going until a future time, ex. "2018-04-20 04:20:00" (Times in UTC.)
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: stop watching when &lt;code&gt;stop-now&lt;/code&gt; file is created and then open it in vim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~$ loop -e 6s 'clear;date;ls -l' -c 'stop-now'; vi stop-now
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://kevcui.github.io/videos/loop-example.svg"&gt;loop example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Actually, using &lt;code&gt;loop&lt;/code&gt; to replace &lt;code&gt;for&lt;/code&gt; command is also promising and full of pleasure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# create 10 markdown files: 0.md, 1.md ... 9.md

# for
~$ for ((i=0; i &amp;lt; 10; i++)); do touch ${i}.md; done

# loop
~$ loop -n 10 'touch ${COUNT}.md'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  man? tldr, pet and how2!
&lt;/h3&gt;

&lt;h4&gt;
  
  
  tldr
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/tldr-pages/tldr"&gt;tldr&lt;/a&gt; is a simplified collection of man pages. It returns some command snippets with practical examples:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--isRN9N45--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/tldr-example.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--isRN9N45--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://kevcui.github.io/images/tldr-example.jpg" alt="tldr-example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  pet
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/knqyf263/pet"&gt;pet&lt;/a&gt; is a CLI snippet manager. It’s a handy tool to save some commands snippets which are easily forgotten. The idea is to use &lt;code&gt;pet&lt;/code&gt; building own reference manuals.&lt;/p&gt;

&lt;h4&gt;
  
  
  how2
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/santinic/how2"&gt;how2&lt;/a&gt; takes another approach to search for the right command: it queries questions and answers from stackoverflow!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kevcui.github.io/videos/how2-example.svg"&gt;how2 example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In case the displayed answer is not what exactly you want, &lt;code&gt;how2&lt;/code&gt; provides &lt;a href="https://github.com/santinic/how2#usage"&gt;the interactive mode&lt;/a&gt; to select in a list of all relative questions and answers.&lt;/p&gt;

&lt;p&gt;From now on, we can get confident to “save the world”!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C3uS6lmx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/tar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C3uS6lmx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/tar.png" alt="xkcd-tar"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Share this list if you think it’s a good read for other CLI nerds. 💝&lt;/p&gt;

&lt;p&gt;Drop me a message if you have other commands to recommend. ❤️&lt;/p&gt;

</description>
      <category>cli</category>
      <category>linux</category>
      <category>commands</category>
    </item>
    <item>
      <title>3 mitmproxy Tips You Might Not Know About</title>
      <dc:creator>Kevin Cui</dc:creator>
      <pubDate>Sat, 28 Jul 2018 13:13:04 +0000</pubDate>
      <link>https://dev.to/kevcui/3-mitmproxy-tips-you-might-not-know-about-5dbg</link>
      <guid>https://dev.to/kevcui/3-mitmproxy-tips-you-might-not-know-about-5dbg</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AaleslIm6g3NqRL1xLQ3w5g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AaleslIm6g3NqRL1xLQ3w5g.jpeg" alt="coverimage"&gt;&lt;/a&gt;&lt;sup&gt;&lt;br&gt;
        &lt;em&gt;&lt;br&gt;
            Photo by &lt;a href="https://unsplash.com/photos/betmVWGYcLY" rel="noopener noreferrer"&gt;Ashley Batz&lt;/a&gt;&lt;br&gt;
        &lt;/em&gt;&lt;br&gt;
    &lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mitmproxy.org/" rel="noopener noreferrer"&gt;mitmproxy&lt;/a&gt; is a powerful proxy tool for debugging network requests and responses. It’s my favorite proxy tool and becoming one of my daily essential tools for working. I would like to share with you 3 mitmproxy tips you might not know about.&lt;/p&gt;

&lt;p&gt;First things first, a small checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.mitmproxy.org/stable/concepts-modes/" rel="noopener noreferrer"&gt;Do you know how mitmproxy works?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.mitmproxy.org/stable/overview-installation/" rel="noopener noreferrer"&gt;Do you know how to install mitmproxy?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.mitmproxy.org/stable/concepts-certificates/" rel="noopener noreferrer"&gt;Do you know how to install CA cert on a client side?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If these questions are way too easy for you and your answers are &lt;em&gt;“Yes! Yes! Yes!”&lt;/em&gt;, then continue reading. Otherwise, please click and read the links above, and see you here later.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tips 1: Custom configuration and key binding
&lt;/h3&gt;

&lt;p&gt;One of the advantages of mitmproxy is highly customizable. It’s very continent to set up once configurations that every time mitmproxy loads them automatically when it starts. All the available handy &lt;strong&gt;options&lt;/strong&gt; are in the &lt;a href="https://docs.mitmproxy.org/stable/concepts-options/" rel="noopener noreferrer"&gt;mitmproxy document&lt;/a&gt;. Here is my &lt;code&gt;~/.mitmproxy/config.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console_palette: "dark"
console_palette_transparent: True
console_mouse: False
console_focus_follow: True
ignore_hosts: []
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As I’m using &lt;a href="https://dev.to/kevcui/one-week-with-colemak-482c-temp-slug-2571522"&gt;colemak keyboard layout&lt;/a&gt;, &lt;em&gt;j&lt;/em&gt; and &lt;em&gt;k&lt;/em&gt; keys are opposite for the navigation of up and down in mitmproxy. I have to change these 2 keys to make navigation smooth. Before, to change key bindings in old versions, I have to hack around code in &lt;code&gt;defaultkeys.py&lt;/code&gt;. Since &lt;a href="https://mitmproxy.org/posts/releases/mitmproxy4/" rel="noopener noreferrer"&gt;mitmproxy v4.0&lt;/a&gt;, custom key binding is finally officially supported! Here are my key bindings in &lt;code&gt;~/.mitmproxy/keys.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-
  key: j
  ctx: ["global"]
  cmd: console.nav.up
-
  key: k
  ctx: ["global"]
  cmd: console.nav.down
-
  key: l
  ctx: ["flowlist"]
  cmd: console.nav.select
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To know more about which &lt;strong&gt;command&lt;/strong&gt; to use in &lt;strong&gt;cmd&lt;/strong&gt; field, type &lt;code&gt;K&lt;/code&gt; (shift + k) in mitmproxy. A list of current key bindings will show up. More information about key binging configuration is in the &lt;a href="https://docs.mitmproxy.org/stable/tools-mitmproxy/" rel="noopener noreferrer"&gt;mitmproxy document&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips 2: Knowing client connection status when a filter is applied
&lt;/h3&gt;

&lt;p&gt;It happens quite often to me: when I applied all filters in advance and then tried to connect a client to mitmproxy. However, there is nothing show up in the flow list. How do I know if it’s because &lt;em&gt;the client is not connected to the proxy successfully&lt;/em&gt; or &lt;em&gt;no requests are matching the filter&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;A usual but not good way: Well, I have to remove the filter to see all requests. If I can see requests from the client, then I will again apply the filter…&lt;/p&gt;

&lt;p&gt;An easy way is to add &lt;code&gt;| .*&lt;/code&gt; in the filter, which will reveal all incoming requests. Yep, regex magic:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kevcui.github.io/videos/mitmproxy-filter-on.svg" rel="noopener noreferrer"&gt;mitmproxy filter on&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another easy way is to simply type &lt;code&gt;E&lt;/code&gt; (shift+e), which will open events logs. It shows the client connection status. Use &lt;code&gt;q&lt;/code&gt; to quit events view:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kevcui.github.io/videos/mitmproxy-events-view.svg" rel="noopener noreferrer"&gt;mitmproxy events view&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips 3: Using mitmproxy as a mock server
&lt;/h3&gt;

&lt;p&gt;The killer feature of mitmproxy is scripting. Using python scripts, all requests and responses are fully controlled and changeable &lt;strong&gt;on the fly&lt;/strong&gt;. Besides that, mitmproxy is super robust to handle multiple clients simultaneously connected to one host. These features make mitmproxy a decent mock server. Therefore, I use mitmproxy a lot as &lt;a href="https://dev.to/kevcui/bad-use-of-a-good-tool-4ja7-temp-slug-6954387"&gt;a mock server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example, a script for the purpose of rewriting and mocking response body, &lt;a href="https://github.com/KevCui/mitm-scripts/tree/master/mitm-rewrite" rel="noopener noreferrer"&gt;mitm-rewrite&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Map &lt;code&gt;http://example.com/pass&lt;/code&gt; to &lt;code&gt;test_pass.json&lt;/code&gt; &lt;em&gt;(terminal on the bottom left)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Create mock response data in &lt;code&gt;test_pass.json&lt;/code&gt; &lt;em&gt;(terminal on the bottom right)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Visit &lt;code&gt;http://example.com/pass&lt;/code&gt; on the client side&lt;/li&gt;
&lt;li&gt;The initial response is now replaced by the one in &lt;code&gt;test_pass.json&lt;/code&gt; &lt;em&gt;(terminal on top)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FKevCui%2Fmitm-scripts%2Fmaster%2Fscreenshot%2Fmitm-rewrite-example.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FKevCui%2Fmitm-scripts%2Fmaster%2Fscreenshot%2Fmitm-rewrite-example.jpg" alt="mitmproxy mock server picture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to know more useful scripts, I have a &lt;a href="https://github.com/KevCui/mitm-scripts" rel="noopener noreferrer"&gt;mitm-scripts collection&lt;/a&gt; to check out. If you want to make your own scripts, there are &lt;a href="https://github.com/mitmproxy/mitmproxy/tree/master/examples/simple" rel="noopener noreferrer"&gt;some examples&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Didn’t try mitmproxy yet? Get it a try. 😉&lt;br&gt;
Know other mitmproxy tricks? Tell me more. 😍&lt;/p&gt;

</description>
      <category>mitmproxy</category>
      <category>proxy</category>
      <category>tool</category>
      <category>mock</category>
    </item>
    <item>
      <title>One Week with Colemak</title>
      <dc:creator>Kevin Cui</dc:creator>
      <pubDate>Sun, 27 Aug 2017 08:07:30 +0000</pubDate>
      <link>https://dev.to/kevcui/one-week-with-colemak-489k</link>
      <guid>https://dev.to/kevcui/one-week-with-colemak-489k</guid>
      <description>&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%2F0quyc7r9r91k9157i16s.png" 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%2F0quyc7r9r91k9157i16s.png" alt="coverimage" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last weekend, I decided to &lt;a href="https://dev.to/kevcui/why-i-switch-to-colemak-keyboard-layout-190i-temp-slug-1657816"&gt;switch from QWERTY to Colemak keyboard layout&lt;/a&gt;. Did I suffer a lot since then? Of course no, well, maybe a little bit. After “one-week intensive typing training”, actually I quite enjoy the fresh feeling of typing with Colemak. I’m pretty happy that now I am able to type on Colemak keyboard layout with the average speed &lt;strong&gt;50 WPM&lt;/strong&gt;. I would say that it’s good enough for daily life. If you happen to be interested in switching to Colemak, here are my short notes for every day of last week and how my “intensive” training looks like.&lt;/p&gt;

&lt;h3&gt;
  
  
  D1 - Saturday
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Time Spent: 1 hour&lt;/li&gt;
&lt;li&gt;Typing Speed: 15 WPM&lt;/li&gt;
&lt;/ul&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%2F0olol980gqvdw7l2beva.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%2F0olol980gqvdw7l2beva.gif" alt="Jon knows" width="245" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Plan? Just do it!
&lt;/h4&gt;

&lt;p&gt;There are some different approaches to help people switching to Colemak progressively. One interesting approach is called &lt;a href="https://forum.colemak.com/topic/1858-learn-colemak-in-steps-with-the-tarmak-layouts/" rel="noopener noreferrer"&gt;Tarmak&lt;/a&gt; (Transitional Colemak) learning layouts. Tarmak has 4 layouts in total, &lt;em&gt;each of the 4 Tarmak layouts changes 3–4 new keys from the previous step until you’ve made the full transition to Colemak.&lt;/em&gt; &lt;sup&gt;&lt;a&gt;&lt;/a&gt;[1]&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;In deed, it sounds like a good plan. But I didn’t go that way, I chose a crazy approach: go &lt;a href="https://www.phrases.org.uk/meanings/cold-turkey.html" rel="noopener noreferrer"&gt;cold turkey&lt;/a&gt;. I get rid of QWERTY and use Colemak immediately. Because I believe that I could handle the change to Colemak completely at once. At the end, it’s all about training &lt;strong&gt;muscle memory&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Remember the layout
&lt;/h4&gt;

&lt;p&gt;First things first, remember &lt;a href="https://colemak.com/wiki/images/8/80/Colemak_layout_2.png" rel="noopener noreferrer"&gt;the layout&lt;/a&gt;. To be familiar with Colemak layout, I spent 30 minutes on typing alphabet “abcdefgh…” repeatedly, until I am 100% sure that all 26 letters are in their correct positions.&lt;/p&gt;

&lt;h3&gt;
  
  
  D2 - Sunday
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Time spent: 3 hours (3 1-hour sessions)&lt;/li&gt;
&lt;li&gt;Typing speed: 25 WPM&lt;/li&gt;
&lt;/ul&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%2F9tz0tijelu8ikrbdl26d.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%2F9tz0tijelu8ikrbdl26d.gif" alt="little finger" width="277" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Brain takes full control
&lt;/h4&gt;

&lt;p&gt;After I memorized the layout, the real “intensive” training began. The main site I used is &lt;a href="https://www.speedtypingonline.com/typing-test" rel="noopener noreferrer"&gt;Speed Typing Online&lt;/a&gt;. One article after another, I keep typing. Meanwhile, I have to let my brain know exactly what I need to do and then my fingers would be forced to do it. This process of erasing muscle memory is slow. My brain needs to be highly focused in order to control each single movement of my fingers, and to prevent these movements initialized by old muscle memory.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pinky is weaky
&lt;/h4&gt;

&lt;p&gt;One difficulty I did realize is that my right little finger is weaker than my other fingers. Before with QWERTY, it takes control of letter “P”, which appearance frequency is way more lower than the letter “O”. Now with Colemak, it has to take care of letter “O”. This sudden increase of heavy work load on the shoulder of right pinky finger makes it clumsy. I can really feel the “stop” moment when letter “O” is needed. So I have to focus on training pinky finger, even more.&lt;/p&gt;

&lt;h3&gt;
  
  
  D3 - Monday
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Time spent: 1 hour training + 8 hours working&lt;/li&gt;
&lt;li&gt;Typing speed: 28 WPM&lt;/li&gt;
&lt;/ul&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%2Fs9sldkefpwz17jjwypll.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%2Fs9sldkefpwz17jjwypll.gif" alt="shame" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Productivity?
&lt;/h4&gt;

&lt;p&gt;As I decided to go cold turkey and I don’t want a detour, I changed the keyboard layout on my working laptop to Colemak as well. I remember my first and second login attempts were failed, after that, nothing was really struggling. To be honest, the typing speed around 25 WPM is enough for daily work, but the efficiency is… meh… Especially, when replying someone’s questions in chat app, I feel sorry to let people on another side waiting a bit longer than usual. Besides that, when I was coding/scripting, I felt that I have more time for thinking, which might be a good thing.&lt;/p&gt;

&lt;h4&gt;
  
  
  Smartphone out!
&lt;/h4&gt;

&lt;p&gt;As the inventor of Colemak mentioned, &lt;em&gt;Colemak isn’t recommended for smartphones as it increases finger travel and error rate compared to QWERTY. On smartphones I would recommend gesture typing on a QWERTY layout&lt;/em&gt;. &lt;sup&gt;&lt;a&gt;&lt;/a&gt;[2]&lt;/sup&gt; Furthermore, the muscle memory of typing on smartphone keyboard is not the same. Therefore, I will still keep using QWERTY layout in smartphone until one day another “advanced” keyboard layout invented for smartphone.&lt;/p&gt;

&lt;h3&gt;
  
  
  D4 - Tuesday
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Time spent: 1 hour training + N hours working + N hours imagining&lt;/li&gt;
&lt;li&gt;Typing speed: 30 WPM&lt;/li&gt;
&lt;/ul&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%2Fd31llrov8bj7q7yaafv2.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%2Fd31llrov8bj7q7yaafv2.gif" alt="imagining" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Use imagination
&lt;/h4&gt;

&lt;p&gt;I found a magic way to perform typing training without a physical keyboard: using my imaginations. For instance, when I am in public transport, I’d like to listen to podcasts. From the earphones I heard the words, then I put my hands in the air and move fingers to type these words. Others who were watching at me may think that I could be a pianist, or probably a madman.&lt;/p&gt;

&lt;h3&gt;
  
  
  D5 - Wednesday
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Time spent: 1 hour training + N hours working + N hours imagining&lt;/li&gt;
&lt;li&gt;Typing speed: 40 WPM&lt;/li&gt;
&lt;/ul&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%2Frf6e9157bn4wa0iha4hu.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%2Frf6e9157bn4wa0iha4hu.gif" alt="aiming" width="500" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Targeted training
&lt;/h4&gt;

&lt;p&gt;It’s time to have more targeted training of some common suffixes. In theory, if I could type them unconsciously as a reflection, my typing speed would increase a lot. So I made a list of suffixes to focus on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-ly, -ing, -ion, -er, -or, -ment, -ous, -ful, -able
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the other hand, I found that I made many mistakes on top row letters “f”, “g”, “l” and “y”. I keep in my mind to pay attention to them: be accurate first, then speed up.&lt;/p&gt;

&lt;p&gt;Moreover, I started to learn typing systematically by following the lessons on &lt;a href="https://www.typing.com/student" rel="noopener noreferrer"&gt;typing.com&lt;/a&gt;. I skipped the entire beginner lessons and some lessons designed for QWERTY only.&lt;/p&gt;

&lt;h3&gt;
  
  
  D6 - Thursday
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Time spent: 1 hour training + N hours working + N hours imagining&lt;/li&gt;
&lt;li&gt;Typing speed: 50 WPM&lt;/li&gt;
&lt;/ul&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%2Fjtjs99dxz397brk929i9.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%2Fjtjs99dxz397brk929i9.gif" alt="repeat" width="320" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Repetition, Repetition, Repetition…
&lt;/h4&gt;

&lt;p&gt;Every day, I am better at typing than yesterday. I felt my muscle memory is improved little by little: now I don’t need to think about the layout ahead! It means that I can think other stuff in my mind while typing letters on the keyboard. It’s definitely a good sign, which tastes so sweet. It’s the power of repetition and the outcome of never-give-up.&lt;/p&gt;

&lt;h3&gt;
  
  
  D7 - Friday
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Time spent: 1 hour training + N hours working + N hours imagining&lt;/li&gt;
&lt;li&gt;Typing speed: 52 WPM&lt;/li&gt;
&lt;/ul&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%2F464e72va8tuhx0o3n40z.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%2F464e72va8tuhx0o3n40z.gif" alt="fun" width="320" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Time to have fun
&lt;/h4&gt;

&lt;p&gt;After these days’ practices, I know I am on the right track to achieve the success. Although it’s important as my daily routine to keep using &lt;a href="https://www.speedtypingonline.com/typing-test" rel="noopener noreferrer"&gt;Speed Typing Online&lt;/a&gt; and following basic lesson on &lt;a href="https://www.typing.com/student" rel="noopener noreferrer"&gt;typing.com&lt;/a&gt;, learning typing can also be full of fun, without the boredness of repetition. It’s time to discover something new and have some fun:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://thetypingcat.com/typing-speed-test/" rel="noopener noreferrer"&gt;TypingCAT&lt;/a&gt;: It’s an ordinary typing site. But its UI is super clean and comfortable. It will make you feel awesome when you are typing.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ratatype.com/typing-test/test/" rel="noopener noreferrer"&gt;Ratatype typing test&lt;/a&gt;: Instead of the usual time-box approach, this site requires you to finish the whole article and then shows your score. Their typing materials are really good. They normally have 50-100 words, with the mix of letters, numbers and punctuations.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://play.typeracer.com/" rel="noopener noreferrer"&gt;typeracer&lt;/a&gt;: A typing competition is presented as a form of car racing game. It supports Multiplayer “racing” together. Its UI is okish and its material is so-so. But if you want to see how is your performance under stress, it’s a good game to play.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  D(n) - In the future…
&lt;/h3&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%2F1t21rxwvofuu2rja4170.png" 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%2F1t21rxwvofuu2rja4170.png" alt="success kid" width="160" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Use Caps Lock as…?
&lt;/h4&gt;

&lt;p&gt;Colemak maps Caps Lock key to Backspace. It makes sense to have another Backspace on the left hand to balance its usage in two hands. But so far I don’t use it at all. Maybe I will map it to Esc, which is useful in Vim.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Get rid of bad habits
&lt;/h4&gt;

&lt;p&gt;I still need to get rid of some bad habits of using QWERTY:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always use left thumb to tap Space bar&lt;/li&gt;
&lt;li&gt;Always use left pinky to tap Shift&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I know how to do it correctly, but… Fine, I will do it correctly in the future.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Colemak x Vim
&lt;/h4&gt;

&lt;p&gt;New layout for Vim is a tough challenge. I had several oops-moment which are caused by “gg” vs. “dd”. But I don’t think I will remap keys to make the original Vim style alike. I prefer to relearn it with Colemak from scratch. Here is the &lt;a href="https://c1.staticflickr.com/6/5060/5421396271_68f3d12c9e_b.jpg" rel="noopener noreferrer"&gt;Colemak/vim cheat sheet&lt;/a&gt; &lt;sup&gt;&lt;a&gt;&lt;/a&gt;[3]&lt;/sup&gt;. I know it will take a while to fully operate Vim with Colemak.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Get “QWERTY mode” back?
&lt;/h4&gt;

&lt;p&gt;As a side effect, the muscle memory of QWERTY is completely lost. I cannot type with QWERTY layout anymore. Should I train myself to get QWERTY mode back in the future? I guess no ¯_(ツ)_/¯&lt;/p&gt;




&lt;p&gt;[1] Øystein Bech Gadmar: &lt;a href="https://forum.colemak.com/topic/1858-learn-colemak-in-steps-with-the-tarmak-layouts/" rel="noopener noreferrer"&gt;How does Tarmak work?&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[2] Shai Coleman: &lt;a href="https://colemak.com/FAQ#Is_Colemak_suitable_for_smartphones.3F" rel="noopener noreferrer"&gt;Is Colemak suitable for smartphones?&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[3] Aimee Rivers: &lt;a href="https://sermoa.wordpress.com/2011/12/16/colemak-and-vim-but-what-about-hjkl/" rel="noopener noreferrer"&gt;“Colemak and vim”: But what about h/j/k/l?&lt;/a&gt;&lt;/p&gt;

</description>
      <category>colemak</category>
      <category>keyboard</category>
    </item>
    <item>
      <title>Why I Switch to Colemak Keyboard Layout?</title>
      <dc:creator>Kevin Cui</dc:creator>
      <pubDate>Sat, 19 Aug 2017 18:48:03 +0000</pubDate>
      <link>https://dev.to/kevcui/why-i-switch-to-colemak-keyboard-layout-24h4</link>
      <guid>https://dev.to/kevcui/why-i-switch-to-colemak-keyboard-layout-24h4</guid>
      <description>&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%2F5eftdzn9cgjh81r8z5r6.png" 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%2F5eftdzn9cgjh81r8z5r6.png" alt="coverimage" width="730" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://colemak.com/FAQ" rel="noopener noreferrer"&gt;Colemak&lt;/a&gt;, pronounced /‘ko:lmæk/ (Coal-Mac), is a keyboard layout based on QWERTY. It’s developed by &lt;a href="https://ie.linkedin.com/in/shaicoleman" rel="noopener noreferrer"&gt;Shai Coleman&lt;/a&gt; and released in 2006. Colemak keyboard layout looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;q w f p g j l u y ;
   a r s t d h n e i o
    z x c v b k m , . /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What’s special about Colemak? Why do I decide to switch from QWERTY to Colemak?&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason 1: Discard QWERTY
&lt;/h3&gt;

&lt;p&gt;As we all known, QWERTY was originally designed for the typewriter to solve the problem of the type bars colliding with each other and jamming. The idea behind is &lt;em&gt;to arrange the keys with the most common letters in hard to reach spots, to slow typists down and try to avoid typewriter jams&lt;/em&gt;. &lt;sup&gt;&lt;a&gt;&lt;/a&gt;[1]&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;If you’re interested in more stories of QWERTY, &lt;a href="http://discovermagazine.com/1997/apr/thecurseofqwerty1099" rel="noopener noreferrer"&gt;The Curse of QWERTY&lt;/a&gt; is a nice article to read.&lt;/p&gt;

&lt;p&gt;Since the mechanical typewriters vanished from historical stage and all the modern computers don’t have “mechanical sticking” problem, why we still need to bear the pain of the inefficiency of QWERTY? It’s time to let QWERTY be retired with honor. Let it go!&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason 2: I want a challenge
&lt;/h3&gt;

&lt;p&gt;When I was 14 years old, I started to learn to type on a typewriter in school. Yes, a real typewriter and it’s amazing! I can still recall the comment when type bars hit on paper, the sound and the feeling are so satisfying. At the end of the semester, I successfully passed typing exam with the speed of 70 WPM. Now it has been 15 years, my speed stays around 75 WPM. For me, it’s obviously not improved at all…&lt;/p&gt;

&lt;p&gt;As a guy who is eager for something new and obsessed with efficiency, I don’t believe that 75 WPM is my limit. I’m afraid that QWERTY itself is the obstacle. Maybe an alternative keyboard would unchain my ability. That’s why I want a challenge to see how fast I’m able to type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason 3: Efficiency is the key
&lt;/h3&gt;

&lt;p&gt;Colemak is designed to be &lt;em&gt;ergonomic, comfortable and fast.&lt;/em&gt; &lt;sup&gt;&lt;a&gt;&lt;/a&gt;[2]&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;According to &lt;a href="http://mkweb.bcgsc.ca/carpalx/?popular_alternatives" rel="noopener noreferrer"&gt;carpalx analysis&lt;/a&gt;, Colemak has a quite low typing effort among 10 keyboard layouts. The carpalx detailed analysis &lt;sup&gt;&lt;a&gt;&lt;/a&gt;[3]&lt;/sup&gt; shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Colemak has a great home row usage 74%, compared to QWERTY 34% and Dvorak 71%&lt;/li&gt;
&lt;li&gt;Colemak bottom row usage is low at 9%, the same as Dvorak, which is better than QWERTY 15%&lt;/li&gt;
&lt;li&gt;Colemak is more balanced in hand use, with a 6% preference for the right hand. Dvorak has 14% for the right and QWERTY 15% for the left&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is an app to analyze the different keyboard layouts. It’s called &lt;a href="http://patorjk.com/keyboard-layout-analyzer/#/main" rel="noopener noreferrer"&gt;Keyboard Layout Analyzer&lt;/a&gt;. I’m curious how the result would be. So I tried to input:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A recent &lt;a href="http://www.bbc.com/news/world-europe-40990927" rel="noopener noreferrer"&gt;BBC article&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;George R. R. Martin &lt;a href="https://www.biography.com/people/george-r-r-martin-20786615?_escaped_fragment_=" rel="noopener noreferrer"&gt;Biography&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;One of my &lt;a href="https://github.com/kevcui/hearthstone-cards-searcher/blob/master/hsSearch.py" rel="noopener noreferrer"&gt;python script&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;My blog &lt;a href="https://raw.githubusercontent.com/kevcui/kevcui.github.io/master/index.html" rel="noopener noreferrer"&gt;index.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;One of my blog &lt;a href="https://kevcui.github.io/2016/12/23/my-year-2016/" rel="noopener noreferrer"&gt;post&lt;/a&gt; plain text&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result of these 5 rounds: Colemak scores the highest in each round.&lt;/p&gt;

&lt;p&gt;High home row usage, less finger travel distance, and balanced left-right hands… These advantages of Colemak make it as one of the best keyboard layouts for improving efficiency and ergonomics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason 4: Easy to learn
&lt;/h3&gt;

&lt;p&gt;I remember 5 years ago, I planned to switch to Dvorak. But I was totally failed after 1-week struggling. Because the transition phrase from QWERTY to Dvorak is really hard, I was not good enough to use only Dvorak at work. Therefore, it required me to memorize 2 different keyboard layouts at the same time, which was possible for my brain but impossible for my muscles. I was kidding at that time: I need at least a 2-months vacation to train Dvorak without any productivity.&lt;/p&gt;

&lt;p&gt;To learn Colemak, I feel it would be a different story. Colemak is based on QWERTY layout, which means it’s built without the terrifying prospect of changing everything. &lt;em&gt;The Colemak layout is reasonably similar to QWERTY with just 17 different keys as opposed to Dvorak’s 33, and only two letters P and E that move from one hand to the other, whereas with Dvorak it’s 22.&lt;/em&gt; &lt;sup&gt;&lt;a&gt;&lt;/a&gt;[4]&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Colemak is rather easy to learn. It took me only 30 min to memorize Colemak keyboard layout without any frustration. After 1 day training, now I’m already used to it. I estimate that a 2-days weekend should be enough for me to have a reasonable typing speed. It wouldn’t cause my huge headache to use Colemak at work next Monday.&lt;/p&gt;




&lt;p&gt;These tantalizing reasons give me the motivation to switch to Colemak. I guess I have to face this challenge and I will be busy with training next week. Challenge is on and change is now.&lt;/p&gt;

&lt;p&gt;Happy typing Colemak!&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%2Fxpwnadax2zaihzdhmh1t.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%2Fxpwnadax2zaihzdhmh1t.gif" alt="typing" width="490" height="294"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;[1] HowStuffWorks: &lt;a href="https://computer.howstuffworks.com/question458.htm" rel="noopener noreferrer"&gt;Why are the keys arranged the way they are on a QWERTY keyboard?&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[2] Shai Coleman: &lt;a href="https://colemak.com/" rel="noopener noreferrer"&gt;Colemak advantages&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[3] Carpalx: &lt;a href="http://mkweb.bcgsc.ca/carpalx/?colemak" rel="noopener noreferrer"&gt;Colemak typing effort&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[4] Eric Limer: &lt;a href="http://www.popularmechanics.com/technology/a20524/learning-to-type-again-colemak" rel="noopener noreferrer"&gt;Why I’m Learning To Type All Over Again&lt;/a&gt;&lt;/p&gt;

</description>
      <category>colemak</category>
      <category>keyboard</category>
    </item>
  </channel>
</rss>
