<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Darren Burns</title>
    <description>The latest articles on DEV Community by Darren Burns (@_darrenburns).</description>
    <link>https://dev.to/_darrenburns</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F125606%2F7fd81198-de76-479c-8e92-6f43e1b4cc8f.JPG</url>
      <title>DEV Community: Darren Burns</title>
      <link>https://dev.to/_darrenburns</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_darrenburns"/>
    <language>en</language>
    <item>
      <title>A short example of how types can make your life easier</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Sat, 29 Jun 2019 18:47:51 +0000</pubDate>
      <link>https://dev.to/_darrenburns/a-simple-example-of-how-types-can-make-your-life-easier-bfa</link>
      <guid>https://dev.to/_darrenburns/a-simple-example-of-how-types-can-make-your-life-easier-bfa</guid>
      <description>&lt;p&gt;What follows is an example covering of some of the issues I encounter frequently when writing code in dynamic programming languages, and how rewriting the same code using type annotations (and more specifically, enums) makes my life easier. The code snippets below are written in Python, but apply to any language that supports enums, such as TypeScript, Java, etc.&lt;/p&gt;




&lt;p&gt;Imagine you work for an online book store, and you've been tasked with writing some code to predict and store a user's book format preferences. In the codebase you're working on, you find a method that sounds useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_preferred_book_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You want to make use of this method somewhere in your code, but at a glance, you can't tell how to correctly call it. It clearly takes a single argument, &lt;code&gt;format&lt;/code&gt;, but there's no indication as to what &lt;code&gt;format&lt;/code&gt; &lt;em&gt;is&lt;/em&gt;. Is it a string, a number, or maybe an object of some kind?&lt;/p&gt;

&lt;p&gt;You dig into the method body and see code like this buried in the middle of it, which checks that the argument is valid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;VALID_BOOK_FORMATS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;f"format must be one of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;VALID_BOOK_FORMATS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You jump through to the &lt;code&gt;VALID_BOOK_FORMATS&lt;/code&gt; variable, and see that it is defined as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;VALID_BOOK_FORMATS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"AUDIOBOOK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"EBOOK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"PAPERBACK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"HARDBACK"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Given that this is a list of strings, and our method checks that the &lt;code&gt;format&lt;/code&gt; argument is contained within this list, we can deduce that when we call &lt;code&gt;save_preferred_book_format&lt;/code&gt;, we must pass it a string, and if it's not one of the strings defined in this list, our program will crash!&lt;/p&gt;

&lt;p&gt;If we hadn't read the full implementation of this method, we wouldn't have known this. The signature of the method does not contain enough information in order to safely use it. In this case, the original developer was kind enough to include a reference to the list of &lt;code&gt;VALID_BOOK_FORMATS&lt;/code&gt;, so we were able to use our detective skills to work out how to call the method.&lt;/p&gt;

&lt;p&gt;This is a common ritual in code bases written in dynamically typed languages such as JavaScript and Python, and it quickly becomes tiresome if you have to perform it every time you want to call a function. If the function has multiple parameters, the complexity can vastly increase the amount of time required to understand it.&lt;/p&gt;

&lt;p&gt;This is problematic. If the one of the key ideas behind clean code is &lt;strong&gt;reusability&lt;/strong&gt;, why should you have to jump through so many hoops just to understand &lt;em&gt;how&lt;/em&gt; to reuse a function? Well designed code lets you spend more calling functions and less time trying to work out how to use them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You shouldn't have to read the body of a function to learn how to call it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;How could the method above have been written to avoid this problem?&lt;/p&gt;

&lt;p&gt;We know that a copy of a book be an &lt;code&gt;EBOOK&lt;/code&gt; or a &lt;code&gt;PAPERBACK&lt;/code&gt;, but it can't be both. Many programming languages come with a handy way of modelling this: &lt;strong&gt;enumeration types&lt;/strong&gt; (enums)!&lt;/p&gt;

&lt;p&gt;Here's how we could rewrite &lt;code&gt;VALID_BOOK_FORMATS&lt;/code&gt; using an enum instead of a list of strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;enum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;AUDIOBOOK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;EBOOK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;PAPERBACK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;HARDBACK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;How you use an enum is similar to how you interact with radio buttons. There's a defined set of options, but you can only select one of them at a time.&lt;/p&gt;

&lt;p&gt;Now we can update the original method signature to annotate the previously confusing parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_preferred_book_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BookFormat&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Just by adding this type annotation, we've told the reader of our code that the &lt;code&gt;format&lt;/code&gt; parameter has type &lt;code&gt;BookFormat&lt;/code&gt;, and so the method expects any of the 4 possible variations: &lt;code&gt;AUDIOBOOK&lt;/code&gt;, &lt;code&gt;EBOOK&lt;/code&gt;, &lt;code&gt;PAPERBACK&lt;/code&gt;, or &lt;code&gt;HARDBACK&lt;/code&gt;. We've decreased the size of the set of possible input values from infinity to four, and you no longer need to look beyond the signature of the method to understand how to use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;save_preferred_book_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BookFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EBOOK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Not only that, but if we pass an invalid value to the function, our static analyser, editor, or compiler (e.g. &lt;code&gt;tsc&lt;/code&gt;, PyCharm, &lt;code&gt;mypy&lt;/code&gt;) will tell us about it before we even run our code. If we were to make a typo when calling the method, we'd be told about that before running our code too!&lt;/p&gt;

&lt;p&gt;Enums are just one benefit of using a type system. They make code easier to read, save you from having to jump around your codebase to discover how to call functions, and your code becomes far less error prone.&lt;/p&gt;

&lt;p&gt;This post is not even close to being an exhaustive exploration of the benefits of refactoring your code to use types, but hopefully it has given some readers food for thought.&lt;/p&gt;




&lt;h3&gt;
  
  
  A note on Python 3.8
&lt;/h3&gt;

&lt;p&gt;Python 3.8 offers "literal types", which let us specify that our code must be called with a specific literal. We could potentially rewrite our method to inform readers of our code that it will only accept specific strings using literal types as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;_FormatType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"AUDIOBOOK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"EBOOK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"PAPERBACK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"HARDBACK"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_preferred_book_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_FormatType&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, if we call our code with any literal string that isn't contained within the list, we'll be informed of it before we run it!&lt;/p&gt;




</description>
      <category>beginners</category>
      <category>refactorit</category>
    </item>
    <item>
      <title>Simulating millions of particles to create the Sun</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Wed, 26 Jun 2019 21:18:38 +0000</pubDate>
      <link>https://dev.to/_darrenburns/simulating-millions-of-particles-to-create-the-sun-2ppo</link>
      <guid>https://dev.to/_darrenburns/simulating-millions-of-particles-to-create-the-sun-2ppo</guid>
      <description>&lt;p&gt;I recently wrote a blog post about how I was learning to make video games in the Unity game engine. In that post, I built a simple space scene, and added some basic game mechanics. After writing that post, I wanted to try something a little flashier by building a dramatic version of the Sun to sit at the centre of the scene. This project let me dive into the depths of particle simulation in Unity. At first, the simulation was done entirely on the CPU. Later, I discovered the Unity Visual Effect Graph and the incredible performance a GPU is capable of.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh6hjexyzm6n2eox12fdx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh6hjexyzm6n2eox12fdx.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My first attempt involved adding a sphere to my scene and wrapping it with an equirectangular projection of the surface of the Sun, just like I'd done with Mars in my previous post. The results were underwhelming. The solar surface is alive and radiating energy, but my sphere looked like a giant tangerine floating through space.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvwxg5x1ybupon3jm2zhi.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvwxg5x1ybupon3jm2zhi.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make things feel a bit more lively, I created a densely packed particle system in Unity, and then created a custom texture using Photoshop using an image of smoke. I created this texture by finding an image of a boat on fire, cropping out a section of the smoke, and adding alpha values to each pixel based on how dark it was, essentially converting darkness into transparency. Here's how it looked with ~1000 particles fading in and out on the surface of the sphere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2ir821km9ty6ic7uceou.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2ir821km9ty6ic7uceou.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The surface of the Sun now has motion, which certainly makes things more interesting than they were before. Unfortunately, that's still not very interesting, and things look a little bit &lt;em&gt;off&lt;/em&gt;. I soon realised that the texture I created wasn't actually transparent. Areas of thin smoke weren't rendering with transparency, they were rendering completely opaquely!&lt;/p&gt;

&lt;p&gt;The fix took &lt;em&gt;hours&lt;/em&gt; to find, with the majority of the time trying to work out how to convert darker pixels to transparency in my image. Working with alpha channels in Photoshop is &lt;em&gt;not&lt;/em&gt; intuitive for beginners! After fixing the alpha channels in my image, and figuring out how to import a transparent texture into Unity, here's what things looked like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4vpmv8d1ipd99btkom6g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4vpmv8d1ipd99btkom6g.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Much better! The next thing I tried was to add the corona. The corona is the outer layer of the sun's atmosphere, and it's much dimmer than the surface of the sun. So, I added another layer of particles, but made them dimmer and more orange in colour.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4br46447i7fcccru9vng.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4br46447i7fcccru9vng.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was really happy with this, but I wanted to take things further. The Sun pictured above contains approximately 1200 particles, all of which are simulated on the CPU. Recently, I'd been reading about the Visual Effect Graph, an upcoming feature in Unity which allows you to simulate particles entirely on the GPU. It turns out the GPU is &lt;em&gt;very&lt;/em&gt; good at this task. This project was a great excuse to dive into the VFX Graph and see what it was capable of.&lt;/p&gt;

&lt;p&gt;To kick things off, I created a sphere containing hundreds of thousands of particles. Then I started increasing the numbers, eventually simulating 2,000,000 particles at once:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fy9q0t95uhyoii41mooeb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fy9q0t95uhyoii41mooeb.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Despite having a huge number of particles rendering on my screen, I was able to fly around the scene and maintain a constant 200 FPS. In order to bring my FPS down to a steady 60, here's what it took (note that the FPS looks lower because my GIF recording software is capped at 15 FPS):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9wgrwq9ijzjca08jy00t.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9wgrwq9ijzjca08jy00t.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's an explosion of &lt;strong&gt;14 million&lt;/strong&gt; individual particles being simulated in real-time.&lt;/p&gt;

&lt;p&gt;I wanted to make use of the power of the VFX Graph in order to bring my Sun to life.&lt;/p&gt;

&lt;p&gt;I created a spherical volume of particles, and configured the graph in order to have new particle instances spawn on the surface of the sphere. To do this, I created a vector of random numbers, then normalised it so that it had a length of 1. This vector represents a random point on the unit sphere. The sphere representing the Sun in my scene has a radius of 42. To get a random point on this surface, I multiplied the vector representing the random point on the unit sphere by 42. The final result is a random point on the surface of the Sun.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9264mylrdzz18k2b5sp9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9264mylrdzz18k2b5sp9.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the ability to spawn miniature particle systems on the surface of my sphere, my next task was to introduce some chaos. I wanted them to look like they belonged on the surface of a star.&lt;/p&gt;

&lt;p&gt;The "turbulence" node of the Unity VFX Graph gave me an effect I was happy enough with, and one that I think is beautiful in isolation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5riefyu8dc2rmyhcijdb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5riefyu8dc2rmyhcijdb.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point I had constructed a giant hollow sphere of particles, which I hoped wouldn't look out of place when I wrapped them around the Sun I made earlier. I placed the Sun inside this particle ball, then added a script to make the whole thing rotate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F090g1a7npjjua7tx9iv8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F090g1a7npjjua7tx9iv8.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point I was happy enough with where I was at, but I realised the motion of particles on and around the Sun were really effective at drawing focus to it. To further draw attention to the Sun, and make things more dramatic, I added a stream of particles which spawn on the surface of the Sun, and travel outwards before fading away.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fa4r3igtb0ktw8bm99ikq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fa4r3igtb0ktw8bm99ikq.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To finish things off I wanted to add some solar prominence, so I fired up Photoshop and painted another texture. This time I just painted it manually rather than basing it off of a real image. I spawned 50 instances of it such that it wrapped around the Sun, and added so slight variation to the scale of the particles as they spawn. The particles spawn at a random rotation, and slowly rotate around the Sun.&lt;/p&gt;

&lt;p&gt;The final result isn't the most realistic, but it's certainly quite dramatic, and I'm pretty happy with it overall.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh6hjexyzm6n2eox12fdx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh6hjexyzm6n2eox12fdx.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If I were to continue working on it, I would likely replace the surface of the sun with a shader rather than repeatedly spawning smoke particles, and try to make it appear to "glow" more than it currently does using lighting rather than particles.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>gamedev</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Learning to Create Video Games</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Thu, 30 May 2019 13:19:41 +0000</pubDate>
      <link>https://dev.to/_darrenburns/learning-to-create-video-games-504n</link>
      <guid>https://dev.to/_darrenburns/learning-to-create-video-games-504n</guid>
      <description>&lt;p&gt;Video games have been a huge part of my life since I unwrapped my first console, the SEGA Dreamcast, on Christmas morning back when I was 5 years old. To me, they are the ultimate combination of storytelling, art, and technology.&lt;/p&gt;

&lt;p&gt;The process of developing video games became one of my earliest endeavours when I first started learning to code. Unfortunately, it was a frustrating experience akin to learning to draw without knowing how to hold a pencil, and my motivation quickly faded. At that point in time, my programming knowledge extended about as far as knowing what a &lt;code&gt;for&lt;/code&gt; loop was. After a few weeks of trying and failing to understand why almost nothing would work, I threw in the towel, feeling deflated and defeated.&lt;/p&gt;

&lt;p&gt;A year later I went to university to study Computer Science and it sparked my passion for programming outside of video game development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coding and creativity
&lt;/h2&gt;

