Determine OS X keyboard layout ("input source") in the terminal/a script?
applescript, macos
Solution
Note: @MarkSetchell deserves credit for coming up with the fundamental approach - where to [start to] look and what tools to use. After further investigation and back and forth in the comments I thought I'd summarize the solution (as of OS X 10.9.1):
do shell script "defaults read ~/Library/Preferences/com.apple.HIToolbox.plist \\
AppleSelectedInputSources | \\
egrep -w 'KeyboardLayout Name' | sed -E 's/^.+ = \"?([^\"]+)\"?;$/\\1/'"
Note how `\` is escaped as `\\` for the benefit of AppleScript, which ensures that just `\` reaches the shell. If you want to execute the same command directly from the shell (as one line), it would be: `defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources | egrep -w 'KeyboardLayout Name' |sed -E 's/^.+ = \"?([^\"]+)\"?;$/\1/'`
- The currently selected keyboard layout is stored in the user-level file `~/Library/Preferences/com.apple.HIToolbox.plist`, top-level key `AppleSelectedInputSources`, subkey `KeyboardLayout Name`.
- `defaults read` ensures that the current settings are read (sadly, as of OSX 10.9, the otherwise superior `/usr/libexec/PlistBuddy` sees only a cached version, which may be out of sync).
- Since `defaults read` cannot return an individual key's value, the value of interest must be extracted via `egrep` and `sed` - one caveat there is that `defaults read` conditionally uses double quotes around key names and string values, depending on whether they are a single word (without punctuation) or not.
Update:
Turns out that AppleScript itself can parse property lists, but it's a bit like pulling teeth. Also, incredibly, the potentially-not-fully-current-values problem also affects AppleScript's parsing.
Below is an AppleScript handler that gets the current keyboard layout; it uses a `do shell script`-based workaround to ensure that the plist file is current, but otherwise uses AppleScript's property-list features, via the `Property List Suite` of application `System Events`.
Note: Obviously, the above shell-based approach is much shorter in this case, but the code below demonstrates general techniques for working with property lists.
# Example call.
set activeKbdLayout to my getActiveKeyboardLayout() # ->, e.g., "U.S."
on getActiveKeyboardLayout()
# Surprisingly, using POSIX-style paths (even with '~') works with
# the `property list file` type.
set plistPath to "~/Library/Preferences/com.apple.HIToolbox.plist"
# !! First, ensure that the plist cache is flushed and that the
# !! *.plist file contains the current value; simply executing
# !! `default read` against the file - even with a dummy
# !! key - does that.
try
do shell script "defaults read " & plistPath & " dummy"
end try
tell application "System Events"
repeat with pli in property list items of ¬
property list item "AppleSelectedInputSources" of ¬
property list file plistPath
# Look for (first) entry with key "KeyboardLayout Name" and return
# its value.
# Note: Not all entries may have a 'KeyboardLayout Name' key,
# so we must ignore errors.
try
return value of property list item "KeyboardLayout Name" of pli
end try
end repeat
end tell
end getActiveKeyboardLayout
Problem
I would like to determine the OS X keyboard layout (or "input source" as OS X calls it) from the terminal so that I can show it in places like the tmux status bar. So I want to know if the current layout is "U.S." or "Swedish - Pro" for example. Googling turns up nothing for me. Is this possible?