◀ Back to NotesPublished on April 21, 2023

Keyboard tricks from a macOS app dev

This is a collection of keyboard and trackpad workflows that I accumulated over the last 7 years of using a MacBook.

Here are some important abbreviations I am using in this article:

Term Meaning Explanation
lcmd ⌘ Left Command The Command key on the left side of the spacebar
rcmd ⌘ Right Command The Command key on the right side of the spacebar
lalt ⌥ Left Option The Option key on the left side of the spacebar
ralt ⌥ Right Option The Option key on the right side of the spacebar
hyper ^ ⌥ ⌘ A rarely used combination of modifiers

# Key Sequences

In 6 years of using BetterTouchTool I had no idea this feature existed.

It can map any sequence of keys (even modifiers) to any action.

Sequence: individual keys pressed one after the other, not key combos that you press at the same time

In the below video, I map rcmd then lcmd to the macOS zoom hotkey: 8

Activating macOS zoom by pressing rcmd then lcmd

I only have 2 key sequences at the moment:

  • rcmd then lcmdPicture-in-Picture Zoom
  • lcmd then rcmdSuperkey Seek

Superkey is the Pro version of Hyperkey, the app that maps CapsLock to the hyper key, made by Ryan Hanson (developer of the popular window management app Rectangle).

The below video is a demonstration of how I use it to quickly find and click on things that I know they're somewhere on the screen, but I would be too slow to notice-point-and-click with my eyes and trackpad.

I'm pressing lcmd then rcmd, typing fip then pressing Enter which clicks on the browser tab with fipple in its title.

Clicking on things by searching them with Seek

You can even hold modifiers while pressing Enter to do the same action that clicking with that modifier would do. In my browser's case I can:

  • ^ Enter to right click the tab and show the context menu (for muting or pinning the tab, etc)
  • Enter to close the tab without trying to click on the tiny X

# Double Tap

Raycast added the possibility of mapping a double tap modifier combo to summon it.

I personally mapped and I like it because it doesn't clash with any other keys while being unique enough to remember.

One thing I noticed though is that it is faster and easier to press lalt then ralt to register a double tap, instead of actually pressing one Option key twice. The reverse direction (right then left) works as well.

One could also use BTT's Key Sequences to map arbitrary double or even triple taps to any action.

For example here I mapped ^ ^ to BTT's GPT action and I use it to convert some ObjC code to Swift:

the C and V in the video are synthesised by BTT, I'm not copy-pasting anything

Double tapping ^ Control to summon GPT

# One-key app switching

When using more than 3 apps, it becomes annoying to Command Tab Tab Tab... all of the time.

I'd like to switch to exactly the app I need, with a single keypress. Previously I did this by manually assigning rcmd + letter to my most used apps, using Karabiner or BTT.

I finally wrote the imagercmd app to do the assigning automatically for me, while also adding nice features like show/hide app by pressing the same letter twice, or launch app if not already running etc.

Holding ⌘ Right Command while pressing letters to focus apps


As a bonus, I was able to implement focusing and opening specific projects, documents or windows of an app using the same method.

image

I have many projects in my code editor and frequently need to switch between them. And when opening up such a project, I also need to open a terminal tab and cd to the directory of that project.

For some of those I also need to open a specific Sketch or Pixelmator file which contains the graphics of the app or website. And of course, if it's a website, I also need to open the damn webpage in my browser to see how it looks while I develop it.

ლ(╹◡╹ლ)

That's too much work. And way too many things to remember.

And I don't always need all of them at once, I want to be able to open things selectively, so a script that does it all isn't a good choice for me

So I dedicated the ralt key for opening and switching between these projects.

Using ⌥ ralt + letters to focus windows and open projects

Configuring image rcmd to do the window focusing thingie is a bit convoluted because of the App Store sandbox limitations, but if you have many projects to switch between, it's worth it.