&lt;p&gt;Despite being an engineer and the "sciencey" type, I've always been driven by creativity. Until I was about 13 years old I couldn't decide whether I wanted to be an animator or a graphic designer, and couldn't imagine ever becoming a software engineer. How could something as technical as programming be considered enjoyable?&lt;/p&gt;

&lt;p&gt;What I realised is that coding is a largely creative process, and one that would allow me to scratch both my technical and artistic itches at once. With coding satisfying my need to express my creativity, I never found myself taking the leap back into video game development.&lt;/p&gt;

&lt;p&gt;A few weeks ago I discovered &lt;a href="https://twitter.com/SebastianLague"&gt;Sebastian Lague's&lt;/a&gt; fantastic "Coding Adventures" series on YouTube, where he explores coding concepts in &lt;a href="https://unity.com/"&gt;Unity&lt;/a&gt;, a popular video game engine. The &lt;a href="https://www.youtube.com/watch?v=Cp5WWtMoeKg"&gt;first video&lt;/a&gt; I watched mesmerised me. In it, Sebastian uses a "ray-marching" algorithm to generate a stunning &lt;a href="https://en.wikipedia.org/wiki/Mandelbulb"&gt;Mandelbulb&lt;/a&gt; fractal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hCFxIdQb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/y6nl0r20mow4rcyupisj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hCFxIdQb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/y6nl0r20mow4rcyupisj.gif" alt="" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although there is always creativity to be found in coding, the output of the code I typically write doesn't evoke the same feelings that a piece of art like the one above does, nor does it evoke the joy you get when you play your favourite video game. In my case, the end result is often a value being written to a database, or some data being sent over a network.&lt;/p&gt;

&lt;p&gt;I will always achieve some amount of satisfaction from these things, just like I did the first time the words &lt;code&gt;"Hello, World!"&lt;/code&gt; popped up in my terminal window. However, when the code you wrote today is similar in purpose to the code you wrote yesterday and the day before that, your vision can narrow, and you might forget that computers are capable of so much more. It's easy to forget that code can create truly beautiful things; art, in a very literal sense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making planets
&lt;/h2&gt;

&lt;p&gt;On discovering Sebastian's series, I was inspired to pick up game development where I left off, and to prove to myself I was now capable of doing something which once left me feeling defeated. I downloaded the Unity game engine, and after watching &lt;a href="https://www.youtube.com/watch?v=QN39W020LqU&amp;amp;list=PLFt_AvWsXl0cONs3T0By4puYy6GM22ko8"&gt;another tutorial&lt;/a&gt; from the same creator, decided to try my hand at procedurally generating planet surfaces.&lt;/p&gt;

&lt;p&gt;I constructed a spherical &lt;strong&gt;mesh&lt;/strong&gt; (a mesh is a collection of points joined together by triangles which together form a 3-dimensional object) using the scripting API provided by Unity. We can do this by providing Unity with a bunch of 3-dimensional vectors (called &lt;strong&gt;vertices&lt;/strong&gt;) which represent points in the world, and some integers indicating how we wish to join these points together using triangles. With these seemingly primitive tools we can create any 3-dimensional shape imaginable.&lt;/p&gt;

&lt;p&gt;To generate the mountains of the planet, I pass in each the location of each vertex to a &lt;strong&gt;gradient noise&lt;/strong&gt; function. Gradient noise has been used in computer graphics for years, for a variety of purposes, and it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BlkTxfFQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/r64e3ro0s2l1ggt5g372.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BlkTxfFQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/r64e3ro0s2l1ggt5g372.PNG" alt="" width="196" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For each pixel in the image above, imagine that the brighter it is, the greater the altitude of the pixel. So, we can think of areas of pure white as being the apex of a mountain, the grey areas represent somewhere around half way up a mountain, and the darkest areas represent the lowest elevations.&lt;/p&gt;

&lt;p&gt;Now lets "wrap" this noise around our sphere like you might wrap a basketball with wrapping paper.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JLEi-8zZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/m9tt431lp763crwqnt0m.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JLEi-8zZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/m9tt431lp763crwqnt0m.PNG" alt="" width="347" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we were to elevate the brighter points of the sphere away from the centre of the circle, we'd find ourselves with a "lumpy" sphere. We can customise the noise to increase it's density (by "zooming out" of the noise), which would result in a rougher surface. Similarly, we can zoom in to the noise to make the surface of the sphere appear smoother.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---5MnOqOq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/f5yjtl762kivygw2l0im.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---5MnOqOq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/f5yjtl762kivygw2l0im.gif" alt="" width="386" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, the distribution of the noise over the sphere is entirely uniform. The surface of our "planet", much like Edinburgh, is a bit &lt;em&gt;too&lt;/em&gt; consistent when it comes to hills. So, to generate more realistic planetary surfaces, we apply the noise in several layers. One layer will model the sea; another will model land; a third will form hills; and a final rough layer of noise will sculpt the highest peaks of our planet's mountains.&lt;/p&gt;

&lt;p&gt;There's a couple of smaller additional tricks involved which Sebastian explains in the series, but the end result was a generator that created relatively realistic planetary surfaces. The image below shows what it looks like when I manipulate some of the parameters relating to how the noise is applied to the surface sphere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bf1Ii2ZQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/zafj2ju2phf2t6aeet8m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bf1Ii2ZQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/zafj2ju2phf2t6aeet8m.gif" alt="" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the end, I never finished all of the tutorials in this series. Paradoxically, my motivation was so high after reaching this point that I didn't &lt;em&gt;want&lt;/em&gt; to finish the series there and then. Instead, I wanted to explore as many other areas of Unity as possible, as quickly as I could.&lt;/p&gt;

&lt;h2&gt;
  
  
  The dance of the planets
&lt;/h2&gt;

&lt;p&gt;Next, I would simulate planetary motion. I wanted to make things a little more realistic this time, so I found myself a space &lt;strong&gt;skybox&lt;/strong&gt; on the Unity asset store. A skybox consists of six images that are placed around the player in a cubic shape, so that the player is completely surrounded by them. In this case, it means that wherever the player looks, it looks like space.&lt;/p&gt;

&lt;p&gt;Then, I created a sphere in Unity and applied an image of the surface of Mars to it (&lt;a href="https://www.solarsystemscope.com/textures/"&gt;from Solar System Scope&lt;/a&gt;). The image is called an &lt;strong&gt;equirectangular projection&lt;/strong&gt;, which means it was formed by projecting the spherical surface of Mars on to a flat surface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q6aKPQcN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hxol75ga1sxnywrkhlzq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q6aKPQcN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hxol75ga1sxnywrkhlzq.jpg" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wrote a script and attached it to the planet in order to have it apply a pulling force to things around it, based on the mass of the planet. You know, gravity. I placed a few of these "planets" around the scene, then added a glowing effect around them for no reason other than I had just discovered it was possible and I thought it looked pretty cool.&lt;/p&gt;

&lt;p&gt;With the scene set, I sat back, and prepared for the elegance that is the dance of the planets.&lt;/p&gt;

&lt;p&gt;Here's what happened...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fKZ4biNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ilj8htsgvs7x0pb833xg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fKZ4biNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ilj8htsgvs7x0pb833xg.gif" alt="" width="480" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I remembered the fundamental law of gravity which states that when the apple drops from the tree it falls to the ground. The apple does &lt;em&gt;not&lt;/em&gt; drop from the tree and immediately begin orbiting the planet. With the realisation that this dance was far too dependent on the choreographer's physics knowledge, I decided to beam off to my next adventure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interactivity
&lt;/h2&gt;

&lt;p&gt;Both of these experiments were really enjoyable and gave me a feel for working with Unity, but neither were "games". Without interactivity, they're really just simulations. &lt;/p&gt;

&lt;p&gt;Despite the fact that it was basically an advert for why NASA should never hire me, I enjoyed the "feel" of the previous scene. I decided to keep things in space. This also meant that I didn't have to fill my scene with assets in order to achieve a sense of realism. After all, space is mostly empty.&lt;/p&gt;

&lt;p&gt;I wanted to build in some mechanics from real-time strategy (RTS) games. Although I didn't have a goal in mind for where I wanted my game to go at the time, implementing interesting game mechanics is great experience whether you end up using them or not. I'd learn the concepts behind creating the mechanics, and find out what works, and what doesn't work.&lt;/p&gt;

&lt;p&gt;I started by creating a cube which would represent a space ship. Then I added the ability to click the cube in order to select it. This involved learning about &lt;strong&gt;raycasting&lt;/strong&gt;, where you fire off a ray in a direction, and check what it collides with. In order to implement unit selection, I had to send a ray out from the camera, through the cursor position, and detect whether the ray collided with my cube. Then, with the cube selected, I made it so you could right click to have the cube travel to a point in space after rotating to face the correct direction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--maJs0ftc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yz1jya8rwuk74br8zmaq.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--maJs0ftc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yz1jya8rwuk74br8zmaq.PNG" alt="" width="755" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After getting movement down, I upgraded my cube to a &lt;a href="https://assetstore.unity.com/packages/3d/luminaris-starship-71439"&gt;cool ship asset&lt;/a&gt; I found on the &lt;a href="https://assetstore.unity.com/"&gt;Unity Asset Store&lt;/a&gt;, and added the ability to pan, zoom and rotate the camera. It took me almost two hours to figure out how to make my ship not fly with its nose pointing down. After some research I found that this was happening because the 3D modelling software Blender uses a different coordinate system from Unity. The axis that the ship model perceived to be "forward", was Unity's idea of "down". To fix the problem, I placed the ship model inside an empty Unity GameObject, adjusted it so that it was facing forward (for real this time), and applied all future rotations to the parent instead of to the ship directly.&lt;/p&gt;

&lt;p&gt;I wrote a small script called &lt;code&gt;Rotator&lt;/code&gt; to make planets slowly rotate by slightly increasing the rotation on every physics update, which made the scene feel less static.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Rotator&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;FixedUpdate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Vector3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="m"&gt;01f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Box selection
&lt;/h2&gt;

&lt;p&gt;Most top down strategy games allow you to select multiple units at once by dragging a rectangle around them. I used the skills I learned from the planet generation tutorial to dynamically construct a plane as you click and drag the mouse. I applied a &lt;strong&gt;shader&lt;/strong&gt; to the mesh that is generated to make it slightly colourful, and a little transparent. A shader is a concept in computer graphics which lets you apply special effects to an object using your GPU, making them really efficient.&lt;/p&gt;

&lt;p&gt;Shaders are usually written using a special scripting language, which looks a bit daunting to learn. However, In Unity, you can build shaders using an amazing visual tool called Shader Graph, which is so much fun to use and something I definitely want to dive deeper into in the future.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h6KBP4QT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/u60zwvhk8n3x2o3kapr5.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h6KBP4QT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/u60zwvhk8n3x2o3kapr5.PNG" alt="" width="880" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After implementing this, I realised that performing the selection in 3-dimensional space can be a little tricky, especially if you have multiple units on screen and if the camera has been rotated at all. It can be hard for the brain to quickly understand the rotation the camera is currently at, and to know the angles that the edges of the box will appear at when you start dragging.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EHYfpIYO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/znd7qkem6n75jax5e8rm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EHYfpIYO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/znd7qkem6n75jax5e8rm.gif" alt="" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the future, I may update my rectangular selection code so that you draw the rectangle in 2-dimensional space, and project it onto the 3-dimensional space of the game world. This is how it works in games like StarCraft 2, and it &lt;em&gt;definitely&lt;/em&gt; feels more intuitive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wAtMMjec--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ecsfknk0fxpzf9ztqojt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wAtMMjec--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ecsfknk0fxpzf9ztqojt.png" alt="" width="576" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Right now it's also not clear which units you currently have selected. In the future I'll decide how I want to convey this information to the player. It's a tricky problem, especially with the potential for many units to appear on screen at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combat
&lt;/h2&gt;

&lt;p&gt;A game with space ships &lt;em&gt;obviously&lt;/em&gt; requires that they have the ability to unleash a barrage of missiles at each other!  I wrote a script called &lt;code&gt;BasicAttack&lt;/code&gt; and attached it to my ship prefab. This script defines things like "how much damage do my attacks do". At first, attacks were performed using raycasting. An invisible ray was fired out from the selected ship towards the direction of the mouse click. If the ray collided with another ship, it immediately deducted the attack damage of the attacking ship from the hitpoints of the ship that took damage. If the hitpoints of a ship falls to zero or below, it gets immediately removed from the world.&lt;/p&gt;

&lt;p&gt;Without any visual feedback, this made for a rather dull experience. So I added a few more features in order to liven things up a little.&lt;/p&gt;

&lt;p&gt;I attached a &lt;code&gt;LineRenderer&lt;/code&gt; (used to draw lines, and comes with Unity) component to my ship &lt;strong&gt;prefab&lt;/strong&gt;. A prefab in Unity is similar to a class in programming. It's defines a blue print for what an instance of it will look like, and can easily be reused anywhere. The start point of the line is set to be the centre of the selected ship, and the endpoint is set to the position of the cursor. If a ship is selected, and the user presses &lt;code&gt;A&lt;/code&gt;, the ship will enter "Attack Mode", and the &lt;code&gt;LineRenderer&lt;/code&gt; will become visible on screen. I created a shader using Shader Graph and applied it to the line to make it slowly fade in and out over time, just to make things a little more visually interesting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nsqgVd6v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/7vf2ihg4nllw99y1q0lm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nsqgVd6v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/7vf2ihg4nllw99y1q0lm.gif" alt="" width="386" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, I updated the &lt;code&gt;BasicAttack&lt;/code&gt; code to spawn a missile instead of casting an invisible ray. The missile is just a capsule, with a &lt;code&gt;TrailRenderer&lt;/code&gt; (built in to Unity) attached to it, which results in a trail of light which follows the missile as it travels towards its target. For now, the missiles always travel at a speed such that it takes 3 seconds to reach their target. After 3 seconds, the target takes damage. This isn't the most realistic approach, but it works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bodvt0ep--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/azzr39oao3ti9d62sxc8.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bodvt0ep--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/azzr39oao3ti9d62sxc8.PNG" alt="" width="684" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To let the player know how much damage the target has taken, I implemented (after &lt;em&gt;hours&lt;/em&gt; of headaches) floating damage numbers above the target. I absolutely &lt;em&gt;love&lt;/em&gt; this effect in video games. When a target takes damage, the amount of damage it's taken briefly appears above the unit. The size of the font also dynamically scales based on the damage taken. &lt;/p&gt;

