<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[The Flying Dev]]></title><description><![CDATA[I'm The Flying Dev - a self-taught developer by night and a flight attendant by day.  Founder and host of the Landing in Tech podcast.  I build projects live on]]></description><link>https://node.theflying.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 18 Apr 2026 17:16:36 GMT</lastBuildDate><atom:link href="https://node.theflying.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Email aliases to fight off spam and improve security]]></title><description><![CDATA[If you use an email long enough, you know how much spam that email will get - some even pass through the filter and reach your inbox. When this happens, you can do three things:

Add filtering to delete emails from a specific domain/email address aut...]]></description><link>https://node.theflying.dev/email-aliases-to-fight-off-spam-and-improve-security</link><guid isPermaLink="true">https://node.theflying.dev/email-aliases-to-fight-off-spam-and-improve-security</guid><category><![CDATA[email]]></category><category><![CDATA[Security]]></category><category><![CDATA[spam]]></category><category><![CDATA[infosec]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Mon, 06 Mar 2023 12:52:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/LPZy4da9aRo/upload/ca78654c1c7ff13a4b2d7c98f1204308.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you use an email long enough, you know how much spam that email will get - some even pass through the filter and reach your inbox. When this happens, you can do three things:</p>
<ul>
<li><p>Add filtering to delete emails from a specific domain/email address automatically</p>
</li>
<li><p>Ignore them as always and keep using your email</p>
</li>
<li><p>Declare email bankruptcy and move to a new email</p>
</li>
</ul>
<p>As part of my journey to improve security and account hardening, I started looking for an email forwarding service. I could create random aliases for different services, permitting me to create new emails and forward them all to a single place.</p>
<p>Ideally, the final email would never be used, which means that the only way this email could get hit by spam is if you used it somewhere or if one of the email aliases received it.</p>
<h2 id="heading-enter-simplelogin">Enter SimpleLogin</h2>
<p>The free plan of <a target="_blank" href="https://simplelogin.io/">SimpleLogin</a> allows you to create 10 aliases to forward to a single email address. It also allows you to reply directly from your alias; this prevents you from leaking your original email address to any message. SimpleLogin is also open source, which is an essential aspect for me.</p>
<p>Using the service is pretty straightforward. Once you connect your email to SimpleLogin, you can create a custom alias or generate a random one. You can also generate temporary aliases and disable them after some time. The settings are also brilliant and allow you a great deal of control.</p>
<h3 id="heading-how-it-helps-fight-spam">How it helps fight spam</h3>
<p>This is all great, but you may be thinking:</p>
<p><strong>"How does all of that will help me fight spam?"</strong></p>
<p>Glad you asked. Once you receive an email from an alias, SimpleLogin allows you to block the sender, so even if the sender tries to send you more emails, they get blocked and will never reach your inbox.</p>
<p>As I mentioned above, it also allows you to generate temporary aliases, generating some for a set period and rotating them.</p>
<p>If you subscribe, you can even go a bit crazy (like I did) and generate a single alias for each website where I have an account. The fun thing with this approach is that you know who might have sold your email address, making it easier for you to delete your account with these services.</p>
<h2 id="heading-moving-a-domain-to-simplelogin">Moving a domain to SimpleLogin</h2>
<p>I used a forwarding service with my primary email address from this domain. Although, I wasn't thrilled with it. Not only did the service expose the original email through a DNS checker, but it also didn't provide DMARC records.</p>
<p>SimpleLogin provided all that for me, so I didn't have to worry too much about email forwarding other than updating the DNS records.</p>
<p>The service also allows you to create catch-all aliases for your domain names, although that isn't recommended if you want to fight off spam, since folks can type any email address with your domain name, and you will get the email.</p>
<p>For example, <a target="_blank" href="mailto:i-really-want-to-spam-you@your-domain-name.com"><code>i-really-want-to-spam-you@your-domain-name.com</code></a> would create a new alias with the name <code>i-really-want-to-spam-you</code>, and the email would be forwarded to your original inbox.</p>
<h2 id="heading-the-not-so-great">The not so great</h2>
<p>Okay, so this entry is starting to sound like I will get anything from SimpleLogin (I don't). Let's now look at the not-so-great aspects of the service.</p>
<p>It's unclear what you need to do if you want to reply to an email that was forwarded to you with the alias. You don't need to do anything, just hit reply and SimpleLogin will use your alias to send the reply.</p>
<p>If you haven't received an email from this email address, you need to add it to your contact list so SimpleLogin can generate a reverse-alias. To send a new email to a contact, click the <code>contacts</code> button and copy the reverse-alias from the list. SimpleLogin will then use your alias to send this email.</p>
<p>Look at the <a target="_blank" href="https://simplelogin.io/docs/getting-started/send-email/">documentation for sending emails</a> to learn more about how this works and how to add an email to your contact list.</p>
<p>As I mentioned above, the settings are great, but it can be confusing to know what each one of them does. You should refer to the documentation to know what each bit does.</p>
<h2 id="heading-closing-thoughts">Closing thoughts</h2>
<p>It's pretty clear that I enjoy SimpleLogin. Not only it helps me with various email forwarding scenarios. It also allows me to create new aliases for each new account. This is important for account hardening since I can generate a new email alias and delete the breached alias.</p>
]]></content:encoded></item><item><title><![CDATA[Journey of improving security and account hardening]]></title><description><![CDATA[When I first learned about haveibeenpwned a couple of years ago, it put into perspective how bad my security practices were. At that time, I committed all the primary sins:

Reusing passwords

Using the same email for everything

Using easy-to-guess ...]]></description><link>https://node.theflying.dev/journey-of-improving-security-and-account-hardening</link><guid isPermaLink="true">https://node.theflying.dev/journey-of-improving-security-and-account-hardening</guid><category><![CDATA[#cybersecurity]]></category><category><![CDATA[Security]]></category><category><![CDATA[passwords]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Sun, 12 Feb 2023 20:50:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/iIJrUoeRoCQ/upload/8470337aba3d8ea82fea4eb82c0cd5b6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I first learned about <a target="_blank" href="https://haveibeenpwned.com">haveibeenpwned</a> a couple of years ago, it put into perspective how bad my security practices were. At that time, I committed all the primary sins:</p>
<ul>
<li><p>Reusing passwords</p>
</li>
<li><p>Using the same email for everything</p>
</li>
<li><p>Using easy-to-guess passwords</p>
</li>
<li><p>Not using 2FA because it was annoying</p>
</li>
<li><p>Thinking <em>I'm not important enough for anyone to do anything with my information</em></p>
</li>
</ul>
<p>Then I pasted my old email into haveibeenpwned and saw an extensive list of how many times that email was found.</p>
<h2 id="heading-first-steps">First steps</h2>
<p>The very first thing I did was research how to mitigate risk, which summed up to the following:</p>
<ul>
<li><p>Stop reusing passwords, silly</p>
</li>
<li><p>Stop using the same email</p>
</li>
<li><p>Make passwords hard to guess</p>
</li>
<li><p>2FA all the things!</p>
</li>
</ul>
<p>To solve the issue of password management, I registered for LastPass and started using it as my password management. Until one day, I lost the master password and had to start all over again. Still, the second time LastPass was the winner again (mainly due to familiarity).</p>
<p>I've also occasionally started cycling passwords but not keeping a proper schedule.</p>
<h2 id="heading-the-nail-in-the-coffin">The nail in the coffin</h2>
<p>When it comes to breaches and hacking, it's not <em>if you get breached/hacked</em>, but <strong>when</strong>. This last LastPass breach put into perspective how (un)safe your data can be. In the end, you trust a specific company with the keys to all your accounts (and extra things if you use them to store cards and notes).</p>
<p>It is evident that LastPass wasn't an option, so I started looking for a replacement. At the same time, I started following the <a target="_blank" href="https://fosstodon.org/tags/infosec">#infosec</a> tag in Mastodon and saw a lot of great content about the LastPass breach and alternatives from <a target="_blank" href="https://infosec.exchange/@epixoip">Jeremi M Gosney</a>.</p>
<h2 id="heading-enter-bitwarden">Enter BitWarden</h2>
<p>In the end, I decided to go with BitWarden for two reasons:</p>
<ul>
<li><p>Great price for the premium plan</p>
</li>
<li><p>Is Open Source</p>
</li>
</ul>
<p>Migrating from LastPass was easy; all you need to do is export your data. The export was easy but left a sour taste in the mouth since it opened a new browser tab with all the data in plaintext in a CSV format.</p>
<p>Then all that was left to do was to use the BitWarden import option to import the CSV file. Once that was done, the highly tedious task of changing ALL passwords began!</p>
<p>Even though the task was tedious, it was good because I could delete a bunch of accounts I was no longer interested in having.</p>
<h2 id="heading-account-hardening">Account hardening</h2>
<p>As with the first discovery of haveibeenpwned, this LastPass breach made me want to improve even more my security practices. I would have to rely on a company to help me with this task.</p>
<p>I've used both the email and VPN services from <a target="_blank" href="https://proton.me/">Proton</a> in the past, and I like that they are both Open Source and focus on privacy. I was going to rely on Proton to help me harden my accounts. So it was a no-brainer.</p>
<p>Here's what I have implemented:</p>
<ul>
<li><p>Regular password changes</p>
</li>
<li><p>Use email alias for different accounts through <a target="_blank" href="https://simplelogin.io">simplelogin</a></p>
</li>
<li><p>Delete any account that I haven't used in the past three months</p>
</li>
<li><p>Call email bankrupt to my other emails</p>
</li>
<li><p>Create a bunch of different proton emails for different purposes and use simplelogin to sieve email into through an alias</p>
</li>
<li><p>I got an Yubikey and started using it as a 2FA alternative</p>
</li>
</ul>
<p>There are a lot of things that I could do to harden my accounts even further. Please share your thoughts and ideas!</p>
]]></content:encoded></item><item><title><![CDATA[How to make a UI element persistent in Gatsby]]></title><description><![CDATA[When I built the website for Landing in Tech I wanted to have a bar on top of the page with the latest episode. 
The idea was to allow users to listen to the episode while browsing the page.
I added the iframe on my layout.js file and expected it to ...]]></description><link>https://node.theflying.dev/how-to-make-a-ui-element-persistent-in-gatsby</link><guid isPermaLink="true">https://node.theflying.dev/how-to-make-a-ui-element-persistent-in-gatsby</guid><category><![CDATA[Gatsby]]></category><category><![CDATA[tips]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Sat, 07 Nov 2020 20:10:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1604779687140/huK4EJ7uz.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<iframe width="560" height="315" src="https://www.youtube.com/embed/aysyFVflljU"></iframe>

