Jekyll2022-03-23T16:16:40+00:00https://echosa.github.io/feed.xmlDev and SuchA blog in which I discuss things related to programming, development, software, and tech in general.Brian ZwahrQuick Save with Git2022-03-04T00:00:00+00:002022-03-04T00:00:00+00:00https://echosa.github.io/blog/2022/03/04/quick-save-with-git<p>A feature that video game players are very aware of and often use is something called “quick save”. Quick save allows you to save your game, anytime and anywhere, so that you can always come back to that spot via a “quick load”. For instance, if you’re about to fight a boss, you can quick save right before the fight. That way, if you lose, you can just quick load back to that same spot without having to trek all the way back to the boss after losing and being put back at the beginning of a level. This is very useful and a huge time-saver.</p>
<p>As software developers, we can get similar usefulness in our development using <code class="language-plaintext highlighter-rouge">git</code>! Bonus: it’s actually very easy to do! So how does one achieve this? Simple: <strong>commit changes often</strong>.</p>
<p>That’s it!</p>
<p>No, really. That’s all there is to it!</p>
<p>How does committing often give “quick save” benefits? Let me give an example!</p>
<p>Let’s say I’m writing some code and I start by writing a test. TDD is still a thing people do, right? I write a failing test (failing because I’m writing the test first). I now have two options. I can either:</p>
<ul>
<li>continue immediately on to writing code to make the test pass, or</li>
<li>commit my changes before doing so</li>
</ul>
<p>I decide I want to “quick save”, so I commit my changes to git. (Note: I’m talking about committing locally. I’m not pushing anything to a remote, like Github, yet.) Once I’ve done that, I start working on making the test pass.</p>
<p>I write some code, run the test, and see it’s not working. I realize I completely went about my solution in the wrong way, so I need to redo the work.</p>
<p>It’s time to “quick load”! Instead of having to manually find and undo all my changes, I can simply <code class="language-plaintext highlighter-rouge">git reset --hard HEAD</code>, and I’m right back to exactly where I was: a written by failing test, waiting for me to make it pass. So I try another solution. This one also doesn’t work, so I quick load and try again.</p>
<p>Hopefully you can see the convenience <code class="language-plaintext highlighter-rouge">git</code> is providing me, but the benefits do not stop there! There’s another reason I committed the test first before moving on</p>
<p>Let’s say I hadn’t committed the test. Instead I wrote the test and immediately started working on the code to make it pass. The code doesn’t work, so I want go undo it. However, I do not want to undo the test. So, I have to manually go undo all my non-test changes to get back to where I was after writing the test but before working on the code to make it pass. If I’d just committed the test first, then this wouldn’t be an issue! I’d just quick load with <code class="language-plaintext highlighter-rouge">git reset</code>. Done!</p>
<p>Let’s keep going, though. I’ve written the test and committed it. I’ve make the test pass. I can now commit that code for a new “quick load” point. By committing the changes, I essentially give myself a clean slate for the next changes and an easy rollback if needed. So, I write another test, commit it, make the test pass, commit it, etc.</p>
<p>To complete the video game analogy, often video games give you multiple “save slots”, essentially you can have multiple saves stored at once which you can load at will. Perhaps I save at the beginning of a level, then halfway through level after finding an item or secret, and then right before the boss. If I need to, I can go back in time to any of these positions, giving myself a redo, essentially.</p>
<p>Committing changes in small, complete batches gives this same effect. Every git commit is basically a save point that you can always load.</p>
<p>I will say, it can be weird to put this into practice at first, for a couple of reasons. The first is that you have to change the way you think. Instead of thinking of an entire coding project or task as one atomic unit, you have to think about how you can break it down into smaller, atomic units that can be completed and committed individually. Second, you have to get into the habit of remembering to commit between each of these smaller atomic units of work.</p>
<p>I believe everyone can benefit from adopting this quick save/quick load model into their workflows. It adds very little in terms of overhead and additional time while providing significant benefits.</p>
<p>Hopefully, someone who reads this gets use out of my suggestions! Happy coding!</p>Brian ZwahrA feature that video game players are very aware of and often use is something called “quick save”. Quick save allows you to save your game, anytime and anywhere, so that you can always come back to that spot via a “quick load”. For instance, if you’re about to fight a boss, you can quick save right before the fight. That way, if you lose, you can just quick load back to that same spot without having to trek all the way back to the boss after losing and being put back at the beginning of a level. This is very useful and a huge time-saver.ed Golf: Letterbox2019-04-15T00:00:00+00:002019-04-15T00:00:00+00:00https://echosa.github.io/blog/2019/04/15/ed-golf-letterbox<p>Well, after a couple of weeks off, I’m back with another episode of ed Golf! Today, we’re taking on a very interesting challenge, so let’s try our hand at <a href="http://www.vimgolf.com/challenges/5c7b244ae74665000c0598a9">Letterbox</a>!</p>
<p>A couple of notes, first. After some suggestions on Twitter, I’m making a couple of changes to how ed Golf is played. First, since Vimgolf requires saving and existing (<code class="language-plaintext highlighter-rouge">ZZ</code>), we should do the same with ed Golf, so we’ll be ending with <code class="language-plaintext highlighter-rouge">wq</code> and adding 3 to the score. (Remember to count when you press return!)</p>
<p>Secondly, since we’re saving and exiting, we need to work with an actual file rather than just the in-memory buffer. Therefore, instead of opening ed and adding the starting text, I’ll be opening a file already populated with the start text. I’ll still print it out at the start, for reference, though.</p>
<p>Third, because we’re working with files and exiting, which counts towards the score, we’re already out of ed by the time it comes to check our answer. I’ve decided to have a pre-populated file with the correct answer, similar to the starting text file, and I’ll be using <code class="language-plaintext highlighter-rouge">diff</code> to check my answer against it. No output from <code class="language-plaintext highlighter-rouge">diff</code> means the files are the same.</p>
<p>With all that out of the way, let’s take a look at what we’re starting with:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cat start
abcdefg
</code></pre></div></div>
<p>And what we’re trying to end up with:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cat end
a b c d e f g
b f
c e
d d
e c
f b
g f e d c b a
</code></pre></div></div>
<p>Now let’s give this a shot!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ed start
8
,p
abcdefg
####################
GOLF STARTS HERE
####################
### 9 - Use `rev` command to get reverse copy of the string on the next line
r !rev %
rev start
8
### 4 - Duplicate first line
1t1
### 68 - Use regular express to get the correct letters on the correct lines
2s#\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)#\2\6\
\3\5\
\4\4\
\5\3\
\6\2
fb
### 19 - Add spaces to create the square shape
2,6s#\(.\)#\1
#Spaces end here ^
f b
### 15 - Add additional spaces between the characters
,s#\(.\)#\1 #g
### 7 - Delete trailing spaces
,s/ $/
g f e d c b a
### 3 - Save and quit
wq
98
####################
GOLF ENDS HERE - Total: 125
####################
$ diff start end
$
</code></pre></div></div>
<p>Oh, boy. That was a doozy! It’s not a score I’m proud of, but what I am proud of is being able to complete the challenge at all! Let’s break this one down a bit, since there’s quite a bit to unpack here.</p>
<p>The first thing I did was run the contents of the file (just the starting text) through the <code class="language-plaintext highlighter-rouge">rev</code> command, reading the result into a new line in the file.. This is obviously system-specific, but ed is all about working with what you have on your system, right? ed edits text, and other programs do other things. The result of this command is that we end up with two lines, the starting one and the reverse:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>abcdefg
gfedcba
</code></pre></div></div>
<p>Next, my idea was to have some text to work with, without touching the already correct first and last lines, so I duplicated the first line. Now I have:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>abcdefg
abcedfg
gfedcba
</code></pre></div></div>
<p>Let’s leave the first and last lines alone and just work with the second line. The next command is the big one. I use substitution to break apart the line and put the correct letters on the correct lines (no spaces yet). After this command, I have:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>abcdefg
bf
ce
dd
ec
fb
gfedcba
</code></pre></div></div>
<p>Getting closer! Next, I add spaces to create the square shape, leaving me with:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>abcdefg
b f
c e
d d
e c
f b
gfedcba
</code></pre></div></div>
<p>So close, now! All we’re missing is the space padding. After adding it, I have this (the <code class="language-plaintext highlighter-rouge">$</code> represents where the lines end):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>a b c d e f g $
b f $
c e $
d d $
e c $
f b $
g f e d c b a $
</code></pre></div></div>
<p>As you can see, we have trailing spaces that shouldn’t be there, so I get rid of them before saving and exiting, leaving:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>a b c d e f g$
b f$
c e$
d d$
e c$
f b$
g f e d c b a$
</code></pre></div></div>
<p>Like I said before, I’m not particularly happy with this score. Let’s see what we can shave off. The first thing I notice is that, in the big substitution, I don’t actually need all the matches. Specifically, I don’t need <code class="language-plaintext highlighter-rouge">a</code> (the first match) or <code class="language-plaintext highlighter-rouge">g</code> (the seventh and last match). So, we can lower our score with a slightly improved substitution command:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2s#.\(.\)\(.\)\(.\)\(.\)\(.\).#\1\5\
\2\4\
\3\3\
\4\2\
\5\1
</code></pre></div></div>
<p>Simply removing the matching from the first and last characters (i.e. replacing <code class="language-plaintext highlighter-rouge">\(.\)</code> with <code class="language-plaintext highlighter-rouge">.</code>) saves 8 characters, bringing the total down to 117. Still not great but better than before.</p>
<p>We can save even more by reducing the command to add the necessary spaces required to create the initial square shape. I keep forgetting to use <code class="language-plaintext highlighter-rouge">&</code> in substitutions ever since I learned about it recently, but let’s use it here. An <code class="language-plaintext highlighter-rouge">&</code> in the replacement text is replaced with the entire matched text from the search part of the command. This means we don’t have to use parentheses to get a match to put back in during replacement. Instead, we can do this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2,6s/./& #command ends here, with five trailing spaces
</code></pre></div></div>
<p>This saves another 5, giving us 112 now. We can save another 5 by doing the same with the command that adds the padding spaces:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>,s/./& /g
</code></pre></div></div>
<p>That leaves us with a total improved score of 107, much better than the 125 we started with.</p>
<p>Can you do better? If so, let me know either in the comments or <a href="https://twitter.com/echosa">on Twitter</a>. Happy golfing!</p>Brian ZwahrWell, after a couple of weeks off, I’m back with another episode of ed Golf! Today, we’re taking on a very interesting challenge, so let’s try our hand at Letterbox!ed Golf: Applying Same Text Modification in Several Lines2019-03-25T00:00:00+00:002019-03-25T00:00:00+00:00https://echosa.github.io/blog/2019/03/25/applying-same-text-modifications-in-several-lines<p>Continuing with our ed golf exercises, today we tackle one that is more relevant to programming than the previous ones. We also have the first big mistake… fun! Let’s jump into <a href="http://www.vimgolf.com/challenges/5bbb82f969a25f0009541350">Applying same text modification in several lines</a>!</p>
<p>One note before we begin. I have changed the scoring system based on <a href="https://twitter.com/tpenguinltg/status/1108688836958318592">this suggestion</a> on Twitter. Each session will now end with <code class="language-plaintext highlighter-rouge">wq</code>, which will be counted.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ed
### Insert start file
i
Assert.ThrowsAsync<Exception>(() => _auction.StartSellingItem());
Assert.ThrowsAsync<Exception>(() => _application.StartBiddingIn(_auction));
Assert.ThrowsAsync<Exception>(() => _auction.HasReceivedJoinRequestFromSniper());
Assert.ThrowsAsync<Exception>(() => _auction.AnnounceClosed());
Assert.ThrowsAsync<Exception>(() => _application.ShowsSniperHasLostAuction());
.
####################
### GOLF STARTS HERE
####################
### 14 - Remove everything that's not between _ and () [INCORRECT!]
g/_.*()/s//&;
Assert.ThrowsAsync<Exception>(() => _auction.StartSellingItem(););
Assert.ThrowsAsync<Exception>(() => _auction.HasReceivedJoinRequestFromSniper(););
Assert.ThrowsAsync<Exception>(() => _auction.AnnounceClosed(););
Assert.ThrowsAsync<Exception>(() => _application.ShowsSniperHasLostAuction(););
### 2 - Undo
u
### 21 - Remove everything that's not between _ and () [CLOSER, BUT STILL INCORRECT]
g/.*\(_.*\));/s//\1;
_auction.StartSellingItem();
_auction);
_auction.HasReceivedJoinRequestFromSniper();
_auction.AnnounceClosed();
_application.ShowsSniperHasLostAuction();
### 2 - Undo
u
### 22 - Remove the unwanted text from all lines
g/.* \(_.*\));/s//\1;
_auction.StartSellingItem();
_application.StartBiddingIn(_auction);
_auction.HasReceivedJoinRequestFromSniper();
_auction.AnnounceClosed();
_application.ShowsSniperHasLostAuction();
### 3 - Save and quit
wq
367
####################
### GOLF ENDS HERE - Total: 64 [HORRENDOUS!]
####################
### Output result
$ cat golf.txt
_auction.StartSellingItem();
_application.StartBiddingIn(_auction);
_auction.HasReceivedJoinRequestFromSniper();
_auction.AnnounceClosed();
_application.ShowsSniperHasLostAuction();
</code></pre></div></div>
<p>Whew! Well, that could have gone better… 64. OUCH. Let’s take a look at what went wrong. We learn from our mistakes, right?</p>
<p>As you can see, it took me three tries to get it right. The first time, I tried to use a new trick I learned from <a href="https://twitter.com/ed1conf/status/1107839605368385536">this tweet</a> and <a href="https://twitter.com/tpenguinltg/status/1107841838143234049">this tweet</a>. <code class="language-plaintext highlighter-rouge">&</code> references the matched text in a substitution’s search, so I figured I’d search for the text I want and substitute it back in. Obviously, that doesn’t work because it doesn’t address all the text I <em>don’t</em> want. Oops.</p>
<p>Next, I did what I should have done, search for the lines with the part I want to keep in a sub-expression that I can replace back in, without the cruft, via <code class="language-plaintext highlighter-rouge">\1</code>. However, on the second line, the regular expression didn’t do what I expected. The <code class="language-plaintext highlighter-rouge">_</code> matched with the second one on the line, not the first. I guess the regular expressions are not greedy by default. I thought they were.</p>
<p>Finally, third time’s the charm. In order to always match the correct <code class="language-plaintext highlighter-rouge">_</code>, I prepended a space to it in the regular expression. Success!</p>
<p>My score was terrible, but I learned a lot. Hopefully you did, too! I have to say, I like using the <code class="language-plaintext highlighter-rouge">g</code> (global) command for substitutions, since it outputs all the affected lines, instead of just the last affected line, like <code class="language-plaintext highlighter-rouge">s///g</code> does.</p>
<p>It shouldn’t be too hard to beat my score this time. However, if you have any new tips or tricks to share for this one, please do so in the comments or <a href="https://twitter.com/echosa">on Twitter</a>.</p>Brian ZwahrContinuing with our ed golf exercises, today we tackle one that is more relevant to programming than the previous ones. We also have the first big mistake… fun! Let’s jump into Applying same text modification in several lines!ed Golf: I Forgot Quotes2019-03-18T00:00:00+00:002019-03-18T00:00:00+00:00https://echosa.github.io/blog/2019/03/18/ed-golf-i-forgot-quotes<p>Well, since the <a href="/blog/2019/03/11/ed-golf-one-number-per-line/">previous ed golf</a> was so much fun and such a hit, especially on Twitter, let’s keep doing more! Today, the challenge is a pretty simple one. How low of a score we can get on <a href="http://www.vimgolf.com/challenges/5462e3f41198b80002512673">I Forgot Quotes</a>?</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ed
### Insert start file
i
foo = a
ab
abc
.
####################
### GOLF STARTS HERE
####################
### 16 - Insert quotes
,s/\(a.*\)/"\1"
"abc"
####################
### GOLF ENDS HERE - Total: 16
####################
### Output result
,p
foo = "a"
"ab"
"abc"
</code></pre></div></div>
<p>I was able to do this one with just a single substitution command for a score of 16. I think that’s pretty good! I just search for <code class="language-plaintext highlighter-rouge">a.*</code> and wrap all results in quotes - easy peasy!</p>
<p>However, looking back at it, I wonder if it would be less keystrokes to run two simpler substitutions rather than a combined one. Let’s find out.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ed
### Insert start file
i
foo = a
ab
abc
.
####################
### GOLF STARTS HERE
####################
### 8 - Insert starting quotes
,s/a/"a
"abc
### 7 - Insert ending quotes
,s/$/"
"abc"
####################
### GOLF ENDS HERE - Total: 15
####################
### Output result
,p
foo = "a"
"ab"
"abc"
</code></pre></div></div>
<p>Well, look at that! 15 strokes - one less than the combined substitution! Perhaps clever is not always best.</p>
<p>Is there a way to get a score of less than 15? I’d love to know! Comment below or <a href="https://twitter.com/echosa">on Twitter</a>.</p>
<p>Also, if you’re enjoying these ed golf posts, let me know! I’m certainly enjoying them, but I’ll definitely keep them coming if you do, too!</p>
<h3 id="update">Update</h3>
<p>Thanks to <a href="https://twitter.com/ed1conf/status/1107839605368385536">@ed1conf</a> and <a href="https://twitter.com/tpenguinltg/status/1107841838143234049">@tpenguinltg</a> for this awesomeness:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>,s/a.*/"&"
</code></pre></div></div>
<p>A score of 11! Amazing. I didn’t know that <code class="language-plaintext highlighter-rouge">&</code> is replaced with the entire matched context in substitutions. That will come in extremely handy in the future!</p>Brian ZwahrWell, since the previous ed golf was so much fun and such a hit, especially on Twitter, let’s keep doing more! Today, the challenge is a pretty simple one. How low of a score we can get on I Forgot Quotes?ed Golf: One Number Per Line2019-03-11T00:00:00+00:002019-03-11T00:00:00+00:00https://echosa.github.io/blog/2019/03/11/ed-golf-one-number-per-line<p>As I mentioned in my <a href="/blog/2019/03/06/learning-and-using-the-standard-editor/">last post</a>, I have been using the text editor ed for lots of things lately. In an effort to become more familiar with it and get some practice in, I have decided to try some <a href="https://www.vimgolf.com">VimGolf</a> exercises in ed! I don’t expect to beat the VimGolf scores. I do expect to learn more about ed, how to use it effectively, and try and see if I can find the minimum number of commands/keystrokes necessary for each exercise. So, without further ado, let’s take a look at our first exercise: <a href="https://www.vimgolf.com/challenges/56fb2e75ccffcc0009026473">One Number Per Line</a>.</p>
<p>The exercise is pretty simple. Take a file that has comma-separated numbers and change it so that each number is on its own line. In these posts, I’ll be posting commented ed sessions showing everything I’ve done between starting ed and getting the final result. For this challenge, here’s what I did:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ed
### Input start file
i
- One number per line -
-----------------------
2,3,5,7,
11,13,17,
19,23,29,
.
####################
### GOLF STARTS HERE
####################
### 6 - Delete all lines without a comma
v/,/d
### 3 - Join all lines into one
,j
### 10 - Replace all commas with newlines
,s/,/\
/g
### 2 - Delete trailing empty line
d
####################
### GOLF ENDS HERE - Total: 21
####################
### Output result
,p
2
3
5
7
11
13
17
19
23
29
</code></pre></div></div>
<p>As you can see, my score was 21. Not bad! At least, I don’t think so. However, I feel like there are some improvements that can be made, so let’s explore.</p>
<p>The first command I ran, <code class="language-plaintext highlighter-rouge">v/,/d</code>, scored 6 (we can’t forget to count pressing return/enter!). This command is what I used to get rid of the heading text by deleting all lines without commas. This works, of course, but we can do better. If we directly delete the heading text with <code class="language-plaintext highlighter-rouge">1,2d</code> (which deletes the first two lines), we can shave two points off of our score, giving us 19 instead.</p>
<p>I’m not able to see any other improvements, but I’m sure I’m missing something. If you see any ways to improve the score, let me know! Let’s all learn together!</p>Brian ZwahrAs I mentioned in my last post, I have been using the text editor ed for lots of things lately. In an effort to become more familiar with it and get some practice in, I have decided to try some VimGolf exercises in ed! I don’t expect to beat the VimGolf scores. I do expect to learn more about ed, how to use it effectively, and try and see if I can find the minimum number of commands/keystrokes necessary for each exercise. So, without further ado, let’s take a look at our first exercise: One Number Per Line.Learning and Using the Standard Editor2019-03-06T00:00:00+00:002019-03-06T00:00:00+00:00https://echosa.github.io/blog/2019/03/06/learning-and-using-the-standard-editor<p>It’s no secret that I enjoy text editors. Emacs. Vim. Acme. Even modern editors like VS Code. I don’t know why, but I just really like learning and using them. I’ve even written about them many times on this blog. So it shouldn’t surprise anyone that I would turn my attention to ed(1) at some point.</p>
<p>Well, that point is now. For a few months, I’ve been learning to use, and actually using, ed(1) (which I’ll just refer to as ed for the rest of this article). Ed pre-dates most other text editors. It was used before monitors were even a thing, when computer output was all printed on paper. It was the main editor used while things like Unix were being created. Because of this history and heritage, ed has been given the moniker of the Standard Editor.</p>
<p>Of course, calling it that at this point is half true, half tongue-in-cheek. While there is some claim for it, the entire idea of it has become something of a <a href="https://www.gnu.org/fun/jokes/ed-msg.txt">joke</a>. You can see countless posts across the Internet, especially on Reddit, claiming ed’s standard-ness, both as a joke and as a serious topic for discussion. I don’t make any claims of it being “standard”, but I do claim that it is still relevant and useful today.</p>
<p>It’s easy to overlook ed or pass it up. It’s old. It’s weird. It seems really useless at first glance. Honestly, for many things, I’d say it is useless. I wouldn’t use it to program a giant Symfony project in PHP, for sure. My IDE is too helpful to give up for even newer editors like VS Code, let alone something like ed. However, for quick edits (like editing dotfiles) or plain-text writing (like this post), ed is actually quite good at what it does! This post is being written in ed right now, in fact. Even more than that, almost everything I’ve done since reviving this blog has been done using ed.</p>
<p>Describing ed is a bit tricky. The best way to really understand it is to use it. So, to everyone reading this, I recommend giving ed a shot. Even if you hate it or never use it again, I think it’s a good exercise to learn it. You’ll gain a new way of thinking about editing text, you’ll gain new skills and a new appreciation for regular expressions, and, if nothing else, you’ll learn first-hand about some important computer history.</p>
<p>So, where to start? Well, install it. Most (but not all) Linux distributions already have ed. macOS also has ed, but it is the BSD version. I prefer GNU ed, which I installed on macOS through <a href="https://brew.sh">Homebrew</a> with <code class="language-plaintext highlighter-rouge">brew install ed</code>. I’m not sure about Windows. I imagine there’s a version of ed for Windows, or maybe it needs to be run with Cygwin or Windows 10’s built-in Linux subsystem.</p>
<p>Next, I recommend reading the man page. If it didn’t get installed, you can always <a href="https://www.systutorials.com/docs/linux/man/1-ed/">find it online</a>. This will give you a brief explanation of how ed works but honestly doesn’t serve as a good teaching tool for new users. For that, I recommend the following three resources.</p>
<p>First and foremost, I recommend the book <a href="https://www.tiltedwindmillpress.com/product/ed/">Ed Mastery</a> by Michael W. Lucas. Not only is it a wonderful and modern teaching tool for ed, the author’s writing style makes it fun to read! I had difficulty putting this book down like it was a fiction novel. Seriously. This book is worth every penny, I promise.</p>
<p>If you’re looking for something a little less lengthy, there’s a wonderful blog post from 2012 by Tom Ryder called <a href="https://sanctum.geek.nz/arabesque/actually-using-ed/">Actually using ed</a>. I read this before I bought Ed Mastery, and it was a great “quick start” of sorts.</p>
<p>Finally, the Twitter account <a href="https://twitter.com/ed1conf">@ed1conf</a> has been very helpful in answering any questions that I’ve asked. Keep in mind, that’s not some sort of official support Twitter account or anything. It’s just some person (as far as I know) who has has taken the time to help me, for which I am extremely grateful. I only mention this because I don’t recommend flooding the account with questions.</p>
<p>I could continue here by trying to explain ed, showing how it works, etc. I won’t do that, though. I feel I couldn’t do it justice, and the resources I’ve already mentioned are way better than anything I would produce here. I will repeat this, though: ed is best learned by doing. Install it. Run it. Try it!</p>
<p>If you do try ed, or if you already use it, I’d like to hear about it! Leave a comment here or on <a href="https://twitter.com/echosa">Twitter</a>. I’ve already have several conversations about ed on Twitter, actually, and I’ve seen other people comment the same thought I’ve had: I didn’t realize how big of a following/user base ed still has! My tweets about ed have been some of my most reacted to and responded to. That still amazes (and amuses) me.</p>
<p>ed, man! !man ed</p>Brian ZwahrIt’s no secret that I enjoy text editors. Emacs. Vim. Acme. Even modern editors like VS Code. I don’t know why, but I just really like learning and using them. I’ve even written about them many times on this blog. So it shouldn’t surprise anyone that I would turn my attention to ed(1) at some point.New Comments System - Staticman!2019-03-05T00:00:00+00:002019-03-05T00:00:00+00:00https://echosa.github.io/blog/2019/03/05/new-comments-system<p>As I mentioned in my previous post I wrote about the new site theme and layout, I have now switched the comment system here from Disqus to <a href="https://staticman.net/">Staticman</a>! Right now, all the previous Disqus comments are not available. However, I eventually plan on manually adding them all here Staticman comments instead. Until that happens, though, only new comments will appear. Note that comments require approval before appearing on the page.</p>
<p>Happy commenting!</p>Brian ZwahrAs I mentioned in my previous post I wrote about the new site theme and layout, I have now switched the comment system here from Disqus to Staticman! Right now, all the previous Disqus comments are not available. However, I eventually plan on manually adding them all here Staticman comments instead. Until that happens, though, only new comments will appear. Note that comments require approval before appearing on the page.A New Look!2019-03-01T00:00:00+00:002019-03-01T00:00:00+00:00https://echosa.github.io/blog/2019/03/01/a-new-look<p>As mentioned in the last post, I was looking for a new theme for this blog. Well, I found it! I’m now using the awesome <a href="https://mmistakes.github.io/">Minimal Mistakes</a> theme for Jekyll. It looks great. It’s easy to configure. I highly recommend it! Hopefully you like it as much as I do!</p>
<p>I’m still looking into replacing Disqus for comments, but I haven’t quite gotten there yet. I’m currently looking into <a href="https://staticman.net/">Staticman</a>, which seems super cool and exactly what I want. I’ll be trying to switch away from Disqus soon. My hope is that I’ll be able to import or convert all existing comments. If not, however, I’m sorry for losing the existing comments.</p>
<p>So, now that I’ve got the blog configured, revamped, and lookin’ good, I can start focusing on posting content again! I’ve got an idea or two for upcoming posts/series, so stay tuned! I think you’ll enjoy it.</p>Brian ZwahrAs mentioned in the last post, I was looking for a new theme for this blog. Well, I found it! I’m now using the awesome Minimal Mistakes theme for Jekyll. It looks great. It’s easy to configure. I highly recommend it! Hopefully you like it as much as I do!Blog Resurrection and Revamp!2019-02-21T00:00:00+00:002019-02-21T00:00:00+00:00https://echosa.github.io/blog/2019/02/21/blog-resurrection-and-revamp<p>It’s been a long, long time since I did anything with this blog. I think it’s time to bring it back!</p>
<p>First and foremost, you’ll notice a new look. I’ve moved away from using <a href="http://octopress.org">Octopress</a> and am now just using straight <a href="https://jekyllrb.com">Jekyll</a>. For now, I’m using the default theme, <a href="https://github.com/jekyll/minima">Minima</a>. I’ll be keeping my eye out for a more full-featured theme in the future (specifically looking for one that handles tags). I’m open to suggestions!</p>
<p>Now, what about content? Well, for the most part, the content will be the same: programming, software, etc. I’ve got a couple of new ideas and series’ in the works, though, so stay tuned!</p>
<p>I’m still getting used to the new site myself, so you might see it change in the near future as I poke, prod, and tweak it. Either way, it’s good to be back, and I hope everyone enjoys the posts to come!</p>Brian ZwahrIt’s been a long, long time since I did anything with this blog. I think it’s time to bring it back!Git, GPG, and IDE2016-08-18T00:00:00+00:002016-08-18T00:00:00+00:00https://echosa.github.io/blog/2016/08/18/git-gpg-ide<p>Today, I discovered that <code class="language-plaintext highlighter-rouge">git</code> allows for signing commits and tags with <code class="language-plaintext highlighter-rouge">gpg</code>. Awesome. However, I’ve gotten rather used to using the git integration in IntelliJ’s IDEA IDE, which is actually quite nice. In order to get the git/gpg stuff working, though, a few tweaks were required. I’m writing those here so I can remember them in the future.
<!--more-->
A quick overview of the problem and the solution. The issue is that when you tell git to sign commits or tags (either via a command line argument or git config change), gpg will require your passphrase for the key. Makes sense. If you’re using git from the command line, there’s no issue. However, since gpg defaults to a CLI prompt for the password, if you try to make a git commit from an external program (say, an IDE, like IntelliJ IDEA), you won’t be prompted for a passphrase and the commit won’t be made. The solution, then, is to get gpg to ask for the passphrase in a way compatible with external applications, beyond pure CLI usage.</p>
<p>Note: these instructions will be specific to OS X (soon to be macOS [again]).</p>
<p>Required installs (can be installed with <a href="http://brew.sh">homebrew</a>): git, gpg, pinentry-mac</p>
<ol>
<li>
<p>Create a new gpg key (or use an existing one), and configure git to use it. GitHub has <a href="https://help.github.com/articles/generating-a-gpg-key/">excellent documentation</a> about how to do this.</p>
</li>
<li>
<p>Tell gpg to use a GUI program, not the terminal, to ask for passphrase when signing things by adding this to <code class="language-plaintext highlighter-rouge">~/.gnupg/gpg.conf</code>:</p>
</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>no-tty
use-agent
</code></pre></div></div>
<ol>
<li>Tell gpg-agent to use the <code class="language-plaintext highlighter-rouge">pinentry-mac</code> program by adding this to <code class="language-plaintext highlighter-rouge">~/.gnupg/gpg-agent.conf</code> (you’ll need to create the file if it doesn’t exist):</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pinentry-program /usr/local/bin/pinentry-mac
</code></pre></div></div>
<p>The pinentry-mac program exactly as it sounds: a pin entry program for Macs. This is the GUI program that will replace the default CLI passphrase prompt.</p>
<ol>
<li>[Optional] If you don’t want to have to tell git to sign every commit manually by using <code class="language-plaintext highlighter-rouge">git commit -S</code>, you can tell git to always sign. I’ve done so globally, but you could do so on a project-by-project basis:</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config --global commit.gpgsign true
</code></pre></div></div>
<p>Now, whenever you commit and have git sign with gpg, you’ll be prompted with a GUI popup instead of gpg trying to ask for a password on the command-line. Added bonus: pinentry-mac allows you to check “Save in keychain” so you don’t have to put in your passphrase every single time. <em>WARNING</em> Only select this option if your computer already has other security precautions, is not used by anyone else, and is safe and secure. Otherwise, anyone with access to your computer would be able to make commits signed by your key!</p>
<p>So, there you have it. That should be all that’s required to get git’s gpg signing playing nice with external programs.</p>
<p>One last thing: just so you know, GitHub now has <a href="https://github.com/blog/2144-gpg-signature-verification">built-in GPG verification</a>.</p>Brian ZwahrToday, I discovered that git allows for signing commits and tags with gpg. Awesome. However, I’ve gotten rather used to using the git integration in IntelliJ’s IDEA IDE, which is actually quite nice. In order to get the git/gpg stuff working, though, a few tweaks were required. I’m writing those here so I can remember them in the future. A quick overview of the problem and the solution. The issue is that when you tell git to sign commits or tags (either via a command line argument or git config change), gpg will require your passphrase for the key. Makes sense. If you’re using git from the command line, there’s no issue. However, since gpg defaults to a CLI prompt for the password, if you try to make a git commit from an external program (say, an IDE, like IntelliJ IDEA), you won’t be prompted for a passphrase and the commit won’t be made. The solution, then, is to get gpg to ask for the passphrase in a way compatible with external applications, beyond pure CLI usage.