&lt;p&gt;In my implementation, for damage numbers between 1 and 50, the standard font size is used (it results in a &lt;code&gt;fontScaleFactor&lt;/code&gt; of 1). As we start doing more than 50 damage, the font size used to display the damage numbers increases in size, up to a maximum damage of 300. If an attack applies 300 or more damage, the font size will be double the standard size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fontScaleFactor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Mathf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InverseLerp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;damage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;damageText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fontSize&lt;/span&gt; &lt;span class="p"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;fontScaleFactor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since a ship can take multiple damage instances in quick succession, I added some random variation to the position these damage numbers spawn at. Without this variation, the numbers overlap perfectly, and it isn't possible to determine how many instances of damage the ship has received. Here's the function I wrote to apply the randomness to the spawn position of the floating damage numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="nf"&gt;ApplyRandomOffsets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;minOffset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;xOff&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minOffset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;yOff&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minOffset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;zOff&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minOffset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vector3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;xOff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;yOff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;zOff&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these changes, things became a little bit more visually exciting:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5RdyFEEM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rma8fzxul63c9ypqk72o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5RdyFEEM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rma8fzxul63c9ypqk72o.gif" alt="" width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Explosions
&lt;/h2&gt;

&lt;p&gt;To give the player more visual feedback that that their attacks do damage, I added explosions that trigger when the missiles reach their target. Explosions in Unity are usually achieved using the Unity Particle System, which lets you create amazing physics based particle effects. Rather than attempting to create my own textures and particle systems, I used some of the particle systems available in the &lt;a href="https://assetstore.unity.com/packages/essentials/tutorial-projects/unity-particle-pack-127325"&gt;Unity Particle Pack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My initial attempts at making things explode didn't really go to plan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uzAZ6XHx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/24sk0pqwwgtpudu50tke.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uzAZ6XHx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/24sk0pqwwgtpudu50tke.gif" alt="" width="760" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After some messing around, I upgraded my weird pink box shapes and arrived at something which looked a bit like a firework. Not exactly the high impact effect I was looking for, but certainly a step in the right direction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vhonEnUX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/g8baf26oicke7sbk922d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vhonEnUX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/g8baf26oicke7sbk922d.gif" alt="" width="760" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A bit of Googling and some more messing around with settings, and I finally realised the cause of my problems was my use of Unity's newish Lightweight Render Pipeline (LWRP). The shaders used by the explosion weren't supported. After updating them to ones that are supported by the LWRP, the particle system actually started looking like a realistic explosion:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7RvJRJkS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dr520cwjxsh3ato4mxbx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7RvJRJkS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dr520cwjxsh3ato4mxbx.gif" alt="" width="760" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the missiles reach their targets, the target will play an explosion effect. As an extra challenge, I gave each ship "shields", which is an additional layer of hitpoints. If a missile strikes a ship and it still has shields, the explosion is blue. After a ship runs out of shield energy, the explosions become orange as a visual cue to the player that the ship is low on total health.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ncTNjq28--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/poklgtpdsegptb7x6uac.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ncTNjq28--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/poklgtpdsegptb7x6uac.gif" alt="" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I still have lots of ideas about how I could improve the effects here. Randomly varying the missile strike locations, and making the explosion effects spawn at those locations will add to the realism. Instead of hard-coding the explosion to appear at the centre of the target ship 3 seconds after the missile is fired, moving to a collision based system will allow the missile to explode immediately upon striking its target. A blue explosion isn't how "shield" effects are typically portrayed in films or video games either, so a shader which simulates a "force-field" effect might work better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving forward
&lt;/h2&gt;

&lt;p&gt;There's still lots to learn, but I'm really happy with my progress over the course of the past couple of weeks. Although there's no real gameplay in the project beyond "fly around and attack ships", it was an incredible learning experience and one that still makes me feel like I accomplished my goal of learning to create video games.&lt;/p&gt;

&lt;p&gt;Going forward, I'd like to learn how to add a UI to the project above, and perhaps implement some interesting gameplay systems. I have a bunch of notes on how gameplay might work, and some ideas I want to experiment with. I may also move onto other projects, such as implementing interesting game mechanics I've experienced from other games, like the portal gun from &lt;em&gt;Portal&lt;/em&gt;, or the Leviathan Axe from &lt;em&gt;God of War&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Either way, learning the basics of Unity has opened up a whole new world of creativity for me. There's now so many things I now want to explore and learn to create, and I now have the confidence in myself that I'll be able to succeed at learning them!&lt;/p&gt;

&lt;p&gt;In the future I might create more development/learning logs like these discussing the things I've built, and what I learned in the process. If you're interested, follow me on &lt;a href="https://dev.to/_darrenburns"&gt;DEV&lt;/a&gt;, &lt;a href="https://twitter.com/_darrenburns"&gt;Twitter&lt;/a&gt;, and check out my personal blog at &lt;a href="https://darrenburns.net"&gt;darrenburns.net&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>beginners</category>
      <category>learning</category>
      <category>unity3d</category>
    </item>
    <item>
      <title>Making Mistakes</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Sat, 25 May 2019 13:27:01 +0000</pubDate>
      <link>https://dev.to/_darrenburns/making-mistakes-584e</link>
      <guid>https://dev.to/_darrenburns/making-mistakes-584e</guid>
      <description>&lt;p&gt;If you ever struggle with learning to code, I want you to know that my code to generate a CSV file of user IDs has produced the output in the image below. I've been coding for 8 years, and it's one of the many mistakes I've made this week.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fxqusquryxpr399eq3sw6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fxqusquryxpr399eq3sw6.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I started coding I had a constant feeling of having no idea what I was doing. &lt;/p&gt;

&lt;p&gt;I still have no idea what I'm doing, and make mistakes daily.&lt;/p&gt;

&lt;p&gt;Long ago, these would make me frustrated and angry with myself. As I gain more experience, my attitude towards mistakes evolves.&lt;/p&gt;

&lt;p&gt;Some of my current thoughts on making mistakes are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mistakes are human, and are always an opportunity to improve&lt;/li&gt;
&lt;li&gt;Every programmer makes mistakes, even the really famous ones, and even if they hide it well&lt;/li&gt;
&lt;li&gt;My team is compassionate and will help me rather than shame me for slipping up&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I can't stress enough how important the last point is. It's so important to find a team where you feel psychologically safe. In my current team a mistake often feels like an opportunity to collaborate, learn, and improve our process. It's something to reflect on without shame.&lt;/p&gt;

&lt;p&gt;Some teams turn the very human act of making a mistake into exercise in assigning blame. Every line of code is another potential slip up, another layer of anxiety, and another step towards burnout.&lt;/p&gt;

&lt;p&gt;This is just one aspect of a toxic company culture and it will have a negative impact on your mental well-being.&lt;/p&gt;

&lt;p&gt;For this reason it's important not to be afraid to ask difficult questions about company culture and attitude towards mental health at interviews. If a potential employer isn't receptive to questions on these subjects, you probably don't want to work with them.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>5 CLI Utilities to Boost Your Productivity</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Tue, 07 May 2019 13:43:51 +0000</pubDate>
      <link>https://dev.to/_darrenburns/5-cli-utilities-to-boost-your-productivity-3ae8</link>
      <guid>https://dev.to/_darrenburns/5-cli-utilities-to-boost-your-productivity-3ae8</guid>
      <description>&lt;p&gt;Here are 5 command line tools I've found recently which can speed up your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;fx&lt;/code&gt;, a command-line JSON processing tool
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fx&lt;/code&gt; (&lt;a href="https://github.com/antonmedv/fx"&gt;GitHub&lt;/a&gt;) is a CLI tool written in JavaScript which allows you to process JSON using your terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KhDDt9d2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xib6bmqvh44347z7nv6f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KhDDt9d2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xib6bmqvh44347z7nv6f.gif" alt="fx"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can explore and modify JSON using small snippets of plain JavaScript, and use your cursor to dive into the structure. For all of the functionality offered by &lt;code&gt;fx&lt;/code&gt;, check out the &lt;a href="https://github.com/antonmedv/fx/blob/master/DOCS.md"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;fx&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;brew install fx&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;http-prompt&lt;/code&gt;, for interacting with APIs
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;http-prompt&lt;/code&gt; (&lt;a href="http://http-prompt.com/"&gt;website&lt;/a&gt;) is useful for exploring and interacting with HTTP APIs. It comes with autocomplete and syntax highlighting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IfGMaURv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fr1nejgr4ugiwfjbcyw3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IfGMaURv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fr1nejgr4ugiwfjbcyw3.gif" alt="http-prompt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http-prompt&lt;/code&gt; is written in Python, and builds on top of &lt;a href="https://httpie.org/"&gt;HTTPie&lt;/a&gt;, which was covered earlier in this series.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;http-prompt&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pip install --user http-prompt&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;fselect&lt;/code&gt;, for querying files with an SQL-like syntax
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fselect&lt;/code&gt; (&lt;a href="https://github.com/jhspetersson/fselect"&gt;GitHub&lt;/a&gt;) is an alternative way to search your filesystem. It lets you use a syntax similar to SQL to find what you're looking for. For example, to find the size and path of all &lt;code&gt;.cfg&lt;/code&gt; and &lt;code&gt;.tmp&lt;/code&gt; files in &lt;code&gt;/home/user/&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fselect size, path from /home/user where name = '*.cfg' or name = '*.tmp'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fselect&lt;/code&gt; also supports aggregation functions, similar to those you find in SQL:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fselect "MIN(size), MAX(size), AVG(size), SUM(size), COUNT(*) from /home/user/Downloads"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The query above will find the smallest file size, the largest file size, the average file size, the total file size, and the number of files present in your &lt;code&gt;Downloads&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fselect&lt;/code&gt; is written in Rust, and it can do much more than the examples above suggest. It has extensive &lt;a href="https://github.com/jhspetersson/fselect"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;fselect&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;brew install fselect&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;ranger&lt;/code&gt;, a command-line file manager
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ranger&lt;/code&gt; (&lt;a href="https://github.com/ranger/ranger"&gt;GitHub&lt;/a&gt;) is a command-line file manager written in Python that lets you browse and manipulate your file system using Vim like keybindings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IZAk6Dy---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/h5ng3h3obd2vekxen6s4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IZAk6Dy---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/h5ng3h3obd2vekxen6s4.png" alt="ranger"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It offers a multi-column display, the ability to preview files, and lets you perform common file operations (such as creation, deletion, chmod, copying, etc.) from within the ranger interface.&lt;/p&gt;

&lt;p&gt;You can extend &lt;code&gt;ranger&lt;/code&gt; by installing some Python packages which allow it to preview images, HTML documents, and PDF files. The image below is an example posted on the &lt;a href="https://ranger.github.io/screenshots.html"&gt;gallery&lt;/a&gt; available on the Ranger website, showing the image previewing functionality in action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ksC5jqA3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/p8a57yo2wruw0r2sluo4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ksC5jqA3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/p8a57yo2wruw0r2sluo4.png" alt="ranger-screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ranger is a deep piece of software with countless features that don't fit within the scope of this post. More information can be found in the &lt;a href="https://github.com/ranger/ranger/wiki/Official-user-guide"&gt;official user guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;ranger&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;brew install ranger&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;tokei&lt;/code&gt;, to view statistics on your code
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;tokei&lt;/code&gt; (&lt;a href="https://github.com/XAMPPRocky/tokei"&gt;GitHub&lt;/a&gt;) lets you view code statistics for your projects by breaking down the languages you've used. It's written in Rust, which helps make it &lt;a href="https://github.com/XAMPPRocky/tokei/blob/master/COMPARISON.md"&gt;very fast&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's some example output from running &lt;code&gt;tokei&lt;/code&gt; in my &lt;a href="https://adventofcode.com/"&gt;Advent of Code&lt;/a&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-------------------------------------------------------------------------------
 Language            Files        Lines         Code     Comments       Blanks
-------------------------------------------------------------------------------
 Markdown                1          165          165            0            0
 Rust                   13         1071          854           51          166
 Plain Text             17         4032         4032            0            0
 TOML                    1           11           10            0            1
-------------------------------------------------------------------------------
 Total                  32         5279         5061           51          167
-------------------------------------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing &lt;code&gt;tokei&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;brew install tokei&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thanks for reading! Hopefully, you found something on this page that interests you. If you’re interested in more content like this, follow me on &lt;a href="https://twitter.com/_darrenburns"&gt;Twitter&lt;/a&gt; and on &lt;a href="https://dev.to/_darrenburns"&gt;DEV&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tips</category>
      <category>unix</category>
      <category>commandline</category>
    </item>
    <item>
      <title>The Piece Table - the Unsung Hero of Your Text Editor</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Thu, 24 Jan 2019 00:32:59 +0000</pubDate>
      <link>https://dev.to/_darrenburns/the-piece-table---the-unsung-hero-of-your-text-editor-al8</link>
      <guid>https://dev.to/_darrenburns/the-piece-table---the-unsung-hero-of-your-text-editor-al8</guid>
      <description>&lt;p&gt;The piece table is the unsung hero data-structure that is responsible for much of the functionality and performance characteristics we’ve come to expect from a text editor. Visual Studio Code has one. Microsoft Word 2.0 had one back in 1984. &lt;/p&gt;