<p>When I built the website for <a target="_blank" href="https://landingintech.com">Landing in Tech</a> I wanted to have a bar on top of the page with the latest episode. </p>
<p>The idea was to allow users to listen to the episode while browsing the page.</p>
<p>I added the iframe on my <code>layout.js</code> file and expected it to work, obviously, it didn't. With each route change, the whole layout reloads which means that you would lose your progress if you started to listen to the episode.</p>
<p>Yesterday, I asked on Twitter if anyone knew a way to fix this issue. <a target="_blank" href="https://twitter.com/BasileSamel">Baz</a> gave great advice on how to achieve this. He mentioned that Gatsby should have a way to handle this, that was my lightbulb moment - perhaps using the <a target="_blank" href="https://www.gatsbyjs.com/docs/browser-apis/"><code>gatsby-browser</code></a> api, might do exactly what I needed.</p>
<h2 id="a-lucky-strike">A lucky strike</h2>
<p>I have to admit that I came to the solution by luck. I was scrolling through the browser api pages and came across the <code>wrapRootElement</code>.</p>
<blockquote>
<p>"This is useful to set up any Provider components that will wrap your application. For setting persistent UI elements around pages use wrapPageElement."
<a target="_blank" href="https://www.gatsbyjs.com/docs/browser-apis/">Gatsby documentation</a></p>
</blockquote>
<p>After playing around with it, I have realised that both <code>wrapRootElement</code> and <code>wrapPageElement</code> do what I wanted, but since Gatsby suggests using the former for persistent UI elements, I've used that one instead.</p>
<p>Let's open the <code>gatsby-browser.js</code> file and add the SoundCloud iframe inside our Layout.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> React = <span class="hljs-built_in">require</span>(<span class="hljs-string">"react"</span>)
<span class="hljs-keyword">const</span> Layout = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./src/components/layout"</span>).default

<span class="hljs-built_in">exports</span>.wrapPageElement = <span class="hljs-function">(<span class="hljs-params">{ element }</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Layout</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"sound-cloud"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">iframe</span>
                    <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-0"</span>
                    <span class="hljs-attr">width</span>=<span class="hljs-string">"100%"</span>
                    <span class="hljs-attr">height</span>=<span class="hljs-string">"20"</span>
                    <span class="hljs-attr">scrolling</span>=<span class="hljs-string">"no"</span>
                    <span class="hljs-attr">frameBorder</span>=<span class="hljs-string">"no"</span>
                    <span class="hljs-attr">allow</span>=<span class="hljs-string">"autoplay"</span>
                    <span class="hljs-attr">title</span>=<span class="hljs-string">"latest episode"</span>
                    <span class="hljs-attr">src</span>=<span class="hljs-string">"https://w.soundcloud.com/player/..."</span>
                /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            {element}
        <span class="hljs-tag">&lt;/<span class="hljs-name">Layout</span>&gt;</span></span>
    )
}
</code></pre>
<h2 id="refactoring-pages">Refactoring Pages</h2>
<p>Since I am importing the Layout and using it in <code>wrapPageElement</code> that means that each page will have two <code>Layout</code> components, the one that I have imported in each page and the one being set in <code>gatsby-browser</code>. </p>
<p>This meant that I had Ito refactor every page and remove the Layout component on every single one. A tedious task, but the end result does exactly what I wanted.</p>
<p><strong>Update</strong></p>
<p>After sharing this article on Twitter a lot of great developers told me that I need to add the same to the <code>gatsby-ssr.js</code> file, this is because Gatsby uses that file when running gatsby build. So, make sure you add the code to both <code>gatsby-browser</code> and <code>gatsby-ssr</code> file.</p>
]]></content:encoded></item><item><title><![CDATA[Git: Understanding version control]]></title><description><![CDATA[Version control systems are tools to keep track of changes to source code or other collections of files and folders. They help to track the changes of documents, they make it easy collaborating with someone else.
Version Control track changes in a se...]]></description><link>https://node.theflying.dev/git-understanding-version-control</link><guid isPermaLink="true">https://node.theflying.dev/git-understanding-version-control</guid><category><![CDATA[Git]]></category><category><![CDATA[version control]]></category><category><![CDATA[basics]]></category><category><![CDATA[introduction]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Thu, 05 Nov 2020 15:12:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1604589359242/7ZHdbCOD-.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Version control systems are tools to keep track of changes to source code or other collections of files and folders. They help to track the changes of documents, they make it easy collaborating with someone else.</p>
<p>Version Control track changes in a series of snapshots and they contain the entire state of files or folders within a directory. They also add metadata that contains things like who created the snapshot, messages, changes, etc.</p>
<p>Version control is useful because it let you look at old snapshots of a project, keep a log of changes, work on different branches, see who wrote a specific line or who added a change and more.</p>
<h2 id="git-data-model">Git data model</h2>
<p>Git has a data model that enables features of version control such as keeping track of changes in history, allowing branches and collaboration with other folks.</p>
<h3 id="snapshots">Snapshots</h3>
<p>A snapshot is what we know as a commit. It contains the history of files, folders and metadata. A snapshot is the top-level tree/directory that is being tracked.</p>
<blockquote>
<p><strong>Note:</strong> We can track a top-level tree with the command <code>git init</code></p>
</blockquote>
<p>We can think of a snapshoot as being built like this:</p>
<pre><code>type <span class="hljs-keyword">commit</span> = <span class="hljs-keyword">struct</span> {
    <span class="hljs-keyword">parent</span>: <span class="hljs-built_in">array</span>&lt;<span class="hljs-keyword">commit</span>&gt;
    author: <span class="hljs-keyword">string</span>
    message: <span class="hljs-keyword">string</span>
    <span class="hljs-keyword">snapshot</span>: tree
}
</code></pre><blockquote>
<p><strong>Note:</strong> this is pseudo-code</p>
</blockquote>
<p>In Git terminology, a file is called a "blob" because it's just a bunch of bytes. We can think of blobs as an array of bytes:</p>
<pre><code><span class="hljs-keyword">type</span> blob = <span class="hljs-keyword">array</span>&lt;bytes&gt;
</code></pre><p>A directory is called a tree. A tree maps names to trees or blobs which means that a directory can contain other directories.</p>
<pre><code><span class="hljs-keyword">type</span> tree = <span class="hljs-keyword">map</span>&lt;<span class="hljs-keyword">string</span>, tree | blob&gt;
</code></pre><h3 id="objects-and-content-addressing">Objects and content-addressing</h3>
<p>Even though we name each file, directory and commit differently, they are all objects. And git stores all this data as objects inside a content address store.</p>
<pre><code><span class="hljs-attr">objects</span> = map&lt;string, objects&gt;
</code></pre><p>This means that the core of git is a simple key-value data store. You can insert any object into your git storage and git will store it with a unique key.</p>
<p>This unique key is the <a target="_blank" href="https://en.wikipedia.org/wiki/SHA-1">SHA-1 hash</a> of that object and it allows us to access the object with that key.</p>
<blockquote>
<p><strong>Note:</strong> Using a hash allows us to take a big piece of data and turn it into a short string</p>
</blockquote>
<p>Taking the example from that <code>git log</code> that I have shown before:</p>
<pre><code>* <span class="hljs-selector-tag">8f0dede</span> (HEAD -&gt; twitter, upstream/master, master) <span class="hljs-selector-tag">Add</span> <span class="hljs-selector-tag">twitch</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">config</span> <span class="hljs-selector-tag">example</span> (<span class="hljs-number">#1653</span>)
| * <span class="hljs-selector-tag">a03b68c</span> (origin/twitch, twitch) <span class="hljs-selector-tag">Add</span> <span class="hljs-selector-tag">twitch</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">config</span> <span class="hljs-selector-tag">example</span>
|/
* <span class="hljs-selector-tag">2c9b684</span> <span class="hljs-selector-tag">Migrate</span> <span class="hljs-selector-tag">helper</span> <span class="hljs-selector-tag">and</span> <span class="hljs-selector-tag">connector</span> <span class="hljs-selector-tag">tests</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">pytest</span> (<span class="hljs-number">#1648</span>)
* <span class="hljs-selector-tag">af00ac9</span> <span class="hljs-selector-tag">Fix</span> <span class="hljs-selector-tag">typo</span> <span class="hljs-selector-tag">on</span> <span class="hljs-selector-tag">documentation</span> <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">Gitter</span> (<span class="hljs-number">#1652</span>)
</code></pre><p>If we want to access or reference the snapshot <em>"Migrate helper and connector tests to pytest"</em> I can reference the first seven characters of that object hash: <code>af00ac9</code>.</p>
<h2 id="git-branches">Git Branches</h2>
<p>We can look at snapshots as to what we call  <em>commits</em> in git, they contain all the changes done inside the directory. Each snapshot/commit points back to the one that precedes it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604585925486/YsjUiiRpM.png" alt="main_branch.png" /></p>
<p>Since all these snapshots point back to the previous one, we can this <em>history/line</em> a branch. Usually, you will always have the main branch when you start tracking the changes of a folder with git.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604585937285/3g78pgfI-.png" alt="git_branch.png" /></p>
<p>Usually, this branch is the one that folks use to keep the latest version of a project. The powerful thing of git is that it allows you to branch off from a specific snapshot/commit, so you can work with different branches of a commit and then merge them.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604585945145/0jfpnF_Us.png" alt="gitcommit.png" /></p>
<p>Here you can see the log of a project that I work on. You can see that each <code>*</code> is a snapshot, each line shows the <em>path</em> that each snapshot took, you can also see the times that a branch was created and then merged back into the main one.</p>
<h2 id="references-and-repositories">References and Repositories</h2>
<p>Now that we know that git objects can be identified by their SHA-1 hash and that snapshots live inside branches we can explore more about what is a reference inside git. </p>
<p>A reference is a human-readable label to refer to a particular snapshot in history instead of using the whole SHA-1 hash.</p>
<pre><code>references = <span class="hljs-keyword">map</span>&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt;
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604585945145/0jfpnF_Us.png" alt="gitcommit.png" /></p>
<p>Let's look at the image from that <code>git log</code> that I used before. You can see things such as:</p>
<ul>
<li><code>HEAD</code></li>
<li><code>upstream/master</code></li>
<li><code>master</code></li>
<li><code>refs/stash</code></li>
<li><code>origin/ibm-watson</code></li>
<li><code>...</code></li>
</ul>
<p>These are all references that reference something. The <code>HEAD</code> means that this is the current commit that we are working on, <code>master</code> refers to the main branch while <code>upstream/master</code> is the main branch from the original repository for this project.</p>
<p>So what is a repository?</p>
<p>Putting very simply, a git repository contains all the objects and references. These repositories live inside our disk, but you could use services like GitHub, Gitlab or Bitbucket to save your repositories on these services. They also allow better collaboration with other folks and the reason why they become so popular.</p>
<h2 id="the-stating-area">The Stating Area</h2>
<p>The last thing that is worth to mention is that git has this concept of stating area. This is where you add files to this staging area to keep track of changes done and include them in your next snapshot.</p>
<p>By using the command <code>git status</code>, git tells you if you have any files that are currently untracked inside a project - these files will not be included on your next snapshot.</p>
<p>To include these files you can run the command <code>git add &lt;name of the file&gt;</code> or <code>git add .</code> to include all untracked files into the staging area.</p>
<p>After running that command you can type <code>git status</code> again and you will see your file names in green and bellow the text: <em>Changes to be committed:</em></p>
<p>To create a new snapshot with these files in staging you need to run the command <code>git commit</code> which will open your text editor for you to choose a name for that snapshot. Alternatively, you can run the command <code>git commit -m "&lt;message&gt;"</code> to do it in a single command.</p>
<p><em>This article was written when taking the lesson on git from <a target="_blank" href="https://www.youtube.com/c/MissingSemester">missing semester</a> lessons on youtube.</em></p>
<hr />
<p><strong>References:</strong></p>
<ul>
<li><a target="_blank" href="https://missing.csail.mit.edu/2020/version-control/">Official course notes</a></li>
<li><a target="_blank" href="https://includejs.dev/notes/missing-semester-06/">IncludeJS: Eva's lesson notes</a></li>
<li><a target="_blank" href="https://alexwlchan.net/a-plumbers-guide-to-git/1-the-git-object-store/">The git object store</a></li>
<li><a target="_blank" href="https://git-scm.com/book/en/v2">Book: Pro Git - Free</a></li>
<li><a target="_blank" href="https://jwiegley.github.io/git-from-the-bottom-up/">Git from the Bottom up</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Useful Command Line Shortcuts]]></title><description><![CDATA[As developers, we use the terminal all the time, it makes sense to learn some shortcuts that can help you do things in the command line. 
Learning these will also help you boost your productivity because you don't have to retype your commands again j...]]></description><link>https://node.theflying.dev/useful-command-line-shortcuts</link><guid isPermaLink="true">https://node.theflying.dev/useful-command-line-shortcuts</guid><category><![CDATA[command line]]></category><category><![CDATA[terminal]]></category><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Productivity]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Fri, 30 Oct 2020 16:22:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1604074931654/R6WnMWB3w.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As developers, we use the terminal all the time, it makes sense to learn some shortcuts that can help you do things in the command line. </p>
<p>Learning these will also help you boost your productivity because you don't have to retype your commands again just because you found a mistake.</p>
<p>I've also created a short(ish) video that shows some of the shortcuts mentioned in this article.</p>
<div>
  <iframe width="560" height="315" src="https://www.youtube.com/embed/yZZmW3KTYr4">

</iframe></div>

<blockquote>
<p><strong>Note:</strong> When I recorded this video, I thought the shortcut <code>CTRL+U</code> was deleting the line, but it's just cutting the whole line, you can paste the text with <code>CTRL+Y</code>.</p>
</blockquote>
<h2 id="shortcuts-for-moving-around">Shortcuts for moving around</h2>
<p>Let's be honest how many times do we write a command, just to notice that around the beginning of the line there is a mistake and we delete everything and type the command again? These shortcuts will help you move the cursor easier without the need to delete the whole thing.</p>
<ul>
<li><code>CTRL + A</code> - Moves the cursor to the beginning of the line</li>
<li><code>CTRL + E</code> - Moves the cursor to the end of the line</li>
<li><code>CTRL + arrow keys</code> - Moves the cursor from word to word </li>
<li><code>ALT + B</code> - Moves the cursor back from word to word</li>
<li><code>ALT + F</code> - Moves cursors forward from word to word</li>
</ul>
<h2 id="cutting-and-pasting">Cutting and pasting</h2>
<ul>
<li><code>CTRL + W</code> - Cut the word left of the cursor</li>
<li><code>CTRL + K</code> - Cut the entire text at the right of the cursor</li>
<li><code>ALT + W</code> - Cut the entire text at the left of the cursor</li>
<li><code>CTRL + U</code> - Cut the entire line</li>
<li><code>CTRL + Y</code> - Paste the previous cut text</li>
</ul>
<h2 id="text-manipulation">Text manipulation</h2>
<ul>
<li><code>CTRL + T</code> - Swap two letters between the cursor<ul>
<li>Example: <code>this</code> if the cursor is between the <strong>h</strong> and <strong>i</strong> it turns into <code>tihs</code></li>
</ul>
</li>
<li><code>ESC + T</code> - Swap two words between the cursor<ul>
<li>Example: <code>this text</code> will become <code>text this</code></li>
</ul>
</li>
<li><code>ESC + U</code> - Uppercases text right of the cursor - moves cursor to the end of word</li>
<li><code>CTRL + Q</code> - Deletes text from line - clears line only</li>
</ul>
<h2 id="other-useful-shortcuts">Other useful shortcuts</h2>
<ul>
<li><code>CTRL + L</code> - Clears the terminal -&gt; No need to write <code>clear</code> all the time!</li>
<li><code>CTRL + R</code> - Reverse search your history for a term<ul>
<li>Use <code>CTRL + R</code> again to cycle through results</li>
</ul>
</li>
<li><code>!!</code> Repeat the last command used in the terminal<ul>
<li>Use <code>sudo !!</code> to repeat the last command with <code>sudo</code></li>
</ul>
</li>
</ul>
<h2 id="cheatsheets">Cheatsheets</h2>
<p>I've created a cheatsheet with these commands, hopefully, this will help you get used to using the commands.</p>
<h3 id="dark-theme">Dark Theme</h3>
<p><img src="https://theflying.dev/static/ff18b68fbca034910f339026fe6ab672/29114/terminal_shortcuts_dark.png" alt /></p>
<h3 id="light-theme">Light Theme</h3>
<p><img src="https://theflying.dev/static/8cc2a8846dea00ea807d2e6cac56cf5b/29114/terminal_shortcuts_light.png" alt /></p>
]]></content:encoded></item><item><title><![CDATA[How to use the Gatsby elasticlunr plugin with MDX]]></title><description><![CDATA[Since I've recently moved from using markdownRemark to MDX on all my Gatsby Sites, the instructions to some plugins might not be that straightforward to follow. Recently, I've created a Digital Garden and wanted to add a search bar to it. 
On one of ...]]></description><link>https://node.theflying.dev/how-to-use-the-gatsby-elasticlunr-plugin-with-mdx</link><guid isPermaLink="true">https://node.theflying.dev/how-to-use-the-gatsby-elasticlunr-plugin-with-mdx</guid><category><![CDATA[Gatsby]]></category><category><![CDATA[2Articles1Week]]></category><category><![CDATA[search]]></category><category><![CDATA[elasticsearch]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Tue, 27 Oct 2020 12:53:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1603803215420/4LIgjWYM1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Since I've recently moved from using markdownRemark to MDX on all my Gatsby Sites, the instructions to some plugins might not be that straightforward to follow. Recently, I've created a <a target="_blank" href="https://theflying.dev">Digital Garden</a> and wanted to add a search bar to it. </p>
<p>On one of my first Gatsby projects, I had used the <a target="_blank" href="https://www.gatsbyjs.com/plugins/@gatsby-contrib/gatsby-plugin-elasticlunr-search/?=search">Elasticlurn Plugin for Gatsby</a> to add a search bar to a website. I decided to try and use this plugin since I don't have to use an external service like Algolia.</p>
<h2 id="installing-and-configuration">Installing and Configuration</h2>
<p>Installing the plugin is pretty straightforward. You need to run the command:</p>
<pre><code class="lang-sh">npm install @gatsby-contrib/gatsby-plugin-elasticlunr-search
</code></pre>
<p>Then on your gatsby-config.js file, you can add the configuration for the plugin. If you read the README.md, you can see that one of the configuration options is the <strong>resolvers</strong>, here you need to replace <code>MarkdownRemark</code> for <code>Mdx</code>.</p>
<pre><code class="lang-javascript"> {
      <span class="hljs-attr">resolve</span>: <span class="hljs-string">`@gatsby-contrib/gatsby-plugin-elasticlunr-search`</span>,
      <span class="hljs-attr">options</span>: {
        <span class="hljs-attr">fields</span>: [<span class="hljs-string">`title`</span>, <span class="hljs-string">`category`</span>, <span class="hljs-string">`tags`</span>, <span class="hljs-string">`excerpt`</span> ],
        <span class="hljs-attr">resolvers</span>: {
          <span class="hljs-attr">Mdx</span>: {
            <span class="hljs-attr">title</span>: <span class="hljs-function"><span class="hljs-params">node</span> =&gt;</span> node.frontmatter.title,
            <span class="hljs-attr">category</span>: <span class="hljs-function"><span class="hljs-params">node</span> =&gt;</span> node.frontmatter.category,
            <span class="hljs-attr">tags</span>: <span class="hljs-function"><span class="hljs-params">node</span> =&gt;</span> node.frontmatter.tags,
            <span class="hljs-attr">excerpt</span>: <span class="hljs-function"><span class="hljs-params">node</span> =&gt;</span> node.frontmatter.excerpt,
            <span class="hljs-attr">slug</span>: <span class="hljs-function"><span class="hljs-params">node</span> =&gt;</span> node.fields.slug
          }
        },
        <span class="hljs-attr">filter</span>: <span class="hljs-function">(<span class="hljs-params">node, getNode</span>) =&gt;</span> node.frontmatter.category
      }
    }
