Quick Tip: Checking for modifier keys in shell scripts

Yesterday I found a handy little command line utility for checking whether a modifier key is held down. It’s great for scripting of all kinds. The solution came from this post on the Apple Mailing List:

keys.mraw
#import <Carbon/Carbon.h>
// `keys` utility for checking whether a modifier key is held
// From <http://lists.apple.com/archives/applescript-users/2009/Sep/msg00374.html>
//
// $ clang keys.m -framework Carbon -o keys

int main (int argc, const char * argv[]) {
    unsigned int modifiers = GetCurrentKeyModifiers();

    if (argc == 1)
        printf("%d\n", modifiers);

    else {

        int i, result = 1;
        for (i = 1; i < argc; ++i) {

            if (0 == strcmp(argv[i], "shift"))
                result = result && (modifiers & shiftKey);

            else if (0 == strcmp(argv[i], "option"))
                result = result && (modifiers & optionKey);

            else if (0 == strcmp(argv[i], "cmd"))
                result = result && (modifiers & cmdKey);

            else if (0 == strcmp(argv[i], "control"))
                result = result && (modifiers & controlKey);

            else if (0 == strcmp(argv[i], "capslock"))
                result = result && (modifiers & alphaLock);

        }
        printf("%d\n", result);
    }
    return 0;
}

The code compiles into a little utility called keys. Here’s a version compiled on Mountain Lion that you can download if you don’t have the developer tools installed: keys.zip. If you do have clang or gcc and the Carbon framework available, run this to compile:

clang keys.m -framework Carbon -o keys

Move the resulting keys file into /usr/local/bin/ and make sure that’s in your path. Now, from a shell script (or with AppleScript’s do shell script command), you can run something like keys option to see if the Option key is held down at the time. If you put a sleep 2 before it in a shell script, you can press a modifier key at runtime and change the behavior accordingly.

As an example, here’s the AppleScript for launching your Dock apps from the other day, with the ability to exclude certain apps if the Option key is held down:

Launch All in Dock.applescriptraw
-- Launch All in Dock.applescript
-- Brett Terpstra 2012
--
-- Modified version of an AppleScript to launch all 
-- persistent (Keep in Dock) apps[^1]. Allows you to exclude
-- apps based on modifier keys held when it runs.
-- 
-- Uses the `keys` utility found on the Apple Mailing Lists[^2].


set optDoNotOpen to {"com.adiumx.adiumx", "com.skype.skype"}
set shiftDoNotOpen to {"com.apple.mail"}

delay 2
set optKeyDown to (do shell script "/usr/local/bin/keys option")
set shiftKeyDown to (do shell script "/usr/local/bin/keys shift")
set _exclude to ""
if optKeyDown = "1" then
	repeat with _app in optDoNotOpen
		set _exclude to _exclude & "|grep -v " & _app
	end repeat
end if
if shiftKeyDown = "1" then
	repeat with _app in shiftDoNotOpen
		set _exclude to _exclude & "|grep -v " & _app
	end repeat
end if

return do shell script "for app in $(defaults read com.apple.dock persistent-apps|grep bundle-identifier" & _exclude & "| awk '{print $3}'| tr -d '\";'); do open -g -b $app; done"

-- [^1]: <http://brettterpstra.com/launching-your-entire-dock-at-once/>
--
-- [^2]: <http://lists.apple.com/archives/applescript-users/2009/Sep/msg00374.html>

Very handy.

Brett Terpstra

Brett is a writer and developer living in Minnesota, USA. You can follow him as ttscoff on Twitter, GitHub, and Mastodon. Keep up with this blog by subscribing in your favorite news reader.

This content is supported by readers like you.