&lt;p&gt;Despite being an almost ubiquitous feature of modern text editors, it remains relatively poorly documented. In this article, I’ll explain how a piece table is structured, why they’re used, and how your text editor interacts with it as you edit files.&lt;/p&gt;

&lt;p&gt;My aim is to make this post as beginner-friendly as possible, so we’ll explore each concept slowly. You should, however, have a basic understanding of arrays, strings, and objects (or dicts/structs) before continuing.&lt;/p&gt;




&lt;p&gt;When you open a file in your text editor, the contents are read from disk and into a data structure in memory. If you were to write a text editor, how would you store an open file in memory?&lt;/p&gt;

&lt;h2&gt;
  
  
  First instincts - the array of strings
&lt;/h2&gt;

&lt;p&gt;Our first instinct might be to use an array of strings, where each string is a single line in the file. In other words, we’d represent this file…&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

the quick brown fox
jumped over the lazy dog


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;…like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;the quick brown fox&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# line 1 of the file
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jumped over the lazy dog&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# line 2 of the file
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is an intuitive way to represent a text file in memory. It lets us think about the file in a way that is similar to how it appears on-screen in our text editor.&lt;/p&gt;

&lt;p&gt;It’s also a perfectly acceptable approach, and you could argue that the intuitiveness of it outweighs any potential flaws it may have. In fact, Visual Studio Code used a similar model until early 2018.&lt;/p&gt;

&lt;p&gt;Unfortunately, this method becomes costly when we’re dealing with large files. To see why, think about what would happen if someone were to insert a new line (&lt;code&gt;"went to the park and"&lt;/code&gt;) into the middle of the file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

the quick brown fox
went to the park and
jumped over the lazy dog


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In order to make room for this new line, all of the lines below it in the array need to be shifted along in memory. For large files, this quickly becomes expensive. As the file grows larger, there’s more data to be moved.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzgtqqdu6x4etiy8moz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzgtqqdu6x4etiy8moz4.png" alt="shifting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is just one of the downfalls of this method. In this fantastic &lt;a href="https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation#_piece-tree" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; by the Visual Studio Code team, they highlight other flaws with this approach such as excessive memory usage and performance issues relating to splitting up the file into multiple strings on newline characters.&lt;/p&gt;

&lt;h2&gt;
  
  
  An append-only representation
&lt;/h2&gt;

&lt;p&gt;If we append something to the end of an array, we don’t have to shift any data along to make space for it, so we don’t incur the same performance penalty as in the case where we insert into the middle of an array (more technically, appending to an array has O(1) time complexity, but insertion is O(n)).&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;piece table&lt;/em&gt; is the powerful data-structure behind many text editors, old and new. A key characteristic of the piece table is that it records all of the insertions we make to a file in an append-only manner. &lt;/p&gt;

&lt;p&gt;Let’s explore how the piece table works.&lt;/p&gt;

&lt;p&gt;When we read a file from disk into a piece table, the text inside the file is stored in a single string which we never modify. We call this string the &lt;em&gt;original buffer&lt;/em&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;piece_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;original&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;the quick brown fox&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;jumped over the lazy dog&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When we add text to the file in our editor, that text is appended to the &lt;em&gt;add buffer&lt;/em&gt; of the piece table, which is initially just an empty string.&lt;/p&gt;

&lt;p&gt;Adding a copyright notice at the top of the file? Append it to the add buffer. A new function in the middle of the file? Add buffer. An extra newline at the end of the file? Add buffer!&lt;/p&gt;

&lt;p&gt;The add buffer is the second of the two buffers in which make up a piece table, and it is append-only.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;original&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;the quick brown fox&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;jumped over the lazy dog&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;add&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By appending everything that gets inserted into the file onto the add buffer, we record the text that the user has typed into the editor, whilst avoiding those pesky mid-array insertions we mentioned earlier.&lt;/p&gt;

&lt;p&gt;Let’s open our hypothetical text editor again, and add a line into the middle of our file as we did before. That makes our piece table look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;original&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;the quick brown fox&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;jumped over the lazy dog&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;add&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;went to the park and&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The text we added to the middle of the file is in the add buffer. The original buffer has stayed the same (and always will).&lt;/p&gt;

&lt;p&gt;These two strings, &lt;code&gt;original&lt;/code&gt; and &lt;code&gt;add&lt;/code&gt;, hold within them the entire contents of the file that is open in your editor, as well as everything that has ever been contained in the file since it was opened.&lt;/p&gt;

&lt;p&gt;When the editor displays an open file, it combines different sections of these two strings together to form the what you see on your screen. Some sections of these strings may be ignored if they’re no longer present in the file (for example if the user of the text editor deletes some text). &lt;/p&gt;

&lt;p&gt;In the text below, the middle section comes from the add buffer since it was inserted, and the rest of the text comes from the original buffer since it was part of the original file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F32gurzud8wrbs9ufn5nt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F32gurzud8wrbs9ufn5nt.png" alt="pt-basic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Right now, our hypothetical editor knows the user has inserted the string &lt;code&gt;"went to the park and\n"&lt;/code&gt; into the file, but not &lt;em&gt;where&lt;/em&gt; they inserted it. We haven’t yet got enough information in the piece table for the editor to be able to correctly display the contents of the file. The missing piece of the puzzle (pun intended) is to track where in the document the user inserted the text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Piece descriptors
&lt;/h2&gt;

&lt;p&gt;In order to know where the user inserted the text in the file, the piece table needs to track which sections of the file come from the &lt;code&gt;original&lt;/code&gt; buffer, and which sections come from the &lt;code&gt;add&lt;/code&gt; buffer. It does this by iterating through a list of &lt;em&gt;piece descriptors&lt;/em&gt;. A piece descriptor contains three bits of information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;source&lt;/code&gt;: tells us which buffer to read from.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;start&lt;/code&gt;: tells us which index in that buffer to start reading from.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;length&lt;/code&gt;: tells us how many characters to read from that buffer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we first open a file in our editor, only the &lt;code&gt;original&lt;/code&gt; buffer has content, and there’s a single piece descriptor which tells our editor to read entirely from the &lt;code&gt;original&lt;/code&gt; buffer. The add buffer is empty because we haven’t yet added any text to our file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;original&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;the quick brown fox&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;jumped over the lazy dog&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;add&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pieces&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Piece&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;original&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Adding text to a file
&lt;/h2&gt;

