My favourite small tools, scripts and aliases
Published: 2022-06-19 01:32:54

---
title: My favourite small tools, scripts and aliases
published: true
date: 2022-06-14 14:45:00 UTC
tags: 
canonical_url: https://kevincox.ca/2022/06/14/small-tools/
---

<main style="--width:min(36em,100%);display:grid;grid-template-columns:1fr var(--width) 1fr;overflow:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;padding:0"><p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">I enjoyed reading <a href="https://jvns.ca/blog/2022/03/08/tiny-programs/" style="margin:0;box-sizing:border-box;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">Julia Evans’ post on Tiny Personal Programs</a> so I thought I would share some of my own. I’m hoping that they can be useful for others to copy or at least consider if they can steal some useful parts of my workflow.</p>
<aside style="box-sizing:border-box;grid-column:2;margin:.2em 1em .6em;padding:.4em;background:#333;color:#fff;box-shadow:4px 4px 8px #000;background:#600"><p style="margin:0;box-sizing:border-box"><strong style="margin:0;box-sizing:border-box">Warning</strong>: These tools are use-at-your-own-risk. They work well for me but aren’t “production” ready or necessarily hardened in any way.</p></aside><p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Also note that all the shell scripts are written in ZSH. I’ve also summarized some of them, so they may require small adjustments to run on your machine.</p>
<h2 id="w" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#w" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">w (watch)</a></h2>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">This program is a cornerstone of my everyday life. So important that I gave it a one-letter name shadowing a classic UNIX utility.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">The current source is simply this:</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">f</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">${</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">XDG_RUNTIME_DIR</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">:-</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">/tmp</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">}</span>/save
<span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">[</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-e</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$f</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">]</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">||</span> <span style="margin:0;box-sizing:border-box;padding:0">touch</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$f</span>
<span style="margin:0;box-sizing:border-box;padding:0">exec </span>entr <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-r</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$@</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">&lt;&lt;&lt;</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$f</span>
</code></pre></div>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">It is just a tiny wrapper around <a href="https://eradman.com/entrproject/" style="margin:0;box-sizing:border-box;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">entr</a>, a brilliantly simple program to watch files and run programs.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">They key innovation is that I realized that I don’t need to bother telling entr which files to watch 99% of the time. I can save myself brainpower and avoid requiring a restart when files are added or renamed by just telling it to watch a specific file, then I just touch that file whenever I want a rerun.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Almost all of my updates come from when I save a file. I have a simple keybind in Vim to save and touch this file.</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">let</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">g:touchfile</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#999">=</span> <span style="margin:0;box-sizing:border-box;padding:0">expand</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">(</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'$XDG_RUNTIME_DIR/save'</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">)</span>
nnoremap <span style="margin:0;box-sizing:border-box;padding:0;color:#999">&lt;</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">silent</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">&gt;</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#999">&lt;</span>Leader<span style="margin:0;box-sizing:border-box;padding:0;color:#999">&gt;</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">w</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#999">:</span>echo <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'No changed files.'</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">&lt;</span>CR<span style="margin:0;box-sizing:border-box;padding:0;color:#999">&gt;:</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">wa</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">&lt;</span>CR<span style="margin:0;box-sizing:border-box;padding:0;color:#999">&gt;:</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">call</span> <span style="margin:0;box-sizing:border-box;padding:0">writefile</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">([],</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">g:touchfile</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">)&lt;</span>CR<span style="margin:0;box-sizing:border-box;padding:0;color:#999">&gt;</span>
</code></pre></div>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Instead of doing <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">:w</code> or <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">:wa</code> I just do <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">&lt;Leader&gt;w</code> and it saves everything, then touches the magic file.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">My dev workflow almost always consists of some program running under <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">w</code> on the left side of my screen and it re-runs every time I save my editor on the right side of the screen.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">A random selection of commands from my shell history:</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff">w cargo <span style="margin:0;box-sizing:border-box;padding:0">test
</span>w d python3 ./test.py

<span style="margin:0;box-sizing:border-box;padding:0;color:#ccc;font-style:italic;white-space:pre-wrap"># Using a command rather than an alias works great with "nested" commands.</span>
nix-shell <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-A</span> ecl <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--run</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'w cargo run'</span>

<span style="margin:0;box-sizing:border-box;padding:0;color:#ccc;font-style:italic;white-space:pre-wrap"># Build my site, then do a word-diff against a reference copy.</span>
w zsh <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-c</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'nix-build -A www &amp;&amp; git dw /nix/store/0nf7l88dpbjfzp64lfmiyl8c52xgip85-kevincox.ca result/ | cat'</span>

