Today I Learned

A Hashrocket project

60 posts about #workflow

Debug :hover selectors in CSS

When styling HTML you may need to define a hover style the css of which might look like this:

div.something:hover {
  background-color: red;

The div with class something will now have a red background when your mouse hovers over it.

This can be hard to debug however, if this were a regular style we could inspect it and change the style of the element in dev tools. With hovers, the style is only available in dev tools when the mouse is physically over the element.

Chrome has a facility to declare that a hover state should be on for an element. Simply open dev tools and in the Elements tab right click an element to get a context menu. The menu will have options :active, :hover, :focus, and :visited. Choose :hover and the hover state will be permenantly affixed to that element. You can now play with the hover style until it looks right.

Full page screenshots in Firefox

Firefox has an interesting feature called the Developer Toolbar. This toolbar is entirely separate from the JS console and provides a cli for custom commands for specific functionality. It can opened with shift-F2 or Tools > Developers > Developer Toolbar.

In that toolbar, type:

screenshot --fullpage my-page.png

A png file with the given name will be saved to the Downloads folder. The file format will always be png.


More Developer Toolbar information can be found here.

Type help in the toolbar to see all the commands.

Images in markdown

Images in markdown are the same as links except for the bang (!) character preceding the syntax.

The syntax for links is squares-parens. I have a hard time remembering this, and I try parens-squares as often as not, but its squares-parens, like this:

[My text](

The syntax for images is also squares-parens but preceded by a bang (!), like this:

![My alt text](

Understanding Github's Language Calculations

Ever noticed this at the top of a Github repo?

This filetype percentage is calculated by Github's Linguist project.

There's just one problem: 'Today I Learned' isn't a JavaScript project; it's a Rails application. I would expect the majority of the files to be Ruby files. Labeling 'Today I Learned' a JavaScript project misrepresents it to the Github community.

I found several techniques to correct the Linguist evaluation; this pull request explains one I tried in greater detail. TL;DR – once I moved some vendored JS files into a directory with a name that Linguist ignores (ace-builds/), the calculation started to look more like a Rails app.

Here's the updated header:

🐚 Private Shell History

Sometimes you don't want to put a dangerous command into your shell history, for example:

git reset --hard HEAD~

In zsh you can prevent a command from being saved in you history by setting the zsh option: setopt HIST_IGNORE_SPACE

then just prefix your command with a space:

 git reset --hard HEAD~

Business Development

Today I learned to use a new scheduling tool called, The Clock. It will keep your client meetings across multiple time zones on point! The Clock App

Exclude Whitespace Changes From GitHub Diffs

If you run a tidy ship and use plugins like vim-spacejam, then whitespace changes cluttering up your git diffs probably isn't much of an issue.

However, if you are working with other people or messier code bases, then you may not be so lucky. If there are a bunch of whitespace changes in a commit, then that is going to make the diff view of a commit on GitHub annoying, and perhaps hard, to read.

You can cut to the chase by excluding whitespace changes from GitHub's diff view by adding w=1 to the diff URL.

Check out this view of the diff and then this view of the diff that excludes whitespace.


Simulating Various Connection Speeds In Chrome

I spend everyday building web apps from a machine that has a wired connection to the internet. Though I spend a lot of time loading various pages and experiencing the app like a user might, I end up having a pretty narrow perspective. What will this app be like for people on various qualities of mobile connections?

Chrome has a feature built in to its devtools that makes it easy to throttle your connection to simulate various speeds. Open up devtools with Cmd+Opt+J, navigate to the Network tab, and then open the throttling drop down.

From here we can select the connection speed we want to simulate. If we then reload the page, we will not only experience the page load at that speed, we will also see the numbers in that Network tab.

You have new mail.

Sometimes you forget to give that cron task somewhere to output its results... so it dumps them in your mail box... πŸ“¬πŸ˜£ all 30,000 times it failed to run.

You don't have to delete all those emails one by one πŸ˜‰

echo 'd *' | mail -N

d * means delete all mail. The -N means:

-N      Inhibit the initial display of message headers
        when reading mail or editing a mail folder.

View your Github Project's Forks

Today I clicked on the number next to the fork count on a Github project, and landed on this page (TIL used as an example):

This chart is pretty coolβ€” it visualizes the recent forking activity around your project, and gives you insight into activity happening downstream on different forks.

Get selected element in Chrome Console

Today I learned that you can use $0 to grab the selected element inside chrome console:

screen shot 2016-09-30 at 10 21 41 am

Here's a list of more useful chrome-commands.

h/t @joshuadavey

Map Caps Lock to Escape in macOS Sierra #seil

macOS Sierra was made available to the public yesterday and many of us early adopters rushed to install and test it out.

One of the things that broke and really affected my workflow was that Seil, the program I use to remap Caps Lock to ESC, no longer works. It's sister application Karabiner also stopped working.

Fortunately there's a solution available from the developer of Karabiner and Seil. It's a little more complicated than usual:

  1. Download and install Karabiner-Elements:

  2. Karabiner Elements will install a virtual keyboard driver, and you probably want to disable the default capslock behavior for the new virtual driver:

    disable capslock

  3. Use your favorite editor and edit the following file (create it if does not exist):

    vim ~/.karabiner.d/configuration/karabiner.json

    And add the following to it:

        "profiles": [
                "name": "Default profile",
                "selected": true,
                "simple_modifications": {
                    "caps_lock": "escape"

That's it. Just make sure you have Karabiner Elements running.

View Source Repos on Github

A neat hack when browsing a Github profile is to view only source repositories with the 'Source' button.

This excludes repository forks, as might be used for open-source contribution, only showing original repos.

Markdown link references

Today I learned that we can use link references in markdown like this:

# Link by Reference with `alt` option
[Link by reference][my-link]

[my-link]: "My Link"

# Regular link
[Regular link](

In this case the first link will be displayed as: Link by reference

Find Dead Code with Unused

Today I discovered a fascinating tool called Unused, written by Josh Clayton.

Unused leverages two of my favorite projects, Exhuberant Ctags and The Silver Searcher, to identify dead code. I installed it with homebrew.

Dead code is code that is never used by your application. It wastes electricity and mental bandwidth, and can hang around unnoticed for years. We need powerful tools to find and remove it.

Unused threw out a few false positives, as expected. Use with caution and a solid test suite.

The Unused website highlights several pull requests removing dead code from popular open source projects. I was able to use it on 'Today I Learned' itself. A small win:

Github Advanced Search Parameters

I really enjoy browsing Github. The search feature in particular is a fantastic way to stumble on interesting projects.

Search has an 'advanced' menu that lets you restrict your query. I've used it enough that I have some preferences that I enter directly into the search bar: is:issue is:open label:"help wanted" finds open issues actively seeking outside contributions. Not everybody uses labels, so removing that can yield even more results.

Add a language filter as a query parameter, and you're on your way to some good open source contribution opportunities. Drill down further with a search term, such as 'testing' or 'flicker'.

Drop connections with Nginx

You can ignore requests sent to nginx by responding with the status 444

server {
  listen 80;
  listen [::]:80;
  listen 443;
  listen [::]:443 ssl http2;

  location /no-response {
    return 444;

The primary use for this is to prevent processing requests with undefined server names:

# block for requests with undefined server names
server {
  listen 80;
  listen [::]:80;

  return 444;

Restart the ubuntu window manager

Somehow our ubuntu dev machine window manager often craps out. We have a lot of dev's shelled in, coding away, so rebooting isn't an option. This does the trick:

sudo service lightdm restart

Toggle Mute in Hangouts (Mac)

During client calls, I mute and unmute my microphone dozens of times. Mute to listen and cut ambient office noises, unmute to speak.

Google Hangouts provides some shortcuts for this and other common activities. In particular, ⌘ + d toggles mute on a Mac.

Step your videoconferencing game up! πŸ–₯

Swap tmux panes

To swap panes in tmux use

prefix {


prefix }

Ordering Issues on Github Milestones

Github released a long waited feature and now we can order issues inside a milestone.


Collapsable content in Github issues

Today I learned that we can use HTML 5 detail tag to wrap a bunch of lines. This is specially useful when reporting errors and its backtrace in a repository in Github.

  `` `ruby
  `` `


h/t by @ericclemmons

Loopback to different 127.*.*.* ips mac osx

You can't bind to the loopback interface automatically on mac osx.

> rails -b
ERROR: Can't assign requested address - bind(2) for (Errno::EADDRNOTAVAIL)

Mac OSX will disable all loopback addresses other than by default, but they can be enabled with ifconfig.

> sudo ifconfig lo0 alias up

And now your server can bind to that address.

h/t Jack Christensen

Script for bootstrapping a new project #bash #git

Creating a new project and publishing it usually involves many repeatitive steps. As developers we like to automate the tedious repetitive tasks to allow our creative juices to flow freely.

I wrote the following script for boostrapping a new project. Feel free to modify and add to your zshrc or bashrc:

function initprj() {
  # create the directory and cd into it unless the user uses '.'
  # to indicate current directory
  if [[ "$1" != "." ]]; then
    mkdir $1
    cd $1

  # setup git
  git init

  # setup remote repo on github and add it to git remote
  hub create

  # setup base files (add your own if you'd like)
  touch .gitignore

  # You must use tabs if you want to indent heredocs that use the <<- syntax
  cat <<-EOF > LICENSE
        Copyright (c) $(date +"%Y") Dorian Karter

        Permission is hereby granted, ...

To run the script simply type initprj my-project and watch the magic happen.

Note: you must have hub installed to create the remote repo.

`CTRL` commands in Chrome's Address Bar

The Hashrocket Dotmatrix binds some of the UNIX CTRL- commands to commands in Chrome's address bar. Here are a few examples:

  • CTRL-a to move cursor to the beginning of the line
  • CTRL-e to move cursor to the end of the line
  • CTRL-b to move the cursor one space backward
  • CTRL-f to move the cursor one space forward

There are more to try; some work the same as they do in the command line, and some work differently.

Here's the code that makes this possible.

h/t Brian Dunn

Find the error description in a tmux window

At Hashrocket we have a tmux binding ctrl-z e that will find the last instance of the word Error in the current window. This is great when error output for a test might consume 9 full windows worth of spaces at times.

This comes with Hashrocket's dotmatrix command line environment and is defined as:

bind-key e copy-mode \; send-keys "?Error" C-m

Defined at this location.

H/T Micah Woods

Rust Array Access is Bound Checked at Runtime

Today I encountered a feature of Rust that I hadn't seen beforeβ€” uses of array subscript notation ('array[n]') are checked at runtime to ensure they fit into the bounds of the array.

Here's a passing test I wrote to demonstrate:

// src/
#[should_panic(expected="index out of bounds: the len is 3 but the index is 5")]
fn array_access_is_bound_checked_at_runtime() {
    let elements = ["Wind", "Fire", "Water"];
    assert_eq!("Wind", elements[5]);

'Such errant access is the source of many bugs in other systems programming languages.' β€”The Rust Programming Language

More information:

The Rust Docs Appear

The The Rust Programming Language is a great introduction to the Rust Language. But what if I want to read the book offline?

Today I learned that if you have Rust installed, you have the documentation locally, via this pull request:

Here's the starting point (Unix):

$ open /usr/local/share/doc/rust/html/book/README.html

Execute this command and start reading.

Resizing Both Corners Of A Window (On Mac)

Hold the option key while resizing a corner of a window and it will simultaneously and equivalently resize the opposite corner.

Trust Issues πŸ€”

Our computers trust a scary amount of Root Certificate Authorites, and sometimes I have trust issues with some of them. Most recently being the StartCom bug, which allowed anyone to get a certificate for any domain they wanted.

I can't trust them. Period. And I don't have to.

Here is how you can revoke trust for any Root CA in OSX:

  1. Open Keychain Access.
    open /Applications/Utilities/Keychain\
  2. Click on System Roots from the left Keychains sidebar.
  3. Typestartcom in the search bar.
  4. Select all the root certificates and press ⌘i.
  5. Expand the Trust section
    and change the option
    When using this certificate
    Never Trust.

Github Reactions and Merge Strategy

Recently Github has launched 2 new features:

Reactions to comments

Now users can add few reactions to Issues, Pull Requests or Comments. This will reduce a lot of noise on issues like the πŸ‘ (:+1:) for new feature. Really cool.

Squash and rebase as a new merge strategy

Github always create a new commit merging a branch into another one (usually master).

So now we can choose to squash commits and merge. So all commits in a branch will become just one and this one will be rebased into the branch. Sounds cool for a few situations.

Check it out!

Add Emoji To GitHub Repository Description

GitHub restricts the set of unicode characters that can appear in the description field of a repository to anything up to 0xffff. Most emoji have unicode values above this. This means you will have limited success adding emoji via your system's emoji keyboard.

Fortunately, GitHub allows you to add any recognized emoji to a repository description with its specialized emoji syntax (e.g. :memo:). You may have used this syntax in other parts of GitHub such as the issue tracker.

If you add an emoji like this:

it will show up like so:

Check out this Emoji Cheat Sheet for the names of all recognized emojis.

Put -L in your ssh config

If you've used ssh you've probably had to use local port forwarding before. If you use complex flags often, you will find remembering what you need is tiresome. Stop. Write it down so you can forget all about it. Save your memory.

Instead of doing this:

ssh -L 3000:localhost:3002

Add those flags to the ~/.ssh/config file instead:

# /home/dillon/.ssh/config

Host example
  User         not_dillon
  LocalForward 3000 localhost:3002

From now on, all you need to type is:

ssh example

OS X WiFi Menu With Additional Info

Sometimes you want to know more about the WiFi network you're currently connected to - OS X has your back, just option-click on the WiFi icon in your menu:

WiFi Menu With More Info

h/t @chriserin

Pretty Print Tabular Data

Looking at a bunch of data in the Chrome dev tools console isn't great. It can be a bit difficult to read because of the way it is displayed. Fortunately, the Chrome dev tools come with a handy way of displaying tabular data, console.table(). If you give console.table an array of objects or array of arrays, it will format it in a table like so:

Reference The Selected Node

In the Chrome dev tools, if you've selected (highlighted) a node in the DOM, you can reference that node from the console with $0. This is handy if you are debugging or exploring certain parts of a page and need to run commands against that node. For instance, if you were to select the <html> node in the DOM, you could then programmatically check the lang attribute from the console like so:

> $0.lang
// "en-US"

If there is jQuery on the page and you've selected the node that contains all of the page's content, you can do something like the following:

> $($0).html('<h1>Hello, World!</h1>')

Tutorial Better

When I'm going through an online video tutorial, I have to write all of the code shown to really solidify the concepts. As a result I spend a lot of time pressing CMD + TAB to toggle between the browser video and my Vim session. This method is inefficient.

Helium to the rescue. Helium is a floating browser window for OS X, with some nice features like transparency. Position it on top of your console session, watch the video, and hack away in realtime.

Helium Screenshot

h/t Dorian Karter

Twitter Media and Characters

Today while debugging, we realized something surprising about Twitterβ€” attaching media to a tweet counts as characters and reduces the overall amount of characters available.

Try adding any picture to a tweet. You'll see the available characters drop. We experienced a consistent drop of 24, from 140 to 116, although this seems to have varied at different points in Twitter's history.

This can produce subtle failures in an API call; two-dozen (or so) phantom characters are subtracted just by adding an image and may push any tweet over the limit. Turning up our logs helped expose this issue.

Kill Other Connections To A tmux Session

One of the best features of tmux is the ability for multiple people to connect to the same session in order to pair. This can, however, sometimes result in a extra session hanging around if someone forgets to detach. This is no problem though because you can view and kill other connections.



to open up an interactive list of all connections to the current session. Then navigate over the one you want to kill and hit enter. If you are viewing the connections but don't want to kill one, you can hit q to back out.

h/t Josh Davey

The Case of the Default πŸ•΅

In Apple's Swift language switch statements must be what apple calls exhaustive. I've felt the term to be very literal. Literally exhaustive?

Example that does not work:

let count = 42

switch count {
case 1:
case 7:

The above statement does not work because it's missing a default case. Why? What if I don't want to do anything else? Why do I need to write something that won't be used? Don't worry, there is an amazing and less exhaustive way to handle these situations; simply default: ()

Correct example:

let count = 42

switch count {
case 1:
case 7:
default: ()

Enter the PHP REPL

Working in a language you've never worked in before can be challenging. We've been doing some PHP source-diving lately, and I find having a REPL very useful for decoding unfamiliar syntax.

If you have PHP installed, entering the REPL is easy; just type php -a. The flag stands for Run as interactive shell. I guess the -i flag was already taken.

Ternary shortcut in PHP

Sometimes, and hopefully sometimes is rarely, you have to read some PHP in order to rewrite that code in another language. In these cases you might run across this oddity.

$a = $a ?: 2; 

This is pretty much like var a = a || 2; in javascript but it comes out of the ternary operator and definitely doesn't make sense when you first look at it. In every other language that's a syntax error, but php, ya dig?

Get Chrome history from remote machine

Let's say you need to get the url you visited Friday at the office, but its Sunday and you're at home! First, ssh into the remote machine where you were browsing the internet. Second, locate the history file, on OSX its at:

~/Library/Application Support/Google/Chrome/Default/History

Third, try to open the file with a text editor. DOH! Its a sqlite file! Fortunately you have sqlite on your machine so you can use sqlite3 History at the command line. Fourth, type .table to see what tables are available. Oh that doesn't work, you get an error that says Error: database is locked. This is easy to overcome though, just make a copy of the history file.

cp History History.1
sqlite3 History.1
> .tables
downloads             meta                  urls
downloads_url_chains  segment_usage         visit_source
keyword_search_terms  segments              visits

Now you have access to the database. The url you want is definitely in the urls table, you just have to use your sql skills to find it!

Show Clipboard in OS X

With Mac OS X, we can easily view the contents of our system clipboard.

From the command line, load something into the clipboard (I have used pbcopy):

$ echo "you found me" | pbcopy

Open up your Finder, and in the toolbar, click 'Edit > Show Clipboard'. A window will open with you found me on display.

Swap panes and toggle pane layout in tmux

Use <leader>{ to swap panes in tmux.

Use <leader><spacebar> to toggle between different layouts.

How to use the hidden #VNC client in #Mac #OSX

OS X has a built in VNC (Screen Sharing) server, but it is a little known feature that it also has a built in VNC client. No additional software is necessary.

To setup the server go to Preferences->Sharing and check the On checkbox next to Screen Sharing. Make sure to only allow access to Administrators or a specific user/user group.

Screen Sharing

You should see your computer name on the Screen Sharing configuration screen. To connect to your computer from another one using VNC open Finder and press ⌘+k. In the Server Address enter vnc:// followed by your computer name or IP address. Connect To Server

h/t Dillon Hafer

How to donate to charity for free!

If you are like me, you make all of your big purchases on Amazon. You also would like to donate to charity but are not sure what charity to choose or how to be sure it's a legitimate organization.

Choose a charity

You first need to sign up for Amazon Smile choose the charity you would like to support.

Choose a charity

Amazon will now donate 0.5% of the purchase price for every item to the charity you selected! That may not sound like much but that is $1.50 for every $300 you spend, and you have to do LITERALLY nothing. Well... almost nothing. You still have to remember to shop through, and honestly I never remember. So today I figured out a way to make it truly effortless.

Install Switcheroo

Amazon has a Chrome extension that's supposed to give credit automatically but it also shows ads and I'm sure it tracks every page you visit. There is an open source too called Switcheroo that lets you establish custom redirects for any URL. Install Switcheroo

Configure Redirects

Configure Switcheroo

Now you will be redirected automatically and your charity will benefit from your last minute holiday spending!

Paging Up And Down In tmux

When in copy mode (<prefix>[), you can move the cursor around like you would in vim with the directional keys (hjkl). This works fine until you want to move up or down through pages and pages of text, such as when navigating to the top of a long stack trace. One way to get where you need to be more quickly is by paging up and down.

Hit CTRL-u to page up and CTRL-d to page down.

Jumping Between tmux Sessions

If you are using tmux to manage multiple projects by putting each project in a separate session, you may find yourself moving between sessions frequently. Detaching and reattaching can and will get tedious. There are better ways. tmux provides the <prefix>) and <prefix>( bindings as a way of jumping to the next and previous session, respectively. That should reduce some friction.

Link to Headers in Github READMEs

Anytime you add a header to a markdown file, Github attaches an href with its downcased, punctuation-stripped name. 'JavaScript' receives a link to #javascript, for instance.

Spaces become dashes, so 'Command Line' becomes #command-line.

Leverage this by adding a table of contents to your README with links to the headers further down the document:

### Table of Contents

- [Cucumber](#cucumber)

This will link to a header containing 'Cucumber'.

h/t Josh Branchaud

Live markdown preview in Atom

I use vim 99.99% of the time, but for writing a blog post or something in markdown, Github's Atom editor has an awesome live markdown preview feature that you can pull up next to your .md file in a split pane. Super useful, and you can turn on vim mode!

Default Screenshot Location On Mac

By default, Mac saves all screenshots to the desktop. If you'd like screenshots to be dumped somewhere else, you have to configure it manually from the command line. For instance, if you'd like your screenshots to be saved in the ~/screenshots directory, then enter the following commands:

$ mkdir ~/screenshots
$ defaults write location ~/screenshots
$ killall SystemUIServer


Elm type annotations has return type

Here is an add function that takes 2 and 4 and turns these into 24. :)

add : Int -> Int -> String
add x y = (toString x ++ toString y)
x = add 2 4

The first line is a type annotation that lists the first argument, second argument and return type in that order.

Alot of new information absorbed today

Today I learned to use Calabash a testing framework based off of Cucumber for Test Driven Development for iOS and Android. This helped me learn more of the Ruby language and also teach me more about what was going on underneath the framework. Specifically with the use of Rspec ,another tool that works in tandem with Cucumber, I also learned about the expectation commands to help me use the expect method. While learning these tools I was taught some commands that utilize RVM, some of the gem package methods. I am hoping to carry these skills with me on to other projects.

Sublime Text Highlights Heredocs

Sublime Text allows an awesome syntax highlighting trick. If you name a here document something generic, like HEREDOC, all the text within will be highlighted in one color, just like a Ruby string.

But if you name your here document RUBY, Sublime will override the normal highlighting and maintain Ruby-specific syntax highlighting within the here document. Same goes for SQL, JS, and probably more.

This is cool because it makes here documents that contain code a lot easier to write and debug.

Tailing with Less

Ready for some next-level log tailing?

Try opening your log file with the terminal pager Less and executing F. This is called 'scroll forward' and it works like tail -f from the command prompt, but you also get all the features (search, scroll, regex, etc.) of Less.

Tmux Zoom

Tmux 1.8 introduced a great feature, zoom. Zoom expands the current pane to temporarily fill whole screen. It's helpful when you want to focus or read long lines of code.

The long way to this function is resize-pane -Z -t target-pane in the Tmux bar.

By default it is also mapped to prefix + z.

A cool alternative is to map Up and Down to toggle the zoom. That's how it works in the Hashrocket Dotmatrix:

# tmux.conf
unbind Up; bind Up resize-pane -Z; unbind Down; bind Down resize-pane -Z

h/t Chris Erin

Homebrew Info, Doctor, and Search

I learned a couple of Homebrew commands today. The first is brew info, which tells you about your Homebrew installation. Pass it a package name, and Homebrew will tell you about that package.

The next is brew doctor. This will give you an overview of your Homebrew environment, including unexpected files and symlinks, and whether there is a newer version of Homebrew available than the one you have.

The third is brew search. Pass this a package name and Homebrew will tell you all the versions that are available.

$ brew search phantomjs
homebrew/versions/phantomjs17      homebrew/versions/phantomjs192
homebrew/versions/phantomjs182     homebrew/versions/phantomjs198

You can then brew install homebrew/versions/phantomjs182 to get the version you need.

Rename Tmux Windows

When you create a window in tmux, it will be named 'zsh', or 'bash', or whatever your shell is. I think it's important that each tmux tab have an appropriate name. A tab running server should be called 'server'; a tab running sidekiq should be called 'sidekiq'.

You can rename your windows a bunch of ways. For the window you are in:

$ tmux rename-window newname

For another window in your session:

$ tmux rename-window -t otherwindow newname

Using the tmux bar:

prefix + rename-window newname

And my favorite, the tmux bar with a keyboard shortcut:

prefix + , newname

Upgrade Rubygems

To upgrade rubygems:

gem install rubygems-update
gem update --system