</code></pre>
<p>My frontmatter contains all those fields (but the slug). These are the fields that I want users to be able to search. You can choose as many or as little as you want. </p>
<h2 id="search-bar-component">Search Bar Component</h2>
<p>With the plugin installed and configured, we have to create the search bar component. I re-used the component that I had created on the other project. </p>
<p><em>Note: This component needs refactoring. Most of this code was taken from the plugin instructions.</em></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { Index } <span class="hljs-keyword">from</span> <span class="hljs-string">"elasticlunr"</span>
<span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">"gatsby"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Search</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
    <span class="hljs-keyword">constructor</span>(props) {
        <span class="hljs-built_in">super</span>(props)
        <span class="hljs-built_in">this</span>.state = {
            <span class="hljs-attr">query</span>: <span class="hljs-string">``</span>,
            <span class="hljs-attr">results</span>: []
        }
    }

    render() {
        <span class="hljs-keyword">return</span> ( 
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"my-5 relative"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex justify-center items-center"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"gg-search mr-2"</span> /&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{this.state.query}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{this.search}</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Search..."</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                {this.state.results.length !== 0 ? 
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-2 flex flex-col absolute z-10 search-results"</span>&gt;</span>
                        {this.state.results.map(page =&gt; (
                                <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"link m-1"</span> <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">page.slug</span>}`} <span class="hljs-attr">key</span>=<span class="hljs-string">{page.title}</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"underline"</span>&gt;</span>{page.title}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> : <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"green"</span>&gt;</span>{page.tags.join(', ')}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>

                        ))}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                : ''}
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
        )
    }

    getOrCreateIndex = <span class="hljs-function">() =&gt;</span>
        <span class="hljs-built_in">this</span>.index ? <span class="hljs-built_in">this</span>.index : Index.load(<span class="hljs-built_in">this</span>.props.searchIndex)

    search = <span class="hljs-function"><span class="hljs-params">evt</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> query = evt.target.value
        <span class="hljs-built_in">this</span>.index = <span class="hljs-built_in">this</span>.getOrCreateIndex()
        <span class="hljs-built_in">this</span>.setState({
            query,
            <span class="hljs-attr">results</span>: <span class="hljs-built_in">this</span>.index
                .search(query, { <span class="hljs-attr">expand</span>: <span class="hljs-literal">true</span>})
                .map(<span class="hljs-function">(<span class="hljs-params">{ ref }</span>) =&gt;</span> <span class="hljs-built_in">this</span>.index.documentStore.getDoc(ref))
        })
    }
}
</code></pre>
<p>I want users to get partial matches straight away. So when you type something, you will get all matches first.  Then the query will return fewer results. If you don't want this to happen and return the search results instead, you can remove the <code>{ expand: true }</code> parameter from the <code>search</code> method.</p>
<p>You can probably see that on this site I am using <a target="_blank" href="https://tailwindcss.com/">TailwindCss</a>. The only bit of CSS that I added outside Tailwind was the <code>search-results</code> which adds some styling(colour, spacing) to that div. The reason why I decided to use an absolute position, is because I want the search results to drop down and stay above the content.</p>
<h2 id="importing-and-using-the-search-bar">Importing and Using the Search Bar</h2>
<p>Now that the search bar component is completed, you can use it anywhere on your site by importing it. But you also need to provide a <code>searchIndex</code> to the component. Luckily, the plugin adds a query for you to use.</p>
<pre><code class="lang-graphql">query {
    siteSearchIndex {
        index
    }
}
</code></pre>
<p>Then you can import the search bar component and use it like this:</p>
<pre><code class="lang-javascript">&lt;SearchBar searchIndex={props.data.siteSearchIndex.index} /&gt;
</code></pre>
<p>That's all there is to add a search bar with elasticlunr plugin and MDX. If you have any issues feel free to reach me on <a target="_blank" href="https://twitter.com/FabioRosado_">Twitter @FabioRosado</a>, I will be happy to give you a hand!</p>
<h2 id="references">References</h2>
<ul>
<li><a target="_blank" href="https://www.gatsbyjs.com/plugins/@gatsby-contrib/gatsby-plugin-elasticlunr-search/?=search">Elasticlurn Plugin for Gatsby</a></li>
<li><a target="_blank" href="https://tailwindcss.com/">TailwindCss</a></li>
<li><a target="_blank" href="https:////theflying.dev">Digital Garden</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to keep your npm dependencies updated]]></title><description><![CDATA[It's always a good idea to keep dependencies updated, from performance gains to fixing security issues, it just makes sense to update.
But your project might depend on a lot of dependencies and if you haven't worked on a project for a few months, cha...]]></description><link>https://node.theflying.dev/how-to-keep-your-npm-dependencies-updated</link><guid isPermaLink="true">https://node.theflying.dev/how-to-keep-your-npm-dependencies-updated</guid><category><![CDATA[npm]]></category><category><![CDATA[2Articles1Week]]></category><category><![CDATA[nodejs]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Thu, 22 Oct 2020 10:31:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1603362519729/fZYJnNCjG.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It's always a good idea to keep dependencies updated, from performance gains to fixing security issues, it just makes sense to update.</p>
<p>But your project might depend on a lot of dependencies and if you haven't worked on a project for a few months, chances are a lot of these dependencies are really outdated. </p>
<h2 id="list-all-outdated-dependencies">List all outdated dependencies</h2>
<p>You can run the command <code>npm outdated</code> to get a list of all the dependencies that have new releases.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603359369805/1YuZYOLbh.png" alt="outdated.png" /></p>
<h2 id="check-for-updates">Check for updates</h2>
<p>Now that we know how to check for outdated packages, we need to find a way to update them all. This is where we need help from a package called <code>npm-check-updates</code>. This package will look into your <code>package.json</code> versions and upgrade all the outdated ones.</p>
<pre><code class="lang-sh">npm install -g npm-check-updates
</code></pre>
<blockquote>
<p><strong>Note:</strong> You should install this package globally so you can use on other projects.</p>
</blockquote>
<h2 id="upgrading-and-updating-dependencies">Upgrading and updating dependencies</h2>
<p>After installing the package you need to run <code>ncu -u</code>  on your terminal to upgrade your package.json.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603361831962/SbdfsXr1t.png" alt="updated-list.png" /></p>
<p>You can now run the command <code>npm update</code> to update your dependencies.</p>
<h2 id="updating-dependencies-in-one-go">Updating dependencies in one go</h2>
<p>So we have seen that we can upgrade our dependencies with <code>ncu -u</code> and then upgrade them with <code>npm update</code>. How about we create a command that will run both of these so we don't have to type so much?</p>
<p>That's when <em>aliases</em> come in handy!</p>
<p>I keep all my aliases in a <code>.bash_aliases</code> file, in my home directory. You can add this alias anywhere, for example, <code>~/.bashrc</code>, <code>~/.zshrc</code>, <code>~/.bash_profile</code>, etc. If you don't know which to use, you can use <code>~/.bash_profile</code> or <code>~/.profile</code>.</p>
<p>Open the file in your favourite editor and add the following alias:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">alias</span> update=<span class="hljs-string">'ncu -u &amp;&amp; npm update'</span>
</code></pre>
<p>Source that file or restart your terminal and you can now use the <code>update</code> command to update your dependencies in one go!</p>
]]></content:encoded></item><item><title><![CDATA[How to get the PID of process and send signals]]></title><description><![CDATA[On my previous article, I've talked about Linux Signals and how you can send a specific signal with the kill command.
On this article, I will talk a bit more about job control. How you can see running processes and how to use the knowledge we gained ...]]></description><link>https://node.theflying.dev/how-to-get-the-pid-of-process-and-send-signals</link><guid isPermaLink="true">https://node.theflying.dev/how-to-get-the-pid-of-process-and-send-signals</guid><category><![CDATA[Linux]]></category><category><![CDATA[terminal]]></category><category><![CDATA[2Articles1Week]]></category><category><![CDATA[command line]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Wed, 21 Oct 2020 09:18:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1603271862167/GDJRNYkjK.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On my previous article, I've talked about <a target="_blank" href="https://node.theflying.dev/understanding-linux-signals">Linux Signals</a> and how you can send a specific signal with the <code>kill</code> command.</p>
<p>On this article, I will talk a bit more about job control. How you can see running processes and how to use the knowledge we gained with the Linux signals article to send signals to a process.</p>
<h2 id="running-processes">Running Processes</h2>
<p>Everything running in a Linux system is considered a process.  Every time a process is started, the operating system will assign a unique PID (Process Identification Number) to that process.</p>
<p>This is important to know because when a process doesn't terminate as you expect, or something causes it to hang and keep consuming resources, you might need to run the <code>kill</code> command followed by the <strong>PID</strong> of that process.</p>
<h3 id="but-how-do-you-get-a-list-of-all-running-commands">But How do you get a list of all running commands?</h3>
<p>Two useful commands can help you get a list of the running processes - the <code>ps</code> command and the <code>jobs</code> command.</p>
<p><strong>Let's get started with the <code>ps</code> command!</strong></p>
<p>The <code>ps</code> command will show you information about running processes. If you want to get a list of all processes you can run <code>ps aux</code> - these will include processes started by other users including <strong>root</strong>.  </p>
<p>Because <code>ps aux</code> gives you so much information, it's often a good idea to pipe a <code>grep</code> to your command, to get only processes that match the thing that you are looking for.</p>
<p>For example, this command will only show running processes that contain the word <strong>opsdroid</strong>:</p>
<pre><code class="lang-sh">&gt; ps aux | grep opsdroid
</code></pre>
<p><strong>Now let's have a look at the  <code>jobs</code> command!</strong></p>
<p>This command is not a command that comes with Linux but is instead a bash builtin. It allows you to get information about processes spawned by the current shell. </p>
<p>Because <code>jobs</code> shows you only processes started by the current shell, it can be easier to navigate and to find a specific process.</p>
<p>Let's assume that you have a few processes running in the background, you can run the <code>jobs</code> command to get a list of all the process, their status (running or stopped) and which command made that process run.</p>
<p>If you want to get the <strong>PID</strong> of these processes you can use the <code>-l</code> flag with the command.</p>
<p>For example:</p>
<pre><code class="lang-sh">&gt; <span class="hljs-built_in">jobs</span>
[1] + running python3 -m opsdroid start
</code></pre>
<p>Getting the PID of the process with the <code>-l</code> flag</p>
<pre><code class="lang-sh">&gt; <span class="hljs-built_in">jobs</span> -l
[1] + 3258 running python3 -m opsdroid start
</code></pre>
<h2 id="killing-processes">Killing processes</h2>
<p>Now that we know how to get a list of processes and the respective <strong>PID</strong>'s, let's talk a bit about the <code>kill</code> command. This command is an interesting one because what this command does is sending a signal to a process.</p>
<p>The default signal of <code>kill</code> is the <code>SIGTERM</code> signal, which is a gentle request to terminate a specific process.  But since this command is used to send signals to a process, we could easily send a stop signal with the command <code>kill -STOP</code>.</p>
<p>If you want to know what signals you can send with <code>kill</code> you can run the command with the <code>-l</code> flag.</p>
<p>For example, running the command on my ubuntu machine gives me the following:</p>
<pre><code class="lang-sh">❯ <span class="hljs-built_in">kill</span> -l
HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS
</code></pre>
<blockquote>
<p><strong>Note:</strong> Sending a <code>SIGKILL</code> to a process will terminate a program no matter what, but that might leave orphan processes running, which might cause some odd behaviours. This means running <code>kill -9 &lt;PID&gt;</code> or <code>kill -KILL &lt;PID&gt;</code> might not be a good idea.</p>
</blockquote>
<h3 id="why-knowing-about-processes-matter">Why knowing about processes matter?</h3>
<p>You might be wondering, why I talked about processes before talking about the <code>kill</code> command. Well, <code>kill</code> needs the <strong>PID</strong> of the process that you want to send the signal to.</p>
<p>So knowing how to get that <strong>PID</strong> comes in handy. Another good thing that is worth mention is that you can pass more than one <strong>PID</strong> to <code>kill</code>, this allows you to send a signal to multiple processes.</p>
<h3 id="using-a-process-name-to-send-signals">Using a process name to send signals</h3>
<p>You might be thinking that fetching a process <strong>PID</strong> and remembering it is too much work. Luckily, you can also send signals to a process by using its name. The way to do that is by using the <code>killall</code> command.</p>
<p>The thing to remember here is that you need to pass the <em>exact</em> name of the process that you want to kill. </p>
<p>If you want to use just part of the name, there is another command for that - you can use the <code>pkill</code> command. </p>
<p>But there is something to keep in mind.</p>
<p>Let's say that you want to terminate a process and you only know part of its name. Using <code>pkill opsdroid</code> will kill any process that contains <em>opsdroid</em> in its name. This could terminate a process that you might not want to because it contains <em>opsdroid</em> on its name. </p>
<p>This is why using the exact name or the unique <strong>PID</strong> might be a better way to send signals to a process.</p>
<hr />
<p>I hope this article helped you learn more about processes and how you can send signals to a specific process. Let me know if you have a favourite way to search for a process and what you use to send signals to a process.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Linux Signals]]></title><description><![CDATA[Signals provide a method for the user to communicate directly with a process, they indicate that an important event has occurred and something should happen. 
For example, when you are running a program and you use CTRL+C to stop the program, you are...]]></description><link>https://node.theflying.dev/understanding-linux-signals</link><guid isPermaLink="true">https://node.theflying.dev/understanding-linux-signals</guid><category><![CDATA[Linux]]></category><category><![CDATA[2Articles1Week]]></category><category><![CDATA[command line]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Fri, 16 Oct 2020 15:20:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1602861538496/eXZJxZQ8t.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Signals provide a method for the user to communicate directly with a process, they indicate that an important event has occurred and something should happen. </p>
<p>For example, when you are running a program and you use <code>CTRL+C</code> to stop the program, you are sending a signal that tells the process that should interrupt its execution.</p>
<p><em>Why should you care about signals</em></p>
<p>You might be wondering, what's so important about this concept. It's because they are something that you rely on under the hood while using the command line.  You can also write your code to handle the different signals and make your program do something else.</p>
<p>Understanding signals will also help you deal with programs that don't quit with <code>CTRL+C</code> and the only thing that seems to help is running the command <code>kill &lt;pid&gt;</code> to stop a process.</p>
<h2 id="exiting-stopping-and-continuing-signals">Exiting, Stopping and Continuing Signals</h2>
<p>Let's have a look at signals that stops or terminates a process.  Understanding these signals can be useful when your process just seems to freeze and nothing seems to be working when you try to stop it.</p>
<h3 id="the-sighup-signal">The <code>SIGHUP</code> Signal</h3>
<p>This signal stands short for <em>hang up</em>, this signal is usually triggered when you have processes running in the terminal and you decide to close the terminal. </p>
<p>When you have an ssh session open and a running process, if you exit the session that could trigger a <code>SIGHUP</code> signal, if you want to make sure your process keeps running even if you close the terminal window, you can run its command with the <code>nohup</code> prefix.</p>
<p>For example:</p>
<pre><code class="lang-sh">nohup python myscript.py
</code></pre>
<h3 id="the-sigint-signal">The <code>SIGINT</code> Signal</h3>
<p>This signal stands short for <em>Interrupt</em>, this signal is usually triggered when you want to interrupt a process. The keyboard shortcut to send this signal is by using <code>CTRL+C</code>.</p>
<p>This signal doesn't always stop a running process. This can be for various reason, maybe the process has a way to handle this signal, the process is busy or you are dealing with async threads.</p>
<h3 id="the-sigquit-signal">The <code>SIGQUIT</code> Signal</h3>
<blockquote>
<p>this signal is similar to <code>SIGINT</code> but produces a core dump when it terminates the process,  just like a program error signal. You can think of this as a program error condition “detected” by the user.
<a target="_blank" href="https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html">GNU - Termination Signals</a></p>
</blockquote>
<p>The Keyboard shortcut to send this signal is by using <code>CTRL+\</code></p>
<h3 id="the-sigkill-signal">The <code>SIGKILL</code> Signal</h3>
<p>These signal forces terminate the process and it cannot be intercepted, ignored, blocked or handled. This signal is usually generated only by request and should be used as a last resort.</p>
<h3 id="the-sigterm-signal">The <code>SIGTERM</code> Signal</h3>
<p>This signal requests a process to terminate. Unlike <code>SIGKILL</code> this signal can be caught, ignore or interpreted. <code>SIGTERM</code> allows the process to terminate gracefully and release resources.</p>
<p>The shell command <code>kill</code> generates a <code>SIGTERM</code> by default.</p>
<h3 id="the-sigstop-and-sigcont-signals">The <code>SIGSTOP</code> and <code>SIGCONT</code> Signals</h3>
<p>The <code>SIGSTOP</code> signal stops the running process, you can send a <code>SIGSTOP</code> signal by using the keyboard shortcut <code>CTRL+Z</code>. </p>
<p>The <code>SIGCONT</code> signal continues a running process. You can resume a stopped process by running the command <code>bg %1</code></p>
<blockquote>
<p><strong>Note:</strong> <code>%1</code> is the program/job that is located on the first item of the jobs list.</p>
</blockquote>
<pre><code class="lang-sh">&gt; <span class="hljs-built_in">jobs</span>
[1] + suspended sleep 1000
[2] - running nohup sleep 2000
</code></pre>
<blockquote>
<p><strong>NOTE:</strong> <code>bg</code> sends commands to the program running on the background, if we want to continue a program in the current terminal we can use <code>fg</code> instead</p>
</blockquote>
<h2 id="using-signals">Using Signals</h2>
<p>This might be a bit counter-intuitive, but you can use the <code>kill</code> command to send a  signal to a process, if you use a flag with this command.</p>
<p>For example, if you want to send a <code>SIGHUP</code> signal, you can run the command</p>
<pre><code class="lang-sh"><span class="hljs-built_in">kill</span> -HUP &lt;process id&gt;
</code></pre>
<p>Each signal has an alphanumeric value that can be used as a flag with the <code>kill</code> command.  Let's take the previous example, if we want to send a <code>SIGHUP</code> signal again you can run the command</p>
<pre><code class="lang-sh"><span class="hljs-built_in">kill</span> -1 &lt;process id&gt;
</code></pre>
<p>You can check the value of each signal on the <a target="_blank" href="http://www.yolinux.com/TUTORIALS/C++Signals.html">signal man pages</a> or the <a target="_blank" href="http://www.yolinux.com/TUTORIALS/C++Signals.html">C++ Signals Tutorial</a>.</p>
<p>Hope this helps you understand what are signals how you can use them on your day-to-day.  I've learned about this subject on the <a target="_blank" href="https://www.youtube.com/watch?v=e8BO_dYxk5c">lesson 5  of Missing Semester</a>.</p>
<hr />
<p><strong>References:</strong></p>
<ul>
<li><a target="_blank" href="https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html">GNU - Termination Signals</a></li>
<li><a target="_blank" href="https://www.computerhope.com/unix/signals.htm">Linux Signals</a></li>
<li><a target="_blank" href="https://linoxide.com/linux-how-to/linux-signals-part-1/">Kill Signals in Linux</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Setting up Windows Terminal with Zsh]]></title><description><![CDATA[I've written a quick post about Moving to Windows from a Mac. On that post, I've mentioned how I've been using the Windows Terminal as my main terminal.
The Windows Terminal is great, but has a few problems:

Pretty simple theme (a grey text on a bla...]]></description><link>https://node.theflying.dev/setting-up-windows-terminal-with-zsh</link><guid isPermaLink="true">https://node.theflying.dev/setting-up-windows-terminal-with-zsh</guid><category><![CDATA[Windows]]></category><category><![CDATA[WSL]]></category><category><![CDATA[terminal]]></category><category><![CDATA[2Articles1Week]]></category><category><![CDATA[zsh]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Thu, 15 Oct 2020 09:55:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1602755701371/8ijg3JVG0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've written a quick post about <a target="_blank" href="https://theflying.dev/digital-garden/moving-to-windows">Moving to Windows from a Mac</a>. On that post, I've mentioned how I've been using the <a target="_blank" href="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701?SilentAuth=1&amp;wa=wsignin1.0">Windows Terminal</a> as my main terminal.</p>
<p>The Windows Terminal is great, but has a few problems:</p>
<ul>
<li>Pretty simple theme (a grey text on a black background)</li>
<li>It's not using my favourite shell <a target="_blank" href="https://linuxhandbook.com/install-zsh/">zsh shell</a></li>
<li>No icons or interactive profiles</li>
</ul>
<p>The terminal itself it's pretty good and allows you to have different tabs on it. It also comes with integrated support for the Windows Subsystem for Linux, Windows Powershell, Azure cloud shell and the Command Prompt.</p>
<blockquote>
<p>Windows Terminal is a modern terminal application for users of command-line tools and shells like Command Prompt, PowerShell, and Windows Subsystem for Linux (WSL). Its main features include multiple tabs, panes, Unicode and UTF-8 character support, a GPU accelerated text rendering engine, and the ability to create your own themes and customize text, colours, backgrounds, and shortcut key bindings.</p>
</blockquote>
<p>You can read more about the features of the Windows Terminal on the <a target="_blank" href="https://docs.microsoft.com/en-us/windows/terminal/">official documentation website</a>.</p>
<p>You can also download the Windows Terminal from the <a target="_blank" href="https://www.microsoft.com/en-gb/p/windows-terminal/9n0dx20hk701?activetab=pivot:overviewtab">Microsoft Store</a>.</p>
<h2 id="setting-up-wsl-as-the-default-profile">Setting up WSL as the default profile</h2>
<p>When you run the Windows Terminal, you can see that the Terminal opens the <em>Windows PowerShell</em> by default. Since I am going to be using WSL all the time, I want this to be the default.</p>
<p>We can change the default profile by opening the terminal menu (press the down arrow) and select settings.</p>
<ul>
<li>Open settings from the terminal menu</li>
<li>Scroll down to find the <code>guid</code> for the WSL</li>
<li>Copy that <code>guid</code> and scroll back up</li>
<li>Paste the WSL <code>guid</code> inside the <code>defaultProfile</code> setting</li>
</ul>
<p>Now every time we run the terminal, the default profile will be the WSL one.</p>
<h2 id="install-and-setup-zsh-and-oh-my-zsh">Install and setup zsh and Oh-My-Zsh</h2>
<p>The next thing we need to do is installing the <code>zsh</code> shell in our WSL. Open the Windows Terminal (if you haven't it open already) and run the following command:</p>
<pre><code class="lang-sh">sudo apt update &amp;&amp; sudo apt install zsh -y
</code></pre>
<p>This command will install the zsh shell, then we can install <a target="_blank" href="https://ohmyz.sh/">oh-my-zsh</a> which is zsh on steroids. It comes with more functions, helpers, plugins, themes and much more.</p>
<p>We can install oh-my-zsh by running the command:</p>
<pre><code class="lang-sh">sh -c <span class="hljs-string">"<span class="hljs-subst">$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)</span>"</span>
</code></pre>
<p>Now that we have the zsh shell and oh-my-zsh installed, we can go to the next step. Customizing your terminal to look beautiful!</p>
<h2 id="pimp-my-terminal-themes-icons-profiles">Pimp my terminal - Themes, Icons, Profiles</h2>
<p>Remember that I said earlier in this article, that the Windows Terminal was pretty simple? Well, it's now time to pimp our terminal and change how it looks! We will do a few things:</p>
<ul>
<li>Install Powerlevel10k</li>
<li>Install a font that contains icons</li>
<li>Adding the font to Windows Terminal by using Nerd Fonts</li>
<li>Choosing a decent theme for the terminal</li>
<li>Changing the theme for the terminal</li>
</ul>
<h3 id="installing-powerlevel10k">Installing Powerlevel10k</h3>
<p>If you are unfamiliar with Powerlevel10k, the quick way to explain it to you is saying that it's a theme for zsh. It allows you to customize your terminal prompt from a set of default styles.</p>
<p>You can <a target="_blank" href="https://github.com/romkatv/powerlevel10k">read more about Powerlevel10K</a> on the official GitHub repo of the project.</p>
<p>To install Powerlevel10K, you can run this command or <a target="_blank" href="https://github.com/romkatv/powerlevel10k#get-started">read the getting started documentation</a>.</p>
<pre><code class="lang-sh">git <span class="hljs-built_in">clone</span> --depth=1 https://github.com/romkatv/powerlevel10k.git <span class="hljs-variable">${ZSH_CUSTOM:-~/.oh-my-zsh/custom}</span>/themes/powerlevel10k
</code></pre>
<p>Then you will have to edit the <code>~/.zshrc</code> file to activate the powerlevel10k theme. Look for the line that contains:</p>
<pre><code class="lang-sh">ZSH_THEME=<span class="hljs-string">"robbyrussel"</span>
</code></pre>
<p>Replace it with</p>
<pre><code class="lang-sh">ZSH_THEME=<span class="hljs-string">"powerlevel10k/powerlevel10k"</span>
</code></pre>
<h3 id="installing-a-font-pack-that-contains-icons">Installing a font pack that contains icons</h3>
<p>We need to get a font that contains text and icons on the same pack. <a target="_blank" href="https://www.nerdfonts.com/">Nerd Fonts</a> has a lot of different font styles, all supporting the icons that we need.</p>
<p>The one that I've been using all the time is the <strong>DroidSansMono Nerd Font</strong> that you can find on the <a target="_blank" href="https://www.nerdfonts.com/font-downloads">font downloads page</a>. You can also preview some of these fonts on <a target="_blank" href="https://www.programmingfonts.org/">Programming Fonts</a>.</p>
<p>Chose a font that you like, download it and install the font.</p>
<p>Now you need to open your Windows Terminal settings and scroll down to the WSL settings and add the following:</p>
<pre><code class="lang-json"><span class="hljs-string">"fontFace"</span>: <span class="hljs-string">"DroidSansMono NF"</span>
</code></pre>
<p><em>Note: You need to use the same font name as the one shown when you open the <code>.otf</code> file.</em></p>
<p>So your WSL settings will look like this.</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"guid"</span>: <span class="hljs-string">"{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}"</span>,
    <span class="hljs-attr">"hidden"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Ubuntu-20.04"</span>,
    <span class="hljs-attr">"source"</span>: <span class="hljs-string">"Windows.Terminal.Wsl"</span>,
    <span class="hljs-attr">"fontFace"</span>: <span class="hljs-string">"DroidSansMono NF"</span>
}
</code></pre>
<p><em>Note: your guid will have a unique number, don't copy this section of the code.</em></p>
<h3 id="activating-powerlevel10k-with-the-new-font">Activating Powerlevel10K with the new font</h3>
<p>After updating your <code>~/zshrc</code> file together with using a Nerd Font on the terminal, you should restart your terminal. By restarting the terminal, Powerlevel10K should say that it will try to configure itself, but if that doesn't happen, you can start the configure prompt by running the command:</p>
<pre><code class="lang-sh">p10k configure
</code></pre>
<p>This will go through a series of questions and styles that you can choose. Select the options to get the style and combination that looks best for your needs.</p>
<h3 id="updating-the-windows-terminal-colour-scheme">Updating the Windows Terminal colour scheme</h3>
<p>Finally, we want to update the colour scheme of the terminal to look better than just the grey text on a black background.</p>
<ul>
<li><a target="_blank" href="https://windowsterminalthemes.dev/">Windows Terminal Themes</a></li>
</ul>
<p>I recommend this site because it allows you to see in real-time the different colour schemes and you can then click the <strong>Get Theme</strong> button to get the JSON for that colour scheme.</p>
<p>After you've picked a colour scheme that you like, open the Windows Terminal settings again and locate the line that says <code>schemes: []</code>. In this line, you can paste the colour scheme that you picked.</p>
<pre><code class="lang-json">    <span class="hljs-string">"schemes"</span>: [
        {
            <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Tinacious Design (Dark)"</span>,
            <span class="hljs-attr">"black"</span>: <span class="hljs-string">"#1d1d26"</span>,
            <span class="hljs-attr">"red"</span>: <span class="hljs-string">"#ff3399"</span>,
            <span class="hljs-attr">"green"</span>: <span class="hljs-string">"#00d364"</span>,
            <span class="hljs-attr">"yellow"</span>: <span class="hljs-string">"#ffcc66"</span>,
            <span class="hljs-attr">"blue"</span>: <span class="hljs-string">"#00cbff"</span>,
            <span class="hljs-attr">"purple"</span>: <span class="hljs-string">"#cc66ff"</span>,
            <span class="hljs-attr">"cyan"</span>: <span class="hljs-string">"#00ceca"</span>,
            <span class="hljs-attr">"white"</span>: <span class="hljs-string">"#cbcbf0"</span>,
            <span class="hljs-attr">"brightBlack"</span>: <span class="hljs-string">"#636667"</span>,
            <span class="hljs-attr">"brightRed"</span>: <span class="hljs-string">"#ff2f92"</span>,
            <span class="hljs-attr">"brightGreen"</span>: <span class="hljs-string">"#00d364"</span>,
            <span class="hljs-attr">"brightYellow"</span>: <span class="hljs-string">"#ffd479"</span>,
            <span class="hljs-attr">"brightBlue"</span>: <span class="hljs-string">"#00cbff"</span>,
            <span class="hljs-attr">"brightPurple"</span>: <span class="hljs-string">"#d783ff"</span>,
            <span class="hljs-attr">"brightCyan"</span>: <span class="hljs-string">"#00d5d4"</span>,
            <span class="hljs-attr">"brightWhite"</span>: <span class="hljs-string">"#d5d6f3"</span>,
            <span class="hljs-attr">"background"</span>: <span class="hljs-string">"#1d1d26"</span>,
            <span class="hljs-attr">"foreground"</span>: <span class="hljs-string">"#cbcbf0"</span>
        }
    ],
</code></pre>
<p>In my case, I've picked <strong>Tinacious Design</strong> because that's the theme that I am currently using in VS Code.</p>
<p>To activate the theme, we have to also tell Windows Terminal which profile should use this theme. Going back to the WSL configuration, we can add the following option:</p>
<pre><code class="lang-json"><span class="hljs-string">"colorScheme"</span>: <span class="hljs-string">"Tinacious Design (Dark)"</span>
</code></pre>
<p>So our WSL configuration will look similar to this:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"guid"</span>: <span class="hljs-string">"{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}"</span>,
    <span class="hljs-attr">"hidden"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Ubuntu-20.04"</span>,
    <span class="hljs-attr">"source"</span>: <span class="hljs-string">"Windows.Terminal.Wsl"</span>,
    <span class="hljs-attr">"fontFace"</span>: <span class="hljs-string">"DroidSansMono NF"</span>,
    <span class="hljs-attr">"colorScheme"</span>: <span class="hljs-string">"Tinacious Design (Dark)"</span>
}
</code></pre>
<p>By saving the file, we can see that our terminal already changed colours and it's now using the colour scheme that we want.</p>
<h2 id="set-your-wsl-as-default-when-opening-a-new-terminal">Set your WSL as default when opening a new terminal</h2>
<p>You might notice that after opening the windows terminal back and forth, that it defaults to the Powershell. </p>
<p>If you are like me and are just using the WSL for all your dev needs, you probably want to set that shell as your default one.</p>
<p>Let's open the terminal settings again and scroll down to your WSL settings.</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"guid"</span>: <span class="hljs-string">"{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}"</span>,
    <span class="hljs-attr">"hidden"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Ubuntu-20.04"</span>,
    <span class="hljs-attr">"source"</span>: <span class="hljs-string">"Windows.Terminal.Wsl"</span>,
    <span class="hljs-attr">"fontFace"</span>: <span class="hljs-string">"DroidSansMono NF"</span>,
    <span class="hljs-attr">"colorScheme"</span>: <span class="hljs-string">"Tinacious Design (Dark)"</span>
}
</code></pre>
<p>Copy your <code>guid</code> and then scroll back up and look for the <code>"defaultProfile"</code> setting. We can then replace that with the WSL <code>guid</code>, in my case I have to change this setting like this:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"defaultProfile"</span>: <span class="hljs-string">"{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}"</span>
}
</code></pre>
<p>Save the file, restart your terminal and you will see that it will open your WSL shell instead of the Windows Powershell.</p>
<h2 id="setting-a-default-starting-directory">Setting a default starting directory</h2>
<p>The last thing that is worth mentioning on this article, is that, by default, when opening the terminal it starts the shell on <code>mnt/c/Users/&lt;your username&gt;</code>. </p>
<p>If you are happy to have this as your default starting directory, then you are all set. If you would rather change that starting location to the home folder instead, you can open the terminal settings and scroll down to your WSL settings.</p>
<p>We can have a look at the <em>starting directory</em> setting on the <a target="_blank" href="https://docs.microsoft.com/en-us/windows/terminal/customize-settings/profile-settings#starting-directory">Windows Terminal documentation</a>, we have the <code>startingDirectory</code> property that allows us to set the directory that the shell starts in when it's loaded.</p>
<p>Let's update the WSL setting with this <code>startingDirectory</code> property.</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"guid"</span>: <span class="hljs-string">"{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}"</span>,
    <span class="hljs-attr">"hidden"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Ubuntu-20.04"</span>,
    <span class="hljs-attr">"source"</span>: <span class="hljs-string">"Windows.Terminal.Wsl"</span>,
    <span class="hljs-attr">"fontFace"</span>: <span class="hljs-string">"DroidSansMono NF"</span>,
    <span class="hljs-attr">"colorScheme"</span>: <span class="hljs-string">"Tinacious Design (Dark)"</span>,
    <span class="hljs-attr">"startingDirectory"</span>: <span class="hljs-string">"\\\\wsl$\\&lt;distro name&gt;\\home\\&lt;username&gt;"</span>
}
</code></pre>
<p><em>Note: Don't copy this as you will have to change the <code>&lt;distro name</code> and <code>&lt;username</code> for your distro of choice and username.</em></p>
<p>So in my case, I am using <strong>Ubuntu 20.04</strong> as my distro and <strong>FabioRosado</strong> as my username so this setting will become:</p>
<pre><code class="lang-json"><span class="hljs-string">"startingDirectory"</span>: <span class="hljs-string">"\\\\wsl$\\Ubuntu-20.04\\home\\FabioRosado"</span>
</code></pre>
<p>An important thing to mention here is that, if you mess up your path somehow it will just put the shell back on <code>mnt/c/Users/&lt;your username&gt;</code> so there are no issues if you make a mistake.</p>
<p>I hope this helps you, if it does or if you have any suggestions feel free to tweet <a target="_blank" href="https://twitter.com/FabioRosado_">@FabioRosado_</a></p>
<hr />
<p><strong>References</strong></p>
<ul>
<li><a target="_blank" href="https://nickymeuleman.netlify.app/blog/windows-terminal">The Windows Terminal by Nicky Meuleman</a></li>
<li><a target="_blank" href="https://blog.nillsf.com/index.php/2020/02/17/setting-up-wsl2-windows-terminal-and-oh-my-zsh/">Setting up WSL2, Windows Terminal and oh-my-zsh by Nills</a></li>
<li><a target="_blank" href="https://www.ivaylopavlov.com/setting-up-windows-terminal-wsl-and-oh-my-zsh/">Setting up Windows Terminal, WSL and oh-my-zsh by Ivaylo Pavlov</a>.</li>
<li><a target="_blank" href="https://docs.microsoft.com/en-us/windows/terminal/customize-settings/profile-settings#starting-directory">Profile settings in Windows Terminal</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Add code highlighting to MDX]]></title><description><![CDATA[I've recently dropped markdownRemark and started using MDX to write my posts. MDX is great since it allows you to import components and even write code that will be converted as expected. You can also use graphql queries on your posts which is very u...]]></description><link>https://node.theflying.dev/add-code-highlighting-to-mdx</link><guid isPermaLink="true">https://node.theflying.dev/add-code-highlighting-to-mdx</guid><category><![CDATA[React]]></category><category><![CDATA[Gatsby]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Sat, 10 Oct 2020 16:40:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1602348010399/8y47LiFrb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've recently dropped markdownRemark and started using MDX to write my posts. MDX is great since it allows you to import components and even write code that will be converted as expected. You can also use graphql queries on your posts which is very useful.</p>
<p>I have been using the <a target="_blank" href="https://www.gatsbyjs.com/plugins/gatsby-remark-prismjs/?=prism">gatsby prism plugin</a> to get my code highlighting work, but after moving to MDX this plugin stopped working, so I went ahead in search for a way to get the code highlighting working again. <a target="_blank" href="https://codetrain.io/adding-prism-syntax-highlighting-to-gatsby-mdx">This article</a> did that.</p>
<h2 id="dependencies">Dependencies</h2>
<p>To get the code highlighting work with MDX, we need to install the <a target="_blank" href="https://github.com/FormidableLabs/prism-react-renderer">pristm react renderer</a> package.</p>
<pre><code class="lang-shell">npm install prism-react-renderer
</code></pre>
<h2 id="the-code-block-component">The Code Block Component</h2>
<p>Following the tutorial, I wrote a code block component. I've done some changes to my code block component since I wanted to use my code highlighting theme, I've also added line numbers to each line.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> Highlight, { defaultProps } <span class="hljs-keyword">from</span> <span class="hljs-string">"prism-react-renderer"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> (props) =&gt; {

    <span class="hljs-keyword">const</span> className = props.children.props.className || <span class="hljs-string">'language-text'</span> <span class="hljs-comment">//needed for styling``</span>

    <span class="hljs-keyword">const</span> matches = className.match(<span class="hljs-regexp">/language-(?&lt;lang&gt;.*)/</span>)

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"gatsby-highlight"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Highlight</span> {<span class="hljs-attr">...defaultProps</span>} 
                <span class="hljs-attr">code</span>=<span class="hljs-string">{props.children.props.children.trim()}</span> 
                <span class="hljs-attr">language</span>=<span class="hljs-string">{matches</span> &amp;&amp; <span class="hljs-attr">matches.groups</span> 
                        &amp;&amp; <span class="hljs-attr">matches.groups.lang</span> 
                        ? <span class="hljs-attr">matches.groups.lang</span> <span class="hljs-attr">:</span> ''}
                <span class="hljs-attr">theme</span>=<span class="hljs-string">''</span>
            &gt;</span>
            {({ className, tokens, getLineProps, getTokenProps}) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">pre</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{className}</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">code</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{className}</span>&gt;</span>
                    {tokens.map((line, i) =&gt; (
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"code-block"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{i}</span> {<span class="hljs-attr">...getLineProps</span>({<span class="hljs-attr">line</span>, <span class="hljs-attr">key:i</span>})}&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"line-number"</span>&gt;</span>{i + 1}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                            {line.map((token, key) =&gt; (
                                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{key}</span> {<span class="hljs-attr">...getTokenProps</span>({<span class="hljs-attr">token</span>, <span class="hljs-attr">key</span>})} /&gt;</span>
                            ))}
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    ))}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">pre</span>&gt;</span>
            )}
            <span class="hljs-tag">&lt;/<span class="hljs-name">Highlight</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    )
}
</code></pre>
<p>Notice that I am not passing a theme since I am using my own code highlight theme - you could download one theme from the <a target="_blank" href="https://github.com/PrismJS/prism-themes">official PrismJS repository</a> and use it instead.</p>
<p>Or if you want, you can just copy <a target="_blank" href="https://github.com/FabioRosado/fabiorosado.dev/blob/master/src/styles/_syntax-highlighting.scss">my theme</a> and use it.</p>
<h2 id="expanding-the-code-block">Expanding the code block</h2>
<p>I've seen <a target="_blank" href="https://www.christopherbiscardi.com/">Chris Biscardi</a> digital garden and really liked the "header" of his code blocks, so I thought that it could be a nice addition to my code block.</p>
<p>To allow users to copy the code inside a code block, I had to create a function for the copy button and handle the event when someone clicks on it.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> Highlight, { defaultProps } <span class="hljs-keyword">from</span> <span class="hljs-string">"prism-react-renderer"</span>


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> (props) =&gt; {
    <span class="hljs-keyword">const</span> className = props.children.props.className || <span class="hljs-string">'language-text'</span>

    <span class="hljs-keyword">const</span> language = className.replace(<span class="hljs-string">"language-"</span>, <span class="hljs-string">""</span>)
    <span class="hljs-keyword">const</span> matches = className.match(<span class="hljs-regexp">/language-(?&lt;lang&gt;.*)/</span>)

    <span class="hljs-keyword">const</span> CopyButton = <span class="hljs-function"><span class="hljs-params">props</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> [text, setText] = useState(<span class="hljs-string">"Copy"</span>)

        <span class="hljs-keyword">return</span> (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"code-copy-button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> {
                navigator.clipboard.writeText(props.content)
                setText("Copied!")
                setTimeout(() =&gt; { setText("Copy")}, 1000)
            }}
            &gt;
                {text}
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
        )
    }

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"gatsby-highlight"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Highlight</span> {<span class="hljs-attr">...defaultProps</span>} 
                <span class="hljs-attr">code</span>=<span class="hljs-string">{props.children.props.children.trim()}</span> 
                <span class="hljs-attr">language</span>=<span class="hljs-string">{matches</span> &amp;&amp; <span class="hljs-attr">matches.groups</span> &amp;&amp; <span class="hljs-attr">matches.groups.lang</span> ? <span class="hljs-attr">matches.groups.lang</span> <span class="hljs-attr">:</span> ''}
                <span class="hljs-attr">theme</span>=<span class="hljs-string">''</span>
            &gt;</span>
            {({ className, tokens, getLineProps, getTokenProps}) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">pre</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{className}</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"code-header"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"language-name"</span>&gt;</span>{language}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">CopyButton</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{props.children.props.children}</span> /&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">code</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{className}</span>&gt;</span>
                    {tokens.map((line, i) =&gt; (
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"code-block"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{i}</span> {<span class="hljs-attr">...getLineProps</span>({<span class="hljs-attr">line</span>, <span class="hljs-attr">key:i</span>})}&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"line-number"</span>&gt;</span>{i + 1}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                            {line.map((token, key) =&gt; (
                                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{key}</span> {<span class="hljs-attr">...getTokenProps</span>({<span class="hljs-attr">token</span>, <span class="hljs-attr">key</span>})} /&gt;</span>
                            ))}
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    ))}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">pre</span>&gt;</span>
            )}
            <span class="hljs-tag">&lt;/<span class="hljs-name">Highlight</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    )
}
</code></pre>
<h2 id="adding-wrapper-component-to-mdxrenderer">Adding Wrapper Component to MDXRenderer</h2>
<p>The step 3 of the <a target="_blank" href="https://codetrain.io/adding-prism-syntax-highlighting-to-gatsby-mdx">adding syntax highlighting to Gatsby Mdx with Prism</a>, says that we need to add the code block as a component to the <code>MDXProvider</code> and also points to the <a target="_blank" href="https://www.gatsbyjs.org/packages/gatsby-plugin-mdx/#mdxrenderer">MDXRenderer documentation</a>.</p>
<p>I have to admit that I couldn't understand fully how to do this. Everything that I tried was failing, luckily <a target="_blank" href="https://www.willharris.dev/">Will Harris</a> was kind enough to share his repository with me and explained that I should add the component to the <code>gatsby-browser.js</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { MDXProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"@mdx-js/react"</span>

