<?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>Forem: Thomas Hartmann</title>
    <description>The latest articles on Forem by Thomas Hartmann (@hartmann).</description>
    <link>https://forem.com/hartmann</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%2F146438%2F57e31c14-b4ed-41bf-9e75-f97503744caa.jpeg</url>
      <title>Forem: Thomas Hartmann</title>
      <link>https://forem.com/hartmann</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hartmann"/>
    <language>en</language>
    <item>
      <title>Review 2019, prepare for 2020</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Tue, 31 Dec 2019 13:34:54 +0000</pubDate>
      <link>https://forem.com/hartmann/review-2019-prepare-for-2020-1l37</link>
      <guid>https://forem.com/hartmann/review-2019-prepare-for-2020-1l37</guid>
      <description>&lt;p&gt;The year is coming to a close, and it's a great time to look back upon what we've achieved this past year and what we want to focus on in the coming year. Let's talk about a few key things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What things in the last year have been the most significant to you? What are you the most proud of?&lt;/li&gt;
&lt;li&gt;Going forward, what things do you want to focus on?&lt;/li&gt;
&lt;li&gt;And what do you &lt;strong&gt;not&lt;/strong&gt; want to learn? &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  My story
&lt;/h1&gt;

&lt;p&gt;In trying to keep this brief and digestible, here's the short format of my 2019/2020 story. If you want to know a bit more and see the specific &lt;em&gt;SMART&lt;/em&gt; goals that I've set for myself, check out my &lt;a href="https://thomashartmann.dev/blog/goodbye-2019-hello-2020/"&gt;blog post&lt;/a&gt; on the topic. &lt;/p&gt;

&lt;h2&gt;
  
  
  Most significant events of 2019
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Community&lt;/strong&gt;: 2019 was the year I really got involved with the software community and sharing knowledge. I gave talks and workshops at local meetups, I became a co-organizer of the local Rust meetup group, and I started blogging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nix(OS)&lt;/strong&gt;: I switched to Linux (specifically NixOS) about a year ago, and it's been a blast. A lot of crawling the internet and irc logs, a lot of learning to use irc, a lot of time spent tinkering, but a blast. Everyone's been so friendly and welcoming and I have learned a whole lot. I've also started to rely on Nix for my dev environments at work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containers&lt;/strong&gt;: Before 2019, I'd never used containers, but I was aware of them. 2019 saw me working with Docker and Kubernetes on a daily basis, and it's been fantastic. In particular, Kubernetes has become a great interest of mine, and something I'm looking to pursue further.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Goals for 2020
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;More community engagement&lt;/strong&gt;: I want to further work on the community-aspects in the coming year: talk more, share more, meet more. In particular, by the end of the year I want to have:

&lt;ul&gt;
&lt;li&gt;Given at least three (3) talks/workshops at local meetups.&lt;/li&gt;
&lt;li&gt;Applied to at least three (3) conferences as a speaker.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More &lt;em&gt;konfiguration&lt;/em&gt;&lt;/strong&gt;: A big part of 2019 was configuration, either as part of Kubernetes or as part of Nix. I'm really into both these tools, but I don't feel that I have mastered them completely just yet. To improve this situation, I want to set up a Kubernetes cluster somewhere and deploy an application developed using Nix for as much as possible. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More Emacs&lt;/strong&gt;: Another tool that I really enjoy, but that I don't know quite well enough. I've been using Emacs for about a year and a half, and I love it. However, I've never really used raw (or custom configured) Emacs; only a version of Spacemacs. Spacemacs is great, but I feel like I need a better understanding of the underlying editor to really become one with Emacs. First step: RTFM.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;.ignore&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;There's so many cool ideas and concepts around these days, you cannot possibly master them all. If you don't purposefully shut certain things out, it's easy to get overwhelmed. Here's a little list of things that I'm &lt;em&gt;not&lt;/em&gt; planning to look into in the coming year:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Machine Learning / Artificial Intelligence&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IoT / Home automation&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Your turn
&lt;/h1&gt;

&lt;p&gt;So what about you? Got anything to share? Comments? Let's talk it out.&lt;/p&gt;




&lt;p&gt;Happy new year, folks! Hope you achieve everything you set out to do, and if you don't: I hope that you at least learn and grow from it!&lt;/p&gt;

</description>
      <category>yearinreview</category>
      <category>discuss</category>
      <category>goals</category>
    </item>
    <item>
      <title>Async Rust: a gentle introduction</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Mon, 18 Nov 2019 08:21:10 +0000</pubDate>
      <link>https://forem.com/hartmann/async-rust-a-gentle-introduction-93d</link>
      <guid>https://forem.com/hartmann/async-rust-a-gentle-introduction-93d</guid>
      <description>&lt;p&gt;Hot off the heels of RustFest Barcelona and the stabilization of &lt;code&gt;async/.await&lt;/code&gt;, I think it’s safe to say that one of Rust’s most anticipated language features has finally landed. And for that occasion (and because I’ve had some trouble understanding certain bits of it myself), I wanted to write a little introduction to asynchronous programming in Rust. We’ll be creating a super simple application that fetches some data from the internet using the our newfound &lt;code&gt;async&lt;/code&gt; abilities. The stabilization of &lt;code&gt;async/.await&lt;/code&gt; also coincides nicely with another event I’m excited about: This week saw the release of the most recent entries in the mainline Pokémon games, &lt;a href="https://bulbapedia.bulbagarden.net/wiki/Pok%25C3%25A9mon_Sword_and_Shield"&gt;Pokémon Sword and Shield&lt;/a&gt;, and because I’m a bit too busy to pick them up just yet, I’ll make do by fetching data from the &lt;a href="https://pokeapi.co/"&gt;PokéAPI&lt;/a&gt; for now.&lt;/p&gt;

&lt;p&gt;I’m assuming some base knowledge of Rust’s syntax and ecosystem, but I hope that this is pretty accessible even to people very new to the community.&lt;/p&gt;

&lt;p&gt;But before diving into the coding part, let’s cover some basic concepts of asynchronous programming and how it might be a bit different in Rust than what you’d expect.&lt;/p&gt;

&lt;h2 id="what-does-async-mean"&gt;What does &lt;code&gt;async&lt;/code&gt; mean?&lt;/h2&gt;

&lt;p&gt;In Rust, when we talk about &lt;code&gt;async&lt;/code&gt;, we’re talking about running code concurrently, or having multiple overlapping (in time) computations run on a single thread. Multithreading is a related, but distinct concept. Multithreading is ideal for when you’ve got computationally intensive tasks (so-called &lt;em&gt;CPU-bound&lt;/em&gt; tasks) that can be spread across multiple, separated cores. Concurrent programming is better suited for when the task spends a lot of time waiting, such as for a response from a server. These tasks are called &lt;em&gt;IO-bound&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So asynchronous programming lets us run multiple of these IO-bound computations at the same time on a single thread. They can run at the same time because when they’re waiting for a response, they’re just idle, so we can let the computer keep working on something that isn’t waiting. When we reach a point where we need the result of an asynchronous computation, we must &lt;code&gt;.await&lt;/code&gt; it. In Rust, values that are ‘awaitable’ are known as ‘futures’.&lt;/p&gt;

&lt;h2 id="rusty-weirdness"&gt;Rusty weirdness&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;async&lt;/code&gt; in Rust may be a bit different from what you’re used to in other languages. Having done asynchronous coding mostly in JavaScript and C#, it certainly was to me. Here’s a few key things to understand:&lt;/p&gt;

&lt;h3 id="an-async-function-does-not-necessarily-start-executing-immediately"&gt;An &lt;code&gt;async&lt;/code&gt; function does not (necessarily) start executing immediately&lt;/h3&gt;

&lt;p&gt;To start an asynchronous function, you must either &lt;code&gt;.await&lt;/code&gt; it or launch a task using an &lt;em&gt;executor&lt;/em&gt; (we’ll get to that in a moment). Until this happens, all you have is a &lt;code&gt;Future&lt;/code&gt; that has not started. Let’s look at an example to make it clearer:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;async_std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c"&gt;// ^ we need this for task spawning&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;negate_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Negating {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;task&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_secs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="py"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Finished sleeping for {}!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&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="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;neg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;negate_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c"&gt;// ... nothing happens yet&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;neg_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;task&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;negate_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="c"&gt;// ^ this task /is/ started&lt;/span&gt;
    &lt;span class="nn"&gt;task&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_secs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="py"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c"&gt;// we sleep for effect.&lt;/span&gt;

    &lt;span class="n"&gt;neg&lt;/span&gt;&lt;span class="py"&gt;.await&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;neg_task&lt;/span&gt;&lt;span class="py"&gt;.await&lt;/span&gt;
    &lt;span class="c"&gt;// ^ this starts the first task `neg`&lt;/span&gt;
    &lt;span class="c"&gt;// and waits for both tasks to finish&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So in the above little code snippet, here’s what’s going on.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first line imports &lt;code&gt;async_std::task&lt;/code&gt;. There’s more on this below, but we need an external library to run futures as the standard library does not come with an &lt;em&gt;executor&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The async function &lt;code&gt;negate_async&lt;/code&gt; takes as input a signed integer, sleeps for 5 seconds, and returns the negated version of that integer.&lt;/li&gt;
&lt;li&gt;The async function &lt;code&gt;f&lt;/code&gt; is more interesting:
&lt;ul&gt;
&lt;li&gt;The first line (&lt;code&gt;let neg ...&lt;/code&gt;) creates a &lt;code&gt;Future&lt;/code&gt; of the &lt;code&gt;negate_async&lt;/code&gt; function and assigns it to the &lt;code&gt;neg&lt;/code&gt; variable. &lt;strong&gt;Importantly, it does &lt;em&gt;not&lt;/em&gt; start executing yet.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The next line of code (&lt;code&gt;let neg_task ...&lt;/code&gt;) uses the &lt;code&gt;task::spawn&lt;/code&gt; function to &lt;strong&gt;start executing&lt;/strong&gt; the &lt;code&gt;Future&lt;/code&gt; returned by &lt;code&gt;negate_async&lt;/code&gt;. Like with &lt;code&gt;neg&lt;/code&gt;, the &lt;code&gt;Future&lt;/code&gt; returned by &lt;code&gt;negate_async&lt;/code&gt; is assigned to the &lt;code&gt;neg_task&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;Next: we sleep for a second. This is so that it will be obvious from the output when a task starts running.&lt;/li&gt;
&lt;li&gt;Finally, we await both futures, add them together, and return them. By awaiting &lt;code&gt;neg&lt;/code&gt;, we start executing the &lt;code&gt;Future&lt;/code&gt; and run it to completion. Since &lt;code&gt;neg_task&lt;/code&gt; has already been started, we just wait for it to finish.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So what’s the result of this, then?&lt;/p&gt;



