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
I only have 2 key sequences at the moment:
rcmd
thenlcmd
→ Picture-in-Picture Zoomlcmd
thenrcmd
→ Superkey 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.
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 tinyX
# 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
# 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 rcmd 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.
As a bonus, I was able to implement focusing and opening specific projects, documents or windows of an app using the same method.
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.
Configuring 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.
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)
# 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
- (e.g. keeping an always up-to-date database of hotkeys from
- 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 ^_^