I've needed a way to control bash-scripts with other than parameters passed to the script. Modifier keys seemed like an answer, and I've finally discovered how to utilize these keys on a Mac: cmd, shift, capslock, option, control. The solution came from a StefanK posting dated 2009-06-07 at MacScripter Topic. I've modified that code to return an integer that is a binary ORing of codes for all five keys, individualy or in combination. If none of them are being held, 0 is returned. The maximum value is 31 (1+2+4+8+16). Below is a copy of the 'clang' program that does the work. If you don't have 'clang', try 'gcc' instead. Following that program is a sample bash-script the shows how the program can be used. I'll discuss that more at the end.
keysdown.c
#import <Carbon/Carbon.h>
// keysdown` utility for checking whether a modifier key is held
// From <http://lists.apple.com/archives/applescript-users/2009/Sep/msg00374.html>
// Detectable keys: cmd, shift, capslock, option, control
// $ clang keysdown.c -framework Carbon -o keysdown
int main (int argc, const char * argv[]) {
int modifiers = GetCurrentKeyModifiers();
int i, result;
printf("%x modifiers\n", (modifiers >> 8));
for (i = 1; i < argc; ++i)
{ result = 0;
printf("%s\n", argv[i]);
if (0 == strcmp(argv[i], "cmd"))
result = 1 && (modifiers & cmdKey);
else if (0 == strcmp(argv[i], "shift"))
result = 1 && (modifiers & shiftKey);
else if (0 == strcmp(argv[i], "capslock"))
result = 1 && (modifiers & alphaLock);
else if (0 == strcmp(argv[i], "option"))
result = 1 && (modifiers & optionKey);
else if (0 == strcmp(argv[i], "control"))
result = 1 && (modifiers & controlKey);
printf("%d\n", result);
}
return (modifiers >> 8);
}
keystest bash-script
#!/bin/bash
sleep 3
keysdown >/dev/null
result="$?"
if [[ "$result" -gt 0 ]]; then
result=$(( $result & 31 ))
declare -a keys
keys=("" "command" "shift" "caps" "option" "control")
let i=1
while [ $result -gt 0 ]; do
flag=$(($result & 1))
result=$(($result >> 1 ))
if [ "$flag" -ne 0 ]; then
say "${keys[$i]}"
fi
let i+=1
done
else say "no keys down"
fi
exit 0
In Terminal, you copy both 'keysdown.c and 'keystest', and compile the 'clang' program using 'clang keysdown.c -framework Carbon -o keysdown'. The result is 'keysdown'. You make 'keystest' executable with 'chmod 755 keystest'. You're now ready to test. Try this first: ./keystest which should give a 0 result. Then do it again, but immediately hold down a modifier key, like either 'shift' key. There's a 3 second delay in keystest to give you time to press-and-hold the modifier. You can try again holding multiple modifiers with different fingers of your left or right hand. If you try 'caps lock', be sure to release it when done.
On my systems (from Snow Leopard through Sierra), I've placed 'keysdown' in my $HOME directory, and my $PATH is always extended in my .bash_profile or .bashrc file like this: export PATH='$PATH:.:$HOME' That's colon-dot-colon in between the $variables. This tells Terminal to look in my 'current directory' and then my $HOME directory for executables not found in earlier portions of $PATH.
If you want to have any modifier key make a difference in a bash-script, execute 'keysdown >/dev/null' and test "$?" for 0 or non-zero. It will be non-zero if any (or all) Modifier-keys are being held down; and 0 if none are held. Of course you can differentiate on "$?" with simple AND'ing logic, or range-testing.