&lt;pre class="highlight shell"&gt;&lt;code&gt;Negating 2
&lt;span class="c"&gt;# &amp;lt;- there's a 1 second pause here&lt;/span&gt;
Negating 1
Finished sleeping &lt;span class="k"&gt;for &lt;/span&gt;2!
Finished sleeping &lt;span class="k"&gt;for &lt;/span&gt;1!
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;As we can see, the second future, &lt;code&gt;neg_task&lt;/code&gt;, started executing as soon as it was called—thanks to &lt;code&gt;task::spawn&lt;/code&gt;—while &lt;code&gt;neg&lt;/code&gt; did not start executing until it was awaited.&lt;/p&gt;




&lt;/li&gt;

&lt;/ul&gt;

&lt;h3 id="you-need-an-external-library-to-use-async.await"&gt;You need an external library to use &lt;code&gt;async/.await&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;As was briefly alluded to above, you need to reach for an external library to do asynchronous programming in Rust. This took me a while to understand, as I’m used to it being part of the language experience. In Rust, however, &lt;strong&gt;you need a dedicated &lt;em&gt;executor&lt;/em&gt;&lt;/strong&gt;&lt;sup&gt;1&lt;/sup&gt;. The executor is what takes care of &lt;em&gt;executing&lt;/em&gt; the futures, polling them and returning the results when they’re done. The standard library does not come with an executor, so we need to reach out to an external crate for this. There are a few ones to choose from, but the two most prominent ones are &lt;a href="https://async.rs/"&gt;&lt;code&gt;async-std&lt;/code&gt;&lt;/a&gt; (which we’re using here) and &lt;a href="https://tokio.rs/"&gt;&lt;code&gt;tokio&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="a-minimal-async-example"&gt;A minimal async example!&lt;/h2&gt;

&lt;p&gt;Alright, let’s get practical. This is the reason that I’m writing this post. As mentioned at the start, we’ll be creating a super simple application that fetches some Pokémon data and prints it to the console. For preparation, make sure you’ve got at least version 1.39 of Rust and cargo available.&lt;/p&gt;

&lt;h3 id="step-1-creating-the-application"&gt;Step 1: creating the application&lt;/h3&gt;

&lt;p&gt;Let’s create a new application! Simply run this command in your preferred directory:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo new async-basics
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3 id="step-2-dependencies"&gt;Step 2: Dependencies&lt;/h3&gt;

&lt;p&gt;We’re going to be using &lt;a href="https://crates.io/crates/async-std"&gt;&lt;code&gt;async-std&lt;/code&gt;&lt;/a&gt; for spawning tasks, and &lt;a href="https://crates.io/crates/surf"&gt;&lt;code&gt;surf&lt;/code&gt;&lt;/a&gt; to fetch data from the API. Let’s add them to the Cargo.toml file. Your whole file should look something like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[package]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"async-basics"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Your Name &amp;lt;your.email@provider.tld&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;edition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2018"&lt;/span&gt;

&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;async-std&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;
&lt;span class="py"&gt;surf&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Nice! This is going swimmingly!&lt;/p&gt;

&lt;h3 id="step-3-fetch-data"&gt;Step 3: Fetch data&lt;/h3&gt;

&lt;p&gt;Okay, final step. Let’s modify the &lt;code&gt;main.rs&lt;/code&gt; file. We’ll make it as simple as possible. Here’s what we want to use:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;async_std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;surf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;// fetch data from a url and return the results as a string.&lt;/span&gt;
&lt;span class="c"&gt;// if an error occurs, return the error.&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;surf&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;surf&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.recv_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// execute the fetch function and print the results&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://pokeapi.co/api/v2/move/surf"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fetched results: {:#?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Got an error: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;task&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;block_on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="c"&gt;// ^ start the future and wait for it to finish&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That’s all the code you need. In fact, it’s &lt;em&gt;more&lt;/em&gt; than what you need, as some parts have been broken up for legibility. Let’s walk through it!&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;
&lt;code&gt;use&lt;/code&gt; statements&lt;/dt&gt;
&lt;dd&gt;Nothing exciting here. Just importing the crates we declared in the Cargo.toml file: &lt;code&gt;surf&lt;/code&gt; and &lt;code&gt;async_std&lt;/code&gt;.
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;This is simply a thin wrapper around the &lt;code&gt;surf::get&lt;/code&gt; function which returns either the payload as a &lt;code&gt;String&lt;/code&gt; or an &lt;code&gt;Exception&lt;/code&gt; if something went wrong.
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;execute&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;This function calls fetch with the endpoint for the move &lt;code&gt;Surf&lt;/code&gt;, waits for the result to return, and then matches on the result. If everything went well: print the output. Else: print the error.
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;main&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;
&lt;code&gt;main&lt;/code&gt; simply kicks off &lt;code&gt;execute&lt;/code&gt; and waits for it to finish. &lt;code&gt;task::block_on&lt;/code&gt; is a synchronous counterpart to &lt;code&gt;task::spawn&lt;/code&gt; that starts an asynchronous operation, but blocks until it has finished. Because the &lt;code&gt;main&lt;/code&gt; function can’t itself be &lt;code&gt;async&lt;/code&gt; (at least not at the time of writing), we can’t use &lt;code&gt;.await&lt;/code&gt; in it, but we &lt;em&gt;can&lt;/em&gt; block on asynchronous operations.
&lt;/dd&gt;
&lt;/dl&gt;

&lt;h3 id="step-4-extend-it"&gt;Step 4: Extend it!&lt;/h3&gt;

&lt;p&gt;Hey, you made it this far; congrats! That’s all I really have in store for you for this one, but if you want to play around a bit more, how about adding &lt;a href="https://crates.io/crates/serde"&gt;&lt;code&gt;serde&lt;/code&gt;&lt;/a&gt; and try using &lt;code&gt;surf&lt;/code&gt;’s &lt;code&gt;recv_json&amp;lt;T&amp;gt;&lt;/code&gt; instead? If you’d rather keep looking at &lt;code&gt;async/.await&lt;/code&gt;, how about performing multiple requests simultaneously? Or how about making a PokéAPI CLI? (&lt;em&gt;Ooh, that sounds like fun! Hit me up if you’re doing this; I want in!&lt;/em&gt;)&lt;/p&gt;

&lt;h2 id="parting-words-and-resources"&gt;Parting words and resources&lt;/h2&gt;

&lt;p&gt;So there you have it, dear reader. I hope you have found this useful. &lt;code&gt;async/.await&lt;/code&gt; is finally stabilized and it feels like we’ve taken a major leap forward. I’m very much looking forward to seeing what happens in the coming months and what the community makes of this.&lt;/p&gt;

&lt;p&gt;If you’re looking for more resources on async Rust, be sure to check out the &lt;a href="https://rust-lang.github.io/async-book/index.html"&gt;Async Book&lt;/a&gt;. I also recommend the &lt;a href="https://book.async.rs/"&gt;async-std book&lt;/a&gt; for some extra insights.&lt;/p&gt;

&lt;p&gt;Until next time: take care!&lt;/p&gt;

&lt;h2 id="footnotes"&gt;Footnotes&lt;/h2&gt;




&lt;ol&gt;
&lt;li id="fn1"&gt;&lt;p&gt;See &lt;a href="https://www.reddit.com/r/rust/comments/dsy6ax/announcing_rust_1390/f6st41v?utm_source=share&amp;amp;utm_medium=web2x"&gt;this insightful Reddit comment thread&lt;/a&gt; for more on this.↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>Git config management</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Mon, 16 Sep 2019 07:00:10 +0000</pubDate>
      <link>https://forem.com/hartmann/git-config-management-2jb2</link>
      <guid>https://forem.com/hartmann/git-config-management-2jb2</guid>
      <description>&lt;p&gt;We’ve been looking a lot at how to tweak git to your liking, which is usually done through your git config file. Sometimes, though, you’ll find that the configuration isn’t working as you wanted, so I thought it’d be a good idea to look at how you can inspect, unset, and list configuration values from the command line.&lt;/p&gt;

&lt;p&gt;Before we dive in, let’s have a few words about how your git config files work. Your config files use a specific format which, according to the &lt;a href="https://git-scm.com/docs/git-config#_configuration_file"&gt;docs&lt;/a&gt;, “consists of sections and variables. A section begins with the name of the section in square brackets and continues until the next section begins.” That’s enough for what we need right now, but go read up if you’re interested.&lt;/p&gt;

&lt;p&gt;Furthermore, git config files ‘cascade’, and git, by default, searches four locations on your system, where later entries override earlier ones:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;/etc/gitconfig&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;The system wide config
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;$XDG_CONFIG_HOME/git/config&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;Falls back to &lt;code&gt;$HOME/.config/git/config&lt;/code&gt; if &lt;code&gt;$XDG_CONFIG_HOME&lt;/code&gt; is not set or empty.
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;~/.gitconfig&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;Your user-specific, ‘global’ config file
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;$GIT_DIR/config&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;Repo-specific config file
&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Again, see &lt;a href="https://git-scm.com/docs/git-config#FILES"&gt;the specific section of the documentation&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;One last thing: All setting and unsetting of values apply only to your user configurations, and they are local—repo-specific—by default. To make them apply to your global config, pass the &lt;code&gt;--global&lt;/code&gt; flag.&lt;/p&gt;

&lt;h2 id="setting-values"&gt;Setting values&lt;/h2&gt;

