<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>The Efficient Programmer</title>
    <description></description>
    <link>http://www.the-efficient-programmer.com/</link>
    <atom:link href="http://www.the-efficient-programmer.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 07 Jan 2023 14:05:33 +0100</pubDate>
    <lastBuildDate>Sat, 07 Jan 2023 14:05:33 +0100</lastBuildDate>
    <generator>Jekyll v4.2.2</generator>
    
      <item>
        <title>Faster Command Execution</title>
        <description>&lt;p&gt;I had presented in a previous &lt;a href=&quot;/shell/endless-command-execution.html&quot;&gt;post&lt;/a&gt; how I can easily rerun a previous command on the command line.
I used this approach to speed the edit-run cycle for scripting.
A better way yet is to use a custom Vim binding to execute the previous command using tmux’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;send-keys&lt;/code&gt; mechanism.
Furthermore, one can directly switch to the tmux window where that command is running.&lt;/p&gt;

&lt;p&gt;The necessary tmux commands are the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Send the keys &quot;Up&quot; (arrow up) and &quot;Enter&quot; to the pane &amp;lt;pane&amp;gt; in window &amp;lt;window&amp;gt;.&lt;/span&gt;
tmux send-keys &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; :&amp;lt;window&amp;gt;.&amp;lt;pane&amp;gt; Up Enter
&lt;span class=&quot;c&quot;&gt;# Switch to the last (previously active) window.&lt;/span&gt;
tmux &lt;span class=&quot;k&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-window&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; :&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;last&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If we switch to the last window and then send the keys, we do not even have to give &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux send-keys&lt;/code&gt; the target window/pane because by default the currently active pane is used.
This results in the following Vim mapping:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vim&quot; data-lang=&quot;vim&quot;&gt;&lt;span class=&quot;c&quot;&gt;&quot; Save current file and rerun previous command in previous tmux window.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;up&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'silent !tmux select-window -t :{last} &amp;amp;&amp;amp; tmux send-keys Up Enter'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This works right after one has executed the command in question once in the other (i.e. non-Vim) tmux window.
From that point on, pressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;leader&amp;gt;t&lt;/code&gt; results in “instant” script execution.&lt;/p&gt;

&lt;p&gt;You can see the desired behavior in the following video.
In tmux window 1, a shell script is executed once.
In window 0, Vim is used to modify the script.
After pressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;leader&amp;gt;t&lt;/code&gt;, the script is saved, tmux jumps to back to window 1 and executes the previous command (i.e. the script) again.
All in one go.&lt;/p&gt;

&lt;video width=&quot;320&quot; height=&quot;240&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;../noncode/vim-tmux-faster-command-execution.ogv&quot; /&gt;
&lt;/video&gt;
</description>
        <pubDate>Tue, 09 Jul 2019 00:00:00 +0200</pubDate>
        <link>http://www.the-efficient-programmer.com/shell/faster-command-execution.html</link>
        <guid isPermaLink="true">http://www.the-efficient-programmer.com/shell/faster-command-execution.html</guid>
        
        
        <category>shell</category>
        
      </item>
    
      <item>
        <title>Run SQL Queries In Background</title>
        <description>&lt;p&gt;When working with a large database, some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELECT&lt;/code&gt; queries can take really long.
And “really long” starts at a minute or two, of course.
When designing queries, one often limits the result set because one is not yet actually interested in the final data.&lt;/p&gt;

&lt;p&gt;However, you’ll want to have the result eventually.
In the meantime, you probably want to play around further with your queries.
But you don’t want to keep your current database connection (say, the GUI used for query design) busy.
I happen to be in this situation quite often and have written a little script which allows me to run the queries in the background.&lt;/p&gt;

&lt;p&gt;I had the following requirements&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Flexible parametrization&lt;/li&gt;
  &lt;li&gt;Measure execution time&lt;/li&gt;
  &lt;li&gt;Keep results&lt;/li&gt;
  &lt;li&gt;Allow to reproduce the data easily&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The script works as allows:
One has to provide a file containing the query to be executed.
The input file gets copied (for traceability/reproducibility) and executed.
Execution time gets logged and one can provide further arguments like hostname or user/password.&lt;/p&gt;

&lt;p&gt;After a couple of iterations, below is what the final script looks like.
It is tied to MySQL but that doesn’t matter and can be adapted to your needs, of course.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;QUERYFILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;OUTDIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;ARGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;:3&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# everything but the first 2 arguments&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;$#&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-le&lt;/span&gt; 1 &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$QUERYFILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Usage: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; /path/to/query.sql /path/to/existing/outdir [mysql arguments]&quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;fi
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;OUTFILEPREFIX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTDIR&lt;/span&gt;/&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;QUERYFILE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;_&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt; +%Y%m%d_%H%M%S&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Query:&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$QUERYFILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Results: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTFILEPREFIX&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Mysql: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ARGS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[*]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Redirect all output to the log file.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# https://serverfault.com/a/103569/234378&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;3&amp;gt;&amp;amp;1 4&amp;gt;&amp;amp;2
&lt;span class=&quot;nb&quot;&gt;trap&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'exec 2&amp;gt;&amp;amp;4 1&amp;gt;&amp;amp;3'&lt;/span&gt; 0 1 2 3
&lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;1&amp;gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTFILEPREFIX&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.log&quot;&lt;/span&gt; 2&amp;gt;&amp;amp;1

&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# be verbose&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$QUERYFILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OUTFILEPREFIX&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.sql&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# copy input file&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;date
time &lt;/span&gt;mysql &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ARGS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[@]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &amp;lt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;QUERYFILE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;OUTFILEPREFIX&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.tsv&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# run the query&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(&lt;a href=&quot;/code/runsql.sh&quot;&gt;Download&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Let me explain the different steps in more detail.
The only mandatory arguments are the input query file and the output directory.
The output directory will contain a copy of the input file, the log file and the results.&lt;/p&gt;

&lt;p&gt;The output files get timestamp’ed in order to differentiate between several invocations that use the same (possibly modified) input file.
Before running the query, the input parameters are printed to the screen for visual inspection.
Then, all further output is redirected to the log file and the input file gets copied.
Finally, the query is invoked.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;date&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;time&lt;/code&gt; invocations allow to retrospectively study the timings.&lt;/p&gt;