<span class="hljs-keyword">import</span> CodeBlock <span class="hljs-keyword">from</span> <span class="hljs-string">"./src/components/highlight/CodeBlock"</span>

<span class="hljs-keyword">const</span> component = {
    <span class="hljs-attr">pre</span>: CodeBlock
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> wrapRootElement = <span class="hljs-function">(<span class="hljs-params">{ element }</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MDXProvider</span> <span class="hljs-attr">components</span>=<span class="hljs-string">{component}</span>&gt;</span>{element}<span class="hljs-tag">&lt;/<span class="hljs-name">MDXProvider</span>&gt;</span></span>
}
</code></pre>
<p>By adding this bit of code to the <code>gatsby-browser.js</code> made the whole code highlighting work. </p>
<p>If you chose a theme, you should have everything working, if you prefer to build your own, then you can keep on reading and use my theme.</p>
<h2 id="code-highlighting-theme">Code Highlighting Theme</h2>
<p>I am using <code>scss</code> on this website so the theme that I am going to share with you, will be in scss.</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.gatsby-highlight</span> {
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">2.5rem</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">2.5rem</span>;
}

<span class="hljs-selector-class">.code-header</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">justify-content</span>: flex-end;
    <span class="hljs-attribute">border-bottom</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#6089bd</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">1rem</span>;
}