To give you the basics on how to do this:

  • Install Hammerspoon and the window switching script from rcmd's Switcher menu
  • Manually open the project you want to assign (e.g. open a folder in VSCode)
  • Press ralt = (or the key before backspace) to show the assignment menu
  • Press K and then press the letter you want to bind to that project
  • Tell rcmd how it can open that window (usually you'd choose Open a file)

if the ralt hotkeys don't do anything after first installing the script, you might need to restart rcmd and Hammerspoon

# Fn key

It always seemed weird to me how we have this Fn key which only interacts with the function row of keys, backspace and arrows and just takes up keyboard space for the rest of the time.

So of course, after running out of keys to bind, I looked for ways to use that key.

I know BTT and Karabiner can use it, but I prefer skhd for its simplicity. I decided to use it mostly for running scripts, and doing window management with yabai.

Starting with skhd is really simple:

  • brew install skhd
  • brew services start skhd
  • Give it the required permissions
  • Start adding your hotkeys inside ~/.skhdrc

Simply editing and saving the skhdrc file will hot reload the changes. Much faster than clicking around in the BTT UI.

Here are some interesting hotkeys I use with skhd:

# Edit skhd config
fn + k : code $HOME/.skhdrc

# Easy to use Sleep hotkey
fn - q : pmset sleepnow

# Turn on lights to warm colors
fn - w : shortcuts run "Warm Blend"

# Connect or disconnect Sidecar
fn - s : $HOME/.local/bin/lunar toggle-connection sidecar

# Search selected text on Google
fn - g : skhd -k 'cmd - c'; open "https://www.google.ro/search?q=$(pbpaste)"
# Upload selected file and copy URL to clipboard
fn - f : skhd -k 'cmd + alt - c'; \
       terminal-notifier -title "Uploading file" -message "$(pbpaste)" -ignoreDnD; \
       curl --upload-file "$(pbpaste)" "https://transfer.sh/$(basename $(pbpaste))" | pbcopy; \
       terminal-notifier -title "File uploaded" -message "$(pbpaste)" -ignoreDnD


# --- Things that need SIP disabled ---
()
# Decrease window opacity (more transparent) -- "0x1B" => "minus (-)"
fn - 0x1B : yabai -m window --opacity $(bc -e "$(yabai -m query --windows --window | jq -r '."opacity"') - 0.05")
# Increase window opacity (less transparent) -- "0x18" => "plus (=)",
fn - 0x18 : yabai -m window --opacity $(bc -e "$(yabai -m query --windows --window | jq -r '."opacity"') + 0.05")

# Toggle Picture-in-Picture for the current window
fn - p : yabai -m window --toggle pip

# Text expansions

Everyone has these snippets of text that they type often: email address, phone number, specific emojis, URLs etc.

I use Raycast's Snippets feature to quickly type these things by assigning mnemonics to them.

Typing mnemonics to expand Raycast Snippets

I also map typos I frequently do to their correct words. Examples:

  • oyu -> you
  • improt -> import
  • stirng -> string

Adding a snippet in Raycast is as simple as copying some text, then opening its clipboard manager and pressing S.

Here's how I have it configured in case you want to replicate my setup exactly:

# Trackpad gestures

I've been working on MacBooks exclusively for the last 6 years, and the Trackpad has always been right there at the center.

It's such a good input device, with multitouch, Force Touch and great OS support. It would be a shame to neglect it.

I'm using BTT to configure all kinds of gestures for it, the below video shows some of my most used ones:

(contains sound)

Controlling music and tabs with the Trackpad

# Remembering key bindings

How do you keep all this in mind??

I get that question often. And the truth is it's becoming harder and harder.

I cope by dedicating modifiers to sets of actions and by always looking at the places where these key bindings are configured when I need them.

Very often I forget where a hotkey was defined.

# FuzzyKey

About a year ago, I started writing FuzzyKey, a fuzzy search Spotlight-like UI for all types of hotkeys. There are multiple apps doing similar things, but I wanted to take things further.

The defining features would have been:

  • Parsers and ingesters for user defined hotkeys in most common apps
    • (e.g. keeping an always up-to-date database of hotkeys from skhdrc, keybindings.json etc.)
    • this could be extensible by users who want to write their own parsers
  • Really good fuzzy search that surfaces the keys most likely to be forgotten
  • Easily edit a key binding without having to remember where it's defined

After a few months, me and 2 friends wrote the parser architecture, the key bindings change watchers, a bit of UI, a bit of CLI, and the following parsers:

  • Shells: Bash, ZSH, Fish
  • Browsers: Chrome (for extension hotkeys)
  • Terminals: iTerm, Kitty
  • Code Editors: Sublime Text, VSCode, XCode, JetBrains
  • Menubar (basically what CheatSheet does)
  • skhd

But there was so much more work to do, and some parsers were already getting compatibility issues from app updates, that we paused working on it.

I gained a lot more experience in macOS app dev, so I'm hoping to revisit this idea soon.

I'm also secretly hoping to start crafting wood flutes and composing music so that I don't have a need for remembering any hotkeys anymore.

Here's my first Romanian Kaval ^_^