How to break up with your mouse: Part 2, App Switcher

How to Break Up with Your MouseDeveloper ProductivitymacOS

I hate using my mouse when I'm writing code! It slows me down, and throws me off of my groove. I love being able to keep my hands on the keyboard, and the home row, as much as possible. It helps me to be faster and more efficient, and keep my mind flowing while I'm working. If you're using macOS, I've got some tips to share to help you get away from your mouse and speed up your workflow on your keyboard, quickly and easily. If you haven't read How to Break Up With Your Mouse, Part 1, I suggest you do so.

In this installment of How to Break Up With Your Mouse, I'll show you:

What is Hammerspoon?

Hammerspoon is a utility for macOS that lets you write scripts that interface and integrate with the OS. It's useful for things like window management, automation, keyboard mapping, and more. It's geared toward developers who understand scripting languages, and the scripst are written in Lua. Check out their website to learn more.

My Ultimate App Switcher

For the past few years, I've been using Hammerspoon to help me switch apps in the quickest way possible. Many people just click on the app in the dock to switch between apps. Others will use Mission Control or Expose to find the app they are looking for. People who prefer keyboard shortcuts are probably already familiar with using command+tab to switch between apps.

These are all fine, but they all have one thing in common: You have to look for the app you want by its icon, then once you find it, you can switch to it. If I'm pressing command+tab, I might have to press it several times in order to get to the app I'm looking for.

I wanted something that could take me directy to the app I'm looking for with one keyboard shortcut, so I made it. All of my most-used apps are assigned a letter, and by pressing a keyboard shortcut with that letter, I can switch to the app. If it's not open yet, it will be open. If I press it more than once, I'll switch between windows within that app.

In my case, I've used the hyper key as my modifier. (To learn about the hyper key, please check out Part 1.) So, for example, hyper+C switches to Chrome, hyper+I switches to iTerm, and hyper+V switches to VS Code. You can use any modifier, not just the hyper key, but simpler combinations such as command+control are more likely to conflict with existing keyboard shortcuts. If you want to use this app switcher, I strongly suggest setting up a hyper key using the instructions in Part 1.

Installing Hammerspoon

Installing Hammerspoon itself works like installing any other non-App Store app. It's pretty straightforward. You can grab it from https://www.hammerspoon.org/. After you download it, unzip it, move it to your Applications folder, and open it. You may have to give macOS permission to run it the very first time.

Once it's installed and running, you'll see its hammer+spoon icon in your menu bar. From there you can open the preferences and make sure it's set to run at startup, and give it the necessary Accessibility permissions to run.

At this point, Hammerspoon isn't going to do anything yet. When Hammerspoon starts up, it will look for a Lua file at ~/.hammerspoon/init.lua. If it finds it, it will run that file, so in that file you should write (...or paste in) the code that sets up whatever special functionality you need.

You're working with a full-featured programming language here that provides a ton of access to system functionality, so the sky is the limit if you are willing to learn some Lua and study the Hammerspoon docs. But even if you're not a programmer, you can use it for an app switcher, simply by using and modifying the script below. First, let's see the whole thing:

-- if you want to use a different keyboard combo, define it here.
local hyper = {"cmd", "alt", "ctrl", "shift"}

-- define your own shortcut list here
local windows = {
	A = "Amazon Music",
	C = "Google Chrome",
	E = "Emacs",
	F = "Finder",
	I = "Iterm",
	M = "Messages",
	N = "Notion",
	S = "Slack",
	-- V = "Visual Studio Code",
	V = "Code",
	['\\'] = "Hammerspoon", -- opens the Hammerspoon console. useful
}

-- if the app has to be launched by a different name
-- than the one the windows are found by, this list
-- will take precedence when opening the app.
local windowLaunchNames = {
	-- currently just VS Code
	V = "Visual Studio Code",
}

local lastKey = ''
local lastKeyTime = 0
local lastWindowIndex = 1
local appWindows = nil
local doubleKeyThreshold = .8

-- set up the binding for each key combo
for key, appName in pairs(windows) do
	hs.hotkey.bind(hyper, key, function()
		local keyTime = hs.timer.secondsSinceEpoch()
		-- for a repeated key press, cycle through windows
		if key == lastKey and keyTime - lastKeyTime < doubleKeyThreshold then
			if appWindows == nil then
				-- find the switchable windows
				local app = hs.application.find(appName)
				if app then
					appWindows = hs.fnutils.filter(app:allWindows(), function(w)
						return w:isStandard()
					end)
				end
			end

			if appWindows and #appWindows > 0 then
				-- increment and loop
				lastWindowIndex = lastWindowIndex % #appWindows + 1

				--cycle apps
				appWindows[lastWindowIndex]:focus()
			end
		else
			-- switch to window
			appWindows = nil
			lastWindowIndex = 1

			local app = hs.application.get(appName)
			if app then
				app:activate(true)
			else
				local launchName = windowLaunchNames[key] or appName
				hs.application.launchOrFocus(launchName)
			end
		end

		lastKey = key
		lastKeyTime = keyTime
	end)
end

It defines a key combo to be used with each keyboard shortcut, then a map of keys to programs they should switch to. After those are defined, the rest of binds the keyboard shortcuts to handlers that do that app switching. This version includes my shortcut list. To customize it, just remove the lines with apps you don't use, and add in the ones you want to have shortcuts to. The name should match the name that shoul If you're using Hyper+HJKL with arrow keys as suggested in Part 1, you'll need to avoid using those letters for app shortcuts. Sorry, Limewire.

This app switcher works beautifully. I typically switch back and forth constantly between three or four apps, and it sames me seconds each time, because not only am I able to switch faster, but I'm able to keep my focus better, and not lose my train of thought as I'm looking for the next app I need.

*Some apps can't be switched by the same name that they are launched by. Currently, VS Code is the only app I have this issue with. Generally, the name shown under the app's icon when switching with command+tab should work in the windows table. VS Code doesn't, however. It needs to be called 'Code' in order for hammerspoon to find it. But 'Code' doesn't work when launching it, thus the need for the windowLaunchNames table.

Sometimes developers spend more time automating a task than they would have spent doing the task manually for as long as they will have to do it. I believe this one has already more than paid off, and I continue to make use of it every day. But now that I'm sharing it with the world, I'm excited for it to save even more time for even more people.

Stay tuned – In Part 3, I'll give some tips for avoiding the mouse in specific apps like Chrome, Firefox, and VS Code, plus a utility to help you use the keyboard for clicking around almost any application.