&lt;p&gt;Now let’s add the same text to the middle of our file just like before. Here’s how the piece table is updated to reflect this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;original&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;the quick brown fox&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;jumped over the lazy dog&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;add&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;went to the park and&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pieces&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;Piece&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;original&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Piece&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;add&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Piece&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;original&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The text we inserted in our file using our text editor has been appended to the add buffer, and what was previously a single piece is now three.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first piece in the list now tells us that only the first 20 characters of the original buffer (&lt;code&gt;the quick brown fox\n&lt;/code&gt;) make up the first span of text in our file (note that &lt;code&gt;\n&lt;/code&gt;, representing a line break, is a single character).&lt;/li&gt;
&lt;li&gt;The second piece tells us that the next 21 characters of the file can be found between indices 0 and 21 in the add buffer (&lt;code&gt;went to the park and\n&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The third and final piece tells us that the final span of text in the file can be found between indices 20 and 44 (start + length) of the original buffer (&lt;code&gt;jumped over the lazy dog&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The act of inserting text into a file typically results in splitting a piece into three separate pieces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One piece to point to the text that falls to the left of the newly inserted text.&lt;/li&gt;
&lt;li&gt;Another piece to refer to the inserted text itself (in the add buffer). &lt;/li&gt;
&lt;li&gt;The third piece refers to the text that got pushed to the right of the newly inserted text.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymhjhs3windbum2kqqd7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymhjhs3windbum2kqqd7.png" alt="pt-example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Things are a little different when you insert text at the beginning or end of an existing piece. In this case, adding text doesn’t “split” an existing piece in half, so we only need a single extra piece to represent the newly inserted text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saving and displaying the open file
&lt;/h2&gt;

&lt;p&gt;As mentioned at the very beginning of this post, when we open a file in a text editor, it gets read from disk and stored inside a data structure in memory (very likely a piece table or some variant). Likewise, when we do the inverse operation and save the file, our editor needs to be able to read the piece table and write the contents back to the file on disk.&lt;/p&gt;

&lt;p&gt;By reading the piece descriptors in consecutive order, our text editor can transform its internal representation of the file in the piece table into what you see on your screen, and what gets written to the file when you save it.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;piece&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;piece_table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pieces&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;piece&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;  &lt;span class="c1"&gt;# "original" or "add"
&lt;/span&gt;    &lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;piece_table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;span_of_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;piece&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;piece&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;piece&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;span_of_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# alternatively, write to a file
&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; In Python, the &lt;code&gt;string[start:end]&lt;/code&gt; syntax can be used to return a substring from a string. For example, &lt;code&gt;“hello”[1:3]&lt;/code&gt; returns &lt;code&gt;"el"&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deleting text
&lt;/h2&gt;

&lt;p&gt;When we delete some text from a file, we split an existing piece into two pieces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One piece points to the text to the left of the deleted text.&lt;/li&gt;
&lt;li&gt;A second piece points to the text to the right of the deleted text.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The deleted text will still be present in one of our buffers, but with no pieces referring to it, it is not considered part of our file.&lt;/p&gt;

&lt;p&gt;You can think of piece descriptors like spotlights pointed at a wall with all of the text ever written to a file painted on it. At any point in time, these lights illuminate sections of the wall, revealing the text there. The illuminated text is considered as part of the file. Although we know there’s more written on the wall, it’s hidden in the darkness and considered irrelevant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Undoing and redoing
&lt;/h2&gt;

&lt;p&gt;One benefit of keeping all of that text around even when it’s not currently part of the file is that it makes the implementation of undo/redo considerably easier.&lt;/p&gt;

&lt;p&gt;Text that is currently “in darkness” may be required again in the future. Wouldn’t it great if we could just adjust our lighting to illuminate that text once again, instead of having to repaint the wall?&lt;/p&gt;

&lt;p&gt;In the array of strings approach discussed at the start of this post, an undo operation could result in millions of characters of text being inserted or deleted across millions of different strings. With the piece table method, the cost of this action becomes trivial. The text to be added or removed as part of an undo or redo is already there in one of the buffers, and we just need to update our piece descriptors to point to it once again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are several ways we could improve the piece table described above. They’re often combined with other data structures such as trees in order to improve aspects of their performance.&lt;/p&gt;

&lt;p&gt;That said, my goal for this post was to leave you with intuition and some appreciation for how your text editor works internally, and those tweaks fall out with that goal.&lt;/p&gt;

&lt;p&gt;If you have any constructive feedback on this post, or if you’ve noticed any errors in it, let me know!&lt;/p&gt;

&lt;p&gt;If you’re interested in more content like this, follow me on &lt;a href="https://twitter.com/_darrenburns" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://dev.to/_darrenburns"&gt;DEV&lt;/a&gt;, and check out my &lt;a href="https://darrenburns.net/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  References/Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.cs.unm.edu/~crowley/papers/sds.pdf" rel="noopener noreferrer"&gt;Data Structures For Text Sequences (PDF)&lt;/a&gt; - Charles Crowley&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://web.archive.org/web/20160308183811/http://1017.songtrellisopml.com/whatsbeenwroughtusingpiecetables" rel="noopener noreferrer"&gt;What’s been wrought using the Piece Table?&lt;/a&gt; - David Lu (I think)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation#_piece-tree" rel="noopener noreferrer"&gt;Text Buffer Reimplementation, a Visual Studio Code Story&lt;/a&gt; - Peng Lyu&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>datastructures</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>8 Productivity Tips for GitHub</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Wed, 09 Jan 2019 08:39:47 +0000</pubDate>
      <link>https://dev.to/_darrenburns/8-productivity-tips-for-github-44kn</link>
      <guid>https://dev.to/_darrenburns/8-productivity-tips-for-github-44kn</guid>
      <description>&lt;p&gt;With the recent announcement of &lt;a href="https://blog.github.com/2019-01-07-new-year-new-github/"&gt;unlimited private repositories&lt;/a&gt;, let's take a few minutes before we push up the code we don’t want anyone else to see, and make sure we’re making the most of what GitHub has to offer.&lt;/p&gt;

&lt;p&gt;GitHub is built with some extremely helpful shortcuts and productivity-boosting features. From personal experience, however, it’s clear that these often fall under the radar amongst developers. If I’ve ever witnessed a specific GitHub feature surprise or assist someone, then that feature is on this page. That said, what follows is by no means an exhaustive list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick fuzzy file search in repositories
&lt;/h2&gt;

&lt;p&gt;This is, without doubt, the fastest way to browse a repository when you know what you’re looking for. Open up any repository and press &lt;code&gt;t&lt;/code&gt;. You can now search for the name of any file in the repository, and use the arrow keys on your keyboard to move through the results. Press Enter to open the file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfsts6urw0s023qvacni.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfsts6urw0s023qvacni.gif" alt="github-fuzzy-search" width="614" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code change suggestions in pull requests
&lt;/h2&gt;

&lt;p&gt;When commenting on a piece of code in a pull request, you can suggest alternative code using the “Suggested Changes” feature. The author of the pull request will be able to apply your suggestion instantly without leaving GitHub.&lt;/p&gt;

&lt;p&gt;To make the suggestion, surround a code snippet with a multiline Markdown snippet, with the tag &lt;code&gt;suggestion&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygnpawam67m8aokzz0wb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygnpawam67m8aokzz0wb.gif" alt="gh-make-suggestion" width="640" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you’ve made the suggestion, the author of the pull request can immediately apply it to their branch, without the hassle of manually changing the file!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4he9ok7t1ehwf7pox37f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4he9ok7t1ehwf7pox37f.gif" alt="gh-apply-suggestion" width="640" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigate the code tree like in an IDE
&lt;/h2&gt;

&lt;p&gt;This one requires an unofficial Chrome extension, but it’s a slightly more familiar way to navigate your code compared to the default interface. The &lt;a href="https://chrome.google.com/webstore/detail/octotree/bkhaagjahfmjljalopjnoealnfndnagc"&gt;Octotree extension&lt;/a&gt; lets you browse GitHub repositories with a sidebar tree view similar to what you get in applications like VS Code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2zm3j65wh4oy8kfr7ny.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2zm3j65wh4oy8kfr7ny.gif" alt="octotree" width="640" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Jump to a function when reviewing code
&lt;/h2&gt;

&lt;p&gt;Unless you’re reviewing a single function, a code review often involves a lot of jumping between function calls and their definitions (and therefore a lot of scrolling up and down). GitHub lets you jump to a symbol by pressing &lt;code&gt;t&lt;/code&gt; when you’re looking at files in a pull request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0lyxots6zhpxtsdmzr2i.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0lyxots6zhpxtsdmzr2i.gif" alt="gh-jump-to-symbol" width="640" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a permalink to a file
&lt;/h2&gt;

&lt;p&gt;When viewing a file or directory, press &lt;code&gt;y&lt;/code&gt;, and the URL will be converted to a permalink, which you can share knowing that the contents of the file will never change.&lt;/p&gt;

&lt;p&gt;If you send a link to a file or directory on GitHub without making it into a permalink, you’ll need to accept the possibility that the file could disappear tomorrow, breaking the link!&lt;/p&gt;

&lt;h2&gt;
  
  
  Viewing the blame and change recency heatmap
&lt;/h2&gt;

&lt;p&gt;When viewing a file, you can press &lt;code&gt;b&lt;/code&gt; to view the Git blame and a heatmap showing how recently each line was changed. It’ll tell you who most recently changed each line of code, and give you a clickable link taking you to the full commit the change was part of.&lt;/p&gt;

&lt;p&gt;On the right-hand side of the gutter (which contains the commit message and author), you’ll notice an orange vertical bar. The more vivid this bar is, the more recent the change, meaning you can easily scan the file to find the freshest code!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvprabc0j5ola18hpune.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvprabc0j5ola18hpune.gif" alt="gh-blame" width="640" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Powerful code search
&lt;/h2&gt;

&lt;p&gt;GitHub indexes most code and offers powerful search functionality over it. If you need to find something in a repository, but don’t plan on making any changes to it. There’s usually no need to check the repository out. Press &lt;code&gt;/&lt;/code&gt;  to search all the code in the repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdxwvjn3r2c241vt5y14.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdxwvjn3r2c241vt5y14.gif" alt="gh-code-search" width="640" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your search contains multiple words and you want to search for occurrences of your specific search query, put the quotations around the query. You can filter your searches by other things too, such as file size, extension, the path the file is on, and much more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saved replies
&lt;/h2&gt;

&lt;p&gt;If you ever find yourself repeating the same comments, you’ll save some time by creating a &lt;a href="https://github.com/settings/replies"&gt;saved reply&lt;/a&gt;. The next time you find you’re going to type that comment again, you can instead just select it from a drop-down menu:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2q94ap1nd0ikrwfcrl49.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2q94ap1nd0ikrwfcrl49.gif" alt="gh-saved-replies" width="640" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To perform the above action without using my mouse, I can do &lt;code&gt;ctrl + .&lt;/code&gt; followed by &lt;code&gt;ctrl + 1&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thanks for reading. I hope you found at least one thing on this page that will make you a more productive GitHub user. If you enjoyed this post or have any feedback in general, let me know!&lt;/p&gt;

&lt;p&gt;If you’re interested in more content like this, follow my &lt;a href="https://twitter.com/_darrenburns"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on my &lt;a href="https://darrenburns.net/posts/github-tips"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S. You can make your own Octocat for sharing like the one in the cover photo at &lt;a href="https://myoctocat.com"&gt;myoctocat.com&lt;/a&gt;!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>github</category>
      <category>git</category>
    </item>
    <item>
      <title>Power Up Your Command Line, Part 3</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Mon, 07 Jan 2019 06:31:47 +0000</pubDate>
      <link>https://dev.to/_darrenburns/power-up-your-command-line-part-3-4o53</link>
      <guid>https://dev.to/_darrenburns/power-up-your-command-line-part-3-4o53</guid>
      <description>&lt;p&gt;This is part three of the &lt;em&gt;Power Up Your Command Line&lt;/em&gt; series. In this article, I’ll showcase five utilities that make common problems a little easier to solve using the command line.&lt;/p&gt;

&lt;p&gt;This post was originally published &lt;a href="https://darrenburns.net/posts/even-more-tools" rel="noopener noreferrer"&gt;on my blog&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;tig&lt;/code&gt;, for interactively browsing your git repo
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;tig&lt;/code&gt; (&lt;a href="https://github.com/jonas/tig" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) is an excellent way to browse your Git repository using an interactive interface, without leaving the command line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbegtel0euvo9zd0ppire.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbegtel0euvo9zd0ppire.gif" alt="tig"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tig&lt;/code&gt; is simple and intuitive to use, and has different views for things like your stash, staging area (which it lets you quickly alter), logs, and so on.&lt;/p&gt;

&lt;p&gt;Thanks for Renato Suero (&lt;a href="https://twitter.com/renatosuero" rel="noopener noreferrer"&gt;@renatosuero&lt;/a&gt;) for introducing me to &lt;code&gt;tig&lt;/code&gt;  on DEV.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;tig&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS with (&lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;): &lt;code&gt;brew install tig&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  PathPicker (&lt;code&gt;fpp&lt;/code&gt;), for quickly selecting files
&lt;/h2&gt;

&lt;p&gt;PathPicker (&lt;a href="https://github.com/facebook/PathPicker" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) is a library by Facebook for quickly selecting files on the command line. The animated example below is taken from the PathPicker documentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F498ik89ukpwhiu2fxncn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F498ik89ukpwhiu2fxncn.gif" alt="fpp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the &lt;a href="http://facebook.github.io/PathPicker/" rel="noopener noreferrer"&gt;PathPicker website&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PathPicker accepts a wide range of input -- output from git commands, grep results, searches -- pretty much anything. After parsing the input, PathPicker presents you with a nice UI to select which files you're interested in. After that, you can open them in your favorite editor or execute arbitrary commands.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks to Nikolay Dubina (&lt;a href="https://twitter.com/nikolayid" rel="noopener noreferrer"&gt;@nikolayid&lt;/a&gt;) for suggesting this utility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing PathPicker
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS with (&lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;): &lt;code&gt;brew install fpp&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;tldr&lt;/code&gt;, for practical examples of how to use CLI tools
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://tldr.sh" rel="noopener noreferrer"&gt;&lt;code&gt;tldr&lt;/code&gt;&lt;/a&gt; (&lt;a href="https://github.com/tldr-pages/tldr/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) lets you quickly access practical examples (simplified, “tl;dr” versions of man pages) of how to use command line tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fha3htknkv4qu7uenk2qn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fha3htknkv4qu7uenk2qn.gif" alt="tldr"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The examples are maintained by the community in the &lt;code&gt;tldr&lt;/code&gt; &lt;a href="https://github.com/tldr-pages/tldr" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;tldr&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;With npm (recommended): &lt;code&gt;npm install -g tldr&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;On macOS with (&lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;): &lt;code&gt;brew install tldr&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;gron&lt;/code&gt;, for exploring JSON
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;gron&lt;/code&gt; (&lt;a href="https://github.com/tomnomnom/gron" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) transforms JSON text into discrete assignments, to make it easier to find what you need. I particularly like using it for interactively exploring APIs in combination with &lt;code&gt;fzf&lt;/code&gt; (mentioned earlier in this series):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fl01ti86m1p15homi04na.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fl01ti86m1p15homi04na.gif" alt="gron-with-fzf"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also use &lt;code&gt;gron&lt;/code&gt; to help you transform JSON objects (&lt;a href="https://github.com/tomnomnom/gron/blob/master/ADVANCED.mkd" rel="noopener noreferrer"&gt;examples&lt;/a&gt;). This isn’t the main use-case of &lt;code&gt;gron&lt;/code&gt; though, and you’d probably be better served using a purpose built tool like &lt;a href="https://stedolan.github.io/jq/" rel="noopener noreferrer"&gt;&lt;code&gt;jq&lt;/code&gt;&lt;/a&gt; for such things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;gron&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS with (&lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;): &lt;code&gt;brew install gron&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  thefuck, for quickly correcting command line typos
&lt;/h2&gt;

&lt;p&gt;If you mistype a command, type &lt;code&gt;fuck&lt;/code&gt; (&lt;a href="https://github.com/nvbn/thefuck" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) and you’ll be given a list of corrections to choose from.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7f5s5xt1whw5me9ogd9k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7f5s5xt1whw5me9ogd9k.gif" alt="thefuck"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The name of the command is unfortunately slightly NSFW, so you may wish to alias it to something else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing thefuck
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS with (&lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;): &lt;code&gt;brew install thefuck&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bonus: explainshell, for explaining shell commands
&lt;/h2&gt;

&lt;p&gt;If you’re in the situation where you already have a complex shell command and want to understand what it does without browsing &lt;code&gt;man&lt;/code&gt; or &lt;code&gt;tldr&lt;/code&gt; pages, you can use &lt;a href="https://explainshell.com" rel="noopener noreferrer"&gt;explainshell&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3whyhkn8c3bgfwym8mn2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3whyhkn8c3bgfwym8mn2.png" alt="explain_shell"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hopefully you found something on this page that interests you! If you’re interested in more content like this, follow me on &lt;a href="https://twitter.com/_darrenburns" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and on &lt;a href="https://dev.to/_darrenburns"&gt;DEV&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tips</category>
      <category>unix</category>
      <category>commandline</category>
    </item>
    <item>
      <title>5 More Tools To Power Up Your Command Line (Part 2 Of Series)</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Fri, 04 Jan 2019 17:03:02 +0000</pubDate>
      <link>https://dev.to/_darrenburns/tools-to-power-up-your-command-line-part-2-2737</link>
      <guid>https://dev.to/_darrenburns/tools-to-power-up-your-command-line-part-2-2737</guid>
      <description>&lt;p&gt;This is part II of the series “&lt;em&gt;Power Up Your Command Line&lt;/em&gt;”, which showcases excellent non-standard tools that will make using the command line easier and more enjoyable.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;peco&lt;/code&gt;, interactively filter anything
&lt;/h2&gt;

&lt;p&gt;Pipe the output of any command into &lt;code&gt;peco&lt;/code&gt; (&lt;a href="https://github.com/peco/peco"&gt;GitHub&lt;/a&gt;), and you’ll be able to interactively filter it to find the information you need. Think of it like an interactive form of &lt;code&gt;grep&lt;/code&gt;, where the real-time updating of results as you type allows for a more exploratory search process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S9ZDMT_k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2dtk7o5v8xubnzffhok7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S9ZDMT_k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2dtk7o5v8xubnzffhok7.gif" alt="peco-processes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can move up and down through the search results using the arrow keys, and select a result with the enter key. When you press enter, the command outputs the result to your terminal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;peco&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS with Homebrew: &lt;code&gt;brew install peco&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;hexyl&lt;/code&gt;, a hex viewer
&lt;/h2&gt;

&lt;p&gt;If you want to examine a binary file, you typically do so by looking at the hexadecimal representation of the file. &lt;code&gt;hexyl&lt;/code&gt; (&lt;a href="https://github.com/sharkdp/hexyl"&gt;GitHub&lt;/a&gt;) is a command line tool for doing just that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X4pvExVH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/x6r3lg9fsing46ol4fq8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X4pvExVH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/x6r3lg9fsing46ol4fq8.gif" alt="hexyl"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The view is split into three columns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An &lt;em&gt;offset&lt;/em&gt; column, which tells you how many bytes into the file you are.&lt;/li&gt;
&lt;li&gt;A  &lt;em&gt;hex&lt;/em&gt; column (which itself has a divider down the middle - not visible in the example gifs), which contains the hexadecimal representation of the file.&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;representation&lt;/em&gt; column (also split in two, and not shown in the example gifs), which contains a textual representation of the file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each byte in &lt;code&gt;hexyl&lt;/code&gt; is colour-coded depending on the type of byte it is (NULL, ASCII, non-ASCII, etc.) which really helps with readability.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bonus tip&lt;/em&gt;: If viewing binary files or large text files, the output will often be too large for your screen, so you can pipe the output from &lt;code&gt;hexyl&lt;/code&gt; into &lt;code&gt;bat&lt;/code&gt; or &lt;code&gt;less&lt;/code&gt; to give you the ability to paginate through it! You’ll need to use the &lt;code&gt;--raw-control-chars&lt;/code&gt;/&lt;code&gt;-r&lt;/code&gt; flag for the output to be coloured correctly if you use &lt;code&gt;less&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1Y7uYnBj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/k271fbip61yswdp1yg0w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Y7uYnBj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/k271fbip61yswdp1yg0w.gif" alt="hexyl-less"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hexyl&lt;/code&gt; is written in Rust, and is developed by &lt;a href="https://github.com/sharkdp"&gt;David Peter&lt;/a&gt; who also wrote &lt;code&gt;bat&lt;/code&gt;, &lt;code&gt;fd&lt;/code&gt;, and &lt;code&gt;hyperfine&lt;/code&gt;, all of which I mentioned in part one of this series.&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__95033"&gt;
  
    .ltag__user__id__95033 .follow-action-button {
      background-color: #61122F !important;
      color: #FFFFFF !important;
      border-color: #61122F !important;
    }
  
    &lt;a href="/sharkdp" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eXxPefbl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--ExC6EBzv--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/95033/a9643c1c-3e0f-423b-8139-f0b193f75139.jpeg" alt="sharkdp image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/sharkdp"&gt;David Peter&lt;/a&gt;
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/sharkdp"&gt;&lt;/a&gt;
    &lt;/div&gt;
    &lt;p class="ltag__user__social"&gt;
        &lt;a href="https://github.com/sharkdp" rel="noopener"&gt;
          &lt;img class="icon-img" alt="github logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--C74Jn3f1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo.svg"&gt;sharkdp
        &lt;/a&gt;
        &lt;a href="https://david-peter.de" rel="noopener"&gt;
          &lt;img class="icon-img" alt="external link icon" src="https://res.cloudinary.com/practicaldev/image/fetch/s--WsHTbjfA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/link.svg"&gt;https://david-peter.de
        &lt;/a&gt;
    &lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Installing &lt;code&gt;hexyl&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Installing &lt;code&gt;hexyl&lt;/code&gt; requires a few steps on macOS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the binary from GitHub: &lt;code&gt;curl -L -o hexyl.tar.gz https://github.com/sharkdp/hexyl/releases/download/v0.3.0/hexyl-v0.3.0-x86_64-apple-darwin.tar.gz&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Extract the tarball: &lt;code&gt;tar -xf hexyl.tar.gz&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add it to your &lt;code&gt;PATH&lt;/code&gt;: &lt;code&gt;mv hexyl-v0.3.0-x86_64-apple-darwin/hexyl /usr/local/bin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Make executable: &lt;code&gt;chmod +x /usr/local/bin/hexyl&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;pomo&lt;/code&gt;, a pomodoro timer
&lt;/h2&gt;

&lt;p&gt;The pomodoro technique is a great way to boost your productivity. If you haven’t heard of it before, it works like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For &lt;em&gt;25 minutes&lt;/em&gt;, you &lt;em&gt;work&lt;/em&gt; and allow for no distractions.&lt;/li&gt;
&lt;li&gt;For &lt;em&gt;5 minutes&lt;/em&gt;, you &lt;em&gt;relax&lt;/em&gt; and do whatever you want (as long as it isn’t work 😁).&lt;/li&gt;
&lt;li&gt;Repeat the steps above 4 times (you can adjust this number to suit yourself), then rest for  &lt;em&gt;15 minutes&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you follow the plan above, the theory is that you’ll get considerably more done in considerably less time. It might not work for everyone, but I can personally vouch for its effectiveness!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eUsjP3jW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2qdj1c0yq9mww11soap5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eUsjP3jW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2qdj1c0yq9mww11soap5.gif" alt="pomo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pomo&lt;/code&gt;  (&lt;a href="https://github.com/kevinschoon/pomo"&gt;GitHub&lt;/a&gt;) is a simple, configurable CLI tool to help you manage your time through the pomodoro technique.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;pomo&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;There are a few steps to follow to install this one (on macOS):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the binary from GitHub: &lt;code&gt;curl -L -o pomo https://github.com/kevinschoon/pomo/releases/download/0.6.0/pomo-0.6.0-darwin-amd64&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Grant permissions: &lt;code&gt;chmod +x pomo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Put it on your &lt;code&gt;PATH&lt;/code&gt; so you can use it from anywhere: &lt;code&gt;mv pomo /usr/local/bin&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Initialise the database: &lt;code&gt;pomo init&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;ncdu&lt;/code&gt;, analyse and free disk space
&lt;/h2&gt;

&lt;p&gt;If you’ve got a lot of projects on your computer and haven’t cleaned up your disk recently, you’ll almost certainly find a rogue folder that is hogging disk space (I’ve found some &lt;code&gt;node_modules&lt;/code&gt; folders in older projects to be particularly susceptible). &lt;a href="https://dev.yorhel.nl/ncdu"&gt;&lt;code&gt;ncdu&lt;/code&gt;&lt;/a&gt; is my favourite tool for fixing this. In fact, in the process of creating the demonstration for &lt;code&gt;ncdu&lt;/code&gt; below, I freed up over 10GiB of disk space!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_h8qC3mq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/lkoffquem4zz1nqre9ez.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_h8qC3mq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/lkoffquem4zz1nqre9ez.gif" alt="ncdu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To use it, run &lt;code&gt;ncdu&lt;/code&gt;. It’ll scan all subdirectories from the directory you ran it in, so if you run it in your home directory, it might take some time.&lt;/p&gt;

&lt;p&gt;You can use the interactive interface to browse through your filesystem using the arrow keys, or the navigation keys from &lt;code&gt;vim&lt;/code&gt; if that’s your thing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;ncdu&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS with &lt;a href="https://brew.sh"&gt;Homebrew&lt;/a&gt;: &lt;code&gt;brew install ncdu&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  HTTPie, a modern replacement for &lt;code&gt;curl&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://httpie.org"&gt;HTTPie&lt;/a&gt; (&lt;code&gt;http&lt;/code&gt;) is a simpler (meaning I don’t have to Google it every time, unlike with &lt;code&gt;curl&lt;/code&gt;), feature-rich and beautiful alternative to &lt;code&gt;curl&lt;/code&gt;, which will let you call APIs over HTTP from the command line. It’s the most popular utility I’ve reviewed so far and has exceptional &lt;a href="https://httpie.org/doc"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yEIOdF7I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/n5spphjp7tm5xqm5lwsw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yEIOdF7I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/n5spphjp7tm5xqm5lwsw.gif" alt="httpie"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The output from the &lt;code&gt;http&lt;/code&gt; command is what really sets it apart from cURL. JSON responses are pretty printed with syntax highlighting, making them far more readable. If you'd rather use a graphical UI for interacting with APIs, you might like Insomnia, Postman or Paw (Paw requires a license and is macOS only).&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing HTTPie
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS with Homebrew: &lt;code&gt;brew install httpie&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thanks for reading! There are a couple more tools I’d like to mention in the next post in the series, but if you have any suggestions let me know in the comments. If you’re interested in more content like this, follow me on &lt;a href="https://twitter.com/_darrenburns"&gt;Twitter&lt;/a&gt; and on &lt;a href="https://dev.to/_darrenburns"&gt;DEV&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Originally &lt;a href="https://darrenburns.net/posts/more-tools"&gt;posted on my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tips</category>
      <category>commandline</category>
      <category>unix</category>
    </item>
    <item>
      <title>Debug Faster With Colourful Diffs For Your Failing Tests</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Fri, 04 Jan 2019 01:19:53 +0000</pubDate>
      <link>https://dev.to/_darrenburns/debug-faster-with-colourful-diffs-for-your-failing-tests-4i57</link>
      <guid>https://dev.to/_darrenburns/debug-faster-with-colourful-diffs-for-your-failing-tests-4i57</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/pytest-dev/pytest"&gt;Pytest&lt;/a&gt; is quickly becoming the de facto testing framework in the Python community, but I've always found the way it reports assertion errors to rather difficult to quickly parse in many circumstances. In this post, I'll explore how we can use a lesser known part of the Python standard library to build a pytest plugin that outputs colourful diffs similar to those seen in testing frameworks for languages such as Elixir and JavaScript. This &lt;em&gt;isn't&lt;/em&gt; a tutorial, but it should give you an overview of the following topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting started with making a pytest plugin&lt;/li&gt;
&lt;li&gt;How to use the Python standard library to calculate diffs between text&lt;/li&gt;
&lt;li&gt;A brief description of how to use partial application in Python&lt;/li&gt;
&lt;li&gt;Formatting terminal output with escape sequences (programming language agnostic)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's what a failing test looks like with &lt;code&gt;pytest-clarity&lt;/code&gt; (&lt;a href="https://github.com/darrenburns/pytest-clarity"&gt;GitHub&lt;/a&gt;) installed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0cPI9Ryv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yp7wmfren9ioon2e3llp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0cPI9Ryv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yp7wmfren9ioon2e3llp.png" alt="Colourful Pytest Output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From this output, it's easy to see &lt;em&gt;at a glance&lt;/em&gt; why your assertion has failed. Your eyes are immediately drawn to the differences between the dictionaries, and the colours inform you what would need to be added or removed from either side of the assertion in order for them to match.&lt;/p&gt;

&lt;p&gt;If you want to try the plugin, but don't want to read about my experience implementing it, you can install it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install pytest-clarity
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;After running this command, you can run your tests as normal and you'll get the coloured output! If you have any issues or want to uninstall for whatever reason, you can do so by running &lt;code&gt;pip uninstall pytest-clarity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For comparison, I've attached the output for the same test using vanilla pytest below (with very verbose logging &lt;code&gt;-vv&lt;/code&gt; enabled).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R-Ql6INi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3er3g51rsdn5fva790ql.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R-Ql6INi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3er3g51rsdn5fva790ql.png" alt="Vanilla Pytest Output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my opinion there are many things wrong with this output, but the most glaring issue is that the it distracts from the actual content of the objects under comparison. The representations of these objects are interspersed with &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, and &lt;code&gt;^&lt;/code&gt; symbols, making it overly difficult to answer the question &lt;em&gt;"what do the objects I'm comparing actually look like, and how do they differ?"&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Modifying Pytest Output With A Plugin
&lt;/h2&gt;

&lt;p&gt;Pytest has a powerful plugin system, and an active &lt;a href="https://plugincompat.herokuapp.com/"&gt;ecosystem&lt;/a&gt; of useful plugins. The easiest way to get started with plugin development is to use &lt;a href="https://github.com/hackebrot"&gt;@hackebrot&lt;/a&gt;'s Cookiecutter template for pytest plugins.&lt;/p&gt;

&lt;p&gt;After we've created the project using the Cookiecutter template, we need to find the &lt;em&gt;hook&lt;/em&gt; that will enable us to customise how assertion errors are reported.&lt;/p&gt;

&lt;p&gt;Pytest provides a number of hooks, allowing us to add to or customise various aspects of its functionality, but in this case we need &lt;code&gt;pytest_assertrepr_compare&lt;/code&gt;. By creating a function called &lt;code&gt;pytest_assertrepr_compare&lt;/code&gt; inside the &lt;code&gt;pytest_{yourpluginname}.py&lt;/code&gt; file created by Cookiecutter, we can override the default output pytest prints to the terminal when an assertion fails. &lt;/p&gt;

&lt;p&gt;The hook has the following signature (type annotations are my own):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pytest_assertrepr_compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;small&gt;Note: Unfortunately pytest doesn't appear to pass detailed assertion inspection information into this hook, meaning we can't take full advantage of assertion rewriting unless we inspect the AST ourselves.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;The first parameter is a pytest &lt;code&gt;Config&lt;/code&gt; object, which we don't need to worry about. The &lt;code&gt;op&lt;/code&gt; parameter refers to the operation used in the &lt;code&gt;assert&lt;/code&gt; statement in the test. For example, if your assertion looks like &lt;code&gt;assert 1 == 2&lt;/code&gt;, then &lt;code&gt;op&lt;/code&gt; would be &lt;code&gt;"equal"&lt;/code&gt;. &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; refer to the values that appear on the left and right hand side of the &lt;code&gt;op&lt;/code&gt;. In the preceding example, &lt;code&gt;left&lt;/code&gt; would be &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; would be &lt;code&gt;2&lt;/code&gt;. The function returns a list of strings, and each of these strings correspond to a single line of output that pytest will write to the terminal in the event of a failing assertion.&lt;/p&gt;
&lt;h3&gt;
  
  
  A Short &lt;code&gt;assertrepr_compare&lt;/code&gt; Plugin Example
&lt;/h3&gt;

&lt;p&gt;Here's a minimal example of using the &lt;code&gt;assertrepr_compare&lt;/code&gt; hook, which just prints the left and right operands of the &lt;code&gt;assert&lt;/code&gt; statement, as well as the operator used to the terminal:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Basic implementation of the assertrepr_compare hook
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pytest_assertrepr_compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# newline because it looks strange without
&lt;/span&gt;        &lt;span class="s"&gt;'op: {}'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s"&gt;'left: {}'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="s"&gt;'right: {}'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# We'll run this test, and check the output
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_one_equals_two&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The above implementation of the hook results in the following output after running the test:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;___________________ test_compare_strings ___________________

    def test_compare_strings():
&amp;gt;       assert 1 == 2
E       assert
E         op: ==
E         left: 1
E         right: 2

tests/test_util.py:64: AssertionError
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We now have all the information we need to alter pytest's output into whatever format we wish. Let's look at how pytest currently calculates the diffs it shows the user when an assertion fails.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Pytest Calculates Diffs
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pytest-clarity&lt;/code&gt; will rely heavily on &lt;a href="https://docs.python.org/3.7/library/difflib.html"&gt;&lt;code&gt;difflib&lt;/code&gt;&lt;/a&gt;, which is included in the Python standard library. &lt;code&gt;difflib&lt;/code&gt; provides classes and helper functions for comparing sequences, and computing deltas (diffs) between these sequences. As it turns out, pytest also uses &lt;code&gt;difflib&lt;/code&gt; to display the output you see when your assertion is false. It does so using the &lt;a href="https://docs.python.org/3.7/library/difflib.html#difflib.ndiff"&gt;&lt;code&gt;ndiff&lt;/code&gt;&lt;/a&gt; helper function from difflib. This function returns a generator which yields strings, each of which corresponds to one line of the delta output.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;difflib&lt;/span&gt;
&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;
&lt;span class="n"&gt;rhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;
&lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;difflib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndiff&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And here's the output, which is identical to the output you'd see in &lt;code&gt;pytest&lt;/code&gt; if you were to write &lt;code&gt;assert "hello" == "world"&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- hello
+ world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The problem with this approach is that it tightly couples the semantics and the presentation of the delta it generates. It expects that we'll directly output the strings it yields. It'd be nice if we could grab a data structure other than a string which represents the diff itself, and which we can use to generate the colourful output.&lt;/p&gt;

&lt;p&gt;Luckily, &lt;code&gt;difflib&lt;/code&gt; has the answer!&lt;/p&gt;
&lt;h2&gt;
  
  
  Enter The SequenceMatcher
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;SequenceMatcher&lt;/code&gt; class is part of &lt;code&gt;difflib&lt;/code&gt;, and it provides us with a means of comparing pairs of hashable sequences &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt;. We can use it to find the exact index of every element in &lt;code&gt;A&lt;/code&gt; that would have to be replaced, deleted, or inserted, in order to transform &lt;code&gt;A&lt;/code&gt; into &lt;code&gt;B&lt;/code&gt;. This is great, because we can now access an abstract representation of a diff, and we can present it however we desire (colours, &lt;em&gt;everywhere&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Before proceeding, lets look at how to understand and work with the &lt;code&gt;SequenceMatcher&lt;/code&gt;. The method we're interested in is called &lt;code&gt;get_opcodes&lt;/code&gt;. This method returns a list of 5-tuples which describe how to transform &lt;code&gt;A&lt;/code&gt; into &lt;code&gt;B&lt;/code&gt;. The Python difflib documentation has a solid &lt;a href="https://docs.python.org/3/library/difflib.html#difflib.SequenceMatcher.get_opcodes"&gt;explanation&lt;/a&gt; of it, but the code snippet below should give a rough idea of how it works.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;difflib&lt;/span&gt;
&lt;span class="n"&gt;matcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;difflib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SequenceMatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j2&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_opcodes&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# tag can be one of 'replace', 'delete', 
&lt;/span&gt;    &lt;span class="c1"&gt;# 'insert', or 'equal', and represents an operation
&lt;/span&gt;    &lt;span class="c1"&gt;# to be performed in order to transform the 
&lt;/span&gt;    &lt;span class="c1"&gt;# left string into the right string.
&lt;/span&gt;    &lt;span class="c1"&gt;# i1:i2 represents a slice of the left string, 
&lt;/span&gt;    &lt;span class="c1"&gt;# j1:j2 a slice of the right string.
&lt;/span&gt;    &lt;span class="c1"&gt;# i1:i2 and j1:j2 are the ranges within the strings that 
&lt;/span&gt;    &lt;span class="c1"&gt;# the operation should be performed on
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;get_opcodes&lt;/code&gt; method gives us the information we need to determine which colour to write the output to the terminal in.&lt;/p&gt;
&lt;h2&gt;
  
  
  Formatting Terminal Output
&lt;/h2&gt;

&lt;p&gt;Formatting output to the terminal can be tricky. It works by sending &lt;em&gt;escape codes&lt;/em&gt; to our terminal, which are essentially "commands", that we represent using a sequence of characters. If the terminal supports the escape code, rather than printing it, it will perform that command. Terminal escape codes let us do things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change the position of the cursor&lt;/li&gt;
&lt;li&gt;Change the foreground and background colour of the output text&lt;/li&gt;
&lt;li&gt;Change the formatting of the output text (&lt;em&gt;italic&lt;/em&gt;, &lt;strong&gt;bold&lt;/strong&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Make the cursor invisble&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These escape codes can be difficult to manage, and capabilities can vary depending on the type of terminal you have. The fact that terminal based software such as Vim exists should give an idea of the power that these escape sequences offer. Luckily there are plenty of libraries available which make the process much easier for us. For this plugin, I used the &lt;code&gt;termcolor&lt;/code&gt; library. The &lt;code&gt;colored&lt;/code&gt; function it provides makes it easy to write colourful and formatted output.&lt;/p&gt;
&lt;h3&gt;
  
  
  Aside: Partial Function Application In Python
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;colored&lt;/code&gt; function from &lt;code&gt;termcolor&lt;/code&gt; will be used in several places in the plugin. We'll be passing to it a consistent and verbose set of arguments that we don't want to have to repeat everywhere, so it's a great candidate for &lt;em&gt;partial function application&lt;/em&gt;! Partial function application lets us "prep" a function by passing in some arguments in advance. Then, when we want to use the function later, we don't have to pass those arguments in again.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;
&lt;span class="n"&gt;deleted_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colored&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Attr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;diff_intro_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colored&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cyan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Attr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;inserted_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colored&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Attr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now we can call the functions &lt;code&gt;deleted_text&lt;/code&gt;, &lt;code&gt;diff_intro_text&lt;/code&gt;, and &lt;code&gt;inserted_text&lt;/code&gt; in the same way we would call &lt;code&gt;colored&lt;/code&gt;, but we can omit the &lt;code&gt;color&lt;/code&gt; and &lt;code&gt;attrs&lt;/code&gt; named arguments, since they've been applied in advance. Using partial application can make your code more readable, if you give your partially applied functions meaningful names, but use it only where it makes sense.&lt;/p&gt;
&lt;h3&gt;
  
  
  Terminal Escape Sequences
&lt;/h3&gt;

&lt;p&gt;By default, pytest outputs each line of the assertion report as red text (see the screenshot at the start of this post). We don't want this, so we want to instruct our terminal to revert back to standard character formatting. Unfortunately I don't think &lt;code&gt;termcolor&lt;/code&gt; has a function for this, so we have to send the terminal the escape sequence ourselves. &lt;/p&gt;

&lt;p&gt;The escape sequence to clear character formatting for VT-100 compliant terminals (the majority of terminal emulators support this) is &lt;code&gt;\033[0m&lt;/code&gt;. &lt;em&gt;ascii-table.com&lt;/em&gt; has a handy &lt;a href="http://ascii-table.com/ansi-escape-sequences-vt-100.php"&gt;reference&lt;/a&gt; listing terminal escape sequences. The &lt;code&gt;\033&lt;/code&gt; part is an octal representation of the decimal value 27. If you look up an ASCII table, you'll find that 27dec maps to the &lt;code&gt;ESC&lt;/code&gt; (escape) character. Then, we have a &lt;code&gt;[&lt;/code&gt;, which as far as I know is just a separator. The remainder of the sequence is an alphanumeric code that maps to a function. In this case, &lt;code&gt;0m&lt;/code&gt; maps to the "Clear Character Attributes" command. If we print out this escape code at the start of every line of output, we'll override pytest when it attempts to print out everything in bold red characters, and the terminal will output the text in the default format instead.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;plain_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\033&lt;/span&gt;&lt;span class="s"&gt;[0m"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;When a test fails, pytest calls the &lt;code&gt;repr&lt;/code&gt; function on both sides of the &lt;code&gt;assert&lt;/code&gt; statement, and outputs the diff of these object representations. Rather than relying on &lt;code&gt;repr&lt;/code&gt;, we'll use &lt;code&gt;pprint.pformat&lt;/code&gt; which will provide us with a nicely formatted string representation of the object that may span multiple lines for clarity, and make the output more parseable. &lt;code&gt;pprint.pformat&lt;/code&gt; also sorts unordered collections such as &lt;code&gt;dicts&lt;/code&gt; and &lt;code&gt;sets&lt;/code&gt; when constructing the representation. This is essential, since if the representation of two dicts being compared had different key ordering, we'd get different output every time!&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;lhs_repr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;rhs_repr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now that we have our "pretty" representations, we can use the &lt;code&gt;SequenceMatcher&lt;/code&gt; from earlier to generate a delta between them, and our colouring functions to print out text.&lt;/p&gt;

&lt;p&gt;Here's some code for printing out a split diff (a split diff is where the left and right hand sides of the diffs are printed out independently):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;matcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;difflib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SequenceMatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lhs_repr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs_repr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j2&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_opcodes&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;

        &lt;span class="c1"&gt;# Deltas can span multiple lines, but we need to 
&lt;/span&gt;        &lt;span class="c1"&gt;# operate on a line by line basis so we can override
&lt;/span&gt;        &lt;span class="c1"&gt;# pytests attempts to print every individual line red
&lt;/span&gt;        &lt;span class="n"&gt;lhs_substring_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lhs_repr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;rhs_substring_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rhs_repr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;j2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Highlight chars to remove from the left hand side
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lhs_substring&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lhs_substring_lines&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'replace'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;lhs_out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;deleted_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lhs_substring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'delete'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;lhs_out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;deleted_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lhs_substring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'insert'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;lhs_out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;plain_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lhs_substring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'equal'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;lhs_out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;plain_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lhs_substring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lhs_substring_lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;lhs_out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;

        &lt;span class="c1"&gt;# Highlight the stuff to be added on the right hand side
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs_substring&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs_substring_lines&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'replace'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rhs_out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;inserted_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs_substring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'insert'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rhs_out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;inserted_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs_substring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'equal'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rhs_out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;plain_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs_substring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs_substring_lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rhs_out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;

    &lt;span class="c1"&gt;# Return the left and right diffs as lists of strings
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lhs_out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;rhs_out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This post was a quick look at some of the code behind &lt;code&gt;pytest-clarity&lt;/code&gt;. The plugin is currently available on PyPI, and you can install it using &lt;code&gt;pip&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install pytest-clarity
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The full project is available on GitHub (see below). Let me know if you have any questions or issues with it!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/darrenburns"&gt;
        darrenburns
      &lt;/a&gt; / &lt;a href="https://github.com/darrenburns/pytest-clarity"&gt;
        pytest-clarity
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A plugin to improve the output of pytest with colourful unified diffs
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="rst"&gt;
&lt;h1&gt;
pytest-clarity&lt;/h1&gt;
&lt;a href="https://pypi.org/project/pytest-clarity" rel="nofollow"&gt;&lt;img alt="PyPI version" src="https://camo.githubusercontent.com/aee75d135fe6902f6fe27ae971c22bd290eeda9e/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f7079746573742d636c61726974792e737667"&gt;
&lt;/a&gt;
&lt;a href="https://anaconda.org/conda-forge/pytest-clarity" rel="nofollow"&gt;&lt;img alt="conda-forge version" src="https://camo.githubusercontent.com/059c78481f96e9857e7d308e37009ee11901111e/68747470733a2f2f696d672e736869656c64732e696f2f636f6e64612f766e2f636f6e64612d666f7267652f7079746573742d636c61726974792e737667"&gt;
&lt;/a&gt;
&lt;a href="https://pypi.org/project/pytest-clarity" rel="nofollow"&gt;&lt;img alt="Python versions" src="https://camo.githubusercontent.com/e4a3c6d664d7812ad486d328f6c1ed0a655f3954/68747470733a2f2f696d672e736869656c64732e696f2f707970692f707976657273696f6e732f7079746573742d636c61726974792e737667"&gt;
&lt;/a&gt;
&lt;a href="https://travis-ci.org/darrenburns/pytest-clarity" rel="nofollow"&gt;&lt;img alt="See Build Status on Travis CI" src="https://camo.githubusercontent.com/122da285ed16832ec774aaf65ca254c2cf6ecb89/68747470733a2f2f7472617669732d63692e6f72672f64617272656e6275726e732f7079746573742d636c61726974792e7376673f6272616e63683d6d6173746572"&gt;&lt;/a&gt;
&lt;p&gt;A plugin to improve the readability of pytest output.&lt;/p&gt;
&lt;h2&gt;
Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Enables an easier to parse and more understandable diff for your failing tests.&lt;/li&gt;
&lt;li&gt;Can display unified diffs or split diffs, and chooses them depending on the context.&lt;/li&gt;
&lt;li&gt;Adds helpful hints to the output for failing tests to help you track down common issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With pytest-clarity:&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://raw.githubusercontent.com/darrenburns/pytest-clarity/master/pytest-clarity.png"&gt;&lt;img alt="Example output with clarity" src="https://res.cloudinary.com/practicaldev/image/fetch/s--uwZiP6HP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/darrenburns/pytest-clarity/master/pytest-clarity.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The same test, without pytest-clarity:&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://raw.githubusercontent.com/darrenburns/pytest-clarity/master/without-clarity.png"&gt;&lt;img alt="Example output without clarity" src="https://res.cloudinary.com/practicaldev/image/fetch/s--H3xcpmlj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/darrenburns/pytest-clarity/master/without-clarity.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Requirements&lt;/h2&gt;
&lt;p&gt;Supports Python 2.7 and 3.4+&lt;/p&gt;
&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;p&gt;You can install "pytest-clarity" via &lt;a href="https://pypi.org/project/pip/" rel="nofollow"&gt;pip&lt;/a&gt; from &lt;a href="https://pypi.org/project" rel="nofollow"&gt;PyPI&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;$ pip install pytest-clarity
&lt;/pre&gt;

&lt;h2&gt;
Usage&lt;/h2&gt;
&lt;p&gt;Install the plugin as described above.&lt;/p&gt;
&lt;p&gt;** The plugin will only be activated when the -vv option is supplied to pytest.**&lt;/p&gt;
&lt;p&gt;You can choose which type of diff you want with &lt;code&gt;--diff-type&lt;/code&gt; (auto (default), split or unified):&lt;/p&gt;
&lt;pre&gt;pytest -vv --diff-type=split
&lt;/pre&gt;
&lt;p&gt;You can disable hints using the &lt;code&gt;--no-hints&lt;/code&gt; flag:&lt;/p&gt;
&lt;pre&gt;pytest -vv --no-hints
&lt;/pre&gt;
&lt;p&gt;You can configure the width of the output with the &lt;code&gt;--diff-width&lt;/code&gt; option:&lt;/p&gt;
&lt;pre&gt;pytest -vv --diff-width=60
&lt;/pre&gt;

&lt;h2&gt;
Contributing&lt;/h2&gt;
&lt;p&gt;Contributions…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/darrenburns/pytest-clarity"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>python</category>
      <category>testing</category>
    </item>
    <item>
      <title>10 Tools To Power Up Your Command Line</title>
      <dc:creator>Darren Burns</dc:creator>
      <pubDate>Thu, 03 Jan 2019 08:53:31 +0000</pubDate>
      <link>https://dev.to/_darrenburns/10-tools-to-power-up-your-command-line-4id4</link>
      <guid>https://dev.to/_darrenburns/10-tools-to-power-up-your-command-line-4id4</guid>
      <description>&lt;p&gt;This post is the first in a series of showcases of some of the best non-standard command line tools I've discovered in recent years. If you ever make use of the command line, you'll probably find that at least one item on this page will make your life easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;z&lt;/code&gt;, jump around
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnmu47j5o0xjqh4b4uo52.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnmu47j5o0xjqh4b4uo52.gif" alt="Jump Around"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the best and most ubiquitous time-saving features in modern web browsers is the fuzzy and smart search capabilities of the address bar. Want to quickly go to Twitter? Typing "tw" into your address bar and hitting enter is probably enough.&lt;/p&gt;

&lt;p&gt;By comparison, the standard way of navigating our file systems via the command line (using &lt;code&gt;cd&lt;/code&gt;) seems almost prehistoric. Thankfully, &lt;code&gt;z&lt;/code&gt; (&lt;a href="https://github.com/rupa/z" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) brings this browser-style navigation to the command line.&lt;/p&gt;

&lt;p&gt;After a short learning period, &lt;code&gt;z&lt;/code&gt; will allow you to jump to a directory &lt;em&gt;from anywhere&lt;/em&gt;, using only a substring of the target directory name. The directory that &lt;code&gt;z&lt;/code&gt; will take you to is determined by the string argument you gave it, how &lt;em&gt;frequently&lt;/em&gt; you visit the directory, and how &lt;em&gt;recently&lt;/em&gt; you visited the directory. They call it &lt;em&gt;"frecency"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;z&lt;/code&gt; not only increases the speed at which you can navigate your filesystem, it reduces the cognitive load of navigation. With &lt;code&gt;cd&lt;/code&gt;, you need to recall precisely where the destination directory sits in the tree, and work out the path to get there. With &lt;code&gt;z&lt;/code&gt;, knowing the name of the directory is enough.&lt;/p&gt;

&lt;p&gt;Ports of &lt;code&gt;z&lt;/code&gt; to other shells (such as fish and zsh) are readily available too. &lt;code&gt;autojump&lt;/code&gt; (&lt;a href="https://github.com/wting/autojump" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) is a similar project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;z&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;bash&lt;/code&gt; version, on macOS (&lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;): &lt;code&gt;brew install z&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Install &lt;code&gt;fish&lt;/code&gt; shell &lt;a href="https://github.com/jethrokuan/z" rel="noopener noreferrer"&gt;version&lt;/a&gt;, on macOS (&lt;a href="https://github.com/jorgebucaran/fisher" rel="noopener noreferrer"&gt;Fisher&lt;/a&gt;): &lt;code&gt;fisher add jethrokuan/z&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;fzf&lt;/code&gt;, a fast fuzzy finder
&lt;/h2&gt;

&lt;p&gt;After installing &lt;code&gt;fzf&lt;/code&gt; (&lt;a href="https://github.com/junegunn/fzf" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;), you can press &lt;code&gt;Ctrl + T&lt;/code&gt; at any point in time to open up an interactive fuzzy search interface, which will recursively search for files inside the current directory. You can enter a search term, and press the up/down keys to move through the results. If you press the enter key, the selected result is inserted into your terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flasfcsdm1yswprwkuybg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flasfcsdm1yswprwkuybg.gif" alt="fzf"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the example above, I typed &lt;code&gt;bat&lt;/code&gt; (but this could be any command, such as &lt;code&gt;less&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, etc.), then pressed &lt;code&gt;Ctrl + T&lt;/code&gt;. I typed &lt;code&gt;five&lt;/code&gt;, hit enter, and the path &lt;code&gt;src/five.rs&lt;/code&gt; was inserted at my cursor position. This saves the alternative of (roughly): type &lt;code&gt;src&lt;/code&gt;, press tab, type &lt;code&gt;fi&lt;/code&gt;, press tab, which doesn't scale to long or hard to remember paths.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;fzf&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS (&lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;): &lt;code&gt;brew install fzf&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Bindings for &lt;code&gt;fish&lt;/code&gt;: &lt;code&gt;fisher add jethrokuan/fzf&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;bat&lt;/code&gt;, to view files with syntax highlighting
&lt;/h2&gt;

&lt;p&gt;If you want to quickly view a source file with full syntax highlighting, &lt;code&gt;bat&lt;/code&gt; (&lt;a href="https://github.com/sharkdp/bat" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) is your friend. &lt;code&gt;bat&lt;/code&gt; can be used as a drop-in replacement for &lt;code&gt;cat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fn28wzi9fctdbodglgfhx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fn28wzi9fctdbodglgfhx.gif" alt="bat"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the output is large enough (as in the example above), &lt;code&gt;bat&lt;/code&gt; will pipe it's output into &lt;code&gt;less&lt;/code&gt;, meaning we get pagination for free!&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;bat&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS (&lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;): &lt;code&gt;brew install bat&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;bench&lt;/code&gt;, for benchmarking your code
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;bench&lt;/code&gt; (&lt;a href="https://github.com/Gabriel439/bench" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) is an incredibly useful tool for benchmarking your code. It's written in Haskell, which makes it the coolest thing on this page. You can pass any command you can run from your terminal to it (in quotes), and it will measure the execution time by repeatedly running the command. When it's finished, it'll output useful statistics to your terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvd9iqp1012k6om51h99b.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvd9iqp1012k6om51h99b.gif" alt="bench"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a considerably more powerful means of measuring the execution time of your code than the built-in &lt;code&gt;time&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hyperfine&lt;/code&gt; (&lt;a href="https://github.com/sharkdp/hyperfine" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) is an alternative to &lt;code&gt;bench&lt;/code&gt; written in Rust that you might also be interested in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;bench&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS using &lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;: &lt;code&gt;brew install bench&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;asciinema&lt;/code&gt; &amp;amp; &lt;code&gt;svg-term&lt;/code&gt;, for recording your terminal as an SVG animation
&lt;/h2&gt;

&lt;p&gt;The terminal clips on the version of &lt;a href="https://darrenburns.net/posts/tools" rel="noopener noreferrer"&gt;this post on my personal blog&lt;/a&gt; are SVG animations (unfortunately dev.to doesn't support SVG uploads)! You'll notice they're much crisper than the gifs on this page. Using SVG rather than a video format or gif has several huge benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perfect quality regardless of zoom 🔍&lt;/li&gt;
&lt;li&gt;We can put them in Markdown files like any other image 😱&lt;/li&gt;
&lt;li&gt;Smaller file sizes compared to video formats and gifs 🧐&lt;/li&gt;
&lt;li&gt;SVG animations are &lt;em&gt;way&lt;/em&gt; cooler than videos 🔥&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To record the terminal, I use &lt;a href="https://asciinema.org" rel="noopener noreferrer"&gt;&lt;code&gt;asciinema&lt;/code&gt;&lt;/a&gt;. Begin recording with &lt;code&gt;asciinema rec&lt;/code&gt;. When you're finished, press &lt;code&gt;Ctrl+D&lt;/code&gt;, and you'll be given the options of either saving the recording locally or uploading it to &lt;a href="https://asciinema.org" rel="noopener noreferrer"&gt;asciinema.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1a83p0nleldkd6ug4uvy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1a83p0nleldkd6ug4uvy.gif" alt="asciinema_example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to generate an SVG animation from your recording using &lt;code&gt;svg-term&lt;/code&gt; (&lt;a href="https://github.com/marionebl/svg-term-cli" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;), and you uploaded your recording to asciinema, you'll have to make it public by visiting the resulting link.&lt;/p&gt;

&lt;p&gt;To convert the recording to an SVG animation, you can supply the ID of the cast (available on the asciinema page after making it public - the ID is in the URL), an output file, and numerous other optional arguments. For example, to save the terminal recording at &lt;a href="https://asciinema.org/a/219486" rel="noopener noreferrer"&gt;https://asciinema.org/a/219486&lt;/a&gt; to the SVG file you see in the example above, I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;svg-term --cast=219486 --out ~/somewhere/out.svg --padding 18 --height 8 --width 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, if you don't want to upload your recording to asciinema, you can supply a local cast file directly to &lt;code&gt;svg-term&lt;/code&gt; (thanks to Mario Nebl, the author of &lt;code&gt;svg-term&lt;/code&gt; for pointing this out to me):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asciinema rec cast.json
cat cast.json | svg-term-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing &lt;code&gt;asciinema&lt;/code&gt; &amp;amp; &lt;code&gt;svg-term&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Installing &lt;code&gt;asciinema&lt;/code&gt; on macOS: &lt;code&gt;brew install asciinema&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Installing &lt;code&gt;svg-term&lt;/code&gt; on macOS: &lt;code&gt;npm install -g svg-term-cli&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;wrk&lt;/code&gt;, for benchmarking your HTTP APIs
&lt;/h2&gt;

&lt;p&gt;This is a handy little tool for performance testing your API. To demonstrate, I've got a minimal Python HTTP API server with a single endpoint (&lt;code&gt;GET /hello&lt;/code&gt;) running on my local machine at port 8001. We can check how well the &lt;code&gt;/hello&lt;/code&gt; endpoint performs using &lt;code&gt;wrk&lt;/code&gt; (with 12 threads, 200 connections, for 5 seconds):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzwk2fopv1cgw27740j1a.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzwk2fopv1cgw27740j1a.gif" alt="wrk"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can tweak the number of threads, connections, and the duration of your test to check performance under different loads. It's not a replacement for performance testing tools such as Locust and JMeter, but it's lightweight and will suffice in many situations.&lt;/p&gt;

&lt;p&gt;Unfortunately, the command line interface for &lt;code&gt;wrk&lt;/code&gt; makes it somewhat awkward to perform POST requests. If you want to do that, you'll need to write a small Lua script and supply it to the command as an argument (there's more information in the docs).&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;wrk&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS using &lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;: &lt;code&gt;brew install wrk&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;exa&lt;/code&gt;, an alternative to &lt;code&gt;ls&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://the.exa.website" rel="noopener noreferrer"&gt;&lt;code&gt;exa&lt;/code&gt;&lt;/a&gt; is a modern replacement for &lt;code&gt;ls&lt;/code&gt; with colour-coded output that's a little easier on the eye, and a larger variety of options for controlling how output is presented.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3eseuz5vx6fc7294tboj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3eseuz5vx6fc7294tboj.gif" alt="Exa"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It supports features such as respecting your &lt;em&gt;.gitignore&lt;/em&gt; files via the &lt;code&gt;--git-ignore&lt;/code&gt; flag, and printing&lt;br&gt;
out a directory as a tree structure with the &lt;code&gt;-T&lt;/code&gt; flag (see above). It even shows the git status of files!&lt;/p&gt;
&lt;h3&gt;
  
  
  Installing &lt;code&gt;exa&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS using &lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;: &lt;code&gt;brew install exa&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;fd&lt;/code&gt;, for finding files &amp;amp; directories
&lt;/h2&gt;

&lt;p&gt;If you're looking for a file or directory, you'd usually use the &lt;code&gt;find&lt;/code&gt; command to perform a search based on a regular expression. &lt;code&gt;fd&lt;/code&gt; (&lt;a href="https://github.com/sharkdp/fd" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) is an alternative to &lt;code&gt;find&lt;/code&gt; written in Rust which offers a more convenient interface by using sensible defaults, and it's faster to boot!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fojytfn8zszkjw51r8x9x.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fojytfn8zszkjw51r8x9x.gif" alt="fd"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It'll respect your &lt;em&gt;.gitignore&lt;/em&gt; files, and it supports parallel command execution, which lets you execute a terminal command (in parallel) for every file or directory returned for a search. For example (from the &lt;code&gt;fd&lt;/code&gt; documentation), to find all .jpg files and convert them to .png files in parallel using the Unix &lt;code&gt;convert&lt;/code&gt; command, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fd -e jpg -x convert {} {.}.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing &lt;code&gt;fd&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS using &lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;: &lt;code&gt;brew install fd&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;rg&lt;/code&gt; (ripgrep), for finding strings in files
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;rg&lt;/code&gt; (&lt;a href="https://github.com/BurntSushi/ripgrep" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) is a (&lt;em&gt;much&lt;/em&gt;) faster alternative to &lt;code&gt;grep&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcmpd8gleajtbj2ycz96n.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcmpd8gleajtbj2ycz96n.gif" alt="rg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rg&lt;/code&gt; is written in Rust, and it powers the search functionality inside the VS Code text editor. It consistently outperforms similar tools in benchmarks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing ripgrep
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On macOS using &lt;a href="https://brew.sh" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;: &lt;code&gt;brew install ripgrep&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hopefully you found something useful in this post! If you’re interested in more content like this, follow me on &lt;a href="https://twitter.com/_darrenburns" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and on &lt;a href="https://dev.to/_darrenburns"&gt;DEV&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This post was originally published on my &lt;a href="https://darrenburns.net" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tips</category>
      <category>unix</category>
      <category>commandline</category>
    </item>
  </channel>
</rss>