&lt;p&gt;To set a value, simply run a command on the form&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# default (local)&lt;/span&gt;
git config &amp;lt;section&amp;gt;.&amp;lt;key&amp;gt; &amp;lt;value&amp;gt;
&lt;span class="c"&gt;# global&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; &amp;lt;section&amp;gt;.&amp;lt;key&amp;gt; &amp;lt;value&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For instance, to change the value of the &lt;code&gt;commentChar&lt;/code&gt; entry of the &lt;code&gt;core&lt;/code&gt; section to &lt;code&gt;;&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git config core.commentChar &lt;span class="s1"&gt;';'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2 id="unsetting-values"&gt;Unsetting values&lt;/h2&gt;

&lt;p&gt;Similarly, if you want to unset a value, use the &lt;code&gt;--unset&lt;/code&gt; flag:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--unset&lt;/span&gt; &amp;lt;section&amp;gt;.&amp;lt;key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So if you have overridden the &lt;code&gt;core.commentChar&lt;/code&gt; value, this is the command to undo that and reset it to the default value, &lt;code&gt;#&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--unset&lt;/span&gt; core.commentChar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2 id="inspecting-config-values"&gt;Inspecting config values&lt;/h2&gt;

&lt;p&gt;Sometimes, you want to know what a value has been set to. For this, pass the &lt;code&gt;--get&lt;/code&gt; flag and the section and key of the value you want to look up:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--get&lt;/span&gt; &amp;lt;section&amp;gt;.&amp;lt;key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So if you’re wondering what your user’s name is, for instance:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--get&lt;/span&gt; user.name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A few things to note about getting the values&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;Git will show you the last value it finds in the chain&lt;/dt&gt;
&lt;dd&gt;So if you set your username in your global config, but set a different one in a repo and invoke this command from the repo, it would show you only the repo-specific one.
&lt;/dd&gt;
&lt;dt&gt;The output will be empty if you have not explicitly set the value&lt;/dt&gt;
&lt;dd&gt;In other words, if it’s not in your config files, git won’t show it to you. So if you’re looking to inspect git’s default values, that’s not going to work.
&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id="finding-the-config-value-sources"&gt;Finding the config value sources&lt;/h2&gt;

&lt;p&gt;Sometimes you just want to inspect what values you’re setting in your config. You can do this by passing the &lt;code&gt;--list&lt;/code&gt; flag:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By default, this will just throw all your configuration at you, which isn’t all that helpful. However, it takes a pretty handy flag, &lt;code&gt;--show-origin&lt;/code&gt;, which lists your configuration in two columns, with the first one being the file in which it was set and the second being the the key-value pairs.&lt;/p&gt;

&lt;p&gt;If you ever find that some value isn’t taking effect the way you expect, this is a great way to check what values are getting set in what locations:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="nt"&gt;--show-origin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For instance, if you’ve changed your global user name, but it’s not taking effect in the current repo, you could pipe it into &lt;code&gt;grep&lt;/code&gt; and look for duplicates:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="nt"&gt;--show-origin&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"user.name="&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>git</category>
      <category>workflow</category>
    </item>
    <item>
      <title>Commit message templates</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Mon, 09 Sep 2019 03:53:29 +0000</pubDate>
      <link>https://forem.com/hartmann/commit-message-templates-2ek0</link>
      <guid>https://forem.com/hartmann/commit-message-templates-2ek0</guid>
      <description>&lt;p&gt;Here’s a statement for ya: if you’re working on a project with someone else, you &lt;em&gt;should&lt;/em&gt; be using a commit message template. Not only will it help increase the consistency and usefulness of your messages, but also, and perhaps more importantly, it will reduce the cognitive load required to write a message and the time it takes to write it. I can only speak for myself, but I know that having to go look up information about how a commit message should be structured and what it references causes some much unneeded context switching, resulting in a less efficient workflow.&lt;/p&gt;

&lt;h2 id="setup"&gt;Setup&lt;/h2&gt;

