Wizards Don’t Do Dishes

They Automate Them

Wizards Don’t Do Dishes

Programming is the closest thing to magic I’ve found. But even in programming, there’s no shortage of mundane nearly-identical tasks. They accumulate like dirty dishes with dismal regularity, sapping our time and willpower.

Maybe you’re a freelancer billing hours, so every day you print out the repo’s git commits, copy your commits, format and save them to your worklog. Endless, like the dishes. But what if you could do it once and be done, forever?

 # Print and format git commits - credit: https://github.com/abaldwin88
alias git-today='git --no-pager log --pretty="- %s. %b" --author=[YOUR GIT USERNAME/EMAIL] --since=midnight --all --no-merges --reverse'

# remove lines with "index on", remove duplicate lines, remove empty lines, add new line delimiter for \*

git-today-clean() { git-today | awk '!/^index on/' | awk '!x[$0]++' | sed 's/\*/\'$'\n\*/g' | sed '/^$/d' }
gitToday() { git-today-clean && git-today-clean | pbcopy }

Still too much work? Set it on a cronjob appending to a work_log.txt file with aliases sourced and loaded, and never think of it again.

When you see a repetitive task, even an easy one, remember: Wizards don’t do dishes, they automate. You should too.

Merlin certainly doesn't do dishes.

What Makes a Good Spellbook?

Any high-frequency, verbose, or hard to research command that makes your life easier is worth keeping. And once you’ve started amassing a treasure trove of one-liners you need a spellbook to put them in. By ‘spellbook’, I mean a modifiable, instantly accessible, and referenceable codebase that is always at your fingertips. Files like .bashrc and .zshrc (RC meaning “run commands”) are great. Cheat sheets, reference notes, and tools like tldr or navi also work, provided they’re command line accessible. Aliases and code editor snippets are perfect as they’re tailored to your use cases and always in your dev environment.

Make your spellbook easy to add to and even easier to search. If it gets too big to browse, tag and grep it. Once your system is set up you can solve a problem once and have the solution ready to go forever.

Start simple

As a junior I was drowning in database commands, unfamiliar syntax and lengthy api calls. I needed something more organized and durable than my bash history, but more seamless than my notes app. So I made my first custom tool. I created a ~/.cheatsheet.txt file and added two simple bash functions to my .zshrc.

# ~/.zshrc
function csadd() { echo "$1" >> ~/.cheatsheet.txt; }
function cs() { cat ~/.cheatsheet.txt | grep "\#$1"; }

# Add a snippet
$ csadd '| python -m json.tool #json'

# Return all tags labeled '#json'
$ cs json
#=> '| python -m json.tool #json'

In two lines of code, I had a working cheatsheet. Not a feature-rich CLI like Navi, just some crude glue around cat and a .txt, but I could already reference commands, add snippets, search, and pipe data in seconds.

Keep commands short

It’s worth speeding up even the simplest actions, if they’re frequent enough. Surprisingly, some of my best time gains are aliases for cd’ing into commonly used directories and project setup.

# ~/.zshrc or ~`/.bashrc`
# -------
# Files and Project
# -------
alias notes="cd ~/Documents/notes/"
alias todo="code ~/work/todo.md"
alias project_notes="open ~/work/my_project/daily_notes.md"
alias spinup="cd ~/work/my_app && bundle exec rails server -p 3000"

# -------
# Git Aliases
# -------
alias ga="git add "
alias gb="git branch "
alias gc="git commit "
alias gd="git diff "
alias gm="git merge "
alias go="git checkout "
alias go="git checkout "
alias gp="git pull "
alias gs="git status "

You might ask, isn’t that overkill?

Short answer: No. Your brain has a very small attention buffer (7 ± 2). The faster you move the less that precious buffer decays.

Why use more chars when few chars do trick?

– Kevin Malone

Your dev environment should fit you, even outside the command line. Getting hacky, you can make a js script to fill out forms or dummy logins, save your localhost app url on chrome Site Search settings so you can simply type @l to go to it.
Adding localhost url as a browser shortcut

Example: pryrc

Let’s show how you might start this process with a Ruby .pryrc file for Rails projects. The .pryrc (or .irbrc, if you use irb) functions pretty much like bashrc in that it gives us a place to load up commands and config so we can access them in our pry or irb console.

Let’s load up our handy .pryrc spellbook and set some default models and convenience methods.

# ~/my_rails_app/.pryrc

# initial boilerplate
if defined?(Rails)
  module Rails::ConsoleMethods
    alias r reload!

    def any_method

Default models

Now let’s write some common model variables models so we don’t have to type them each time by hand.

  # convenience variable
  def admin
    User.where(admin: true).first

  # memoized convenience variable
  def user
    @user ||= User.first

  # longer queries
  def late_books
    Book.where("due_date < ?", Date.today)

Custom commands

Want to save a large output to your clipboard without fiddly mousework?

  def rbcopy(arg)
    `echo "#{arg}" | pbcopy`
  # alternate: IO.popen('pbcopy', 'w') { | io | io.puts arg }

Or maybe execute sql in the rails console without typing 50+ lines?

def ex_sql(sql)
  results = ActiveRecord::Base.connection.execute(sql)&.entries

Or make benchmarking easier?

  # credit: https://gist.github.com/justin808/387d4754d3a3aec35bde64c979857170
  # Usage: do_time(20) { expensive_query }
  def do_time(repetitions = 100, &block)
    require 'benchmark'
    Benchmark.bm { |b| b.report { repetitions.times(&block) } }

Or add a hacky class name alias?

  def rl
  # Now you can call rl.where() instead of ReallyLongModelNameYouAlwaysTypeWrong.where()

Check out what other amazing devs have done in their pryrcs and irbrcs. The possibilities are endless!

Many thanks to Justin Weiss and Rishi Pithadiya’s blogposts for upping my pryrc game.

Loved the article? Hated it? Didn’t even read it?

We’d love to hear from you.

Reach Out

Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *

More Insights

View All