<span style="margin:0;box-sizing:border-box;padding:0;color:#ccc;font-style:italic;white-space:pre-wrap"># Build and upload a docker image on save.</span>
w zsh <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-c</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'nix-build -A docker &amp;&amp; podman load &lt;result &amp;&amp; podman push nix-ci:latest registry.gitlab.com/kevincox/nix-ci:test'</span>
</code></pre></div>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">You get the idea. If you can think of a command you can run it on save. Don’t bother worrying about what files and directories you want to watch and don’t worry about the time to set up watches over large directories. Just call <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">w</code> and save.</p>
<h2 id="d" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#d" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">d</a></h2>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Mostly a companion on <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">w</code>, it adds a number of useful behaviours to commands.</p>
<ol style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">
<li style="margin:0;box-sizing:border-box">Sets up completion notification. So that if a command completes while I am not focused on the terminal I get a desktop notification.</li>
<li style="margin:0;box-sizing:border-box">Prints starting and stopping messages. Some commands are a bit too quiet and it is hard to tell if they are running or have already finished and you are waiting for nothing. This message also includes the expanded command and some resource utilization stats.</li>
</ol>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">if</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">[[</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$VTE_VERSION</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-ge</span> 3405 <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">]]</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">;</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">then
	</span><span style="margin:0;box-sizing:border-box;padding:0">echo</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-n</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">$'</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">\e</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">]777;preexec</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">\e\\</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">fi

</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">color</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">$'</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">\e</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">[2m'</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">nocolor</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">$'</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">\e</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">[0m'</span>

<span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">formatted</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">${</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">(@q-)@</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">}</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span>

<span style="margin:0;box-sizing:border-box;padding:0">echo</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">${</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">color</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">}</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">Starting </span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$formatted$nocolor</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span> 1&gt;&amp;2
<span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">TIMEFMT</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">${</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">color</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">}</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">Done. Total: %*E (%P), User: %*U, System: %*S - </span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$formatted$nocolor</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">if</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">[[</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$VTE_VERSION</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-ge</span> 3405 <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">]]</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">;</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">then
	</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">TIMEFMT</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">$'</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">\e</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">]777;precmd</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">\e\\</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$TIMEFMT</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">fi
</span><span style="margin:0;box-sizing:border-box;padding:0">time</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">(</span><span style="margin:0;box-sizing:border-box;padding:0">exec</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$@</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">)</span>
</code></pre></div>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Another “feature” is that this serves as an easy way to launch a shell. Running <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">d eval "foo &amp;&amp; bar"</code> will run the argument in the shell which is just a bit less typing than <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">zsh -c "foo &amp; bar"</code>.</p>
<h2 id="c" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#c" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">c (clipboard)</a></h2>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Another one important enough for a one-letter name.</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff">xsel <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--clipboard</span>
</code></pre></div>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Ok, this could be an alias at this point. But over the years this has been updated to support different operating systems and use different tools to implement the command. It is also nice to have a “real” executable on your <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">$PATH</code>.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">It comes in handy all the time. Especially since it is the easiest way to get data from programs like a web browser into a command or file without worrying about escaping. In ZSH <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">$(</span>c<span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">)</span></code> is even binary-safe!</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#ccc;font-style:italic;white-space:pre-wrap"># base64 decode your clipboard.</span>
c | <span style="margin:0;box-sizing:border-box;padding:0">base64</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-d</span>

<span style="margin:0;box-sizing:border-box;padding:0;color:#ccc;font-style:italic;white-space:pre-wrap"># Generate a UUID and put it in the clipboard.</span>
uuidgen | c

<span style="margin:0;box-sizing:border-box;padding:0;color:#ccc;font-style:italic;white-space:pre-wrap"># Process the clipboard and put it back into the clipboard afterwards.</span>
c | <span style="margin:0;box-sizing:border-box;padding:0">tr </span>A-Z a-z | c
</code></pre></div>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">I also use this frequently in my reliance on shell history. I will commonly call up commands like the following where a common variable part is pulled from the clipboard so that I can quickly reuse the command with no editing. (I should probably make these into scripts or aliases one day but shell history is just such low overhead and easy to tweak over time.)</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#ccc;font-style:italic;white-space:pre-wrap"># Show an HTTP response with headers in my editor. (expects the URL in the clipboard)</span>
curl <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-i</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">$(</span>c<span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">)</span> | v