&lt;p&gt;Typically, the script is then executed like so&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Input file.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;query.sql
use mydatabase&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
SELECT &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; FROM mytable&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Execute the query at server dbhost using username dbuser and providing a&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# password at the prompt.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$SCRIPTS&lt;/span&gt;/runsql.sh query.sql /outdir &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt; dbhost &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; dbuser &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Possible results.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; /outdir
query.sql_20190322_140308.log
query.sql_20190322_140308.sql
query.sql_20190322_140308.tsv&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The input get gets copied oth the output &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sql&lt;/code&gt; file.
The output &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.tsv&lt;/code&gt; will contain the tab-separated result data.
If any errors occurred, they can be found in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.log&lt;/code&gt; file.
In order to see them immediately, I usually run&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Execute the script and show the latest (tail -n 1) log file immediately&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# afterwards.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;query.sql &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/outdir &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SCRIPTS&lt;/span&gt;/runsql.sh &lt;span class=&quot;nv&quot;&gt;$Q&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$O&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$O&lt;/span&gt;/&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$Q&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;log | &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 1&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I use the script regularly to execute a long-running query in a new &lt;a href=&quot;/shell/my-tmux-dev-setup.html&quot;&gt;tmux&lt;/a&gt; pane.
Sometimes, I even forget about the query.
Next day at work, I happily find all the results I need!&lt;/p&gt;
</description>
        <pubDate>Fri, 22 Mar 2019 00:00:00 +0100</pubDate>
        <link>http://www.the-efficient-programmer.com/misc/run-sql-queries-in-background.html</link>
        <guid isPermaLink="true">http://www.the-efficient-programmer.com/misc/run-sql-queries-in-background.html</guid>
        
        
        <category>misc</category>
        
      </item>
    
      <item>
        <title>How To Make Your Own Paper Wallet</title>
        <description>&lt;p&gt;It is common (and secure) practice to save cryptocurrency/blockchain keys on paper.
There exists &lt;a href=&quot;https://myetherwallet.github.io/knowledge-base/getting-started/creating-a-new-wallet-on-myetherwallet.html&quot;&gt;several&lt;/a&gt; &lt;a href=&quot;https://www.bitaddress.org/&quot;&gt;tools&lt;/a&gt; for the various blockchains to generate a public/private key pair and the corresponding the paper wallet at once.
In this post, I would like to show you how I created my custom paper wallets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Generate QR Codes from the public/private keys, paste everything into a simple document and print it.&lt;/p&gt;

&lt;p&gt;Whenever I created an account for any blockchain, I made sure I got hold of the private key; or at least of the &lt;a href=&quot;https://en.bitcoin.it/wiki/Seed_phrase&quot;&gt;seed phrase&lt;/a&gt;.
No matter what the creation method was (website, local wallet software, browser plugin, etc.): I want to have control over my stakes!&lt;/p&gt;

&lt;p&gt;Now, what’s a &lt;a href=&quot;https://en.bitcoin.it/wiki/Paper_wallet&quot;&gt;paper wallet&lt;/a&gt;?
I am gonna assume a paper wallet is simply an offline (physical) document that stores the necessary data to access a blockchain account.
Depending on the blockchain technology, this might only be the private key or the seed phrase of an account.
Furthermore, the public key as well as some non-mandatory information is handy.
For convenience, the hard-to-remember-and-easy-to-mistype strings are often encoded as &lt;a href=&quot;https://en.wikipedia.org/wiki/QR_code&quot;&gt;Quick Response Code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In practice, my approach is the following:
I generate QR code images of the keys and write a simple markdown document with all necessary information.
Finally, I use &lt;a href=&quot;https://pandoc.org/&quot;&gt;Pandoc&lt;/a&gt; to generate a PDF from that file that can be easily printed.&lt;/p&gt;

&lt;p&gt;The QR code can be generated with various tools.
It is important to do this offline - do not paste any sensitive information to a website that creates QR codes.
I did use &lt;a href=&quot;https://pypi.org/project/qrcode/&quot;&gt;qrcode&lt;/a&gt; for generation in the past which is simply enough.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Generate QR Codes&lt;/span&gt;
qr &lt;span class=&quot;s2&quot;&gt;&quot;WHATEVERTHEPRIVATEKEYIS&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; private.png
qr &lt;span class=&quot;s2&quot;&gt;&quot;WHATEVERTHEPUBLICKEYIS&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; public.png
qr &lt;span class=&quot;s2&quot;&gt;&quot;SOME RANDOM WORDS FOR THE SEED PHRASE&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; seed.png&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, we’ll make a simple markdown document with all information needed.
Note that I only list two blockchain accounts here but more can be used, of course.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-markdown&quot; data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;gh&quot;&gt;# Stellar - XLM&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;~~~&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;
&lt;/span&gt;
Account created on 2018-10-06 with
https://www.stellar.org/laboratory/#account-creator?network=public.

Use https://www.stellar.org/account-viewer/#!/ for access.

public: WHATEVERTHEPUBLICKEYIS
private: WHATEVERTHEPRIVATEKEYIS

            public                      private