<span class="hljs-selector-class">.language-name</span> {
    <span class="hljs-attribute">padding-right</span>: <span class="hljs-number">1em</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#ff85cb</span>;
}

<span class="hljs-selector-class">.code-copy-button</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#79b3fd</span>;
    <span class="hljs-attribute">background</span>: none;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-tag">code</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2px</span> <span class="hljs-number">6px</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#78b2fd</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#1b2530</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#1b2530</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
}


<span class="hljs-selector-tag">code</span><span class="hljs-selector-attr">[class*="language-"]</span>,
<span class="hljs-selector-tag">pre</span><span class="hljs-selector-attr">[class*="language-"]</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#f8f8f2</span>;
    <span class="hljs-attribute">background</span>: none;
    <span class="hljs-attribute">text-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">1px</span> rgba(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.3</span>);
    <span class="hljs-attribute">text-align</span>: left;
    <span class="hljs-attribute">white-space</span>: pre;
    <span class="hljs-attribute">word-spacing</span>: normal;
    <span class="hljs-attribute">word-break</span>: normal;
    <span class="hljs-attribute">word-wrap</span>: normal;
    <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.5</span>;
    -moz-<span class="hljs-attribute">tab-size</span>: <span class="hljs-number">4</span>;
    -o-<span class="hljs-attribute">tab-size</span>: <span class="hljs-number">4</span>;
    <span class="hljs-attribute">tab-size</span>: <span class="hljs-number">4</span>;
    -webkit-<span class="hljs-attribute">hyphens</span>: none;
    -moz-<span class="hljs-attribute">hyphens</span>: none;
    -ms-<span class="hljs-attribute">hyphens</span>: none;
    <span class="hljs-attribute">hyphens</span>: none;
    <span class="hljs-attribute">font-size</span>: large;
}