<span style="margin:0;box-sizing:border-box;padding:0;color:#ccc;font-style:italic;white-space:pre-wrap"># Test building a nixpkgs patch. (expects PR ID or URL in the clipboard)</span>
nixpkgs-review <span style="margin:0;box-sizing:border-box;padding:0">pr</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">$(</span>c<span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">)</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--no-shell</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--post-result</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-c</span> commit
</code></pre></div>
<h2 id="watchlog" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#watchlog" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">watchlog</a></h2>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">This one is actually a full program. It is useful to throw onto the end of something that is streaming logs or otherwise slowly making progress. It gives you an idea of when progress was last made as well as injects some timestamps in to the logs during pauses.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2"><a href="https://gitlab.com/kevincox/watchlog" style="margin:0;box-sizing:border-box;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">watchlog</a></p>
<h2 id="crypt" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#crypt" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">crypt</a></h2>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">From time to time I need to insert a password hash somewhere. The UNIX <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">crypt</code> format is a common standard for upgradable password hashes. I have a small wrapper that can generate or check password hashes.</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">import</span> <span style="margin:0;box-sizing:border-box;padding:0">crypt</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">import</span> <span style="margin:0;box-sizing:border-box;padding:0">getpass</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">import</span> <span style="margin:0;box-sizing:border-box;padding:0">sys</span>

<span style="margin:0;box-sizing:border-box;padding:0">p</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span> <span style="margin:0;box-sizing:border-box;padding:0">getpass</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">.</span><span style="margin:0;box-sizing:border-box;padding:0">getpass</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">()</span>