&lt;span class=&quot;p&quot;&gt;~~~&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;![&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;./public.png&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;{ width=200px } !&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;./private.png&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;{ width=200px }

&lt;span class=&quot;gh&quot;&gt;# Cardano - ADA&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;~~~&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;
&lt;/span&gt;Account created on 2018-10-06 with Cardano wallet Daedalus v1.1.0.960.
Use https://daedaluswallet.io/ for access.

seed: &quot;SOME RANDOM WORDS FOR THE SEED PHRASE&quot;

            seed
&lt;span class=&quot;p&quot;&gt;~~~&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;![&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;./seed.png&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;{ width=200px } &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(&lt;a href=&quot;/noncode/paperwallet/paperwallet.md&quot;&gt;Download&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Finally, we’ll simply generate a PDF from that input …&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Generate a PDF from the Markdown file. Tell Pandoc to reduce the default&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# (LaTeX) margins.&lt;/span&gt;
pandoc &lt;span class=&quot;nt&quot;&gt;-V&lt;/span&gt; geometry:margin&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1.5cm &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; paperwallet.pdf paperwallet.md &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;… giving us our paper wallet:&lt;/p&gt;

&lt;object data=&quot;/noncode/paperwallet/paperwallet.pdf&quot; width=&quot;100%&quot; height=&quot;400&quot; type=&quot;application/pdf&quot;&gt;&lt;/object&gt;

&lt;p&gt;Less nice than other tools but it does the job!
Importantly, this approach makes it possibly to independently create a “paper wallet” for already existing accounts where not printable output has been auto-generated.&lt;/p&gt;

&lt;p&gt;Actually, it would be good to add even further hints to the paper wallet on how to access the funds.
This would help my clueless inheritors ;)&lt;/p&gt;
</description>
        <pubDate>Sat, 06 Oct 2018 00:00:00 +0200</pubDate>
        <link>http://www.the-efficient-programmer.com/misc/how-to-make-your-own-paper-wallet.html</link>
        <guid isPermaLink="true">http://www.the-efficient-programmer.com/misc/how-to-make-your-own-paper-wallet.html</guid>
        
        
        <category>misc</category>
        
      </item>
    
      <item>
        <title>Endless Command Execution</title>
        <description>&lt;p&gt;I happen to find myself regularly in the situation of writing a throw away BASH script.
Often, I need to run the script several times before I have it implemented correctly.
This is the typical edit-(compile-)run cycle most programmers know.
The trial-and-error workflow must be of course as fast as possible.
I am already using &lt;a href=&quot;/shell/my-tmux-dev-setup.html&quot;&gt;tmux&lt;/a&gt; so switching between the editor and the console where the script runs is pretty fast.
Still, I need to switch to that window, recall the previous command and execute it again.
The appropriate tmux/shell key sequence would be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;tmux-prefix&amp;gt;4&amp;lt;CAPSLOCK&amp;gt;k&amp;lt;ENTER&amp;gt;&lt;/code&gt;.
Let’s examine this in detail&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;tmux-prefix&amp;gt;4 	Jump to the window (in this case window #4) where the script is run.
&amp;lt;CAPSLOCK&amp;gt;	Enter Normal mode in Zsh. I am using vi-mode in the shell and have mapped CAPSLOCK to ESC
k		Scroll up to the previous command. This is the previously executed script, of course.
&amp;lt;ENTER&amp;gt;		Execute the command.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These are still quite a lot of keystrokes for something that is going to be repeated all the time.
Luckily, I have two aliases in my &lt;a href=&quot;/shell/organizing-dotfiles-1.html&quot;&gt;alias file&lt;/a&gt; list which allow me to run a command in an endless while loop.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# While True Start&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;wts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'while true ; do echo WHILE BEGIN $(date); '&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# While True End&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;wte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;' ; echo WHILE EXIT $?; echo WHILE END $(date); read ; done'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The usage is pretty simple:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wts &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;runme&quot;&lt;/span&gt; wte
WHILE BEGIN Mon May 28 15:05:01 CEST 2018
runme
WHILE EXIT 0
WHILE END Mon May 28 15:05:01 CEST 2018&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;When I press Enter now, I get the same command repeated again and again.
So my edit-run cycle keystrokes are now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;tmux-prefix&amp;gt;4&amp;lt;ENTER&amp;gt;&lt;/code&gt;.
Plus, I don’t have to retype the while loop every time I am in the edit-run cycle.&lt;/p&gt;

&lt;p&gt;This works of course only due to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g&lt;/code&gt; feature in Zsh’s alias built-in which allows to define global aliases, i.e. aliases that are expanded not only at the beginning of the command.
Typing two distinct aliases is a bit cumbersome.
A more intuitive solution would be a shell function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;wtse &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;do
                &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;WHILE BEGIN &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;WHILE EXIT &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;WHILE END &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;read
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;However, this gets in your way when using more “advanced” shell magic. Watch:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wts &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tee &lt;/span&gt;my.output wte
&lt;span class=&quot;c&quot;&gt;# vs&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wtse &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tee &lt;/span&gt;my.output&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the second case, the file (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my.output&lt;/code&gt;) will also contain the additional information that was printed by the function.
This was arguably not intended and so keeping the original while loop aliases makes sure you do not have to worry about redirections &amp;amp; pipes.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;date&lt;/code&gt; commands serve two purposes.
Firstly, they make it visible that the command has run and finished; just in case the execution didn’t output anything.
Finally, they allow to get a feeling how long the command took to execute.&lt;/p&gt;

&lt;p&gt;There are further ways to shorten the edit-run cycle.
One could setup a trigger in the editor to run the command in the background or send the appropriate tmux keys to run it in another window/pane.
I haven’t tested these options (yet).
I think the trigger-in-the-editor approach is cumbersome  to setup because one has to “configure” the editor every time so that it knows what to run.
Redirection/pipes might also be a problem.&lt;/p&gt;

&lt;p&gt;By “sending the tmux keys” I mean that one could alternatively instruct the editor to tell tmux to run the command in another window/pane.
This would of course assume that the other window/pane is prepared for that.
I.e. one would have had run the command at least once to be able to send the generic instruction “run again”.
If that is the case, a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux send-keys -t &quot;&amp;lt;window&amp;gt;.&amp;lt;pane&amp;gt;&quot; Escape k Enter&lt;/code&gt; should do.
This assumes that the shell uses vi bindings and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;ESC&amp;gt;k&amp;lt;ENTER&amp;gt;&lt;/code&gt; scrolls up and executes the last command.
Again, here I feel the “burden” of the setup (finding the window/pane or always use the preset ones).
Furthermore, it is less convenient to change the actual command being run.&lt;/p&gt;
</description>
        <pubDate>Mon, 28 May 2018 00:00:00 +0200</pubDate>
        <link>http://www.the-efficient-programmer.com/shell/endless-command-execution.html</link>
        <guid isPermaLink="true">http://www.the-efficient-programmer.com/shell/endless-command-execution.html</guid>
        
        
        <category>shell</category>
        
      </item>
    
      <item>
        <title>Some Grep Tips</title>
        <description>&lt;p&gt;In this post, I am going to present some simple tips when using grep.&lt;/p&gt;

&lt;h1 id=&quot;default-grep-command&quot;&gt;Default Grep Command&lt;/h1&gt;

&lt;p&gt;I am using my custom grep command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grr&lt;/code&gt; by default whenever I would run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt;.
It is defined as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;grr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;grep --recursive --line-number &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;
    --exclude-dir=.git --exclude-dir=.svn &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;
    --exclude='*.o' --exclude='*.pyc' --exclude=.ctags&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The command is called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grr&lt;/code&gt; for “GRep Recursive”.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--recursive&lt;/code&gt; switch is self-explanatory.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--line-number&lt;/code&gt; option makes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; prepend each match with the line where it was found.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--exclude&lt;/code&gt; switches can be changed depending on the actual needs.
There are tools dedicated specifically to search in &lt;a href=&quot;https://beyondgrep.com/&quot;&gt;source&lt;/a&gt; &lt;a href=&quot;https://github.com/ggreer/the_silver_searcher&quot;&gt;code&lt;/a&gt; folders.
However, the above alias can be used on any machine - not only within the personal development environment.&lt;/p&gt;

&lt;p&gt;A word of caution:
Do not set an alias for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; without changing the name, i.e. don’t do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alias grep=&quot;grep --recursive ...&quot;&lt;/code&gt;.
This may bite you in shell scripts where the author “blindly” uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; and thus your custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; is called.&lt;/p&gt;

&lt;h1 id=&quot;use-colors-and-pipes&quot;&gt;Use Colors And Pipes&lt;/h1&gt;

&lt;p&gt;I have already written about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G&lt;/code&gt; as a &lt;a href=&quot;/shell/better-alias.html&quot;&gt;better alias&lt;/a&gt; for grep when piping.
Defining …&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'| grep'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;… allows to run:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;some_command G mypattern&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;An improved version of this alias keeps the color code from the input:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'| grep --color=always'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is really handy when piping grep into grep like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;input.txt
aa
ab
ac
bb
bc
cc

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;input.txt | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;a | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; b
aa
ac&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color=alwyas&lt;/code&gt; set up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; will keep the input color codes arriving at stdin.
I really like to pipe grep when it is easy to spell out the search pattern with multiple greps (“search for lines containing this but not that”).
Without that option, only the last grep would colorize - whatever the last pattern than was.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/cat_grep_color.gif&quot; alt=&quot;Cat Grep Color&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;a-grep-wrapper&quot;&gt;A Grep Wrapper&lt;/h1&gt;

&lt;p&gt;At work, there is a database dump containg lots of customer information.
The file roughly looks like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;customer1|somedata|otherdata|whateverdata|...
customer1|evenmoredata|otherdata|dododata|...
customer2|somereallystrangedata|otherdata...
customer2|evenmoredata|otherdata|...
customer3|somedata|otherdata|...
customer3|areyoustillreadingthis?|otherdata|...
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I often find myself to search for data for a specific customer.
For various reasons it is actually easier to grep for the customer in the dump file instead of querying the database.
For this very end I have defined a dedicated shell function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;grc &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# GRep Customer&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;FILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/path/to/dump.txt&quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-hl&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$FILE&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--color&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$FILE&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This function is obviously just a wrapper around a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; with preset options.
I call it like so: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grc &quot;customer1&quot;&lt;/code&gt;.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt; invocation is a hint to the age of the dump.&lt;/p&gt;

&lt;p&gt;This could be achieved in other ways, too.
The point is that it is very handy to type and always accessible from the command line (where I spent my day).
This is not specific to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; but rather a common pattern: A couple of commands belong together? A couple of command line arguments are always used in conjunction? Make a shell function or alias and automatize tedious work away.&lt;/p&gt;
</description>
        <pubDate>Sun, 11 Mar 2018 00:00:00 +0100</pubDate>
        <link>http://www.the-efficient-programmer.com/shell/some-grep-tips.html</link>
        <guid isPermaLink="true">http://www.the-efficient-programmer.com/shell/some-grep-tips.html</guid>
        
        
        <category>shell</category>
        
      </item>
    
      <item>
        <title>How To Link A C Library In Haskell</title>
        <description>&lt;p&gt;In this blog post, I am going to show you how to link a C library in Haskell.
Each step is kept as simple as possible in order to focus on the overall goal.&lt;/p&gt;

&lt;p&gt;I will:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#the-c-program&quot;&gt;develop a small C program&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-static-libraries&quot;&gt;generate two static C libraries from the C program&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#merging-the-libraries&quot;&gt;merge both libraries into one&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-haskell-program&quot;&gt;develop a small Haskell program&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#linking-to-the-c-library&quot;&gt;let GHC link to the merged C library&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#using-the-c-library&quot;&gt;use the functions exported by the C library within Haskell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code snippets can be found &lt;a href=&quot;https://github.com/rolfschr/link-c-lib-in-haskell/commits/master&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;the-c-program&quot;&gt;The C program&lt;/h1&gt;

&lt;p&gt;The C program is going to be extremely simple.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.c&lt;/code&gt; is calling a library function and printing the result:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// main.c&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;liba.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;main.c: main()&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;liba_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 42&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;main.c: a = %f&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The library function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;liba_func()&lt;/code&gt; is provided by, who guessed it, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;liba.c&lt;/code&gt;.
The latter refers to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libb_func()&lt;/code&gt; in order to carry out its work.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// liba.c&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;libb.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;liba_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;liba.c:liba_func() side effects!&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;libb_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// return i + 1 + 40&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// libb.c&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;math.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;libb_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;39&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// return 40&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The corresponding (educational) Makefile:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-makefile&quot; data-lang=&quot;makefile&quot;&gt;&lt;span class=&quot;c&quot;&gt;# gcc -Wall:    Enable all warnings
# gcc -c:       Do not link
# gcc -g:       Add debug symbols
# gcc -lm:      Link to libm(ath)
# gcc -o:       Output file name
#
# Makefile $@:  The file name of the target of the rule
# Makefile $^:  The names of all the prerequisites
&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main.c liba.o libb.o&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;gcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wall&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$^&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-lm&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;liba.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;liba.c&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;gcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wall&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$^&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;libb.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;libb.c&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;gcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wall&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$^&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;clean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;*.o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;main&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;the-static-libraries&quot;&gt;The static libraries&lt;/h1&gt;

&lt;p&gt;We can convert &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib*.o&lt;/code&gt; into static libraries using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ar&lt;/code&gt;.
This tool creates a so called archive file which is basically just a collection of object files.
In our case, both archives each contain only one object file.
For completeness, we’ll let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc&lt;/code&gt; link again the static libraries instead of the object files for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;, too.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt; #
 # Makefile $@:  The file name of the target of the rule
 # Makefile $^:  The names of all the prerequisites
&lt;span class=&quot;gi&quot;&gt;+#
+# ar -c:        Create the archive
+# ar -r:        Update existing files in an archive
+# ar -s:        Add or update an archive index
&lt;/span&gt;
-main: main.c liba.o libb.o
&lt;span class=&quot;gi&quot;&gt;+main: main.c liba.a libb.a
&lt;/span&gt;        gcc -g -Wall -o $@ $^ -lm

...

+liba.a: liba.o
&lt;span class=&quot;gi&quot;&gt;+       ar -csr $@ $^
+
+libb.a: libb.o
+       ar -csr $@ $^&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;One can inspect the archive content with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nm &amp;lt;file.a&amp;gt;&lt;/code&gt;.
We see that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libb.a&lt;/code&gt; defines the function (“symbol”) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libb_func&lt;/code&gt; and expects the symbol &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fmod&lt;/code&gt;.
The latter comes from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;math.h&lt;/code&gt; and the actual function is linked by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc&lt;/code&gt; (see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-lm&lt;/code&gt; in the Makefile’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; target).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nm libb.a

libb.o:
         U fmod
00000000 T libb_func&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;merging-the-libraries&quot;&gt;Merging the libraries&lt;/h1&gt;

&lt;p&gt;The obvious way to merge both static libraries is to create a single archive from both object files (i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ar -csr libab.a liba.o libb.o&lt;/code&gt;).
However, I am going to assume the libraries come as is and the object files are not available.
This allows me to show a trick with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ar&lt;/code&gt;.
The issue with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ar&lt;/code&gt; is that you cannot simply create an archive by listing archive files instead of object files on the command line.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ar&lt;/code&gt; will happily archive the input files without looking into them and thus create a nested archive.
The inner archives are not accessible anymore:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ar &lt;span class=&quot;nt&quot;&gt;-csr&lt;/span&gt; libab.a liba.a libb.a &lt;span class=&quot;c&quot;&gt;# create a new archive from the previous ones&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nm libab.a
nm: liba.a: File format not recognized
nm: libb.a: File format not recognized&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can however ask &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ar&lt;/code&gt; to add the contents of one archive to the current one using the ADDLIB directive from &lt;a href=&quot;https://ftp.gnu.org/old-gnu/Manuals/binutils-2.12/html_chapter/binutils_1.html#SEC3&quot;&gt;GNU ar’s “librarien” compatibility mode&lt;/a&gt;.
In this mode, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ar&lt;/code&gt; is controlled with a script which we can also simply pipe from the command line.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'CREATE libab.a\nADDLIB liba.a\nADDLIB libb.a\nSAVE\nEND'&lt;/span&gt; | ar &lt;span class=&quot;nt&quot;&gt;-M&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nm libab.a

libb.o:
         U fmod
00000000 T libb_func

liba.o:
00000000 T liba_func
         U libb_func
         U puts&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This time, inspecting the archive yields the exported symbols (functions) as expected.
The necessary Makefile changes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt; libb.a: libb.o
        ar -csr $@ $^

+libab.a: liba.a libb.a
&lt;span class=&quot;gi&quot;&gt;+       echo 'CREATE $@\nADDLIB liba.a\nADDLIB libb.a\nSAVE\nEND' | ar -M
+&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;the-haskell-program&quot;&gt;The Haskell program&lt;/h1&gt;

&lt;p&gt;The Haskell program is going to be straight forward.
I’ll let &lt;a href=&quot;https://github.com/commercialhaskell/stack&quot;&gt;stack&lt;/a&gt; create the a simply project for me&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;stack new haskell simple&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The initial &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Main.hs&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-haskell&quot; data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;kr&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Main&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;putStrLn&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello world&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;linking-to-the-c-library&quot;&gt;Linking to the C library&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack&lt;/code&gt; generates a &lt;a href=&quot;https://www.haskell.org/cabal/&quot;&gt;Cabal&lt;/a&gt; file within the project.
This file is kind of like the Makefile of a Haskell app.
We can define GHC options within that file.
In order to tell GHC to link to an external library, we have to give a library path and a library name (pretty similar to GCC).
This is done by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-L&amp;lt;path&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-l&amp;lt;libname&amp;gt;&lt;/code&gt; respectively.
So we could simply use stack’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ghc-options&lt;/code&gt; parameter to add these.
However, it is recommended to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extra-lib-dirs&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extra-libaries&lt;/code&gt; instead.
This is how we need to adapt the cabal file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt; executable haskell
   hs-source-dirs:      src
&lt;span class=&quot;gi&quot;&gt;+--  ghc-options:         -L../c -lab -- don't do this
+  extra-lib-dirs:      ../c
+  extra-libraries:     ab
&lt;/span&gt;   main-is:             Main.hs
   default-language:    Haskell2010
   build-depends:       base &amp;gt;= 4.7 &amp;amp;&amp;amp; &amp;lt; 5&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Of course, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;../c&lt;/code&gt; is the path to the aforementioned C program which contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libab.a&lt;/code&gt;.
The file name’s prefix is striped so that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libab&lt;/code&gt; becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ab&lt;/code&gt; only.&lt;/p&gt;

&lt;h1 id=&quot;using-the-c-library&quot;&gt;Using the C library&lt;/h1&gt;

&lt;p&gt;We are going to make a wrapper Haskell library (file) that exposes the functions of the C library.
Calling the actual C functions is done trough Haskell’s &lt;a href=&quot;https://wiki.haskell.org/Foreign_Function_Interface&quot;&gt;Foreign Function Interfarce&lt;/a&gt;.
The source code is simple and listed below.
You can google around to find lots of information about suing the FFI in more detail.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-haskell&quot; data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;cp&quot;&gt;{-# LANGUAGE ForeignFunctionInterface #-}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- enabling the FFI&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;LibAb&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- declaring the module&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;foreign&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ccall&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;liba_func&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_liba_func&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- importing the C function&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;liba_func&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;liba_func&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_liba_func&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- wrapping the C function inside a Haskell function&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now that we have the Haskell function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;liba_func&lt;/code&gt; at our disposal, we can go ahead and call in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Main.hs&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt; module Main where

+import LibAb
&lt;span class=&quot;gi&quot;&gt;+
&lt;/span&gt; main :: IO ()
 main = do
&lt;span class=&quot;gd&quot;&gt;-  putStrLn &quot;hello world&quot;
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+  putStrLn &quot;Please enter a number:&quot;
+  d &amp;lt;- fmap (read::String-&amp;gt;Double) getLine
+  putStrLn $ &quot;The answer is: &quot; ++ show (liba_func d)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is the outcome:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;stack build &lt;span class=&quot;nt&quot;&gt;--exec&lt;/span&gt; haskell
... 
Please enter a number:
1.1
liba.c:liba_func&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; side effects!
The answer is: 42.1&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note how the pure Haskell function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;liba_func :: Double -&amp;gt; Double&lt;/code&gt; produces side effects!
This is quite expected.
The Haskell compiler cannot look into the compiled C functions and cannot differentiate pure from impure code.
It merely links the foreign functions where asked to.
The programmer needs to provide this information.
In this case, it should have been &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;liba_func :: Double -&amp;gt; IO Double&lt;/code&gt; to accommodate for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt; in the C function.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt; module LibAb where -- declaring the module

-foreign import ccall &quot;liba_func&quot; c_liba_func :: Double -&amp;gt; Double -- importing the C function
&lt;span class=&quot;gi&quot;&gt;+foreign import ccall &quot;liba_func&quot; c_liba_func :: Double -&amp;gt; IO Double -- importing the C function
&lt;/span&gt;
-liba_func :: Double -&amp;gt; Double
&lt;span class=&quot;gi&quot;&gt;+liba_func :: Double -&amp;gt; IO Double
&lt;/span&gt; liba_func = c_liba_func -- wrapping the C function inside a Haskell function&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt; main = do
   putStrLn &quot;Please enter a number:&quot;
   d &amp;lt;- fmap (read::String-&amp;gt;Double) getLine
&lt;span class=&quot;gd&quot;&gt;-  putStrLn $ &quot;The answer is: &quot; ++ show (liba_func d)
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+  a &amp;lt;- liba_func d
+  putStrLn $ &quot;The answer is: &quot; ++ show a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Done!
You just learned how to combined C &amp;amp; Haskell!
Well, at least some part of it.&lt;/p&gt;

&lt;p&gt;You can retrace all steps by looking into the commit history of this &lt;a href=&quot;https://github.com/rolfschr/link-c-lib-in-haskell/commits/master&quot;&gt;Git repo&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 01 Nov 2017 00:00:00 +0100</pubDate>
        <link>http://www.the-efficient-programmer.com/programming/link-c-lib-in-haskell.html</link>
        <guid isPermaLink="true">http://www.the-efficient-programmer.com/programming/link-c-lib-in-haskell.html</guid>
        
        
        <category>programming</category>
        
      </item>
    
      <item>
        <title>Simple MySQL Data Migration</title>
        <description>&lt;p&gt;I find myself more often than I think needing to shuffle around MySQL data.
Usually this is about dumping one table to another database.
For example, I sometimes want to get some production data into a test or development database to reproduce an issue.
On my local box I often need to recreate an existing database structure for development purposes.&lt;/p&gt;

&lt;p&gt;The task happened often enough that I took the time to write a little helper script for that.
I wanted to have it as general as possible so I came up with the following command line interface.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;migrate.pl &lt;span class=&quot;nt&quot;&gt;--from&lt;/span&gt; srchost:srcuser:srcpass:srcdb &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--to&lt;/span&gt; dsthost:dstuser:dstpass:dstdb &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--dump-table&lt;/span&gt; table1 &lt;span class=&quot;nt&quot;&gt;--dump-table&lt;/span&gt; table2 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--rename-table&lt;/span&gt; tableold:tablenew&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--from&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--to&lt;/code&gt; arguments are mandatory and define the source and destination database.
Since the databases could be everywhere (read: on different hosts) one specifies the database’s host and credentials, too.&lt;/p&gt;

&lt;p&gt;The actual table(s) to be copied are set via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dump-table&lt;/code&gt; which can provided multiple times.
Likewise, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--rename-table&lt;/code&gt; will rename a table in the target database.
The script does not dump &amp;amp; rename within one step.&lt;/p&gt;

&lt;p&gt;Using a script with a nice command line interface has several advantages.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;It’s usually faster than any GUI MySQL client.&lt;/li&gt;
  &lt;li&gt;Rerunning the same command or a slightly different (dumper another table) is simple and efficient.&lt;/li&gt;
  &lt;li&gt;Less error-prone compared to manually typing the MySQL commands and/or clicking around in the GUI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the script’s code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-perl&quot; data-lang=&quot;perl&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/perl&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Shuffle some MySQL data around.&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;strict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;warnings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Getopt::&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Long&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;GetOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;from=s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;to=s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;dump_tables|dump-table=s@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;rename_tables|rename-table=s@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;no_data|no-data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;die&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Error in command line arguments!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$to&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Getting the access credentials:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$from_host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$from_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$from_pass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$from_db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/:/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$to_host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$to_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$to_pass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$to_db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/:/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Do some sanity checking:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Data from: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$from_user&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\@&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$from_host&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$from_db&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Data to  : &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_user&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\@&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_host&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_db&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Continue? [y/N] &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;STDIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;chomp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$input&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;ne&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$input&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;ne&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Export using the least intrusive database access:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$mysql_cmd_export&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mysqldump --single-transaction --lock-tables=false --skip-add-locks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$mysql_cmd_export&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -h &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$from_host&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -u &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$from_user&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -p&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$from_pass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;no_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Only copy table structure&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$mysql_cmd_export&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; --no-data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# The Import is a simply mysql client reading from stdin:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$mysql_cmd_import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mysql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$mysql_cmd_import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -h &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_host&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -u &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_user&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -p&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_pass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Dump all specified tables:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$table&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dump_tables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$mysql_cmd_export&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$from_db&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$table&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; | &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$mysql_cmd_import&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Dumping &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$from_db&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$table&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; to &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_db&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$table&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; ...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Rename all specified tables:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$oldcolonnew&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rename_tables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$old&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/:/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$oldcolonnew&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$mysql_cmd_import&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_db&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -e &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;RENAME TABLE &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$old&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; TO &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$new&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Renaming &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_db&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$old&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; to &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$to_db&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$new&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; ...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;usage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;@_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Mandatory:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;$0 --from 'host:user:pass:db' --to 'host:user:pass:db'&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Optionial:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;This will completely dump the named table from &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;from to &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;to.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;--dump-table &amp;lt;tablename&amp;gt;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;This will rename named table from &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;old to &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;new in &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;to.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;--rename-table &amp;lt;oldname&amp;gt;:&amp;lt;newname&amp;gt;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&quot;;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(&lt;a href=&quot;/code/migrate.pl&quot;&gt;Download&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The code is pretty forward I believe.
I’d like to highlight some points, though.&lt;/p&gt;

&lt;p&gt;Using the password on the command line is insecure.
Anyone with read access to the process list (or your history) can read the password.
This script is for development purposes and I believe it is thus okay to leave it like so.&lt;/p&gt;

&lt;p&gt;There is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--no-data&lt;/code&gt; switch which allows to simply copy a table’s structure.&lt;/p&gt;

&lt;p&gt;I am using mysqldump’s &lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_single-transaction&quot;&gt;–single-transaction&lt;/a&gt;, &lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_lock-tables&quot;&gt;–lock-tables=false&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_add-locks&quot;&gt;–skip-add-locks&lt;/a&gt; switches to make the dumping process faster.
This will make sure the database is not blocked (for other applications) while the dump is going on (pretty important for a shared databases).
The downside is that the dumped data may not be consistent (when multiple tables are dumped) but I never experienced any problems with that.&lt;/p&gt;

&lt;p&gt;Before actually doing anything, the script prints the source &amp;amp; target databases and asks the user to confirm.
This is the last resort before overwriting any existing data.
It’s kind of funny: The less steps you have to do manually, the faster you can do stupid things…&lt;/p&gt;
</description>
        <pubDate>Mon, 24 Jul 2017 00:00:00 +0200</pubDate>
        <link>http://www.the-efficient-programmer.com/programming/simple-db-migration-script.html</link>
        <guid isPermaLink="true">http://www.the-efficient-programmer.com/programming/simple-db-migration-script.html</guid>
        
        
        <category>programming</category>
        
      </item>
    
      <item>
        <title>Test Deployments With Git Tags</title>
        <description>&lt;p&gt;Deploying an app to production typically happens using some tool like &lt;a href=&quot;/programming/a-password-deployment-strategy.html&quot;&gt;Jenkins&lt;/a&gt;.
The deployment job usually takes the Git tag as input parameter.
The parameter is used to checkout the expected version of the app, build &amp;amp; deploy it.&lt;/p&gt;

&lt;p&gt;Now, the tag to be used must obviously be assigned in advance.
The developers probably follow a specific development/release procedure (&lt;a href=&quot;http://nvie.com/posts/a-succeßful-git-branching-model/&quot;&gt;Git Flow&lt;/a&gt; anyone?) and tag releases when they are “done”.&lt;/p&gt;

&lt;p&gt;I sometimes want to deploy a version of the software which is not ready yet.
A typical scenario is that I cannot reproduce a bug in my local development environment but can see it in production or staging.
In this case, I’d like to deploy (to staging!) a version of the app with some debugging statements included.&lt;/p&gt;

&lt;p&gt;The deployment tool wants a tag for deployment though.
I surely just need to tag this debug version and deploy it!
I tend to forget how to do this and I also want the process to be as smooth as possible.&lt;/p&gt;

&lt;p&gt;Here’s what I defined in my shell:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;tag_debug_version &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Tag the current HEAD and publish it.&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;TAG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;test_tag_rolf
    git tag &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$TAG&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# delete previous tag&lt;/span&gt;
    git tag &lt;span class=&quot;nv&quot;&gt;$TAG&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# make a new tag on HEAD&lt;/span&gt;
    git fetch &lt;span class=&quot;nt&quot;&gt;--tags&lt;/span&gt; origin &lt;span class=&quot;c&quot;&gt;# update other people's tags&lt;/span&gt;
    git push &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; origin &lt;span class=&quot;nv&quot;&gt;$TAG&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# publish&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Plain and stupid but it does the job.
So the workflow for the described scenario is:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; tmp-debug master &lt;span class=&quot;c&quot;&gt;# create the debug branch&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# add some tracing and commit&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Add debug output&quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tag_debug_version &lt;span class=&quot;c&quot;&gt;# tag &amp;amp; push the debug version&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# deploy version &quot;test_tag_rolf&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Using the same tag has the advantage of not polluting the repo with pretty useless debug versions.
Furthermore, the browser’s form cache will remember it so you don’t have to type it out again during deployment (assuming deployment happens via a web interface).&lt;/p&gt;
</description>
        <pubDate>Thu, 13 Jul 2017 00:00:00 +0200</pubDate>
        <link>http://www.the-efficient-programmer.com/git/git-test-tag.html</link>
        <guid isPermaLink="true">http://www.the-efficient-programmer.com/git/git-test-tag.html</guid>
        
        
        <category>git</category>
        
      </item>
    
      <item>
        <title>Comparing Directories Effectively</title>
        <description>&lt;p&gt;I often want to compare directories.
I need to know which files only exist in one of them and which files differ.
If any files differ, I sometimes want to see the actual change so I need an efficient way to do so.&lt;/p&gt;

&lt;p&gt;For starters, I am using this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drq&lt;/code&gt; &lt;a href=&quot;/shell/organizing-dotfiles-1.html&quot;&gt;alias&lt;/a&gt; to diff directories:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; A B &lt;span class=&quot;c&quot;&gt;# show both folder's content with ls&lt;/span&gt;
A:
a
aonly
b
contentmatters

B:
a
b
bonly
contentmatters

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;drq A B &lt;span class=&quot;c&quot;&gt;# diff both folders&lt;/span&gt;
Only &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;A: aonly
Only &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;B: bonly
Files A/contentmatters and B/contentmatters differ&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The alias &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drq&lt;/code&gt; expands to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff -r -q&lt;/code&gt; which executes a recursive (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt;) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt; that only lists changes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-q&lt;/code&gt;, i.e. quiet).&lt;/p&gt;

&lt;p&gt;In order to inspect file changes, I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vimdiff&lt;/code&gt;.
By default, one could simply run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vimdiff file1 file2&lt;/code&gt;.
However, when I don’t know in advance whether the files do have differences I don’t want to actually fire up Vim unless they do.
Thus, my &lt;a href=&quot;/shell/organizing-dotfiles-1.html&quot;&gt;~/.functions&lt;/a&gt; contains the following definition:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;vd &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    diff &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/null
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-eq&lt;/span&gt; 1 &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;then
        &lt;/span&gt;vimdiff &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'windo set syntax=off'&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This simply first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt;s the files in question and opens Vim only if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt; finds any differences .
Running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vd file1 file1&lt;/code&gt; will just return without starting vim.
This approach causes the two files to be diff’ed twice but I rarely experience any waiting times.
(I turn off the syntax in diff view to not get distracted with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;windo set syntax=off&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;Finally, I have another seemingly strange function defined:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;Files &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    vd &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Files&lt;/code&gt; is now a function which runs my previously mentioned &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vd&lt;/code&gt; on its first and third argument.
Go back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drq&lt;/code&gt; and guess ;-).&lt;/p&gt;

&lt;p&gt;Found it?
Well, once the recursive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt; told me that two files differ and I want to compare them, I can simply copy the whole line with the two files, paste it and execute it as a new command.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Files&lt;/code&gt; function will forward its “arguments” to vimdiff as needed.&lt;/p&gt;

&lt;p&gt;Using &lt;a href=&quot;/shell/my-tmux-dev-setup.html&quot;&gt;Tmux&lt;/a&gt; in visual mode, this looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/drq_tmux_visualmodecopypaste.gif&quot; alt=&quot;Tmux visual mode copy and paste&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After executing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drq A B&lt;/code&gt;, I have to type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;prefix&amp;gt;[k&amp;lt;Space&amp;gt;0&amp;lt;Enter&amp;gt;&amp;lt;prefix&amp;gt;]&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prefix&lt;/code&gt; is the Tmux prefix, of course):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;         Move     Jump to
         up       Line Start  Paste
         |        |           |
&amp;lt;prefix&amp;gt;[k&amp;gt;&amp;lt;Space&amp;gt;0&amp;lt;Enter&amp;gt;&amp;lt;prefix&amp;gt;]
    |        |       |
Open Tmux    Start   Copy
Visual Mode  Selection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is much faster than you would expect.
Hitting Enter at this point will open up Vim and show the changes.
Instead of pressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt;, you can also jump higher with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3k&lt;/code&gt; for example.&lt;/p&gt;

&lt;p&gt;You might wonder why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Files&lt;/code&gt; uses my custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vd&lt;/code&gt; instead of plain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vimdiff&lt;/code&gt;.
The only reason for that is that sometimes the files in questions have changed after the recursive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt;’s execution and this makes sure Vim is not started for no reason.&lt;/p&gt;
</description>
        <pubDate>Tue, 23 May 2017 00:00:00 +0200</pubDate>
        <link>http://www.the-efficient-programmer.com/shell/comparing-directories.html</link>
        <guid isPermaLink="true">http://www.the-efficient-programmer.com/shell/comparing-directories.html</guid>
        
        
        <category>shell</category>
        
      </item>
    
      <item>
        <title>PEP8 Standard Deviation</title>
        <description>&lt;p&gt;Official coding standards ease reading of other people’s code and (usually) kill useless debates.
When I code in Python, I follow &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/&quot;&gt;PEP8&lt;/a&gt;.
Being a VIM user, &lt;a href=&quot;https://github.com/vim-syntastic/syntastic&quot;&gt;Syntastic&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://flake8.pycqa.org/en/latest/&quot;&gt;flake8&lt;/a&gt; are my tools for the job.&lt;/p&gt;

&lt;p&gt;There is one thing in the PEP8 coding style which I don’t comply with: line lengths.
The standard says: “Limit all lines to a maximum of 79 characters.”
This is really to hard to follow.
A typical situation which is easy to imagine is:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cond1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cond2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;call_this_func_with_long_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argument1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argument2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argument3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argument4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This looks made up but happens very often in practice.
The standard specifies &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/#maximum-line-length&quot;&gt;multiple&lt;/a&gt; &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/#multiline-if-statements&quot;&gt;ways&lt;/a&gt; to deal with such a scenario.
Luckily it also says “For […] a team that can reach agreement on this issue, it is okay to increase the […] maximum length to 99 characters”.
25% more helps a lot!&lt;/p&gt;

&lt;p&gt;However, there is one situation where it is really awkward to follow the style guide:
Using the &lt;a href=&quot;https://docs.python.org/2/library/stdtypes.html#str.format&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;str.format()&lt;/code&gt;&lt;/a&gt; method with a lot of arguments within a “long” string.
Consider:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# not okay according to PEP8
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'The {} of {} failed. Please check {} or {}'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logfile_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# fine but ugly
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'The {} of {} failed. Please check {} or {}'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
         &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logfile_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The second version gets nasty once the wrapped &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;format&lt;/code&gt; itself exceeds the 79 (or 99) characters, especially when using keywords within the replacement field, i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'The answer is {answer}'.format(answer=42)&lt;/code&gt;.
Furthermore, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt;‘ing commits where only some string content changed may yield multiple changed lines instead of a single line change (which it is &lt;em&gt;semantically&lt;/em&gt;).
I have to say that I also spend (lost?) quite some time in the past making the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;format&lt;/code&gt; invocation comply with the standard.
For theses reasons, I decided to deviate from the PEP8 maximum line length when formatting strings.
Obviously, I want to have Vim/Syntastic/flake8 help me with this …&lt;/p&gt;

&lt;p&gt;The code linter flake8 can be configured per project or globally.
The latter is done in the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/flake8&lt;/code&gt;.
In order to increase the maximum line length, you simply add the following to the file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[flake8]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;max-line-length&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;99&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once this option is set, flake8 (invoked within Vim by Syntastic) will not grump anymore for lines lengths up to 99 characters.
I have found &lt;a href=&quot;https://pypi.python.org/pypi/flake8-putty&quot;&gt;flake8-putty&lt;/a&gt; to be an easy way to disable the annoying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E501: line too long&lt;/code&gt; error specifically for string formatting.
The following two regexps tell flake8-putty to ignore &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E501&lt;/code&gt; for every line which contains the literal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.format(&lt;/code&gt; or every line ending with a single quote.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[flake8]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;max-line-length&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;99&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;putty-ignore&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;/\.format\(/&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;E501&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;/'$/&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;E501&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Today’s screens are wide enough to view two Python files side by side even if they both have line lengths of 99 characters so I believe it is okay to slightly exceed PEP8’s 79 characters.
All very long lines “only” contain strings and it is usually not the stuff someone is interested in when reading code.&lt;/p&gt;

&lt;p&gt;Caveats:
It may cause problems when the editor autowraps long lines but I don’t do that.
Any CI system (or even Git hooks) enforcing PEP8 needs to be configured properly, too.&lt;/p&gt;
</description>
        <pubDate>Fri, 21 Apr 2017 00:00:00 +0200</pubDate>
        <link>http://www.the-efficient-programmer.com/programming/pep8-standard-deviation.html</link>
        <guid isPermaLink="true">http://www.the-efficient-programmer.com/programming/pep8-standard-deviation.html</guid>
        
        
        <category>programming</category>
        
      </item>
    
  </channel>
</rss>
