<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ruslan Osipov - CLI</title>
    <description>Recent posts in CLI category on Ruslan Osipov.</description>
    <link>https://rosipov.com/</link>
    <atom:link href="https://rosipov.com/blog/categories/cli.xml" rel="self" type="application/rss+xml" />
    <pubDate>Mon, 11 May 2026 17:29:47 +0000</pubDate>
    <lastBuildDate>Mon, 11 May 2026 17:29:47 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>Google Drive on Linux with rclone</title>
        <description>&lt;p&gt;Recently Dropbox hit me with the &lt;a href=&quot;https://help.dropbox.com/accounts-billing/settings-sign-in/computer-limit&quot;&gt;following announcement&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Basic users have a three device limit as of March 2019.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Being the “basic” user, and relying on Dropbox across multiple machines, I got unreasonably upset (“How dare you deny me free access to your service?!”) and started looking for a replacement.&lt;/p&gt;

&lt;p&gt;I already store quite a lot of things in Google Drive, so it seemed like a no brainer: I migrated all my machines to Google Drive overnight. There was but only one problem: Google Drive has official clients for Windows and Mac, but there’s nothing when it comes to Linux.&lt;/p&gt;

&lt;p&gt;I found the Internets to be surprisingly sparse on the subject, and I had to try multiple solutions and spent more time than I’d like researching options.&lt;/p&gt;

&lt;p&gt;The best solution for me turned out to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone&lt;/code&gt;, which mounts Google Drive as a directory. It requires &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone&lt;/code&gt; service to be constantly running in order to access the data, which is a plus for me - I’ve accidentally killed Dropbox daemon in the past and had to deal with conflicts in my files.&lt;/p&gt;

&lt;p&gt;Install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone&lt;/code&gt; (&lt;a href=&quot;https://rclone.org/install/&quot;&gt;instructions&lt;/a&gt;):&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;curl https://rclone.org/install.sh | sudo bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From then on, &lt;a href=&quot;https://rclone.org/drive/&quot;&gt;rclone website some documentation&lt;/a&gt; when it comes to the setup. I found it somewhat difficult to parse, so here it is paraphrased:&lt;/p&gt;

&lt;p&gt;Launch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone config&lt;/code&gt; and follow the prompts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n) New remote&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&amp;gt; remote&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Type of storage to configure: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Google Drive&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Leave &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client_id&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client_secret&amp;gt;&lt;/code&gt; blank&lt;/li&gt;
  &lt;li&gt;Scope: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 \ Full access to all files&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Leave &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root_folder_id&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;service_account_file&amp;gt;&lt;/code&gt; blank&lt;/li&gt;
  &lt;li&gt;Use auto config? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Configure this as a team drive? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Is this OK? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From here on, you can interact with your Google Drive by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone&lt;/code&gt; commands (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone ls remote:&lt;/code&gt; to list top level files). But I am more interested in a continuous running service and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mount&lt;/code&gt; is what I need:&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;rclone mount remote: $HOME/Drive
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now my Google Drive is accessible at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Drive&lt;/code&gt;. All that’s left is to make sure the directory is mounted on startup.&lt;/p&gt;

&lt;p&gt;For Ubuntu/Debian, I added the following line to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/rc.local&lt;/code&gt; (before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exit 0&lt;/code&gt;, and you need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo&lt;/code&gt; access to edit the file):&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;rclone mount remote: $HOME/Drive
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For my i3 setup, all I needed was to add the following to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/i3/config&lt;/code&gt;:&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;exec rclone mount remote: $HOME/Drive
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s been working without an issue for a couple of weeks now - and my migration from Dropbox turned out to be somewhat painless and quick.&lt;/p&gt;

</description>
        <pubDate>Sun, 23 Jun 2019 07:00:00 +0000</pubDate>
        <link>https://rosipov.com/blog/google-drive-on-linux-with-rclone/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/google-drive-on-linux-with-rclone/</guid>
        
        
        <category>CLI</category>
        
        <category>Productivity</category>
        
      </item>
    
      <item>
        <title>Desktop notifications from Chrome Secure Shell</title>
        <description>&lt;p&gt;For the past year or two I’ve been working in the cloud. I use Chrome &lt;a href=&quot;https://chrome.google.com/webstore/detail/secure-shell/pnhechapfaindjhompbnflcldabbghjo?hl=en&quot;&gt;Secure Shell&lt;/a&gt; to connect to my machines, and it works rather well. In fact, I moved away from my work Linux/Mac laptops towards an &lt;a href=&quot;http://amzn.to/2hv68Ck&quot;&gt;HP Chromebook&lt;/a&gt;, which fullfilled both requirements I had: a browser and a terminal. One thing I missed about a Linux machine though is lack of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;notify-send&lt;/code&gt;-like functionality, especially when working with long-running builds.&lt;/p&gt;

&lt;p&gt;Yesterday I pinged hterm team for assistance with this matter, and turns out recent release of Secure Shell supports Chrome desktop notifications! Furthermore, two amazing engineers (thanks Andrew and Mike!) crafted an &lt;a href=&quot;https://chromium-review.googlesource.com/c/601549/3/hterm/etc/hterm-notify.sh&quot;&gt;hterm-notify&lt;/a&gt; script, which propagates notifications to Chrome, and by extent to desktop!&lt;/p&gt;

&lt;p&gt;I made a few tiny changes, mainly since I don’t use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen&lt;/code&gt;, and tmux sets my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$TERM&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen-256color&lt;/code&gt; for some reason:&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;#!/bin/sh
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Write an error message and exit.
# Usage: &amp;lt;message&amp;gt;
die() {
  echo &quot;ERROR: $*&quot;
  exit 1
}

# Send a notification.
# Usage: [title] [body]
notify() {
  local title=&quot;${1-}&quot; body=&quot;${2-}&quot;

  case ${TERM-} in
  screen*)  # This one&apos;s really tmux
    printf &apos;\ePtmux;\e\e]777;notify;%s;%s\a\e\\&apos; &quot;${title}&quot; &quot;${body}&quot;
    ;;
  *)        # This one&apos;s plain hterm
    printf &apos;\e]777;notify;%s;%s\a&apos; &quot;${title}&quot; &quot;${body}&quot;
    ;;
  esac
}

