Okay, I've developed a solution that I believe will be beneficial for Apple Silicon Macs running Sonoma and likely compatible with other macOS versions as well. My approach uses a bash script to manage the Caps Lock LED based on the keyboard layout, activating it for layouts other than "U.S." and deactivating it for the "U.S." layout. This script is both CPU and battery efficient.
It leverages a Mac version of the setleds binary, akin to the one found on Linux, available here: https://github.com/damieng/setledsmac.
Below is the bash script, complete with --install, --uninstall, and --help options for convenience.
#!/bin/bash
# This is the path where setleds resides on my machine
export PATH=$PATH:$HOME/Tools/Shell
# Define the plist path
plist_path="$HOME/Library/LaunchAgents/com.example.keyboardlayoutmonitor.plist"
plist_label="com.example.keyboardlayoutmonitor"
# Obtain the full path of the current script
script_path=$(realpath "$BASH_SOURCE")
function install_service {
# Create a LaunchAgents directory if it doesn't exist
mkdir -p "$HOME/Library/LaunchAgents"
# Create the plist file
cat << EOF > "$plist_path"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>$plist_label</string>
<key>ProgramArguments</key>
<array>
<string>$script_path</string>
<string>--main</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
EOF
# Load the plist to start the service
launchctl load "$plist_path"
echo "Service installed and started."
}
function uninstall_service {
# Unload the plist to stop the service
launchctl unload "$plist_path"
# Remove the plist file
rm -f "$plist_path"
echo "Service uninstalled."
}
function show_help {
echo "Usage: $(basename "$0") [OPTION]"
echo "--install Install the service to start automatically at user login."
echo "--uninstall Uninstall and stop the service, removing it from automatic startup."
echo "--help Display this help and exit."
echo "--main Run the main script functionality. Intended for internal use when the service starts."
echo ""
echo "The --install option sets up the service to be automatically executed at user login through launchd, ensuring the script runs in the background and monitors keyboard layout changes."
}
function main_execution {
# Specify the log file location in StudlyCase
log_file="$HOME/Library/Logs/KeyboardLayoutMonitor.log"
# Redirecting standard output and standard error to the log file
exec >> "$log_file" 2>&1
# Existing main_execution function continues here...
# Initialize previous layout variable
previous_layout=""
while true; do
current_layout=$(defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources | grep -o '"KeyboardLayout Name" = "[^"]*"' | awk -F'"' '{print $(NF-1)}' | head -n 1)
# Only update LED if layout has changed
if [ "$current_layout" != "$previous_layout" ]; then
if [ "$current_layout" == "U.S." ]; then
setleds -caps > /dev/null
else
setleds +caps > /dev/null
fi
# Update previous layout to current layout
previous_layout="$current_layout"
fi
sleep 0.25
done
}
# Main script logic for parameters handling
case "$1" in
--install)
install_service
;;
--uninstall)
uninstall_service
;;
--help)
show_help
;;
--main)
main_execution
;;
*)
echo "Error: Invalid argument."
show_help
;;
esac