&lt;p&gt;Setting up commit message templates requires only a few steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a template.&lt;/p&gt;
&lt;p&gt;You can use any text file as a template; just put what you want to show up in the commit message buffer in there. Plain lines of text will show up as content, while lines starting with the comment character (&lt;code&gt;#&lt;/code&gt; by default) show up as comments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add it to the git config as a commit template: &lt;code&gt;git config commit.template path/to/file&lt;/code&gt;.&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Done! Now try committing something.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;When doing this, you’re assigning the template locally (to the current repo). If you’d rather do it globally, pass the &lt;code&gt;--global&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;If you want to share the template across multiple projects in a certain subdirectory, you can do that by combining the template with git’s functionality for conditional includes. Be aware, however, that given a relative path to a file, git will look for the file relative to the including configuration’s location. While this can potentially be exploited to use different templates for different projects, I’ve not found the need for it thus far, and have stuck with a single template with an absolute path.&lt;/p&gt;

&lt;p&gt;If you want to unset the template, use the &lt;code&gt;git config --unset&lt;/code&gt; functionality:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--unset&lt;/span&gt; commit.template
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2 id="commit-template-ideas"&gt;Commit template ideas&lt;/h2&gt;

&lt;p&gt;Different teams and projects have different needs when it comes to commit messages, so there’s no ‘one size fits all’, but here’s a few ideas based on message formats in teams I’ve been a part of.&lt;/p&gt;

&lt;h3 id="label-listing"&gt;Label listing&lt;/h3&gt;

&lt;p&gt;If you label your commits with the type of work they contain to and have a defined set of labels (e.g. ‘feature’, ‘bug’, ‘chore’, ‘refactor’, etc.), it might be a good idea to list all the different options in the template, so that you can look through them whenever you’re committing some code. List them using commented lines and you don’t even have to delete them; they’ll just show up as extra info in the commit buffer.&lt;/p&gt;

&lt;p&gt;While experienced members of the team are likely to know these by heart, it’s very helpful for a new person to have the list right there in the commit buffer so that they don’t have to go look them up.&lt;/p&gt;

&lt;h3 id="issue-identification"&gt;Issue identification&lt;/h3&gt;

&lt;p&gt;If the standard says to have an issue/ticket ID listed in the commit message, you could put a little placeholder in the template that tells you to replace it with the relevant ID.&lt;/p&gt;

&lt;p&gt;If you also work with feature branches and name them according to the feature/issue ID that they correspond to, you could even have git fill in this issue number automatically by using hooks, as explained in my previous post. I have found this to save me a surprisingly large amount of time and mental overhead.&lt;/p&gt;

&lt;h3 id="very-specific-formats"&gt;Very specific formats&lt;/h3&gt;

&lt;p&gt;For when your message needs to match a very specific format and it’s hard to remember exactly what goes where, templates are a perfect solution.&lt;/p&gt;

&lt;p&gt;For instance, if you’re working with a combination of the above two, where you want both the label &lt;em&gt;and&lt;/em&gt; the ID, and you want them in a specific order, maybe even with a specific separator (&lt;em&gt;seems like a hassle, but just roll with it&lt;/em&gt;), you could create a template that you could just fill in with the relevant parts, saving you having to look up what the format is every time.&lt;/p&gt;

</description>
      <category>git</category>
      <category>workflow</category>
    </item>
    <item>
      <title>Rebasing off a repo root</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Mon, 02 Sep 2019 07:52:55 +0000</pubDate>
      <link>https://forem.com/hartmann/rebasing-off-a-repo-root-4h7a</link>
      <guid>https://forem.com/hartmann/rebasing-off-a-repo-root-4h7a</guid>
      <description>&lt;p&gt;Ever had to change something about all the commits in a git repo before pushing it to a remote? As in from the &lt;em&gt;very first&lt;/em&gt; commit in a repo? Maybe you’ve started a repo locally and when you’re ready to push it, you realize that you’ve used the wrong author or messed up the format of the commit messages; or maybe you just want to squash those first few commits into a single concise package.&lt;/p&gt;

&lt;p&gt;In these situations, my first response is to do to an interactive rebase (&lt;code&gt;git rebase -i&lt;/code&gt;). Usually when I’m rebasing, though, I’m in a project that has an upstream and where I’m rebasing off a specific commit or branch. For situations where you don’t have a commit to rebase off, but you want to rebase the &lt;em&gt;entire&lt;/em&gt; history or at least the &lt;em&gt;very first&lt;/em&gt; commit: What do you do?&lt;/p&gt;

&lt;p&gt;The answer, my friend, is that you pass the &lt;code&gt;--root&lt;/code&gt; option:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;--root&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That’ll let you pick, reword, edit, squash, fixup, exec, drop, label, reset, or merge &lt;em&gt;all&lt;/em&gt; of your commits from the ‘dawn of time.’&lt;/p&gt;

&lt;p&gt;Have fun!&lt;/p&gt;

</description>
      <category>git</category>
      <category>gitgud</category>
    </item>
    <item>
      <title>Automate your commit messages</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Mon, 26 Aug 2019 07:48:50 +0000</pubDate>
      <link>https://forem.com/hartmann/automate-your-commit-messages-3daj</link>
      <guid>https://forem.com/hartmann/automate-your-commit-messages-3daj</guid>
      <description>&lt;p&gt;Git has a lot of inbuilt functionality that you might not use all the time, but which is oh-so-handy when you need it. One such thing is &lt;em&gt;hooks&lt;/em&gt;. These can be used to do stuff like formatting your code before committing or running tests before pushing to the remote. Today, though, let’s look at how we can use it to automatically fill in part of your commit messsage.&lt;/p&gt;

&lt;h2 id="how-did-this-come-up"&gt;How did this come up?&lt;/h2&gt;

&lt;p&gt;The team I’m on at work uses a system for commit messages and branch names where they should both start with the issue id of whatever task we’re working on. Using GitLab, they end up looking something like &lt;code&gt;#2 Adds sorting functionality to UI&lt;/code&gt; (&lt;em&gt;we can argue about commit message tenses later&lt;/em&gt;) and &lt;code&gt;#42/new-sorting-algorithm&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;p&gt;If you’re like me, your mind should be poking you right about now, saying that that’s a lot of duplication; surely we don’t need all of that? Well, you could argue that with feature branches scoped to issues and no fast-forward merges, the branch name should be enough, but it doesn’t really show up in condensed commit logs etc., so it’s nice to have the issue number available for when you need it.&lt;/p&gt;

&lt;p&gt;But not to worry; we can make the computer fill it in for us!&lt;/p&gt;

&lt;h2 id="picking-the-right-hook"&gt;Picking the right hook&lt;/h2&gt;

&lt;p&gt;Git has quite a few hooks available; if you check the &lt;code&gt;.git/hooks&lt;/code&gt; directory of a tracked project, you should find a bunch of files named &lt;code&gt;&amp;lt;hook name&amp;gt;.sample&lt;/code&gt;. Most of the hook names are fairly descriptive, but you could always &lt;a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks"&gt;look them up&lt;/a&gt; if you want to know more.&lt;/p&gt;

&lt;p&gt;In our case we’re interested in hooking into the system right before the commit message buffer appears on our screen, so we’re going to go with the &lt;code&gt;prepare-commit-msg&lt;/code&gt; hook.&lt;/p&gt;

&lt;h2 id="auto-filling-the-message"&gt;Auto-filling the message&lt;/h2&gt;

&lt;p&gt;Now, my team has a template we use for commits, which starts with &lt;code&gt;#[task number]&lt;/code&gt;. Using this knowledge, we can do some fancy shell magic and replace it with the task from the branch name.&lt;/p&gt;

&lt;p&gt;The whole script looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="nv"&gt;TASK_NO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--abbrev-ref&lt;/span&gt; HEAD | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'/'&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; 1&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# BSD sed (macOS)&lt;/span&gt;
&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"s/#&lt;/span&gt;&lt;span class="se"&gt;\[&lt;/span&gt;&lt;span class="s2"&gt;task number&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$TASK_NO&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# GNU sed (Linux)&lt;/span&gt;
&lt;span class="c"&gt;# sed -i -e "s/#\[task number\]/$TASK_NO/" "$1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Depending on whether you use BSD sed (macOS) or GNU sed (Linux), the &lt;code&gt;sed&lt;/code&gt; command will behave slightly differently. For GNU sed, use the commented out line instead of the first one.&lt;/p&gt;

&lt;p&gt;There is a slight difference in how you make the two versions of the programs write files in place.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;git rev-parse --abbrev-ref HEAD&lt;/code&gt; command gives you the name of the current branch, which we then split at the first &lt;code&gt;/&lt;/code&gt; character using &lt;code&gt;cut&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The next (and last) step is a simple &lt;code&gt;sed&lt;/code&gt; replacement, replacing the &lt;code&gt;#[task number]&lt;/code&gt; string with the branch’s task number.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;$1&lt;/code&gt; variable at the very end of the last line is the name of the commit message file and is something the script receives automatically. We use this to tell &lt;code&gt;sed&lt;/code&gt; what file to replace the text in.&lt;/p&gt;

&lt;p&gt;And for the curious, these are all the variables you get access to in the &lt;code&gt;pre-commit-msg&lt;/code&gt; hook (taken from the &lt;code&gt;pre-commit-msg.sample&lt;/code&gt; file):&lt;/p&gt;



&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="nv"&gt;COMMIT_MSG_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="nv"&gt;COMMIT_SOURCE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;
&lt;span class="nv"&gt;SHA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;h2 id="caveats"&gt;Caveats&lt;/h2&gt;

&lt;p&gt;There is a pretty significant exception to when this script does what you want it to: when you’re still on the master branch, where commit messages will start with the text &lt;code&gt;master&lt;/code&gt;. I considered adding a special case for this, but then realized that it’s actually quite helpful in that it helps me remember when I should branch off, so I decided to keep it for now.&lt;/p&gt;

&lt;p&gt;Another drawback is that because the commit message appears different from what git expects to find on disk (presumably), it will assume you put an actual message in and complete the commit. At least that’s what I found when using Vim. A simple workaround is deleting everything in the buffer (&lt;code&gt;dae&lt;/code&gt; if you use the awesome &lt;a href="https://github.com/kana/vim-textobj-entire"&gt;text-obj-entire&lt;/a&gt; plugin) before exiting. Most of the time, though, I use &lt;a href="https://magit.vc/"&gt;Magit&lt;/a&gt; with Emacs, where canceling the commit works as expected.&lt;/p&gt;

&lt;h2 id="alternate-approach"&gt;Alternate approach&lt;/h2&gt;

&lt;p&gt;While I have opted for modifying the commit message before it’s shown to the user, you could potentially also have the machine add the id automatically in the &lt;code&gt;pre-commit&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;You would make the system check the message for a pattern and amend the commit with the expected issue id if it’s not present.&lt;/p&gt;


&lt;p&gt;This solution doesn’t give you any way to verify whether it’s correct or not, though, so you’d probably want some sort of way to bypass it.&lt;/p&gt;

</description>
      <category>git</category>
      <category>workflow</category>
    </item>
    <item>
      <title>Change your git comment character</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Mon, 19 Aug 2019 06:21:57 +0000</pubDate>
      <link>https://forem.com/hartmann/change-your-git-comment-character-e9p</link>
      <guid>https://forem.com/hartmann/change-your-git-comment-character-e9p</guid>
      <description>&lt;p&gt;You prepare to commit your files, having made sure that all the right changes are in, that they belong to one logical change, and that you have the id of the task that they belong to. Your editor opens up and you see those familiar commit message instructions, but wait! You suddenly remember that you should start your commit with the id of the task prepended with a &lt;code&gt;#&lt;/code&gt; character, but that would lead git to think that that line is a comment.&lt;/p&gt;

&lt;p&gt;How do we solve this?&lt;/p&gt;

&lt;p&gt;Easy! We simply tell git not to use the &lt;code&gt;#&lt;/code&gt; character for comments, but pick a different character instead.&lt;/p&gt;

&lt;h2 id="in-short"&gt;In short&lt;/h2&gt;

&lt;p&gt;There’s two ways to do it, both producing the same result. You can either run a command from the command line or edit your git config directly. In this case, imagine we want to use a semicolon (&lt;code&gt;;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Command line:&lt;/p&gt;



&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--local&lt;/span&gt; core.commentChar &lt;span class="s1"&gt;';'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Directly modifying your git config file:&lt;/p&gt;



&lt;pre class="highlight conf"&gt;&lt;code&gt;[&lt;span class="n"&gt;core&lt;/span&gt;]
  &lt;span class="n"&gt;commentChar&lt;/span&gt; = &lt;span class="s2"&gt;";"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;h2 id="motivation"&gt;Motivation&lt;/h2&gt;

&lt;p&gt;So why might you want to do this? As mentioned in the introduction, maybe your team has a standard format for commit messages, where each commit should lead with the id of the task that the commit relates to.&lt;/p&gt;

&lt;p&gt;We use GitLab at work, where if you put a number after a &lt;code&gt;#&lt;/code&gt; in your commit message, it will create a link to the issue with that id, which also adds an entry to the history of said issue. In addition to this, if all commits are prefaced with the task id, it becomes very easy to find out what task a commit relates to when looking at the history.&lt;/p&gt;

&lt;h2 id="what-might-go-wrong"&gt;What might go wrong?&lt;/h2&gt;

&lt;p&gt;This is such a simple modification that there’s not much you need to be aware of, but if you try and use a comment character consisting of more than one character, git will fail when you try and invoke a command:&lt;/p&gt;



&lt;pre class="highlight shell"&gt;&lt;code&gt;error: core.commentChar should only be one character
fatal: bad config variable &lt;span class="s1"&gt;'core.commentchar'&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;file &lt;span class="s1"&gt;'.git/config'&lt;/span&gt; at line 6
&lt;/code&gt;&lt;/pre&gt;



&lt;h2 id="finishing-thoughts"&gt;Finishing thoughts&lt;/h2&gt;

&lt;p&gt;It’s a simple thing, but it’s one of those things that improves your life just that little bit. You can even combine it with the custom config we mentioned last time to have this apply to all repos in your work directory, new &lt;em&gt;and&lt;/em&gt; old.&lt;/p&gt;


&lt;p&gt;Now as a final thought, what should you pick as a comment character? It’s really up to what you need for your specific use case, but I find that &lt;code&gt;;&lt;/code&gt; is very rarely something that you’ll want to start your sentences with, so that’s my go-to.&lt;/p&gt;

</description>
      <category>git</category>
      <category>gitgud</category>
    </item>
    <item>
      <title>Modularizing your git config with conditional includes</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Mon, 12 Aug 2019 08:27:09 +0000</pubDate>
      <link>https://forem.com/hartmann/modularizing-your-git-config-with-conditional-includes-2mlm</link>
      <guid>https://forem.com/hartmann/modularizing-your-git-config-with-conditional-includes-2mlm</guid>
      <description>&lt;p&gt;Do you track your git config across machines or keep it in sync with your dotfiles? Is it full of settings that you want to share between all your different contexts? Are there certain things that you want to change depending on what the context is? Well, I’ve got news for you!&lt;/p&gt;

&lt;h2 id="tldr"&gt;tl;dr:&lt;/h2&gt;

&lt;p&gt;If you want to use an additional config file for all subdirectories below a certain path, use the &lt;code&gt;includeIf&lt;/code&gt; functionality that was introduced in git 2.13.0.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight conf"&gt;&lt;code&gt;[&lt;span class="n"&gt;includeIf&lt;/span&gt; &lt;span class="s2"&gt;"gitdir:/"&lt;/span&gt;]
  &lt;span class="n"&gt;path&lt;/span&gt; = &lt;span class="n"&gt;path&lt;/span&gt;/&lt;span class="n"&gt;to&lt;/span&gt;/&lt;span class="n"&gt;your&lt;/span&gt;/.&lt;span class="n"&gt;config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That’s all you need to get going, but if you want to know more about how this works and some caveats you might to be aware of, keep reading.&lt;/p&gt;

&lt;h2 id="include-and-includeif"&gt;
&lt;code&gt;include&lt;/code&gt; and &lt;code&gt;includeIf&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;First off, I’d be remiss not to direct you to the official documentation for this feature, which can be found &lt;a href="https://git-scm.com/docs/git-config#_conditional_includes"&gt;here&lt;/a&gt;. However, there’s loads more info there than you might need (and want), so let’s extract the important bits.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;include&lt;/code&gt; and &lt;code&gt;includeIf&lt;/code&gt; sections work the same, except the &lt;code&gt;includeIf&lt;/code&gt; has a condition that must be satisfied. They let you &lt;strong&gt;insert configuration from another file&lt;/strong&gt; into your main one.&lt;/p&gt;

&lt;p&gt;In my case, this meant that I could automatically change my email whenever the git directory was a subdirectory of &lt;code&gt;~/projects/work&lt;/code&gt;, allowing me a simple and efficient way to always use my work email for work, without changing my global git config or branching off from my main dotfiles repo.&lt;/p&gt;

&lt;p&gt;Here’s the relevant extract from my config:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight conf"&gt;&lt;code&gt;[&lt;span class="n"&gt;includeIf&lt;/span&gt; &lt;span class="s2"&gt;"gitdir:~/projects/work/"&lt;/span&gt;]
  &lt;span class="n"&gt;path&lt;/span&gt; = ~/&lt;span class="n"&gt;projects&lt;/span&gt;/&lt;span class="n"&gt;work&lt;/span&gt;/.&lt;span class="n"&gt;gitconfig&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I keep a separate config file in the &lt;code&gt;~/projects/work&lt;/code&gt; directory that overrides my email.&lt;/p&gt;

&lt;p&gt;This would also be useful if your team has specific rules about whitespace, merge strategies, comment characters, etc. that you want to enforce.&lt;/p&gt;

&lt;h2 id="things-that-might-trip-you-up"&gt;Things that might trip you up&lt;/h2&gt;

&lt;dl&gt;
&lt;dt&gt;Syntax&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Note the trailing slash after the directory path in the &lt;code&gt;includeIf&lt;/code&gt; line. This makes it so that it will match all subdirectories of the specified directory. As explained by the docs:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If the pattern ends with &lt;code&gt;/&lt;/code&gt;, &lt;code&gt; **&lt;/code&gt; will be automatically added. For example, the pattern &lt;code&gt;foo/&lt;/code&gt; becomes &lt;code&gt;foo/** &lt;/code&gt;. In other words, it matches “foo” and everything inside, recursively.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This also means that &lt;strong&gt;if there is no trailing slash, it’ll match only that specific directory&lt;/strong&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;File insertion&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Here’s another quote from the documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The contents of the included file are &lt;strong&gt;inserted immediately, as if they had been found at the location of the include directive&lt;/strong&gt;. If the value of the variable is a relative path, the path is considered to be relative to the configuration file in which the include directive was found.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So you’ll probably want to put the includes at the bottom of your files to make sure the included config isn’t overridden later on in the source file.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;




&lt;p&gt;I hope that cleared some things up for you and that you found it useful; I know I did. If you want more in-depth information, see &lt;a href="https://git-scm.com/docs/git-config#_conditional_includes"&gt;the documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>gitgud</category>
    </item>
    <item>
      <title>Emacs, VSCode, and me</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Mon, 01 Jul 2019 07:51:32 +0000</pubDate>
      <link>https://forem.com/hartmann/emacs-vscode-and-me-1hkc</link>
      <guid>https://forem.com/hartmann/emacs-vscode-and-me-1hkc</guid>
      <description>&lt;p&gt;It was about a year ago. My life was good. I had things in order (mostly). And most importantly: I had an editor I liked. VSCode and I had been going steady for about a year. With its excellent support for Python and JS—which was most of my work in those days—I rarely ever needed to venture into new territory. It felt good. I was happy.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I was happy!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then it all came crashing down. A good friend and I decided to hang out and program one Saturday. The sky was a clear blue, the temperature high, and summer was just around the corner. We got into his office, sat down, and started setting up. That’s when it happened. Completely out of left field:&lt;/p&gt;

&lt;p&gt;— &lt;em&gt;So I found this cool thing the other day. It’s called Spacemacs.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Spacemacs?&lt;/p&gt;

&lt;p&gt;— &lt;em&gt;Yeah, it’s Emacs, but with “evil mode”. So you can get your Vim bindings!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s true. I had been seduced into the deep, dark depths of Vim about a year prior, and had never found my way out. Never tried, really. I had let it consume me, and there was no way I’d let it go. Not for the world. Of course I had been using the VSCode Vim plugin, but while it had given me most of the functionality I wanted, I did sometimes find myself longing for something more. So I thought I ought to at least give this Spacemacs thing a go.&lt;/p&gt;

&lt;p&gt;With one eyebrow slightly cocked, I went ahead and downloaded Spacemacs. I had tried to run Emacs previously, but had been met with that sheer, white light that comes as the default, and had been unable to figure out how to even close the program without resorting to my mouse. Naturally, I was skeptical.&lt;/p&gt;

&lt;p&gt;So I launch it, resist the white light as I choose ‘evil mode’ and watch the window turn dark. The logo appears. It says it’s loading. Fetching packages. Eventually, the words “Spacemacs is ready” appear at the bottom of the window. I get it up and running and do some basic programming. I don’t know what it is, but something just feels … &lt;em&gt;good&lt;/em&gt;. I spend the rest of the day with Spacemacs, and when the time comes, I don’t want to let it go. I go home, dreaming of what I’ll do to it. VSCode is nowhere to be found.&lt;/p&gt;

&lt;p&gt;That weekend, neither Emacs nor I left my apartment. We were consumed in the fiery throes of passion and configuration, and when the sun rose the following Monday, I knew my heart had been turned.&lt;/p&gt;




&lt;p&gt;In truth, it would be another few weeks before I left VSCode completely and migrated to Emacs even at work, but it was coming. &lt;em&gt;Oh, it was coming&lt;/em&gt;. To this day, I still stay faithful to Emacs for most of my endeavors, only venturing out when there is something I can’t find proper support for (and even then, it’s just a matter of time before I take matters into my own hands!).&lt;/p&gt;

&lt;h2 id="what-i-love-about-it"&gt;What I love about it&lt;/h2&gt;

&lt;dl&gt;
&lt;dt&gt;The extensibility&lt;/dt&gt;
&lt;dd&gt;The fact that you can make it do pretty much &lt;em&gt;whatever&lt;/em&gt; you want to is nothing short of amazing. I have never seen an editor this powerful and versatile.
&lt;/dd&gt;
&lt;dt&gt;It’s the ‘self-documenting editor’&lt;/dt&gt;
&lt;dd&gt;Everything in Emacs is documented. You ever wonder what a key does? &lt;code&gt;C-h k &amp;lt;key (or combination)&amp;gt;&lt;/code&gt; has got you covered. You wonder what the value of a variable is? &lt;code&gt;C-h v &amp;lt;variable name&amp;gt;&lt;/code&gt;. Want help with Emacs? &lt;code&gt;C-h C-h&lt;/code&gt;. &lt;em&gt;Boom.&lt;/em&gt;
&lt;/dd&gt;
&lt;dt&gt;EXWM&lt;/dt&gt;
&lt;dd&gt;The Emacs X Window Manager. Just recently, I finally got it set up to the point where Emacs now manages all of my windows (yes, for &lt;em&gt;all&lt;/em&gt; applications) for me. How many other editors can do that? Your move, &lt;em&gt;’Code&lt;/em&gt;.
&lt;/dd&gt;
&lt;dt&gt;Emacs Lisp&lt;/dt&gt;
&lt;dd&gt;I think Lisp is a pretty cool guy. He lets you configure emacs down to the bone. Much like the &lt;em&gt;monarch of beef patties&lt;/em&gt;, he let’s you ‘have it your way’, and honestly, that’s the way I like it.
&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id="what-im-not-crazy-about"&gt;What I’m not crazy about&lt;/h2&gt;

&lt;dl&gt;
&lt;dt&gt;Its single threaded nature&lt;/dt&gt;
&lt;dd&gt;This is usually not much of an issue, unless you somehow end up freezing the main thread, which can happen. In that case, best restart your editor.
&lt;/dd&gt;
&lt;dt&gt;Lacklustre support for certain languages&lt;/dt&gt;
&lt;dd&gt;While most languages I use are very well supported in Emacs, I struggle with others. In particular, Microsoft’s .NET languages have been hard to get set up properly.
&lt;/dd&gt;
&lt;dt&gt;Emacs Lisp&lt;/dt&gt;
&lt;dd&gt;Yeah, it’s back. Mostly because I don’t really know Lisp yet (relax; it’s on my todo list). Until you’re comfortable with it, it makes changing your config just that little bit trickier.
&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id="what-i-miss-from-the-vscode-days"&gt;What I miss from the VSCode days&lt;/h2&gt;

&lt;p&gt;So it’s not &lt;em&gt;all&lt;/em&gt; roses. There are some things I miss from VSCode.&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;The ease of use&lt;/dt&gt;
&lt;dd&gt;I can’t really that the learning curve is steeper; getting started with VSCode is just &lt;em&gt;so&lt;/em&gt; easy. Also, installing extensions is a piece of cake.
&lt;/dd&gt;
&lt;dt&gt;The massive amount of plugins&lt;/dt&gt;
&lt;dd&gt;Not that Emacs doesn’t have packages, but most communities I see seem to have settled on VSCode as their darling, so that’s just where you’re going to see the most activity and up-to-date plugins in a lot of languages.
&lt;/dd&gt;
&lt;dt&gt;The amount of documentation&lt;/dt&gt;
&lt;dd&gt;I mentioned that Emacs is self-documenting. This is great. But it’s also … over 40 years old (1976?! &lt;em&gt;Gee!&lt;/em&gt;)! So finding documentation online is tricky in comparison.
&lt;/dd&gt;
&lt;dt&gt;The community&lt;/dt&gt;
&lt;dd&gt;Everybody loves &lt;del&gt;Raymond&lt;/del&gt; VSCode. That’s great and makes it super easy to find articles on how to set it up and configure it and so on. Need help? Ask &lt;em&gt;anyone&lt;/em&gt;. Chances are they’re using VSCode. The Emacs community is great too, but much, &lt;em&gt;much&lt;/em&gt; smaller.
&lt;/dd&gt;
&lt;/dl&gt;




&lt;p&gt;In the end, do I regret it? Not for a second. I think it’s a worthwhile tradeoff if you can take the initial learning curve and are willing to put some time into your editor. So if you feel inspired, should &lt;em&gt;you&lt;/em&gt; do it? All I can say is that if you pay the upfront cost, Emacs will return it tenfold.&lt;/p&gt;
    



</description>
      <category>emacs</category>
      <category>vscode</category>
    </item>
    <item>
      <title>QWERTY to Dvorak</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Mon, 24 Jun 2019 05:55:24 +0000</pubDate>
      <link>https://forem.com/hartmann/qwerty-to-dvorak-1l1o</link>
      <guid>https://forem.com/hartmann/qwerty-to-dvorak-1l1o</guid>
      <description>&lt;p&gt;Ever thought about changing up your keyboard layout? Maybe something as small as going from an ISO layout to an ANSI one (hint: tall and thin to short and fat return key), or from Norwegian (or whichever your language of choice is) to American QWERTY? Maybe something more comprehensive, like learning a whole new layout, such as Dvorak, Colemak, or Workman? Well, I’ve done all of the above, and while the smaller changes can offer some pretty significant benefits, they’re pretty easy to get through. The layout-changes are more interesting. I’d like to talk briefly about how I went from QWERTY to Dvorak and what I learned along the way.&lt;/p&gt;




&lt;p&gt;First off: you might wonder why I’d do that. I’d love to tell you that I had some grand epiphany and suddenly realized that the QWERTY life wasn’t worth living or that I discovered that Mr Dvorak himself was actually my great-great-grandfather; but nah, it was actually just an offhand comment someone made.&lt;/p&gt;

&lt;p&gt;See, I had just recently started learning Vim and was talking about it with some fellow students when one of them jokingly suggested I do it in Dvorak instead. As if it wasn’t challenging enough already, right? I laughed it off at first, but it sparked something in me. Thirty minutes and some googling later and I had made my mind up. I didn’t know whether I was gonna make the switch, but I knew I had to check it out to see what all the fuss was about.&lt;/p&gt;

&lt;p&gt;Before starting my degree in computer science (about two years prior to that fateful comment), I had never been much into computers and never properly learned to type, so my keyboard skills weren’t exactly award-winning: I wasn’t very fast (though not remarkably slow either), and I quite often had to look at the keyboard to find the key I was looking for.&lt;/p&gt;

&lt;p&gt;Taking the above into consideration, I realized this was a chance to learn proper form and improve my typing skills; so after some investigation, I decided I was gonna go for it. And seeing this as a chance to pick a layout designed specifically for my purposes, I decided to go for the &lt;a href="https://www.kaufmann.no/roland/dvorak/"&gt;Programmer Dvorak&lt;/a&gt; layout.&lt;/p&gt;

&lt;h2 id="pros-and-cons"&gt;Pros and cons&lt;/h2&gt;

&lt;p&gt;Now, about two years and thousands of key strokes later, I can take stock of what I have gained from switching and what issues arose because of it.&lt;/p&gt;

&lt;h3 id="benefits"&gt;Benefits&lt;/h3&gt;

&lt;p&gt;Proper touch typing form: This might not seem like a big one, and from what I understand, it’s not necessarily the holy grail that some people make it out to be, but it has been a big boon to me. I can’t comment on it being better or more efficient than any other technique, but it sure beats my original, awkward, four-fingered approach.&lt;/p&gt;

&lt;p&gt;Speed: My typing speed has gone up dramatically. I don’t know how many words per minute I could get out of my old QWERTY skills, but it wasn’t breaking any necks. I reckon that after about 3–4 months of Dvorak I had already caught up.&lt;/p&gt;

&lt;p&gt;Accuracy: A nice feature of learning Dvorak on keyboards where you can’t change the physical layout is that you need to memorize the layout because—with the exception of ‘A’ and ‘M’—no letters are placed in the same spot. A side effect of this is that you can’t look down on the keyboard to find a key. In fact, that’ll probably just confuse you further.&lt;/p&gt;

&lt;p&gt;Comfort: There’s something about the alternating hand-motion of the Dvorak layout that I really like. In fact, while learning it, I’d often come across sequences of letters that just felt &lt;em&gt;good&lt;/em&gt; to write.&lt;/p&gt;

&lt;p&gt;It &lt;em&gt;might&lt;/em&gt; be more ergonomic: You often hear that the Dvorak layout is more ergonomic and better for avoiding RSI and the like. I can’t comment on the veracity of these claims, but it sounds plausible.&lt;/p&gt;

&lt;h3 id="drawbacks"&gt;Drawbacks&lt;/h3&gt;

&lt;p&gt;The ramp-up time: It took a while until I got up to a respectable speed. This period where things just don’t move as fast as you want can be annoying and mentally taxing.&lt;/p&gt;

&lt;p&gt;Extra set-up time: Dvorak is by no means the default layout for any system (as far as I’m aware), and so—if you’re using a software-defined layout—you’ll always need to go through some extra steps to set it up properly. Even more so if you go for some esoteric layout like Programmer Dvorak (though Linux comes with this available out of the box). This can of course be offset by going for a programmable keyboard (or getting a Dvorak keyboard).&lt;/p&gt;

&lt;p&gt;Pair programming: If you’re getting help from a coworker, keep a QWERTY layout handy. It’s okay to have a little laugh when they stand there, though, perplexed at why nothing seems to work.&lt;/p&gt;

&lt;p&gt;Losing touch with QWERTY: When I switched, I switched completely. As a result of this, every time I use a QWERTY keyboard now, I need to go looking for keys and I’m super slow. Though, for some reason, this does not apply to phone keyboards, where Dvorak feels awkward but QWERTY is perfectly fine.&lt;/p&gt;

&lt;h2 id="is-it-worth-it"&gt;Is it worth it?&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Absolutely&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Seeing as I spend most of my day using a keyboard, it makes sense to invest in building skills. This might be ‘survivor bias’ talking, but I got so much out of it that I’d recommend it to anyone who’s interested. At least have a little sniff. If you’ve got the time and energy, it can be very fun and offer a real feeling of accomplishment. Plus, it’ll keep your brain active!&lt;/p&gt;

&lt;p&gt;If that was all you wanted to know, you can stop reading now, but if you’re looking for some tips on how to learn a new layout, let’s finish it off with what I found worked for me.&lt;/p&gt;

&lt;h2 id="how-to-learn"&gt;How to learn&lt;/h2&gt;

&lt;p&gt;After picking my target layout (Programmer Dvorak), I had to find out how to learn. While it might be tempting to just sit down with a key map next to you (or shuffle the physical keys around if you can do that) and go for it, this is quite likely to be counterproductive for a number of different reasons; the biggest ones being that you’re more likely to slip out of proper technique and that it’s less efficient (based on my empirical studies with a sample size of one) when it comes to memorizing layout.&lt;/p&gt;

&lt;p&gt;So what do I recommend? Glad you asked! I’ve got some tips for ya:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;Use typing training software&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;These will typically introduce you to one new letter for each hand at a time and slowly work their way through the full layout, often focusing on common patterns. If you want tips on which one to go for, I’d recommend &lt;a href="https://www.typingclub.com/"&gt;Typing Club&lt;/a&gt;; it’s free, effective, and even includes some pretty interesting bits of writing to copy as you progress, so you can learn while you learn. &lt;em&gt;Yo, dawg.&lt;/em&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Take it everywhere (work, studies, whatever)&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Once you’re comfortable enough with the position of the keys to not feel like you need to look up where a key is before pressing it (though thinking is okay), start using it all the time. Once you’ve got the basics down, the most important thing is to get exposure and experience with it. Depending on your situation, this can be more or less acceptable, so keep important deadlines and the like in mind, but don’t let that stop you. Keep your other layout around so you can swap back in case of emergency (or pair programming!).&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Don’t give up!&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Even when it seems hard and you’re tired of making the same typo for the two hundred and twenty-seventh time this hour, stick with it. Take a deep breath, have a cup of tea, and clear your mind. Go back to the keyboard and start again. Consistency is key. This goes doubly for memorizing fingerings and modified keys: Make sure you always hit the key with the correct finger. Some keys might be awkward at first, but you’ll get used to it eventually.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Accurate is the new fast&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;It doesn’t matter how fast you are if you hit the wrong key half the time. It’s important to focus on accuracy, especially at the start. Speed will come.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;If you decide to embark on this exciting journey, be aware: it won’t be easy and the learning curve is pretty steep; but it’s not as difficult as you might think. Time and tenacity is all you need: Once you start, you simply need to stick with it.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;
    



</description>
      <category>keyboard</category>
    </item>
    <item>
      <title>Command Line Control: awk</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Sat, 08 Jun 2019 15:19:18 +0000</pubDate>
      <link>https://forem.com/hartmann/command-line-control-awk-15oi</link>
      <guid>https://forem.com/hartmann/command-line-control-awk-15oi</guid>
      <description>&lt;p&gt;Unless you spend a whole lot of time working primarily on the command line, &lt;code&gt;awk&lt;/code&gt; is one of those commands you’ve likely come across a few times, but never really learned how to use properly. Similar to &lt;a href="https://thomashartmann.dev/blog/xargs-and-the-unruly-tags/"&gt;my recent adventures with &lt;code&gt;xargs&lt;/code&gt;&lt;/a&gt;, though, I recently came across a little use case where I could benefit from using it, so I decided to sit down and look into it.&lt;/p&gt;

&lt;p&gt;Even more so than with &lt;code&gt;xargs&lt;/code&gt;, this is a &lt;em&gt;really&lt;/em&gt; powerful tool, but let’s focus on the basics and see what we can make of it.&lt;/p&gt;

&lt;h1 id="what-is-awk"&gt;What is &lt;code&gt;awk&lt;/code&gt;?&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;awk&lt;/code&gt; is a command that processes text using programs written in the AWK language.&lt;/p&gt;

&lt;p&gt;To understand what it can do, understanding the language it uses is probably a good place to start. Let’s use the words of Alfred Aho—one of the creators of the &lt;em&gt;AWK&lt;/em&gt; language—from a &lt;a href="https://web.archive.org/web/20080808234125/http://www.computerworld.com.au/index.php/id%3B1726534212%3Bpp%3B2"&gt;2008 &lt;em&gt;Computerworld&lt;/em&gt; interview&lt;/a&gt; to get a rough grasp of what it is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AWK is a language for processing files of text. A file is treated as a sequence of records, and by default each line is a record. Each line is broken up into a sequence of fields, so we can think of the first word in a line as the first field, the second word as the second field, and so on. An AWK program is of a sequence of pattern-action statements. AWK reads the input a line at a time. A line is scanned for each pattern in the program, and for each pattern that matches, the associated action is executed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That may be a bit dense, so let’s take it apart:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;“AWK is a language for processing [..] text”&lt;/dt&gt;
&lt;dd&gt;AWK is a &lt;em&gt;domain-specific language&lt;/em&gt; (DSL) focused on text processing. The &lt;code&gt;awk&lt;/code&gt; command expects that its first argument is a script or a string in this language.
&lt;/dd&gt;
&lt;dt&gt;“AWK reads the input a line at a time”&lt;/dt&gt;
&lt;dd&gt;AWK is line-oriented and works through the input line by line. (It’s actually &lt;em&gt;record&lt;/em&gt;-oriented, but the default separator is a newline character, so this is the same thing by default.)
&lt;/dd&gt;
&lt;dt&gt;“Each line is broken into a sequence of fields”&lt;/dt&gt;
&lt;dd&gt;Each word in a line maps to a field. These fields are accessed with the &lt;code&gt;$&lt;/code&gt; operator, e.g. &lt;code&gt;$1&lt;/code&gt; for the first word, &lt;code&gt;$2&lt;/code&gt; for the second, and so on. &lt;code&gt;$0&lt;/code&gt; is the whole line. By default, fields are delimited by whitespace (which is why I’ve called them words) but this can be customized.
&lt;/dd&gt;
&lt;dt&gt;“An AWK program is of a sequence of pattern-action statements”&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;This means it’s a sequence of predicates with actions. If a predicate evaluates to true, perform the specified action. If no predicate is specified, it will always evaluate to true, and if no action is specified, it will default to printing the whole line.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Huh?&lt;/em&gt; Yeah, this is still a bit confusing, but maybe some examples will make it clearer:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Patterns&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;This is a predicate to check each line against. It usually takes the form of a regex enclosed in forward slashes. &lt;code&gt;/foo/&lt;/code&gt;, &lt;code&gt;/b[ar]?/&lt;/code&gt;, &lt;code&gt;/^baz/&lt;/code&gt;, &lt;code&gt;/(fizz|buzz)$/&lt;/code&gt; are all examples. Most of the regex skills you have will be applicable here (character sets, character classes, alternations, etc.).&lt;/p&gt;
&lt;p&gt;You can also match specific fields against a regex. Only want to match lines where the second field contains ‘cheese’? &lt;code&gt;$2 ~ /cheese/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The pattern can also consist of functions and comparisons; so if you wish to act only on lines that aren’t empty: &lt;code&gt;length &amp;gt; 0&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If no pattern is given, every line will match.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Actions&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;These are commands telling &lt;code&gt;awk&lt;/code&gt; what to execute. They are enclosed in curly braces (&lt;code&gt;{}&lt;/code&gt;). This is where you might instruct &lt;code&gt;awk&lt;/code&gt; to print a certain field of the string—&lt;code&gt;print $3&lt;/code&gt;, for instance—or increment a counter if you’re counting words: &lt;code&gt;word_count += NF&lt;/code&gt; (yeah, I’ll get to what &lt;code&gt;NF&lt;/code&gt; means in a bit).&lt;/p&gt;
&lt;p&gt;If no action is given, &lt;code&gt;awk&lt;/code&gt; will print the matching line.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;




&lt;/dd&gt;
&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;/dl&gt;

&lt;h1 id="basic-auth-awk"&gt;Basic &lt;del&gt;auth&lt;/del&gt; &lt;code&gt;awk&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;That’s a quick overview of how the language is structured. Before we start playing with it, let’s explore some of the features.&lt;/p&gt;

&lt;h2 id="built-in-variables"&gt;Built-in variables&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;awk&lt;/code&gt; has a number built-in variables, and while I won’t cover all of them, these are the ones that I’ve found the most useful:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;NR&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Gives you the line number of the current match. Could be used for adding line numbers to an input file: &lt;code&gt;awk '{print NR, $0}'&lt;/code&gt;. Or maybe looking for lines that contain ‘ice cream’ is more your speed: &lt;code&gt;awk '/ice cream/ {print NR}'&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;NF&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;This is the number of fields in a line. Useful if you’re looking for the last field, either for finding out how many fields are in a line or for seeing if it contains a pattern: &lt;code&gt;awk '$NF ~ /out/ {print NR}&lt;/code&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;FS&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;The field separator value. This is what &lt;code&gt;awk&lt;/code&gt; will use to split each line into fields. By default this is whitespace. If you have a file full of comma-separated values and want to split each line on commas instead of whitespace: &lt;code&gt;BEGIN {FS=","}&lt;/code&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;RS&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;This is the line (‘record’) equivalent of the field separator. The default is &lt;code&gt;\n&lt;/code&gt;. Say you want to print your &lt;code&gt;PATH&lt;/code&gt; over multiple lines: &lt;code&gt;echo $PATH | awk 'BEGIN {RS=":"} {print}'&lt;/code&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id="begin-and-end"&gt;
&lt;code&gt;BEGIN&lt;/code&gt; and &lt;code&gt;END&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;awk&lt;/code&gt; lets you supply commands to be executed at the start and end of a script by using &lt;code&gt;BEGIN&lt;/code&gt; and &lt;code&gt;END&lt;/code&gt;. While they may seem like it, they’re not really special at all. Instead, think of them as being patterns that evaluate to true before &lt;em&gt;anything&lt;/em&gt; is evaluated and after &lt;em&gt;everything&lt;/em&gt; is evaluated, respectively.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;BEGIN&lt;/code&gt; could be used to set the field separator or initialize a variable.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;END&lt;/code&gt; is useful for printing out results accrued through the life of the program, such as a word count. If we bring back our word counting example: &lt;code&gt;awk '{word_count += NF} END {print word_count}'&lt;/code&gt;&lt;/p&gt;

&lt;h2 id="functions-and-conditionals"&gt;Functions and conditionals&lt;/h2&gt;

&lt;p&gt;Like most languages, AWK has a number of built-in functions (such as the &lt;code&gt;print&lt;/code&gt; and &lt;code&gt;length&lt;/code&gt; functions we saw earlier) and also lets you define your own functions if you so please. This is probably overkill for most trivial operations but could come in handy in certain cases.&lt;/p&gt;

&lt;p&gt;And AWK has conditionals too! While you can use the &lt;code&gt;if else&lt;/code&gt; construct within actions, I’d like to highlight that you can do conditional statements based on the supplied pattern. I.e. &lt;code&gt;awk '/foo/ {print "FOO"} {print "bar"}'&lt;/code&gt; will print ‘FOO’ for lines that match &lt;code&gt;/foo/&lt;/code&gt; and ‘bar’ for lines that don’t.&lt;/p&gt;

&lt;h1&gt;
  
  
  Applications
&lt;/h1&gt;

&lt;p&gt;Now that we've got some idea how it works, what can we use it for? Let's&lt;br&gt;
look at some sample applications for it:&lt;/p&gt;

&lt;h2&gt;
  
  
  Sorting lines in a file by length
&lt;/h2&gt;

&lt;p&gt;Here's a fun little application: Let's take a file, count the number of&lt;br&gt;
characters in each line, and then sort it based on the number of&lt;br&gt;
characters:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print length, $0}'&lt;/span&gt; &amp;lt;file&amp;gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And if you want to exclude empty lines, try this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'length &amp;gt; 0 {print length, $0}'&lt;/span&gt; &amp;lt;file&amp;gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Friendly &lt;code&gt;PATH&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is the same one that was listed above, and is useful if you're&lt;br&gt;
looking for certain entries that can easily get lost when the path is on&lt;br&gt;
one line:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# bash, zsh&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$PATH&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'BEGIN {RS=":"} {print}'&lt;/span&gt;

&lt;span class="c"&gt;# fish&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$PATH&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'BEGIN {RS=" "} {print}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Counting words
&lt;/h2&gt;

&lt;p&gt;Another example that was used previously. Count the words in a file or&lt;br&gt;
any input stream:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{word_count += NF} END {print word_count}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Parsing git logs
&lt;/h2&gt;

&lt;p&gt;Maybe your team has agreed that all commit messages should start with&lt;br&gt;
&lt;code&gt;#&amp;lt;task_no&amp;gt;&lt;/code&gt; if it relates to a task and &lt;code&gt;#--&lt;/code&gt; if it doesn't. To find&lt;br&gt;
all commits that relate to a specific task—say &lt;code&gt;#42&lt;/code&gt;—we could do this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/#42/ {print $1}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Or how about finding the ratio of commits that belong to a task versus&lt;br&gt;
those that don't?&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--no-decorate&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'$2 ~ /#[0-9]+/ {task += 1} {notask +=1} \
  END {printf "Tasks: %d\nNo-tasks: %d\nTask to no-task ratio: %f", \
  task, notask, task / notask }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(Yeah, the &lt;code&gt;printf&lt;/code&gt; function works pretty much the same as in C—so much&lt;br&gt;
so that I haven't looked it up yet!)&lt;/p&gt;

&lt;h2&gt;
  
  
  Killing processes
&lt;/h2&gt;

&lt;p&gt;This is actually what triggered me to look into &lt;code&gt;awk&lt;/code&gt; and what&lt;br&gt;
eventually led to this post being brought into existence.&lt;/p&gt;

&lt;p&gt;There are a number of ways to kill applications from the command line,&lt;br&gt;
and for a while, my default fallback has been the classic &lt;code&gt;ps aux | grep&lt;br&gt;
&amp;lt;app&amp;gt;&lt;/code&gt; combo.&lt;/p&gt;

&lt;p&gt;While this lists out all the relevant processes and their process IDs&lt;br&gt;
(&lt;em&gt;PIDs&lt;/em&gt;), you then have to manually copy the PID and put it into the&lt;br&gt;
&lt;code&gt;kill&lt;/code&gt; command to shut it down. This is annoying at best, and gets even&lt;br&gt;
worse if the process has spawned children that we want to take down as&lt;br&gt;
well.&lt;/p&gt;

&lt;p&gt;How do we deal with this? Well:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ps aux | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/&amp;lt;app&amp;gt;/ {print $2}'&lt;/span&gt; | xargs &lt;span class="nb"&gt;kill&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;ps&lt;/code&gt; lists all processes on the system&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;awk&lt;/code&gt; then goes over every line that contains the application name,&lt;br&gt;
extracts the second whitespace-delimited word—which in this case is&lt;br&gt;
the PID—and prints that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the last stretch, we use &lt;code&gt;xargs&lt;/code&gt; to feed the PIDs into the&lt;br&gt;
&lt;code&gt;kill&lt;/code&gt; command, thus killing all the processes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This works just fine, though it comes with the caveat that it'll also&lt;br&gt;
try and kill the &lt;code&gt;awk&lt;/code&gt; process (because the application name is part of&lt;br&gt;
the command, so it gets listed by &lt;code&gt;ps&lt;/code&gt;), but that's only a minor&lt;br&gt;
annoyance, and I'll leave fixing that as an exercise for the reader.&lt;/p&gt;

&lt;p&gt;Now, I'm sure you can make &lt;code&gt;killall&lt;/code&gt; do something quite similar to this,&lt;br&gt;
but I've found this way to be more effective (by which I mean: &lt;em&gt;closer&lt;br&gt;
to what I expect&lt;/em&gt;).&lt;/p&gt;

&lt;h1&gt;
  
  
  Closing up
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Phew&lt;/em&gt;. We've learned a lot today, and this post grew much longer than&lt;br&gt;
what I had originally imagined—about four or five times longer—but it's&lt;br&gt;
been quite the journey and I'm glad you were there with me, partner. I&lt;br&gt;
hope you've gleaned some new insight too and that you'll find some&lt;br&gt;
application for this in your day-to-day.&lt;/p&gt;

&lt;p&gt;See you next time!&lt;/p&gt;

</description>
      <category>commandlinecontrol</category>
      <category>shell</category>
    </item>
    <item>
      <title>xargs and the unruly tags: A tale of two commands</title>
      <dc:creator>Thomas Hartmann</dc:creator>
      <pubDate>Sat, 25 May 2019 14:01:57 +0000</pubDate>
      <link>https://forem.com/hartmann/xargs-and-the-unruly-tags-a-tale-of-two-commands-5879</link>
      <guid>https://forem.com/hartmann/xargs-and-the-unruly-tags-a-tale-of-two-commands-5879</guid>
      <description>&lt;p&gt;I thought I was really clever when I configured &lt;a href="https://thomashartmann.dev/"&gt;my blog's&lt;/a&gt; CI/CD pipeline to tag commits that got deployed and push the tags back into the repo, but I’m rarely as clever as I like to think: I had forgotten to put the proper checks in place to avoid these tag pushes triggering subsequent runs of the pipeline, and things got a little … &lt;em&gt;out of hand&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I’d gone to bed just after pushing an update, and when I arose to check on it, I found that the deploy tagging stage had been running over and over and over and over and … you get the point. Thankfully, it had failed after about 130 rounds, so it could have been a lot worse, but I &lt;em&gt;was&lt;/em&gt; left with a large amount of useless and unwanted tags in the remote repo.&lt;/p&gt;

&lt;p&gt;So how do you fix something like this? Yup, &lt;code&gt;xargs&lt;/code&gt; to the rescue!&lt;/p&gt;

&lt;h2 id="where-theres-a-will"&gt;Where there’s a will …&lt;/h2&gt;

&lt;p&gt;At first, I didn’t really know how I’d go about it. I was hoping git would have some nice, built-in functionality for mass-deleting remote tags, but while I have found in retrospect that it does (see the postmortem), I couldn’t find it at the time.&lt;/p&gt;

&lt;p&gt;However, because all the tags were for a specific commit, I &lt;em&gt;did&lt;/em&gt; know that I could list all the relevant tags separated by newlines, using &lt;code&gt;git tag --contains &amp;lt;SHA&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, with some helpful advice from Stack Overflow and &lt;a href="http://theknarf.com/"&gt;this guy&lt;/a&gt;, I constructed this little command which sorted me out just fine:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git tag &lt;span class="nt"&gt;--contains&lt;/span&gt; 9216e97ce7e66090f79eba4d1abe6548d72dd638 &lt;span class="se"&gt;\&lt;/span&gt;
| xargs &lt;span class="nt"&gt;-I&lt;/span&gt; % git push origin :refs/tags/%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, I’d come across &lt;code&gt;xargs&lt;/code&gt; before, even done the ol’ copying and pasting from Stack Overflow trick, but it had always looked really complicated and no-one had ever told me why I’d need it or what it does; so I just carried on in blissful ignorance. Not this time, though. It was time to figure out what was going on.&lt;/p&gt;

&lt;h2 id="groking-xargs"&gt;Groking &lt;code&gt;xargs&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The way &lt;code&gt;xargs&lt;/code&gt; was sold to me was: “execute a command for each item in a list”. It’s actually more powerful than that, but that’s a great place to start.&lt;/p&gt;

&lt;p&gt;Let’s use the &lt;code&gt;man&lt;/code&gt; page to find out what that &lt;code&gt;-I %&lt;/code&gt; bit means :&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;-I&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;&lt;strong&gt;replace-str&lt;/strong&gt;: “Replace occurrences in the initial-arguments with names read from standard input”&lt;/p&gt;
&lt;p&gt;The string to use to indicate where to place arguments in the command to run. In the command above, we chose to use &lt;code&gt;%&lt;/code&gt;, but you’re not limited to this.&lt;/p&gt;
&lt;p&gt;Similar to &lt;code&gt;printf&lt;/code&gt; and format strings in general, this places your arguments at your desired place in the command. In our case it both limits us to using one argument (tag) at a time, and it lets us append it to &lt;code&gt;:refs/tags/&lt;/code&gt; without being separated by a space.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;That means that in the above snippet, &lt;code&gt;xargs&lt;/code&gt; would, for each tag listed, run the command &lt;code&gt;git push origin :refs/tags/&amp;lt;tag_name&amp;gt;&lt;/code&gt;, which pushes that tag with an empty reference, thereby deleting it.&lt;/p&gt;

&lt;p&gt;If all you want is to put the argument at the end of the command, you can even do without the &lt;code&gt;-I&lt;/code&gt;. Say you want to recursively delete all the &lt;code&gt;.swp&lt;/code&gt; files in a directory:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.swp"&lt;/span&gt; | xargs &lt;span class="nb"&gt;rm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Be aware, though, that without either using a &lt;code&gt;-I&lt;/code&gt; or &lt;code&gt;-n&lt;/code&gt; (to limit the number of arguments to use for each command), &lt;code&gt;xargs&lt;/code&gt; will split the list you give it into sizeable chunks and apply as many arguments to the command as it can each time. That means that in this case, it’d likely end up looking something like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;a.swp b.swp c.swp ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;which is usually fine and what you want, but keep this in mind for when it isn’t.&lt;/p&gt;

&lt;p&gt;This is only scratching the surface of what &lt;code&gt;xargs&lt;/code&gt; can do, but it’s enough to make it do some pretty heavy lifting. It might not be something to reach for very often, but for when you do need it, it’s a great tool to have in your belt.&lt;/p&gt;

&lt;h2 id="postmortem"&gt;Postmortem&lt;/h2&gt;

&lt;p&gt;&lt;span id="postmortem"&gt;&lt;/span&gt; Now, you might have noticed that I did a &lt;code&gt;git push&lt;/code&gt; for each tag that I was deleting, and you might be thinking that for over a hundred tags, it must have taken quite some time. You would be right. Luckily, I was working on something else, so I could happily let it run in the background. But we can do better!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;xargs&lt;/code&gt; has an option &lt;code&gt;-P&lt;/code&gt; or &lt;code&gt;--max-procs&lt;/code&gt;, which you can use to decide how many processes to run in parallel. The default is 1, but if you set it to 0, it will run as many as it can. This could have saved us quite some time, assuming git would let us run multiple &lt;code&gt;push&lt;/code&gt; operations from the same repo at the same time. But there is an even better way:&lt;/p&gt;

&lt;p&gt;As outlined in &lt;a href="https://stackoverflow.com/a/12791414"&gt;this Stack Overflow response&lt;/a&gt;, you can use a whitespace-separated list of tag names (&lt;code&gt;&amp;lt;tags&amp;gt;&lt;/code&gt;) with &lt;code&gt;git push&lt;/code&gt;; so we could have run &lt;code&gt;git push --delete origin &amp;lt;tags&amp;gt;&lt;/code&gt; to achieve the same outcome as deleting them one by one.&lt;/p&gt;

&lt;p&gt;If we rewrite the command from earlier, we can both simplify it &lt;em&gt;and&lt;/em&gt; do it all in a single push:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git tag &lt;span class="nt"&gt;--contains&lt;/span&gt; 9216e97ce7e66090f79eba4d1abe6548d72dd638 &lt;span class="se"&gt;\&lt;/span&gt;
| xargs git push &lt;span class="nt"&gt;--delete&lt;/span&gt; origin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;… yeah, that would have been a lot more efficient 😅&lt;/p&gt;

</description>
      <category>git</category>
      <category>shell</category>
    </item>
  </channel>
</rss>