<span class="hljs-comment">/* Code blocks */</span>
<span class="hljs-selector-tag">pre</span><span class="hljs-selector-attr">[class*="language-"]</span> {
    <span class="hljs-attribute">overflow</span>: auto;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">0.3em</span>;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid rgb(<span class="hljs-number">97</span>, <span class="hljs-number">137</span>, <span class="hljs-number">189</span>);
    scrollbar-<span class="hljs-attribute">width</span>: none;

    &amp;::-webkit-scrollbar { 
        display: none; <span class="hljs-comment">/* Chrome Safari */</span>
    }
}

<span class="hljs-selector-pseudo">:not</span>(<span class="hljs-selector-tag">pre</span>) &gt; <span class="hljs-selector-tag">code</span><span class="hljs-selector-attr">[class*="language-"]</span>,
<span class="hljs-selector-tag">pre</span><span class="hljs-selector-attr">[class*="language-"]</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#1A2430</span>;
}

<span class="hljs-comment">/* Inline code */</span>
<span class="hljs-selector-pseudo">:not</span>(<span class="hljs-selector-tag">pre</span>) &gt; <span class="hljs-selector-tag">code</span><span class="hljs-selector-attr">[class*="language-"]</span> {
    <span class="hljs-attribute">padding</span>: .<span class="hljs-number">1em</span>;
    <span class="hljs-attribute">border-radius</span>: .<span class="hljs-number">3em</span>;
    <span class="hljs-attribute">white-space</span>: normal;
}