<span style="margin:0;box-sizing:border-box;padding:0">argc</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span> <span style="margin:0;box-sizing:border-box;padding:0">len</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">(</span><span style="margin:0;box-sizing:border-box;padding:0">sys</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">.</span><span style="margin:0;box-sizing:border-box;padding:0">argv</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">)</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">if</span> <span style="margin:0;box-sizing:border-box;padding:0">argc</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">==</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#ffb433">1</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">:</span>
	<span style="margin:0;box-sizing:border-box;padding:0">salt</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span> <span style="margin:0;box-sizing:border-box;padding:0">None</span>
	<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">assert</span> <span style="margin:0;box-sizing:border-box;padding:0">p</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">==</span> <span style="margin:0;box-sizing:border-box;padding:0">getpass</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">.</span><span style="margin:0;box-sizing:border-box;padding:0">getpass</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">(),</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"Passwords not the same"</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">elif</span> <span style="margin:0;box-sizing:border-box;padding:0">argc</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">==</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#ffb433">2</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">:</span>
	<span style="margin:0;box-sizing:border-box;padding:0">salt</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span> <span style="margin:0;box-sizing:border-box;padding:0">sys</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">.</span><span style="margin:0;box-sizing:border-box;padding:0">argv</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">[</span><span style="margin:0;box-sizing:border-box;padding:0;color:#ffb433">1</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">]</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">else</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">:</span>
	<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">raise</span> <span style="margin:0;box-sizing:border-box;padding:0">ArgumentError</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">(</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"Too many arguments. Expected 0 or 1"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">)</span>

<span style="margin:0;box-sizing:border-box;padding:0">hash</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span> <span style="margin:0;box-sizing:border-box;padding:0">crypt</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">.</span><span style="margin:0;box-sizing:border-box;padding:0">crypt</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">(</span><span style="margin:0;box-sizing:border-box;padding:0">p</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">,</span> <span style="margin:0;box-sizing:border-box;padding:0">salt</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0">salt</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">)</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">print</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">(</span><span style="margin:0;box-sizing:border-box;padding:0">hash</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">)</span>

<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">if</span> <span style="margin:0;box-sizing:border-box;padding:0">salt</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">:</span>
	<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">if</span> <span style="margin:0;box-sizing:border-box;padding:0">hash</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">==</span> <span style="margin:0;box-sizing:border-box;padding:0">salt</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">:</span>
		<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">print</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">(</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"Match"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">);</span>
	<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">else</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">:</span>
		<span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">print</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">(</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"No Match"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">)</span>
		<span style="margin:0;box-sizing:border-box;padding:0">sys</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">.</span><span style="margin:0;box-sizing:border-box;padding:0">exit</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">(</span><span style="margin:0;box-sizing:border-box;padding:0;color:#ffb433">1</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">)</span>
</code></pre></div>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Just call <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">crypt</code> to generate a hash or <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">crypt $hash</code> to check it.</p>
<h2 id="u-unix-timestamp" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#u-unix-timestamp" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">u (UNIX timestamp)</a></h2>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">A simple tool to take a number and guess what time it represents. (Is that timestamp in ns, ms or s???)</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">It can take an argument or pull a number from your clipboard, but the core code looks like this.</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">t</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$1</span>
<span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">t</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">$(</span>perl <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-e</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'$i=$ARGV[1];while($i&gt;1e10){$i/=1000}print($i)'</span> tos <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">${</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">t</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">//[^0-9.]/</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">}</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">)</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span>
<span style="margin:0;box-sizing:border-box;padding:0">date</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"-d@</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$t</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--rfc-3339</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span>ns <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$@</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span>
</code></pre></div>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff">% u 1655150354 # UNIX seconds
2022-06-13 15:59:14.000000000-04:00
% u 1653150192354 # UNIX ms
2022-05-21 12:23:12.354000000-04:00
</code></pre></div>
<h2 id="r" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#r" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">r (retry)</a></h2>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">A simple tool to retry commands. It takes a command as an argument and retries it until it succeeds. It supports options for target exit code, delay and max attempts.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Example: Keep retrying a download on a flakey endpoint.</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff">r <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--delay</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span>10 wget <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--continue</span> https://example.com/somefile.tar.gz
</code></pre></div>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Example: keep tailing kube logs even if the pod restarts. (<code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">-u=-1</code> means <strong style="margin:0;box-sizing:border-box">u</strong>ntil the process returns -1, AKA forever)</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff">r <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-u</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-1</span> kubectl logs <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-f</span> deployment/something
</code></pre></div>
<h2 id="git" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#git" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">Git Tools</a></h2>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">I use git and here is a quick subsection for aliases and commands (for when <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">git x</code> is 4 characters too long).</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">For context here is a convention for my git checkouts. I have <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">origin</code> set to a repo that I have write access to. For example, my personal fork. I set <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">u</code> to the upstream repo. For my projects this may be the same as <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">origin</code> but for other projects this is likely a repo that I don’t have write-access to.</p>
<h3 id="ga" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#ga" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">ga (git amend)</a></h3>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Before publishing, history-rewriting is great. I have a quick alias for quickly merging a fixup into an existing commit.</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff">git commit <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--amend</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--no-edit</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$@</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span>
</code></pre></div>
<h3 id="gf" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#gf" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">gf (git force)</a></h3>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">If you don’t know about <a href="https://git-scm.com/docs/git-push#Documentation/git-push.txt---force-with-leaseltrefnamegtltexpectgt" style="margin:0;box-sizing:border-box;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey"><code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">git push --force-with-lease</code></a> you should really read up! It is similar to plain-old <a href="https://git-scm.com/docs/git-push#Documentation/git-push.txt---force" style="margin:0;box-sizing:border-box;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey"><code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">--force</code></a> but provides an important safety feature. Instead of blindly overwriting whatever is at the target it checks that what you <em style="margin:0;box-sizing:border-box">thought</em> was there is actually there. For example, it may avoid you from overwriting a colleague’s work if they pushed to your branch with a fix. It definitely isn’t perfect (at least not with explicitly specifying which commit you expect) but at least catches some common mistakes.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">But that is a mouthful to spell out and I use this frequently with development branches. So I like the short name. This allows me to simply run <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">gf</code> and is frequently paired like <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">ga &amp;&amp; gf</code> to merge local changes into an existing commit and push the result.</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff">git push <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--force-with-lease</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$@</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"</span>
</code></pre></div>
<h3 id="git-clean-merged" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#git-clean-merged" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">git-clean-merged</a></h3>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">This deletes any branches that are subsets of the <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">HEAD</code> ref on the <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">u</code> remote. For my work this means that they have been fully integrated into the upstream project.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Note that I don’t make any effort to avoid some errors like deleting the current branch. Instead, I just let git emit a nice warning in the log.</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">branch</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">${</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">1</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">-refs/remotes/u/HEAD</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">}</span>
<span style="margin:0;box-sizing:border-box;padding:0">echo</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">"Deleting branches merged into </span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$branch</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">."</span>

git branch <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--merged</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$branch</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--format</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'%(refname:lstrip=2)'</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">\</span>
	| <span style="margin:0;box-sizing:border-box;padding:0">grep</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-vFx</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$branch</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">\</span>
	| <span style="margin:0;box-sizing:border-box;padding:0">grep</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-v</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'\(detached at [0-9a-f]*\)'</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">\</span>
	| xargs <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-r</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--</span> git branch <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-D</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">--</span>
</code></pre></div>
<h3 id="gn" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#gn" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">gn (git new)</a></h3>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">A fast way to start a new branch. This is based off of whatever the <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">HEAD</code> ref of the <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">u</code> remote is. I have this set to be the branch that I want to start new changes off of.</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">branch</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$1</span>

git fetch u
git checkout u

<span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">[[</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-n</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$branch</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">]]</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">&amp;&amp;</span> git branch <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$branch</span>
</code></pre></div>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">This is similar to <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">git checkout master &amp;&amp; git pull</code> but has a key advantage; this doesn’t leave you on the main branch, so you can’t accidentally push it, and you won’t create an accidental merge if your local master is dirty.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">I typically don’t pass the branch name argument. This leaves me in a “detached HEAD state”. The downside is that it is easier to lose your work because it doesn’t have an easy to find name. However, <a href="https://git-scm.com/docs/git-reflog" style="margin:0;box-sizing:border-box;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">git reflog</a> is my friend, so it isn’t a major concern. I prefer to defer giving branches names because I can often think of something more meaningful once I have played around with the code a bit.</p>
<h3 id="gs" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#gs" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">gs (git switch)</a></h3>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">This is a simple command for switching branches. The main reason I use this command is that it is the same to create or switch to a branch. This means that I can type <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">gs &lt;Up&gt;</code> to search my shell history for recent branches and just run the command again to switch to it. I find this much more convenient than <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">git switch -c &lt;Up&gt;</code> then switching the command to <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">git branch</code> once I find it.</p>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">It also has a small convenience feature where you can run <code style="margin:0;box-sizing:border-box;white-space:pre;padding:.1em;border-radius:.3em;background:#000;border:1px solid #555;color:#fff">gs</code> with no arguments to switch to the “main” branch.</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">branch</span><span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">=</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">${</span><span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">1</span><span style="margin:0;box-sizing:border-box;padding:0;color:#999">-</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">$(</span>git symbolic-ref refs/remotes/origin/HEAD | <span style="margin:0;box-sizing:border-box;padding:0">sed</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">'s#^refs/remotes/origin/##'</span><span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">)</span><span style="margin:0;box-sizing:border-box;padding:0;color:#8585e0;font-weight:700">}</span>
git switch <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$branch</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#f5a3a3;font-weight:700">||</span> git switch <span style="margin:0;box-sizing:border-box;padding:0;color:#aaf">-c</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#759ef0">$branch</span>
</code></pre></div>
<h3 id="git-b" style="box-sizing:border-box;grid-column:2;margin:.4em 1rem .8em"><a href="https://kevincox.ca/2022/06/14/small-tools/#git-b" style="margin:0;box-sizing:border-box;text-decoration:inherit;color:inherit!important;text-shadow:inherit!important;text-decoration:underline;-webkit-text-decoration-color:grey;text-decoration-color:grey">git b (git branches)</a></h3>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Show “active” branches in my checkout</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff"><span style="margin:0;box-sizing:border-box;padding:0">[alias]</span>
<span style="margin:0;box-sizing:border-box;padding:0">b</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#999">=</span> <span style="margin:0;box-sizing:border-box;padding:0;color:#b3d733">branch -v --no-merged HEAD</span>
</code></pre></div>
<p style="box-sizing:border-box;margin:0 1rem .8em;grid-column:2">Gives some tidy output like:</p>
<div style="box-sizing:border-box;padding:0;grid-column:2;grid-column:1/4;margin:0 0 .8em;display:grid;grid-template-columns:1fr var(--width) 1fr;background:#222;border-top:1px solid #444;border-bottom:1px solid #444;overflow-x:auto"><pre style="box-sizing:border-box;grid-column:2;margin:.4em 1rem"><code style="margin:0;box-sizing:border-box;white-space:pre;background:none!important;color:#fff">% git b
  renovate/tonic-0.x 670b383 Update Rust crate tonic to 0.7.2
  secure-websub f8e3737 Don't use HTTP WebSub hubs for HTTPS feeds.
</code></pre></div></main>