# Write tool usage and exit.
# Usage: [error message]
usage() {
  if [ $# -gt 0 ]; then
    exec 1&amp;gt;&amp;amp;2
  fi
  cat &amp;lt;&amp;lt;EOF
Usage: hterm-notify [options] &amp;lt;title&amp;gt; [body]

Send a notification to hterm.

Notes:
- The title should not have a semi-colon in it.
- Neither field should have escape sequences in them.
  Best to stick to plain text.
EOF

  if [ $# -gt 0 ]; then
    echo
    die &quot;$@&quot;
  else
    exit 0
  fi
}

main() {
  set -e

  while [ $# -gt 0 ]; do
    case $1 in
    -h|--help)
      usage
      ;;
    -*)
      usage &quot;Unknown option: $1&quot;
      ;;
    *)
      break
      ;;
    esac
  done

  if [ $# -eq 0 ]; then
    die &quot;Missing message to send&quot;
  fi
  if [ $# -gt 2 ]; then
    usage &quot;Too many arguments&quot;
  fi

  notify &quot;$@&quot;
}
main &quot;$@&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Throwing this in as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/bin/notify&lt;/code&gt; (not forgetting to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod +x&lt;/code&gt; and having &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/bin&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PATH&lt;/code&gt;) I can get a notification when a particular long running command is complete:&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;sleep 30 &amp;amp;&amp;amp; notify Hooray &quot;The sleep&apos;s done!&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Fri, 04 Aug 2017 17:33:16 +0000</pubDate>
        <link>https://rosipov.com/blog/desktop-notifications-from-chrome-secure-shell/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/desktop-notifications-from-chrome-secure-shell/</guid>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Browsing MSSQL and Vertica from CLI</title>
        <description>&lt;p&gt;Notes to make sure I don’t forget how to do this in the future. First, install
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mssql&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vcli&lt;/code&gt; tools:&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;npm install -g sql-cli
pip install vcli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Encrypt desired database account passwords:&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;mkdir -p ~/.passwd
echo &apos;$PASSWORD&apos; | gpg --use-agent -e &amp;gt; ~/.passwd/$DB_ACCOUNT.gpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Set up a set of aliases with the desired level of flexibility in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt; to
avoid typing too much:&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;function _sql-helper-command {
  host=$1
  user=$2
  password=$3
  db=$4
  opt_query_file=$5

  if [ -z $opt_query_file ]; then
    mssql -s $host -u $user -p $password -d $db
  else
    mssql -s $host -u $user -p $password -d $db -q &quot;`cat $opt_query_file`&quot;
  fi
}

function _vsql-helper-command {
  host=$1
  user=$2
  password=$3

  vcli -h $host -U $user -w $password
}

# Usage: `sql` for interactive mode, `sql filename.sql` to execute a file.
function sql {
  opt_query_file=$1

  host=&apos;$SOME_HOST&apos;
  user=&apos;$SOME_USER&apos;
  password=`gpg --use-agent --quiet --batch -d ~/.passwd/$SOME_FILENAME.gpg`
  db=&apos;$SOME_DB&apos;

  _sql-helper-command $host $user $password $db $opt_query_file
}

# Usage: `vsql $VERTICA_HOST`
function vsql {
  host=$1
  user=`whoami`
  password=`gpg --use-agent --quiet --batch -d ~/.passwd/$SOME_FILENAME.gpg`

  _vsql-helper-command $host $user $password
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$SOME_USER&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$SOME_HOST&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$SOME_DB&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$SOME_FILENAME&lt;/code&gt; above with
specific user, host, DB, and filenames respectively. I usually make a bunch of
aliases for different environments/machines I use: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sql-prod&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sql-dev&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sql-local&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vsql-host1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vsql-host2&lt;/code&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 28 Sep 2016 18:51:31 +0000</pubDate>
        <link>https://rosipov.com/blog/browsing-mssql-and-vertica-from-cli/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/browsing-mssql-and-vertica-from-cli/</guid>
        
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Profiling slow bashrc</title>
        <description>&lt;p&gt;I’ve recently noticed that it takes a long time for my bash to load. I’ve found
&lt;a href=&quot;http://stackoverflow.com/a/5015179/2578489&quot;&gt;following StackOverflow answer&lt;/a&gt; to be useful, and I based my solution to find a
startup time hog in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt; upon it.&lt;/p&gt;

&lt;p&gt;First off, add following few lines to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/bash.bashrc&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bash_profile&lt;/code&gt;, or wherever you’d like to begin tracing the script:&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;PS4=&apos;+ $(date &quot;+%s.%N&quot;)\011 &apos;
exec 3&amp;gt;&amp;amp;2 2&amp;gt;/tmp/bashstart.$$.log
set -x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And add following few lines where you want to stop the trace:&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;set +x
exec 2&amp;gt;&amp;amp;3 3&amp;gt;&amp;amp;-
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now start your bash session (you can simply open a new terminal Window for
that). The above will create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/bashstart.&amp;lt;PID&amp;gt;.log&lt;/code&gt;. To analyze it, I wrote
a little Python script:&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;import argparse
import heapq

parser = argparse.ArgumentParser(description=&apos;Analyze bashstart log for speed.&apos;)
parser.add_argument(&apos;filename&apos;, help=&apos;often /tmp/bashstart.&amp;lt;PID&amp;gt;.log&apos;)
parser.add_argument(&apos;-n&apos;, default=20, help=&apos;number of results to show&apos;)
args = parser.parse_args()
filename, n = args.filename, int(args.n)

with open(filename, &apos;r&apos;) as f:
    q = []
    prev_time = None
    for line in f.readlines():
        line = line.split()
        if &apos;+&apos; not in line[0] or len(line) &amp;lt; 3:
            continue
        text = &apos; &apos;.join(line[2:])
        seconds, nanoseconds = line[1].split(&apos;.&apos;)
        time = int(nanoseconds)
        diff = time - prev_time if prev_time is not None else 0
        prev_time = time
        heapq.heappush(q, (diff, text))

for diff, text in heapq.nlargest(n, q):
    print float(diff) / 1000000000, &apos;s:&apos;, text
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save it as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bashprofile.py&lt;/code&gt;, and run it as follows (replace file name with an
appropriate):&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;python bashprofile.py /tmp/bashstart.2831.log -n 20
0.050056909 s: _powerline_init_tmux_support
0.045323022 s: _powerline_setup_prompt
0.044722024 s: _powerline_setup_prompt
0.044423727 s: &apos;[&apos; -f /usr/local/google/home/ruslano/.local/lib/python2.7/site-packages/powerline/bindings/bash/powerline.sh &apos;]&apos;
0.044364097 s: &apos;[&apos; -f /usr/local/google/home/ruslano/.local/lib/python2.7/site-packages/powerline/bindings/bash/powerline.sh &apos;]&apos;
0.044137159 s: _powerline_init_tmux_support
0.015839574 s: __shell_name=bash
0.010850276 s: command which which
0.010105462 s: PS2=&apos;\[\]  \[\] \[\]&apos;
0.010000598 s: PS3=&apos; Select variant  &apos;
0.009837956 s: complete -F _svn -o default -X &apos;@(*/.svn|*/.svn/|.svn|.svn/)&apos; svn
0.009767517 s: PS2=&apos;\[\]  \[\] \[\]&apos;
0.0095753 s: PS3=&apos; Select variant  &apos;
0.007915565 s: other_utils=(ant automake autoreconf libtoolize make mount patch readlink)
0.00771205 s: for script in version functions/selector cd functions/cli cli override_gem
0.007008299 s: for gnu_util in &apos;&quot;${gnu_utils[@]}&quot;&apos;
0.00693653 s: complete -F _crow crow
0.006803049 s: complete -F _svn -o default -X &apos;@(*/.svn|*/.svn/|.svn|.svn/)&apos; svn
0.006672906 s: for script in version functions/selector cd functions/cli cli override_gem
0.005912399 s: for entry in &apos;${scripts[@]}&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In my example, &lt;a href=&quot;https://github.com/powerline/powerline&quot;&gt;Powerline&lt;/a&gt; turned out to be a massive hog. Looks like I’ll
have to troubleshoot the speed or plain disable it.&lt;/p&gt;

&lt;p&gt;Don’t forget to remove the lines you added to your bash configuration files
after you’re done profiling.&lt;/p&gt;

</description>
        <pubDate>Wed, 15 Jul 2015 17:07:53 +0000</pubDate>
        <link>https://rosipov.com/blog/profiling-slow-bashrc/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/profiling-slow-bashrc/</guid>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Managing cd bookmarks with apparix</title>
        <description>&lt;p&gt;A couple of months ago I discovered apparix: a set of commands which augment
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt; with bookmarks. It really is an amazing feeling when you zap between
multiple directories far away just with a couple of keystrokes! Apparix
provides three commands I use daily: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bm&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apparix&lt;/code&gt; (program
suggests aliasing last one to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;als&lt;/code&gt;). Here’s how I use it:&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;$ pwd
/Users/ruslan
$ apparix
--- portals
--- expansions
--- bookmarks
j dotfiles     /Users/ruslan/.dotfiles
j blog         /Users/ruslan/Projects/ruslanosipov.github.io
$ to blog
$ pwd
/Users/ruslan/Projects/ruslanosipov.github.io
$ cd source/_posts
$ bm posts
added: posts -&amp;gt; /Users/ruslan/Projects/ruslanosipov.github.io/source/_posts
$ to dotfiles
$ pwd
/Users/ruslan/.dotfiles
$ to posts
$ pwd
/Users/ruslan/Projects/ruslanosipov.github.io/source/_posts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The example above is self explanatory: you can see how over the span of a year
apparix saves hours of navigating directories you frequent.&lt;/p&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;p&gt;If you don’t like reading manuals, installation might be a confusing. But in
reality it’s straightforward, you just need to add some functions or aliases to
your shell’s configuration file.&lt;/p&gt;

&lt;p&gt;Install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apparix&lt;/code&gt; using your favorite package manager, and then pipe examples
apparix offers into your shell’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc&lt;/code&gt; file.&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;apparix --shell-examples &amp;gt;&amp;gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Open your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt; (or another corresponding configuration file), and pick the
preferred way of using apparix: you’ll see functions for bash and aliases for
csh given as examples. Pick whatever works for your shell, source your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc&lt;/code&gt;
file, and you’re all set!&lt;/p&gt;

&lt;p&gt;Happy jumping!&lt;/p&gt;
</description>
        <pubDate>Sat, 21 Feb 2015 00:25:45 +0000</pubDate>
        <link>https://rosipov.com/blog/managing-cd-bookmarks-with-apparix/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/managing-cd-bookmarks-with-apparix/</guid>
        
        <category>apparix</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Ranger - the CLI file manager</title>
        <description>&lt;p&gt;Ranger is a lightweight but powerful file manager with Vi-like key bindings.
It shines at exploring file trees, looking for specific files, and performing
bulk operations on folders and files. Three column layout will be very similar
to Mac OS X users: center column shows contents of the current directory, left
column lists contents of a parent directory, and the right column contains
preview for the selected file or folder.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/ranger-file-preview.png&quot; alt=&quot;File preview screen in Ranger: parent directory in the left column, current directory in the center column, and selected file preview in the left column.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ranger supports movement with familiar to Vi users &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l&lt;/code&gt; keys,
has internal command line which is invoked with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;, as well as many other
features and key bindings similar to Vi. Another great selling point - Ranger
can be extended with custom commands and key bindings. Utility is written in
Python, therefore all the commands are nothing more than Python scripts.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/ranger-marking-files.png&quot; alt=&quot;Marking files for deletion in Ranger.  Files highlighted in yellow will be deleted by executing `:delete` command.&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;p&gt;Ranger is easy to install and can be found in most public repositories, just
install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ranger&lt;/code&gt; package using your favorite package manager. While you’re at
it, you may want to install some external utilities to help Ranger properly
display file previews (list is taken from &lt;a href=&quot;https://wiki.archlinux.org/index.php/ranger&quot;&gt;ArchWiki page on Ranger&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;atool&lt;/code&gt; for archives.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;highlight&lt;/code&gt; for syntax highlighting.
![for image previews]]CII.(libcaca&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)(&lt;/code&gt;))&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lynx&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w3m&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elinks&lt;/code&gt; for HTML.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mediainfo&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perl-image-exiftool&lt;/code&gt; for media file information.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poppler&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pdftotext&lt;/code&gt;) for PDF.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transmission-cli&lt;/code&gt; for BitTorrent information.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w3m&lt;/code&gt; for image previews.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After all the dependencies are installed, quickly start up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ranger&lt;/code&gt;, exit it
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q&lt;/code&gt;, and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ranger --copy-config=all&lt;/code&gt; to generate configuration files in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/ranger&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;/h2&gt;

&lt;p&gt;Here are a few of the key bindings and commands I found useful:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use spacebar to select files one by one. By selecting multiple files, you can
perform bulk operations on them. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;V&lt;/code&gt; to perform visual selection.
Lowercase &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt; reverses current selection. For instance, you can run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:delete&lt;/code&gt;
after selecting multiple files and folders.&lt;/li&gt;
  &lt;li&gt;As mentioned above, execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:delete&lt;/code&gt; to remove currently selected file (or
files).&lt;/li&gt;
  &lt;li&gt;To fullscreen a preview window, hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;. Hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; again to return the preview
window to it’s normal size.&lt;/li&gt;
  &lt;li&gt;Vi’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gg&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G&lt;/code&gt; allow you to jump to the top and bottom of the file list
respectively.&lt;/li&gt;
  &lt;li&gt;Hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zh&lt;/code&gt; to toggle hidden files display.&lt;/li&gt;
  &lt;li&gt;As in Vim, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; searches for a file in a current buffer, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; let
you navigate to the next and previous matches respectively.&lt;/li&gt;
  &lt;li&gt;Similarly, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:filter&lt;/code&gt; allows you to only limit your view to the files matching
a pattern. It’s also interactive - changes are applied as you type.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re an avid Vim user, you’ll find using Ranger surprisingly intuitive.
Otherwise you might get confused and scared away, probably for a good reason.
Ranger is designed to provide Vi-like feel for file browsing, and it does that
job well.&lt;/p&gt;

</description>
        <pubDate>Mon, 09 Feb 2015 03:33:16 +0000</pubDate>
        <link>https://rosipov.com/blog/ranger-the-cli-file-manager/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/ranger-the-cli-file-manager/</guid>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Power of the command line</title>
        <description>&lt;p&gt;&lt;em&gt;Disclaimer: I am not advocating any specific tools or methodologies, but
sharing a workflow I find to be efficient and pleasant.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I am a huge fan of working with CLI applications. I use Vim for editing code,
composing emails, and various kinds of writing. When I have to manipulate huge
amounts of email, I use Mutt: it’s intuitive tagging and regular expression
engine are extremely useful for the task. I employ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt;, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt; - Linux utilities which allow for precise and fast text manipulation.&lt;/p&gt;

&lt;p&gt;However, I would not use CLI browsers like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elinks&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w3m&lt;/code&gt;, and the idea of
reading every email in Mutt gives me the creeps. I love the visualization web
browser offers, something text-based prompt is not able to provide. And it
doesn’t have to.&lt;/p&gt;

&lt;p&gt;There are two components to most of the tasks performed on a computer: analyzing
output and entering input. Certain tasks employ one component more than the
other. In most modern applications it’s rare to have both solid control from
the user perspective and a pleasant informative UI. With increased visual
component, it’s more time consuming to make the application do what you need,
especially if your needs are esoteric. With more editing power, visual display
becomes less complex in order to make editing tasks easier.&lt;/p&gt;

&lt;h2 id=&quot;where-visual-tools-fall-short&quot;&gt;Where visual tools fall short&lt;/h2&gt;

&lt;p&gt;What is the alternative? Using multiple programs with different levels of
control to accomplish one task: to edit text. Each of the programs excels in
it’s own field: word processing software allows for beautiful fonts and document
presentation, IDE lets you access aggregated meta information about your
application. But most of the IDEs and word processors lack the powerful tools
needed to manipulate the foundation of what user is working with - plain text.&lt;/p&gt;

&lt;h2 id=&quot;ode-to-plain-text&quot;&gt;Ode to plain text&lt;/h2&gt;

&lt;p&gt;I spend a lot of time writing and editing plain text. Be it source code, emails,
documentation, or even blog posts. These tasks take up significant amount of my
day, and it is only logical to substitute some of the visual presentation
capabilities for effectiveness.&lt;/p&gt;

&lt;p&gt;It is hard to mentally process data which is not explicitly and unambiguously
visible: different levels of headings, hidden meta information. Unlike more
obscuring formats, plain text is all there is - it has nothing to hide. If you
don’t see it - it’s not there. If you do see it - you know exactly what it is.&lt;/p&gt;

&lt;p&gt;One of my favorite tips from “&lt;a href=&quot;http://amzn.to/1yRe6Th&quot;&gt;Pragmatic Programmer&lt;/a&gt;” goes:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Use a single editor well&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I learned one editor well, and now I use it for all my writing and editing
needs. I don’t have to jump between IDE, browser, and office software. Most of
the text I edit is manipulated with one editor. There is only one set of key
bindings to know, one skill to master and hone. Fast, without any additional
thought, using single text editor and all of it’s powerful features is imprinted
in muscle memory. One less task to worry about.&lt;/p&gt;

&lt;p&gt;I write my documents in Markdown format, and later convert them to the desired
output using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pandoc&lt;/code&gt;: be it an HTML page, PDF, or a Microsoft Word document. I
use Vim, so I can rearrange paragraphs or manipulate lines within a couple of
keystrokes. Since I spend so much time editing text, I also touch type, which
makes me even more effective at the given task.&lt;/p&gt;

&lt;h2 id=&quot;harness-the-power-of-the-command-line&quot;&gt;Harness the power of the command line&lt;/h2&gt;

&lt;p&gt;When it comes to bulk manipulating files or working with version control -
there is no better candidate then command line applications. There’s no need to
go through a number of obscure menus, ticking and unticking checkboxes, and
hoping that your desired result can be achieved with a program’s GUI.&lt;/p&gt;

&lt;p&gt;Let’s look at a few scenarios some users face in their daily workflow.&lt;/p&gt;

&lt;h3 id=&quot;creating-a-backup&quot;&gt;Creating a backup&lt;/h3&gt;

&lt;p&gt;With GUI, you’d have to take multiple steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Right click &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Left click on “Copy”.&lt;/li&gt;
  &lt;li&gt;Right click on some empty space.&lt;/li&gt;
  &lt;li&gt;Left click on “Paste”.&lt;/li&gt;
  &lt;li&gt;Right click on a newly created copy.&lt;/li&gt;
  &lt;li&gt;Left click on “Rename”.&lt;/li&gt;
  &lt;li&gt;Switch to a keyboard.&lt;/li&gt;
  &lt;li&gt;Type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file.bak&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The above steps can be sped up using shortcuts like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-c&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-v&lt;/code&gt;, but not by
much. Here’s an alternative in bash:&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;cp file{,.bak}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While first variant would do great for a novice or a casual user - the second
method would be much more preferred by an experienced user whose concern is
speed.&lt;/p&gt;

&lt;h3 id=&quot;recursively-bulk-replacing-text-in-a-directory&quot;&gt;Recursively bulk replacing text in a directory&lt;/h3&gt;

&lt;p&gt;Let’s assume we want to do a bulk replace text in a directory and all it’s
subdirectories. We have our trusted IDE, let’s assume this IDE is already
configured to work with a desired directory.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open your IDE.&lt;/li&gt;
  &lt;li&gt;Select “Edit” menu.&lt;/li&gt;
  &lt;li&gt;Select “Find and Replace” submenu.&lt;/li&gt;
  &lt;li&gt;Click on a “Find” input field.&lt;/li&gt;
  &lt;li&gt;Switch to a keyboard.&lt;/li&gt;
  &lt;li&gt;Type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function_to_replace&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Switch to a mouse.&lt;/li&gt;
  &lt;li&gt;Click on “Replace” input field.&lt;/li&gt;
  &lt;li&gt;Switch to a keyboard.&lt;/li&gt;
  &lt;li&gt;Type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new_function_name&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Switch to a mouse.&lt;/li&gt;
  &lt;li&gt;Enable “Search in subdirectories” checkbox.&lt;/li&gt;
  &lt;li&gt;Click “OK”.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Again, this can be shortened a bit with some keyboard shortcuts, but not by
much. You still have to switch between keyboard and a mouse a total of 4 times,
and you still have to click through all the menus. This does get time consuming
if you do this often. Now let’s try to perform the same task in command line:&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;find . -type f | xargs sed -i &apos;s/function_to_replace/new_function_name/g&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Much faster, if you’re able to memorize the structure. And remembering what the
commands do is much easier than it looks. Especially with the help of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man&lt;/code&gt; or,
even better, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bro&lt;/code&gt; (see &lt;a href=&quot;http://bropages.org&quot;&gt;http://bropages.org&lt;/a&gt; for latter).&lt;/p&gt;

&lt;p&gt;The above example demonstrates one of the biggest advantages of command line
interfaces: an ability to redirect an output of one program into another,
chaining the tools together. In this example, we first get a list of all files
use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find&lt;/code&gt; tool, and then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt; tool on each of those files in order to
replace the text.&lt;/p&gt;

&lt;p&gt;An output from any CLI tool can be fed into any other CLI tool. This allows for
countless possibilities and high adaptability to unscripted scenarios.&lt;/p&gt;

&lt;h2 id=&quot;is-it-worth-learning-cli-tools-over-their-gui-counterparts&quot;&gt;Is it worth learning CLI tools over their GUI counterparts?&lt;/h2&gt;

&lt;p&gt;This depends on what your intentions are. If you’re a power user who writes and
edits a lot of text or manipulates bulk amounts of text on a daily basis - than
it’s definitely worth it. Time spent learning these tools will pay off. But if
you’re a casual user whose needs end with writing an occasional email or two -
then you probably don’t need to worry about this.&lt;/p&gt;

&lt;p&gt;Hell, if you’ve read this far - this means you’re the former case. I can
practically guarantee that you will benefit from employing command line tools
and modal editors over their GUI counterparts.&lt;/p&gt;

&lt;p&gt;I’ve put together a table for comparison between two. Indeed, there are
different times when either GUI or CLI tools excel:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Factor&lt;/th&gt;
      &lt;th&gt;CLI&lt;/th&gt;
      &lt;th&gt;GUI&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Ability to combine/chain tools&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Easy to learn&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Efficient for a novice user&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Efficient for an experienced user&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Good for occasional use&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Good for repetitive tasks&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Presents visual information well&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;As you can see - both CLI and GUI programs have their pluses and minuses. CLI
tools seem to appeal to experienced users, while GUI tools are great for novice
users and do excel in representing visual information. No matter what kind of
interface you prefer, it’s crucially important to use the right tool for the job.&lt;/p&gt;

</description>
        <pubDate>Fri, 06 Feb 2015 21:13:49 +0000</pubDate>
        <link>https://rosipov.com/blog/power-of-the-command-line/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/power-of-the-command-line/</guid>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Beyond grep</title>
        <description>&lt;p&gt;I search for things a lot, especially in my code. Or even worse - someone else’s
code. For years &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; served as an amazing tool for this: fast, simple, and
yet powerful. That was until I discovered &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack&lt;/code&gt; for myself. An incredibly easy
to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; implementation built to work with large (or not really) code
trees.&lt;/p&gt;

&lt;p&gt;A lot can be said to enforce superiority of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack&lt;/code&gt; over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; when it comes to
working with code, and it’s all said here: &lt;a href=&quot;http://beyondgrep.com/why-ack/&quot;&gt;ack’s features&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Amazing thing is - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack&lt;/code&gt; doesn’t even need a tutorial. Learning progression is
natural and “just happens” by researching necessary use cases as the need
arises (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack&lt;/code&gt; has a great manual entry).&lt;/p&gt;

&lt;p&gt;Here’s a typical use example for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack&lt;/code&gt;:&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;ack --shell &apos;gr[ae]y&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Searches all shell script files in the current code tree for any occurrences of
“gray” or “grey”. It will search &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sh&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zsh&lt;/code&gt;, and just about dot-anything;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack&lt;/code&gt; will even check shebang lines for you.&lt;/p&gt;

&lt;p&gt;Ease of use, the fact that it’s ready to use out of the box, extensive file
types, native support for Perl’s regular expressions: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack&lt;/code&gt; does really good
job at searching through code.&lt;/p&gt;

&lt;p&gt;Download it from &lt;a href=&quot;http://beyondgrep.com&quot;&gt;Beyond grep&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Sun, 21 Sep 2014 19:18:31 +0000</pubDate>
        <link>https://rosipov.com/blog/beyond-grep/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/beyond-grep/</guid>
        
        <category>ack</category>
        
        <category>grep</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Effective search with Mutt</title>
        <description>&lt;p&gt;I generally don’t use Mutt for everyday emails - I find smooth non-monospace
fonts to be more pleasant to the eye, and the visualization my browser offers
is hard to beat. The main use-case for me is composing long emails: Mutt lets
me use my favorite text editor, which speeds up the editing of long and
carefully composed responses.&lt;/p&gt;

&lt;p&gt;Recently I added a new use-case to my work flow: searching through emails.
Mutt has a powerful built-in regular-expressions engine, which is something the
web Gmail client is missing.&lt;/p&gt;

&lt;p&gt;Mutt has two ways of finding things: search and limit. “Search” just jumps from
one matching letter to another, something along the lines what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; command does
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;less&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;more&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt;. “Limit” is something I am more used to with the
web client, and it’s what I use the most.&lt;/p&gt;

&lt;h2 id=&quot;using-limits&quot;&gt;Using limits&lt;/h2&gt;

&lt;p&gt;Limit works the way regular search works in Gmail: it limits the view to
conversations matching the query. Hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l&lt;/code&gt;, and enter a search query.&lt;/p&gt;

&lt;p&gt;By default, Mutt will only search through the subject lines, but this behaviour
can be changed by prefixing the command with a special identifier. For
instance, searching for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~b oranges&lt;/code&gt; will limit the view to all the messages
which mention “oranges” in the message body. Here are a couple I use the most:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~b&lt;/code&gt; – Search in the message body.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~B&lt;/code&gt; – Search in the whole message.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~f&lt;/code&gt; – Message originated from the user.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~Q&lt;/code&gt; – Messages which have been replied to.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find full list in the &lt;a href=&quot;http://www.sendmail.org/~ca/email/mutt/manual-4.html#ss4.2&quot;&gt;Mutt Advanced Usage Manual&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Patterns can be chained to produce narrower results: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~f joe ~B apples&lt;/code&gt;. This
will search for a message mentioning “apples” coming from an author whose name
contains “joe”.&lt;/p&gt;

&lt;h3 id=&quot;caching-mail-for-faster-search&quot;&gt;Caching mail for faster search&lt;/h3&gt;

&lt;p&gt;You may find that searching whole messages is slow, especially if you have more
than a couple hundred messages to search through. That’s because by default
Mutt does not store messages for local use. This can be changed by specifying
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;header_cache&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;message_cachedir&lt;/code&gt; variables in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.muttrc&lt;/code&gt; file:&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;set header_cache     = &quot;$HOME/Mail&quot;
set message_cachedir = &quot;$HOME/Mail&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, after you perform your first search, it will cache every message you open,
making all the consecutive searches lightning fast.&lt;/p&gt;

&lt;p&gt;Oh, and keep in mind, Mutt stores messages and headers in plain text, so make
sure the cache directory is not shared with anyone but yourself.&lt;/p&gt;

</description>
        <pubDate>Sat, 02 Aug 2014 20:32:51 +0000</pubDate>
        <link>https://rosipov.com/blog/effective-search-with-mutt/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/effective-search-with-mutt/</guid>
        
        <category>mutt</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Three favorite bash tricks</title>
        <description>&lt;p&gt;I spend most of my development time in the shell - be it editing text with Vim
or executing various console commands. I have quite a number of tricks in my
daily repertoire, and I would like to share three tips today.&lt;/p&gt;

&lt;h2 id=&quot;edit-current-command-with-a-text-editor&quot;&gt;Edit current command with a text editor&lt;/h2&gt;

&lt;p&gt;I often end up having to change a long command I just typed, and using arrow
keys to get to the correct spot is not favorable. Bash has the feature which
lets you edit current command in a text editor of your choice. Hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl + x&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl + e&lt;/code&gt; (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl + x + e&lt;/code&gt;), and you will be dropped into your text editor.
Now you are able to edit the command, and it will be executed as soon as your
write the file and exit the editor.&lt;/p&gt;

&lt;p&gt;You can use an editor of your choice by adding following line to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt;
file:&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;export EDITOR=vim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt; with the name of your favorite editor.&lt;/p&gt;

&lt;p&gt;Update: It looks like for some machines setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EDITOR&lt;/code&gt; variable is not
enough. In this case, you also need to set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VISUAL&lt;/code&gt; environment variable.&lt;/p&gt;

&lt;h2 id=&quot;edit-recent-command&quot;&gt;Edit recent command&lt;/h2&gt;

&lt;p&gt;You can edit your recent commands in a text editor of your choice by executing
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fc beginning_of_the_command&lt;/code&gt;. For instance, if you run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fc l&lt;/code&gt;, you will open
most recent command starting with the letter “l”.&lt;/p&gt;

&lt;p&gt;You can execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fc&lt;/code&gt; without any arguments to edit last executed command.&lt;/p&gt;

&lt;h2 id=&quot;bash-history-autocomplete&quot;&gt;Bash history autocomplete&lt;/h2&gt;

&lt;p&gt;Another great feature - “reverse intelligent search”. If you hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl + r&lt;/code&gt; in
your shell, you’ll be greeted by the following prompt:&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;(reverse-i-search)`&apos;:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Start typing a part of the command from your history, and you’ll see suggestions
popping up. Hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enter&lt;/code&gt; to pick the command (you’ll be able to edit it before
executing), or push &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl + g&lt;/code&gt; to return back.&lt;/p&gt;

&lt;p&gt;Like any of these tips? Have some of your own? Don’t hesitate to share those in
the comments section down below.&lt;/p&gt;
</description>
        <pubDate>Fri, 25 Jul 2014 01:41:10 +0000</pubDate>
        <link>https://rosipov.com/blog/three-favorite-bash-tricks/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/three-favorite-bash-tricks/</guid>
        
        <category>bash</category>
        
        <category>vim</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Elegant Mutt setup for use with Gmail</title>
        <description>&lt;p&gt;I have been using Mutt for a while now. Wouldn’t say that it saves my time, but
nor does it extend the amount of time I spend reading email. For me, the best
part about Mutt is that it lets me use text editor of my choice - Vim.
Everything else - keyboard shortcuts, minimalist design, and simplicity -
already exists in Gmail.&lt;/p&gt;

&lt;p&gt;I found configuration below to work really well for my needs: all of the
important for me Gmail features are translated. Here’s my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.muttrc&lt;/code&gt; file:&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;bind editor &amp;lt;space&amp;gt; noop
set alias_file        = &apos;~/.mutt/aliases.txt&apos;
set copy              = no
set display_filter    = &apos;$HOME/.mutt/aliases.sh&apos;
set edit_headers
set editor            = &quot;vim +/^$ ++1&quot;
set folder            = &quot;imaps://imap.gmail.com/&quot;
set hostname          = &quot;gmail.com&quot;
set imap_check_subscribed
set imap_pass         = &quot;$PASSWORD&quot;
set imap_user         = &quot;$USERNAME&quot;
set mail_check        = 5
set move              = no
set postponed         = &quot;+[Gmail]/Drafts&quot;
set spoolfile         = &quot;+INBOX&quot;
set text_flowed       = yes
unset imap_passive
unset record

# Gmail-style keyboard shortcuts
macro index ga &quot;&amp;lt;change-folder&amp;gt;=[Gmail]/All Mail&amp;lt;enter&amp;gt;&quot; &quot;Go to all mail&quot;
macro index gd &quot;&amp;lt;change-folder&amp;gt;=[Gmail]/Drafts&amp;lt;enter&amp;gt;&quot; &quot;Go to drafts&quot;
macro index gi &quot;&amp;lt;change-folder&amp;gt;=INBOX&amp;lt;enter&amp;gt;&quot; &quot;Go to inbox&quot;
macro index gs &quot;&amp;lt;change-folder&amp;gt;=[Gmail]/Starred&amp;lt;enter&amp;gt;&quot; &quot;Go to starred messages&quot;
macro index gt &quot;&amp;lt;change-folder&amp;gt;=[Gmail]/Trash&amp;lt;enter&amp;gt;&quot; &quot;Go to trash&quot;
macro index,pager d &quot;&amp;lt;save-message&amp;gt;=[Gmail]/Trash&amp;lt;enter&amp;gt;&amp;lt;enter&amp;gt;&quot; &quot;Trash&quot;
macro index,pager y &quot;&amp;lt;save-message&amp;gt;=[Gmail]/All Mail&amp;lt;enter&amp;gt;&amp;lt;enter&amp;gt;&quot; &quot;Archive&quot;

source $alias_file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is quite self-explanatory, and includes such nice features as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Automatically adding addresses from read emails to address book (see
below).&lt;/li&gt;
  &lt;li&gt;Using vim as a text editor, with an ability to edit message
headers/recipients from within vim.&lt;/li&gt;
  &lt;li&gt;Ability to access all the default Gmail folders: All mail, Drafts, Inbox,
Starred, Trash.&lt;/li&gt;
  &lt;li&gt;Key bindings to delete and archive messages bound to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;
respectfully (I am a huge fun of a zero-mail inbox).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might also want to have your password encrypted by GPG as opposed to
leaving it in plain text in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.muttrc&lt;/code&gt; file. You can read how to do this
here: &lt;a href=&quot;https://rosipov.com/blog/using-mutt-with-gpg/&quot;&gt;Using Mutt with GPG&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As you may have noticed, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.muttrc&lt;/code&gt; above sets &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;display_filter&lt;/code&gt; to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.mutt/aliases.sh&lt;/code&gt;. This script is being executed every time you read an
email, and it collects email address to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.mutt/aliases.txt&lt;/code&gt;. Contents of
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aliases.sh&lt;/code&gt; are below:&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;#!/bin/sh

MESSAGE=$(cat)

NEWALIAS=$(echo &quot;${MESSAGE}&quot; | grep ^&quot;From: &quot; | sed s/[\,\&quot;\&apos;]//g | awk &apos;{$1=&quot;&quot;; if (NF == 3) {print &quot;alias&quot; $0;} else if (NF == 2) {print &quot;alias&quot; $0 $0;} else if (NF &amp;gt; 3) {print &quot;alias&quot;, tolower($(NF-1))&quot;-&quot;tolower($2) $0;}}&apos;)


if grep -Fxq &quot;$NEWALIAS&quot; $HOME/.mutt/aliases.txt; then
    :
else
    echo &quot;$NEWALIAS&quot; &amp;gt;&amp;gt; $HOME/.mutt/aliases.txt
fi

echo &quot;${MESSAGE}&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href=&quot;http://wcaleb.org/blog/mutt-tips&quot;&gt;W. Caleb McDaniel&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This script will create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aliases.txt&lt;/code&gt; file containing email addresses for
search and auto completion of email-addresses.&lt;/p&gt;

</description>
        <pubDate>Wed, 28 May 2014 21:33:55 +0000</pubDate>
        <link>https://rosipov.com/blog/elegant-mutt-setup-for-use-with-gmail/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/elegant-mutt-setup-for-use-with-gmail/</guid>
        
        <category>mutt</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Using Mutt with GPG</title>
        <description>&lt;p&gt;Mutt is a great command line email client, but it does not offer a built-in way
to store passwords. But that’s where GPG comes in. A while back I wrote an
article on how to use GPG to store your passwords: &lt;a href=&quot;https://rosipov.com/blog/gpg-usage/&quot;&gt;GPG Usage&lt;/a&gt;, this is a more
practical note about using GPG to store your passwords for mutt. This note
implies that you already have installed and configured GPG (which you can learn
how to do in above linked article).&lt;/p&gt;

&lt;p&gt;First you will have to record a password to a GPG file. Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PASSWORD&lt;/code&gt;
with your password and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ACCOUNT&lt;/code&gt; with a desired account alias. You probably
want to prefix this command with a space, to avoid writing your password to a
history file.&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;echo &apos;$PASSWORD&apos; | gpg --use-agent -e &amp;gt; ~/.passwd/$ACCOUNT.gpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, open your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.muttrc&lt;/code&gt; file and add following line:&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;set imap_pass = &quot;`gpg --use-agent --quiet --batch -d ~/.passwd/$ACCOUNT.gpg`&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Again, replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ACCOUNT&lt;/code&gt; with the same account alias you specified earlier.
Now you don’t have to re-enter your password every time you start Mutt.&lt;/p&gt;

</description>
        <pubDate>Wed, 28 May 2014 19:11:52 +0000</pubDate>
        <link>https://rosipov.com/blog/using-mutt-with-gpg/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/using-mutt-with-gpg/</guid>
        
        <category>gpg</category>
        
        <category>mutt</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Use vimdiff as git mergetool</title>
        <description>&lt;p&gt;Using vimdiff as a git mergetool can be pretty confusing - multiple windows and
little explanation. This is a short tutorial which explains basic usage, and
what the LOCAL, BASE, and REMOTE keywords mean. This implies that you have at
least a little bit of basic vim knowledge (how to move, save, and switch
between split windows). If you don’t, there’s a short article for you:
&lt;a href=&quot;https://rosipov.com/blog/using-vim-for-writing-code/&quot;&gt;Using vim for writing code&lt;/a&gt;. Some basic understanding of git and branching
is required as well, obviously.&lt;/p&gt;

&lt;h2 id=&quot;git-config&quot;&gt;Git config&lt;/h2&gt;

&lt;p&gt;Prior to doing anything, you need to know how to set vimdiff as a git
mergetool. That being said:&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;git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will set git as the default merge tool, will display a common ancestor
while merging, and will disable the prompt to open the vimdiff.&lt;/p&gt;

&lt;h2 id=&quot;creating-merge-conflict&quot;&gt;Creating merge conflict&lt;/h2&gt;

&lt;p&gt;Let’s create a test situation. You are free to skip this part or you can work
along with the tutorial.&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;mkdir zoo
cd zoo
git init
vi animals.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s add some animals:&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;cat
dog
octopus
octocat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save the file.&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;git add animals.txt
git commit -m &quot;Initial commit&quot;
git branch octodog
git checkout octodog
vi animals.txt  # let&apos;s change octopus to octodog
git add animals.txt
git commit -m &quot;Replace octopus with an octodog&quot;
git checkout master
vi animals.txt  # let&apos;s change octopus to octoman
git add animals.txt
git commit -m &quot;Replace octopus with an octoman&quot;
git merge octodog  # merge octodog into master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s where we get a merge error:&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;Auto-merging animals.txt
CONFLICT (content): Merge conflict in animals.txt
Automatic merge failed; fix conflicts and then commit the result.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;resolving-merge-conflict-with-vimdiff&quot;&gt;Resolving merge conflict with vimdiff&lt;/h2&gt;

&lt;p&gt;Let’s resolve the conflict:&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;git mergetool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/three-way-merge-with-vimdiff.png&quot; alt=&quot;Three-way merge using vimdiff. Local changes are in top left, followed by a common ancestor, and branch `octodog` in the top right corner. Resulting file is at the bottom.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This looks terrifying at first, but let me explain what is going on.&lt;/p&gt;

&lt;p&gt;From left to right, top to the bottom:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LOCAL&lt;/code&gt; – this is file from the current branch
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BASE&lt;/code&gt; – common ancestor, how file looked before both changes
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REMOTE&lt;/code&gt; – file you are merging into your branch
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MERGED&lt;/code&gt; – merge result, this is what gets saved in the repo&lt;/p&gt;

&lt;p&gt;Let’s assume that we want to keep the “octodog” change (from REMOTE). For that,
move to the MERGED file (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl + w, j&lt;/code&gt;), move your cursor to a merge conflict
area and then:&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;:diffget RE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This gets the corresponding change from REMOTE and puts it in MERGED file. You
can also:&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;:diffg RE  &quot; get from REMOTE
:diffg BA  &quot; get from BASE
:diffg LO  &quot; get from LOCAL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save the file and quit (a fast way to write and quit multiple files is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:wqa&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit&lt;/code&gt; and you are all set!&lt;/p&gt;

&lt;p&gt;If you’d like to get even better about using Vim, I wrote a book about it:
&lt;a href=&quot;https://amzn.to/3rne4dk&quot;&gt;Mastering Vim&lt;/a&gt;. I’m pretty proud of how it turned out, and I hope you like
it too.&lt;/p&gt;

</description>
        <pubDate>Fri, 14 Jun 2013 02:18:16 +0000</pubDate>
        <link>https://rosipov.com/blog/use-vimdiff-as-git-mergetool/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/use-vimdiff-as-git-mergetool/</guid>
        
        <category>git</category>
        
        <category>vimdiff</category>
        
        
        <category>Vim</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Download gists from prompt</title>
        <description>&lt;p&gt;I wrote a little script to download gists from the command prompt.&lt;/p&gt;

&lt;p&gt;Generate your Github API Token under Settings -&amp;gt; Applications, change it within
a script, and then:&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;chmod +x shgist.py
mv shgist.py ~/bin/shgist
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where ~/bin is a directory in your path. Now you can use it as shgist file to
quickly download your gists (&lt;a href=&quot;https://gist.github.com/ruslanosipov/5599377&quot;&gt;Gist on Github&lt;/a&gt;).&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;#!/usr/bin/env python

# Ruslan Osipov
# Usage: shgist keywords
# Description: Gists downloader

import urllib
import urllib2
import sys
import json

token = &apos;Personal API Access Token&apos;  # Github Settings -&amp;gt; Applications

class Gist:
    def __init__(self, token):
        &quot;&quot;&quot;
        token -- str, github token
        &quot;&quot;&quot;
        self.token = token
        self.url = &apos;https://api.github.com&apos;

    def find_by_name(self, keywords):
        &quot;&quot;&quot;
        keywords -- list of strings
        &quot;&quot;&quot;
        gists, urls = self._get_gists()
        for i, gist in enumerate(gists):
            for keyword in keywords:
                if keyword not in gist:
                    del gists[i]
                    del urls[i]
                    break
        if len(gists) == 0:
            print &quot;Sorry, no gists matching your description&quot;
            return
        if len(gists) == 1:
            self._download_gist(gists[0], urls[0])
            return
        for i, gist in enumerate(gists):
            print i, gist
        while True:
            num = raw_input(&quot;Gist number, &apos;q&apos; to quit: &quot;)
            if num == &apos;q&apos;:
                print &quot;Quiting...&quot;
                return
            try:
                num = int(num)
                if 0 &amp;lt;= num &amp;lt; len(gists):
                    break
                print &quot;Number should be within specified range&quot;
            except:
                print &quot;Only integers or &apos;q&apos; are allowed&quot;
        self._download_gist(gists[num], urls[num])

    def _download_gist(self, name, url):
        &quot;&quot;&quot;
        name -- str, filename
        url -- str, raw gist url
        &quot;&quot;&quot;
        print &quot;Downloading %s...&quot; % name
        gist = self._send_get_request(url)
        open(name, &apos;wb&apos;).write(gist)

    def _get_gists(self):
        &quot;&quot;&quot;
        Returns 2 lists which should be treated as ordered dict
        &quot;&quot;&quot;
        url = &apos;/gists&apos;
        response = self._send_get_request(self.url + url)
        response = json.loads(response)
        gists, urls = [], []
        for gist in response:
            for name, meta in gist[&apos;files&apos;].items():
                gists.append(name)
                urls.append(meta[&apos;raw_url&apos;])
        return gists, urls

    def _send_get_request(self, url):
        &quot;&quot;&quot;
        url -- str
        &quot;&quot;&quot;
        headers = {
                &apos;Authorization&apos;: &apos;token &apos; + self.token
                }
        request = urllib2.Request(url, headers=headers)
        response = urllib2.urlopen(request)
        return response.read()

argv = sys.argv[1:]
if not len(argv):
    print &quot;Usage: shgist keywords&quot;
    sys.exit(0)

gist = Gist(token)
gist.find_by_name(argv)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Fri, 17 May 2013 18:52:02 +0000</pubDate>
        <link>https://rosipov.com/blog/download-gists-from-prompt/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/download-gists-from-prompt/</guid>
        
        <category>gist</category>
        
        <category>github</category>
        
        <category>python</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>My most used bash commands</title>
        <description>&lt;p&gt;Shell history can tell a lot about its owner. What’s in your shell?&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;history | awk &apos;{CMD[$2]++;count++;}
END { for (a in CMD)print CMD[a] &quot; &quot; CMD[a]/count*100 &quot;% &quot; a;}&apos;
| grep -v &quot;./&quot; | column -c3 -s &quot; &quot; -t | sort -nr | nl |  head -n10

     1  580  38.0328%    git         # I keep everything under VCS
     2  202  13.2459%    cd          # Moving around a lot
     3  171  11.2131%    vi          # Favorite text editor
     4  127  8.32787%    ls          # I&apos;m a curious person
     5  43   2.81967%    rm          # I also like when it&apos;s clean
     6  26   1.70492%    usrswitch   # https://gist.github.com/ruslanosipov/5453510
     7  25   1.63934%    exit        # I don&apos;t like hitting the red cross button
     8  18   1.18033%    source      # Reloading bash configuration files
     9  17   1.11475%    clear       # Like when it&apos;s *really* clean
    10  15   0.983607%   gitk        # Sometimes it is too messy for git log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Wed, 24 Apr 2013 16:47:11 +0000</pubDate>
        <link>https://rosipov.com/blog/my-most-used-bash-commands/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/my-most-used-bash-commands/</guid>
        
        <category>bash</category>
        
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Colorless week results</title>
        <description>&lt;p&gt;A round-up of &lt;a href=&quot;https://rosipov.com/blog/a-week-without-colorful-prompt/&quot;&gt;The Week Without Colorful Prompt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I worked with the colors disabled in bash, git, and vim for a week. So how did
it go? It is definitely an interesting experience, but such a harsh change that
it doesn’t really work out with everything.&lt;/p&gt;

&lt;h2 id=&quot;bash&quot;&gt;Bash&lt;/h2&gt;

&lt;p&gt;Disabling colorful PS1 and removing color output for ls commands forced me to
concentrate more on the actual text, changing the perception of the general
bash workflow. I was more concentrated on the task, missed less details, and
generally paid more attention to the output.&lt;/p&gt;

&lt;h2 id=&quot;git&quot;&gt;Git&lt;/h2&gt;

&lt;p&gt;Never repeat my mistake by disabling colors for git diff. Log and status are
fairly easy to read, but the disabling of colors noticeably slows down the
workflow.&lt;/p&gt;

&lt;h2 id=&quot;vim&quot;&gt;Vim&lt;/h2&gt;

&lt;p&gt;Vim without code highlight forces you to remember your code structure more
effectively, which is a great thing. Not having a need to rely on color can
hint that a programmer has better understanding of the code he/she is writing.&lt;/p&gt;

&lt;p&gt;Now that the experiment is over I have mostly returned to using colorful
prompt. But I do turn syntax highlight off once in a while - it allows you to
see problems from new angle and work more efficiently at finding a solution.
Try it and see for yourself!&lt;/p&gt;

</description>
        <pubDate>Wed, 17 Apr 2013 18:32:46 +0000</pubDate>
        <link>https://rosipov.com/blog/colorless-week-results/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/colorless-week-results/</guid>
        
        <category>bash</category>
        
        <category>git</category>
        
        
        <category>Vim</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>A week without colorful prompt</title>
        <description>&lt;p&gt;I noticed that I rely on colors in the bash terminal a lot, as in git output,
diffs, directory and file listings… It gets worse when using vim - I feel
lost without the cozy syntax highlight guidance.&lt;/p&gt;

&lt;p&gt;Time to stop using output colors for a week whether in shell, git, or vim, and
use only plain text with no fancy colors. Set git config –global color.ui
false and don’t use –color flags in shell. Also, set syntax off and set a
simple color scheme for vim.&lt;/p&gt;

&lt;p&gt;What can I gain from all this? It will definitely reduce my productivity for a
few days. However, I have a hint of an idea that changing the visual code
representation will give me new insight on what I am currently writing.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ruslanosipov/dotfiles/commit/b2b592e4f5b4b2f5bb962651a03f9d83b3ab53b7&quot;&gt;Link to related commit on GutHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check back in a week to see how it went!&lt;/p&gt;
</description>
        <pubDate>Mon, 01 Apr 2013 18:10:31 +0000</pubDate>
        <link>https://rosipov.com/blog/a-week-without-colorful-prompt/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/a-week-without-colorful-prompt/</guid>
        
        <category>bash</category>
        
        <category>git</category>
        
        
        <category>Vim</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Editing bash command in vim</title>
        <description>&lt;p&gt;You can open the current command you are typing for editing in your default
text editor by pressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl + x + e&lt;/code&gt;. It will be executed after you write and
quit the file. This is perfect for editing long/multi-line commands where typos
are likely to occur. Consider something like this:&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;for run in {1..10}
do
    echo &quot;Print me ten times&quot;
done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Editing this in vim is much more satisfying, isn’t it?&lt;/p&gt;

&lt;p&gt;You can also open the last executed command for editing if you execute the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fc&lt;/code&gt;
command. You can also edit the last command starting with a certain pattern
using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fc [pattern]&lt;/code&gt; (you can skip the editor and execute the output of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fc&lt;/code&gt; by
adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-s&lt;/code&gt; option, and a useful tip is to have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alias r=&quot;fc -s&quot;&lt;/code&gt;, which
would allow you to execute the last command starting with “cc” by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r
cc&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;P.S: In order for this trick to open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt; and not any other editor, make sure
you have the line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EDITOR=vim&lt;/code&gt; in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt;. Obviously this works with
any text editor.&lt;/p&gt;
</description>
        <pubDate>Mon, 01 Apr 2013 07:34:28 +0000</pubDate>
        <link>https://rosipov.com/blog/editing-bash-command-in-vim/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/editing-bash-command-in-vim/</guid>
        
        <category>bash</category>
        
        
        <category>Vim</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>IRSSI - ignore all from everyone</title>
        <description>&lt;p&gt;If you visit noisy IRC channels like the programming ones on freenode, you
probably want to ignore all the annoying status messages.&lt;/p&gt;

&lt;p&gt;To permanently ignore joins, parts, quits, and nickname changes from every
channel in IRSSI:&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;/ignore * joins parts quits nicks
/save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I keep forgetting the exact syntax, so maybe clipping the snippet in a blog
post will keep it in my memory.&lt;/p&gt;
</description>
        <pubDate>Wed, 27 Mar 2013 15:37:10 +0000</pubDate>
        <link>https://rosipov.com/blog/irssi-ignore-all-from-everyone/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/irssi-ignore-all-from-everyone/</guid>
        
        <category>irssi</category>
        
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Rename commit author in git</title>
        <description>&lt;p&gt;In some extremely rare cases you end up pushing data to the repo with the wrong
credentials. If you are the only author and you’re as picky as I am, it can be
corrected easily:&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;git filter-branch -f --env-filter
&quot;GIT_AUTHOR_NAME=&apos;Stan Smith&apos;;
GIT_AUTHOR_EMAIL=&apos;stansmith@cia.gov&apos;;
GIT_COMMITTER_NAME=&apos;Stan Smith&apos;;
GIT_COMMITTER_EMAIL=&apos;stansmith@cia.gov&apos;;&quot; HEAD
git push --force
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the case of there being multiple people working on a project, you may want
to use the following gist posted by anonymous:
&lt;a href=&quot;https://gist.github.com/anonymous/2523336/&quot;&gt;https://gist.github.com/anonymous/2523336/&lt;/a&gt; (again, followed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push
--force&lt;/code&gt;).&lt;/p&gt;
</description>
        <pubDate>Fri, 15 Mar 2013 00:09:02 +0000</pubDate>
        <link>https://rosipov.com/blog/rename-commit-author-in-git/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/rename-commit-author-in-git/</guid>
        
        <category>git</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Mintty color scheme (Cygwin)</title>
        <description>&lt;p&gt;&lt;img src=&quot;/images/posts/mintty-softer-color-scheme.png&quot; alt=&quot;Softer colors for mintty.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I find the default cygwin color palette to be a bit ugly, so here’s one that
has softer colors. Add the following lines to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.minttyrc&lt;/code&gt; and restart
cygwin in order to apply changes.&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;ForegroundColour = 131, 148, 150
BackgroundColour =   0,   0,   0
CursorColour     = 220,  50,  47

Black            =   7,  54,  66
BoldBlack        =   0,  43,  54
Red              = 220,  50,  47
BoldRed          = 203,  75,  22
Green            =   0, 200, 132
BoldGreen        =   0, 200, 132
Yellow           = 204, 204, 102
BoldYellow       = 204, 204, 102
Blue             = 102, 153, 204
BoldBlue         = 102, 153, 204
Magenta          = 211,  54, 130
BoldMagenta      = 108, 113, 196
Cyan             =  42, 161, 152
BoldCyan         = 147, 161, 161
White            = 238, 232, 213
BoldWhite        = 253, 246, 227
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Update (December 2018): This theme is now packaged with the default Mintty
distribution! Pull up Mintty/Cygwin and check for a theme called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rosipov&lt;/code&gt; (I
didn’t pick the name).&lt;/p&gt;
</description>
        <pubDate>Wed, 13 Mar 2013 19:35:28 +0000</pubDate>
        <link>https://rosipov.com/blog/mintty-color-scheme-cygwin/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/mintty-color-scheme-cygwin/</guid>
        
        <category>cygwin</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Rails and MongoDB with Cygwin</title>
        <description>&lt;p&gt;Setting up Ruby on Rails with MongoDB on a Windows machine.&lt;/p&gt;

&lt;p&gt;You need to have cygwin installed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; packages (obviously you
may want to have more).&lt;/p&gt;

&lt;p&gt;The following commands are executed in the cygwin prompt:&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;git clone git://github.com/rubygems/rubygems.git
cd rubygems/
ruby setup.rb
gem install rails
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Go to the MongoDB website and download Windows binaries:
&lt;a href=&quot;http://www.mongodb.org/downloads&quot;&gt;http://www.mongodb.org/downloads&lt;/a&gt;. Extract the content of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin/&lt;/code&gt; directory
to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\cygwin\usr\local\bin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create a directory for the db files (the default MongoDB db files directory is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\datadb&lt;/code&gt;):&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;cd /cygdrive/c
mkdir data
mkdir data/db
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Done! Both mongo and rails are in your cygwin’s path now, feel free to tweak it
as you see fit.&lt;/p&gt;
</description>
        <pubDate>Mon, 11 Mar 2013 19:38:30 +0000</pubDate>
        <link>https://rosipov.com/blog/rails-and-mongodb-with-cygwin/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/rails-and-mongodb-with-cygwin/</guid>
        
        <category>mongodb</category>
        
        <category>rails</category>
        
        
        <category>Programming</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Git: merge two repositories</title>
        <description>&lt;p&gt;Today I had to merge changes from one repository into another. Let’s assume you
want to merge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;beta&lt;/code&gt; into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Operations are performed in repo alpha:&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;git remote add beta_repo git@rosipov.com:beta.git
git fetch beta_repo
git merge beta_repo/master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this case, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;beta_repo&lt;/code&gt; is the name you pick for remote.&lt;/p&gt;

&lt;p&gt;If you just need to cherry-pick a certain commit from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;beta&lt;/code&gt; you can omit the
last step and replace it with the cherry-pick.&lt;/p&gt;

&lt;p&gt;More on the topic of remotes: &lt;a href=&quot;http://git-scm.com/book/ch2-5.html&quot;&gt;http://git-scm.com/book/ch2-5.html&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Thu, 21 Feb 2013 20:09:07 +0000</pubDate>
        <link>https://rosipov.com/blog/git-merge-two-repositories/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/git-merge-two-repositories/</guid>
        
        <category>git</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>GPG Usage</title>
        <description>&lt;p&gt;To encrypt and decrypt files in Linux there is a utility called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gpg&lt;/code&gt; (Gnu
Privacy Guard). This is a short GPG tutorial.&lt;/p&gt;

&lt;h2 id=&quot;quick-usage-example&quot;&gt;Quick usage example&lt;/h2&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;gpg -c foo.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It will prompt you for the passphrase and a confirmation. Now you will have the
encrypted &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo.txt.gpg&lt;/code&gt; file. To decrypt a file:&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;gpg -d foo.txt.gpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will forward the output to the console. You can output it into a file:&lt;/p&gt;

&lt;p&gt;gpg -d foo.txt.gpg &amp;gt; foo.txt&lt;/p&gt;

&lt;h2 id=&quot;gpg-keyring&quot;&gt;GPG keyring&lt;/h2&gt;

&lt;p&gt;This is all secure, but not quite enough if you are paranoid. Keys are what
makes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gpg&lt;/code&gt; great. Let’s generate a private key:&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;gpg --gen-key
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And create an ASCII version of a public key:&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;gpg --armor --export &quot;John Doe&quot; --output johndoe.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Public key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;johndoe.txt&lt;/code&gt; can be freely distributed. Now you can encrypt files
for yourself only:&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;gpg -e -r &quot;John Doe&quot; foo.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now if you decrypt a file it will require the passphrase you specified while
generating a key. To encrypt a file for someone else you should have this
person’s public key.&lt;/p&gt;

&lt;p&gt;Let’s assume Stan Smith sent you a key, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stansmith.txt&lt;/code&gt;. You import it using:&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;gpg --import stansmith.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And encrypt the file:&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;gpg -e -r &quot;Stan Smith&quot; foo.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Wed, 26 Dec 2012 20:00:22 +0000</pubDate>
        <link>https://rosipov.com/blog/gpg-usage/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/gpg-usage/</guid>
        
        <category>gpg</category>
        
        <category>linux</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>Create gitolite repository</title>
        <description>&lt;p&gt;A reminder on how to initialize a fresh gitolite repository, assuming that
gitolite has already been set up.&lt;/p&gt;

&lt;p&gt;All actions are performed on a local machine. In this case: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/gitolite-admin&lt;/code&gt;
is admin repository, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/foo&lt;/code&gt; is desired repository, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rosipov.com&lt;/code&gt; is gitolite
hostname. Command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vi&lt;/code&gt; stands for the text editor, but you may use whichever
editor you prefer.&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;cd ~/gitolite-admin
vi conf/gitolite.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add lines (obviously you may want to use individual users instead of @all):&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;repo foo
    RW+ = @all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save it. Next:&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;git add conf/gitolite.conf
git commit -m &quot;Add foo repo for @all&quot;
git pull --rebase &amp;amp;amp;&amp;amp;amp; git push
mkdir ~/foo
cd ~/foo
git init
git remote add origin git@rosipov.com:foo.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add some files at this point. In this example, only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitkeep&lt;/code&gt; is added.&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;git add .gitkeep
git commit -m &quot;Initialize repo&quot;
git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The new repository is all set up now.&lt;/p&gt;
</description>
        <pubDate>Mon, 10 Dec 2012 04:11:23 +0000</pubDate>
        <link>https://rosipov.com/blog/create-gitolite-repository/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/create-gitolite-repository/</guid>
        
        <category>git</category>
        
        <category>gitolite</category>
        
        
        <category>Programming</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>GUI git difftool for Windows</title>
        <description>&lt;p&gt;A quick note on how to set up GUI difftool to use with git on Windows (Git
Bash, Cygwin, etc…).&lt;/p&gt;

&lt;p&gt;Download and install GUI diff tool of your choice, get the path to executable.&lt;/p&gt;

&lt;p&gt;Create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;difftool.sh&lt;/code&gt; in directory included in your path (for example
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\Users\{username}\bin&lt;/code&gt; in Git Bash). Let’s take SourceGear’s DiffMerge as an
example.&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;#!/bin/sh
&quot;C:/Program Files/SourceGear/Common/DiffMerge/sgdm.exe&quot; &quot;$1&quot; &quot;$2&quot; | cat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And in your ~/.gitconfig:&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;[diff]
    tool = diffmerge
[difftool &quot;diffmerge&quot;]
    difftool.sh &quot;$LOCAL&quot; &quot;$REMOTE&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And difftool is available via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git difftool&lt;/code&gt; command now.&lt;/p&gt;
</description>
        <pubDate>Thu, 06 Dec 2012 20:02:24 +0000</pubDate>
        <link>https://rosipov.com/blog/gui-git-difftool-for-windows/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/gui-git-difftool-for-windows/</guid>
        
        <category>git</category>
        
        <category>windows</category>
        
        
        <category>Productivity</category>
        
        <category>CLI</category>
        
      </item>
    
  </channel>
</rss>