<span class="hljs-selector-class">.line-number</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#6272a4</span>;
    <span class="hljs-attribute">padding-right</span>: <span class="hljs-number">2rem</span>;
}

<span class="hljs-selector-class">.token-line</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">1em</span>;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.comment</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.prolog</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.doctype</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.cdata</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#6272a4</span>;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.punctuation</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#f8f8f2</span>;
}

<span class="hljs-selector-class">.namespace</span> {
    <span class="hljs-attribute">opacity</span>: .<span class="hljs-number">7</span>;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.property</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.tag</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.constant</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.symbol</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.deleted</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#ff79c6</span>;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.boolean</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.number</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#bd93f9</span>;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.selector</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.attr-name</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.string</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.char</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.builtin</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.inserted</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#50fa7b</span>;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.operator</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.entity</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.url</span>,
<span class="hljs-selector-class">.language-css</span> <span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.string</span>,
<span class="hljs-selector-class">.style</span> <span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.string</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.variable</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#f8f8f2</span>;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.atrule</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.attr-value</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.function</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.class-name</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#f1fa8c</span>;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.keyword</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#8be9fd</span>;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.regex</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.important</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#ffb86c</span>;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.important</span>,
<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.bold</span> {
    <span class="hljs-attribute">font-weight</span>: bold;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.italic</span> {
    <span class="hljs-attribute">font-style</span>: italic;
}

<span class="hljs-selector-class">.token</span><span class="hljs-selector-class">.entity</span> {
    <span class="hljs-attribute">cursor</span>: help;
}
</code></pre>
<h2 id="share-your-theme">Share your theme!</h2>
<p>If you have used my template to get your own code highlighting and have changed it, I would love to see what you have created! </p>
<p>You can add your own theme to my <a target="_blank" href="https://github.com/FabioRosado/code-highlighting-theme">code highlighting theme repository</a>.</p>
<h2 id="references">References</h2>
<ul>
<li><a target="_blank" href="https://codetrain.io/adding-prism-syntax-highlighting-to-gatsby-mdx">Adding Syntax Highlighting to Gatsby MDX with Prism</a></li>
<li><a target="_blank" href="https://www.christopherbiscardi.com/">Chris Biscardi repository - for the language and copy button</a></li>
<li><a target="_blank" href="https://www.willharris.dev/">Will Harris - for sharing his repo with me</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Command Line Tricks]]></title><description><![CDATA[Working with the command line can be fun. But the more you use the command line, the more you realise that you end up repeating commands over and over again in your workflow.
Luckily there are some easy to remember commands that will help you cut tim...]]></description><link>https://node.theflying.dev/command-line-tricks</link><guid isPermaLink="true">https://node.theflying.dev/command-line-tricks</guid><category><![CDATA[command line]]></category><category><![CDATA[tricks]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Fábio Rosado]]></dc:creator><pubDate>Fri, 09 Oct 2020 15:28:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1602257284825/cLfnU-Sqk.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Working with the command line can be fun. But the more you use the command line, the more you realise that you end up repeating commands over and over again in your workflow.</p>
<p>Luckily there are some easy to remember commands that will help you cut time when repeating commands.</p>
<h2 id="history-using-reverse-i-search">History  - Using reverse-i-search</h2>
<p>Reverse-i-search will search through the whole <code>history</code> to match a command that contains what you typed. You will need to activate reverse-i-search by pressing the keys <code>CTRL+R</code>, your prompt will switch to <code>(reverse-i-search)`':</code></p>
<p>With reverse-i-search activated, you can type the beginning of a command and the last one that was run will be matched. If you want to cycle through all matches you just need to press <code>CTRL+R</code> again.</p>
<p>If you know that you are going to use a command a lot you can write the command like this:</p>
<p> <code>&lt;command&gt; #tag</code></p>
<p>Then all you need is run the reverse-i-search and search for <code>#</code>, your command will be matched straight away. Since the # indicates a start of a comment the terminal will simply ignore the text <code>#tag</code>.</p>
<h3 id="examples">Examples</h3>
<p>History:</p>
<pre><code class="lang-sh">  1  git pull origin master <span class="hljs-comment">#pull-origin-master</span>
  2  git status
  3  git stash
  4  git pull origin master
  5  git stash apply
  6  git add file
  7  git commit -m <span class="hljs-string">"Added file"</span>
  8  git rebase -i HEAD~2
  9  git push
</code></pre>
<p>Start reverse-i-search and type git:</p>
<pre><code class="lang-sh">(reverse-i-search)`git<span class="hljs-string">': git push</span>
</code></pre>
<p>Git push was the last command typed so that's the first match that reverse-i-search returns.</p>
<p>Now let's use the tag trick to run the first command in our history. Let's reverse-i-search for #</p>
<pre><code class="lang-sh">(reverse-i-search)`<span class="hljs-comment">#': git pull origin master #pull-origin-master</span>
</code></pre>
<h2 id="history-using">History - Using !</h2>
<p>If you run the command <code>history</code> you can see a long list with all the commands that you have typed in the command line. To re-run a command you can do one of these two ways:</p>
<ul>
<li>Type: <code>!&lt;number of the command&gt;</code></li>
<li>Type <code>!&lt;first letters of command&gt;</code></li>
</ul>
<p>For you to use the number of the command you probably would have to run <code>history</code>, then get the number and type <code>!&lt;number of the command&gt;</code>, in some cases this will take even longer than typing the command again.</p>
<p>But since you know which command you want to run, you can simply type <code>!&lt;first letters of command&gt;</code> and those first letters will be matched to a command. This little trick can save you some precious time.</p>
<h3 id="examples">Examples</h3>
<p>History:</p>
<pre><code class="lang-sh">  1 ls
  2 <span class="hljs-built_in">cd</span>
  3 <span class="hljs-built_in">cd</span> documents/
  4 mkdir folder
  5 rmdir folder
  6 ls
</code></pre>
<p>Let's run the last command in our history again by typing <code>!!</code></p>
<pre><code class="lang-sh">user ~/documents &gt; !!
ls
folder
</code></pre>
<p>As you can see the terminal will print the command before running it, this is to help you in case something happens that you weren't expecting.</p>
<p>Now let's try to run the second command in our history by using the number reference.</p>
<pre><code class="lang-sh">user ~/documents &gt; !2
<span class="hljs-built_in">cd</span>
user ~ &gt;
</code></pre>
<p>The <code>cd</code> command was run and you should be in your home directory now.</p>
<p>Let's say you want to create a folder with the same name in your home directory you can do:</p>
<pre><code class="lang-sh">user ~ &gt; !mk
mkdir folder
user ~ &gt; ls
folder
</code></pre>
<h2 id="autocomplete">Autocomplete</h2>
<p>Typing long commands can take a while, luckily your terminal can autocomplete commands for you, all you need to do is start typing a few letters and press the <code>TAB</code> key and the command will be auto-completed.</p>
<p>If you forgot how do you type a command, but you know the first letter, you can type the first letter and press the <code>TAB</code> key twice, a long list of all available commands will appear and you can use that to help you.</p>
<h3 id="examples">Examples</h3>
<p>Let's look for a command that starts with the letter K:</p>
<pre><code class="lang-sh">user ~ &gt; K &lt;TAB&gt;&lt;TAB&gt;
kadmin.local     kextfind         keytool          klist            kswitch
kcc              kextload         <span class="hljs-built_in">kill</span>             kramdown         ktutil
</code></pre>
<p>As you can see any command that starts with the letter K will be returned.</p>
<p>I hope you find this helpful, let me know if there are more useful commands that I should add to this list!</p>
<hr />
<p><em>This article was first published on <a target="_blank" href="https://fabiorosado.dev/blog/command-line-tricks">my personal site</a> on 7th of July</em></p>
]]></content:encoded></item></channel></rss>