Level Up Shortcuts And The Hyper Key - Part 1

Even though typing speed is the least of a developer's bottlenecks, there are two particular speed bumps that can disrupt your flow when you are blazing a trail of fire, thinking and typing your way through solving a problem:

  1. Tapping the breaks to shift your hand to use the mouse.  
  2. Pressing a whole lot of keys to do something that you know could be done with fewer keypresses.

I feels like everrrryyyythhhinnnggg sloowwwwws downnnn in those moments.

For that reason, lately I've looking for ways to better enable memorizing useful keyboard shortcuts.  For me, the best way to learn new keyboard shortcuts is to start using them.  To start using them, I need a way to quickly reference a list of the ones I'm interested in.

I ruled out paper/printed cheatsheets because I wanted something that travels with me, only requiring the footprint of my laptop.  I don't like mousing up to a menubar item or having to fall back to the mouse to open a [reference] file either: too much break in flow.  

Commandline keyboard shortcuts + Fish

I do like the idea of a key you can press that pops up a reference list of other keyboard shortcuts.   Various developer IDE's have keyboard shortcuts that do this and they often enable searching lists of available commands.   Cmd-shift-p in VS Code and cmd-shift-a in Jetbrains' IDE's are two examples.   They are typically dealing with a very large list of potential actions/bindings, which is a little different than my case.

There are a handful of shortcuts I'd like to get better at on the commandline.  Some of them are defaults that come with fish shell.  Others are custom behaviors or things I have added.   For my purposes, printing out a list of available bindings in the window seems sufficient.  So, I  set up Alt-K to print out a list of interesting hotkeys that I would like to get better at and internalize:

Alt-K for in-line commandline help, retaining cursor position

One of the cool things about this, is that you can also instruct the fish shell to repaint the existing commandline after sending something to stdout, retaining the original cursor position.  You can be in the in the midst of a carefully assembled commandline instruction, think "Hey what is that key that would help me quickly navigate the cursor over to spot X?" or "what is that key to recursively search a directory under my cursor for a filename to pop it in right here?", access the reference list of keys, find the key you need and use it, all without losing your spot!

I'm hoping this will encourage looking up the shortcuts I would like to get better at, since I won't have to break out of the window or the line I am currently modifying to reference the list.  Hopefully, the shortcuts become rote as I memorize them.

After realizing the power of having this type of thing at one's [literally] fingertips, you tend to want similar functionality in more places...

Spectacle + Karabiner + Quicklook

I have been trying to use Spectacle for OS X window management.  There are several keyboard shortcuts to learn to effectively use it.   These are global keyboard shortcuts that are active across all applications on OS X.   How can I get better at these with as little friction as possible?  

While there is a really interesting CheatSheet application for OS X which shows a combination of foreground application and OS level keyboard shortcuts, it doesn't show the 18 system-wide keyboard shortcuts enabled by something like Spectacle.

I really like the idea of an easy to remember global keyboard shortcut that can pop up a cheat sheet of those Spectacle system-wide shortcuts I'm trying to learn.

One low hanging option is capturing an image of the Spectacle shortcut list and then making a keyboard shortcut show that image.

Leveraging Quicklook via commandline:

$ qlmanage -p filename.png

. . . can be used to trigger the OS X preview of our cheatsheet image for Spectacle:

Spectacle cheatsheet image

I just needed a way to bind that to a keypress.

The range of options for binding keyboard shortcuts to shell commands is a spectrum of everything from elaborate tools like Alfred, to varied quick-launcher tools, to an open source project for keybinding, to writing quick actions in Automator and using some built in os x key binding features.  

None of these were quite what I was looking for.   I wanted something that I could easily codify into some scripts in my version controlled dotfiles repository.  During the search of options I spotted something really interesting though.

One option that rose to the top was Karabiner Elements.   It does some other exotic things I did not even know were possible.  

The series of steps to bind our quicklook command to a keyboard shortcut, using Karabiner is:

Step 1: Install Karabiner Elements via homebrew

$ brew cask install karabiner-elements

Step 2: Define a relevant key binding snippet in Karabiner json config :

{
    "description": "Ctrl-K for spectacle cheatsheet",
    "from": {
        "key_code": "k",
        "modifiers": {
            "mandatory": [
                "left_control"
            ]
        }
    },
    "to": [
        {
            "shell_command": "qlmanage -p ~/cheatsheets/spectacle.png 1>/dev/null 2>/dev/null"
        }
    ],
    "type": "basic"
}```

Step 3: Hit Ctrl-K to pop up the custom cheatsheet image!  

Wait a minute . . . Ctrl-K.   Some applications use that already for other things, right?

Perhaps the more exotic uses of Karabiner are handy now.

The Hyper Key

What if an application has already bound Ctrl-K for another purpose?  For example,  our console binds Ctrl-K to delete to end of the current line.  That would conflict with the global Ctrl-K shortcut for a Spectacle cheatsheet that we enabled above.

One of the interesting ideas people are using Karabiner Elements for is to create a 'Hyper Key'.  Imagine you can press caps-lock and the system thought you has just done a simultaneous press of Ctrl+Option+Cmd+Shift.  It is rare that any application would establish a keyboard shortcut to require pressing all those modifier keys, so that sequence plus any other key on the keyboard is not likely to have keybinding conflicts with anything.  It's a clean slate of keyboard shortcut slots to define your own custom keybindings without having to be concerned about conflicts!  

Dear Caps lock: I AM NOT GOING TO MISS YOU!

Let's define a Hyper Key in Karabiner config:

{
    "description": "Change caps_lock to command+control+option+shift.",
    "from": {
        "key_code": "caps_lock",
        "modifiers": {
            "optional": [
                "any"
            ]
        }
    },
    "to": [
        {
            "key_code": "left_shift",
            "modifiers": [
                "left_command",
                "left_control",
                "left_option"
            ]
        }
    ],
    "type": "basic"
}

⬆️ relevant snippet from a full Karabiner json config

Schweet!  Now caps lock is our Hyper Key and acts like a super duper modifier –  some sort of alien hand that can twist itself into pressing ctrl, option, cmd, and shift all at once.    

You can confirm that key remapping is working as expected by launching the Karabiner-EventViewer app that was installed with Karabiner or turning on something like Keycastr, and then pressing caps lock and viewing the result.

Now, let's adjust our Spectacle cheatsheet to use the Hyper Key:

{
    "description": "Hyper-K for spectacle cheatsheet (Hyper == capslock)",
    "from": {
        "key_code": "k",
        "modifiers": {
            "mandatory": [
                "left_gui",
                "left_control",
                "left_alt",
                "left_shift"
            ]
        }
    },
    "to": [
        {
            "shell_command": "qlmanage -p ~/cheatsheets/spectacle.png 1>/dev/null 2>/dev/null"
        }
    ],
    "type": "basic"
}

(left_gui is the command key on OS X)

Awesome.  Now we can press capslock and 'k' together to pop up our global cheatsheet for Spectacle, and not worry about key binding conflicts with other applications.  That seems like a good first cut at something to help have quicker access to learn those shortcuts.  Now I just have to remember Caps-K to access the key list reference.

Going Further  

There are a number of other things people are using Karabiner for.  Take a look here for examples.  One I immediately jumped at was the chance to try tapping left and right shift to jump words left and right.

This is the tip of iceberg with Karabiner and led me to discover another tool that is  brought up a lot in this context:  Hammerspoon.  It has a number of interesting uses which have some overlap with my cheatsheet and window management needs.   It's a little bit more scripting centric, being driven by Lua scripts.  Someone has even implemented Spectacle in Hammerspoon scripts.  waaaaaat.