Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine OS X keyboard layout ("input source") in the terminal/a script?

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?

like image 975
Henrik N Avatar asked Feb 06 '14 08:02

Henrik N


3 Answers

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
like image 67
mklement0 Avatar answered Oct 26 '22 22:10

mklement0


Recently I had written a small console utility (https://github.com/myshov/xkbswitch-macosx) on Objective-C to do this. It's a lot faster than a script based solutions. It can to get the current input layout but also it can to set the given input layout.

To get a current layout:

$xkbswitch -ge
> US

To set a given layout:

$xkbswith -se Russian
like image 41
Alexander Myshov Avatar answered Oct 26 '22 22:10

Alexander Myshov


I am not sure of this answer, but it may be worth checking out. If you look in file:

/Library/Preferences/com.apple.HIToolbox.plist

there is a variable called

AppleCurrentKeyboardLayoutSourceID

and mine is set to "British" and I am in Britain...

You can read the file in a script with:

defaults read /Library/Preferences/com.apple.HIToolbox.plist  AppleEnabledInputSources

sample output below:

(
    {
    InputSourceKind = "Keyboard Layout";
    "KeyboardLayout ID" = 2;
    "KeyboardLayout Name" = British;
}
)

So, I guess your question can be simply answered using this:

#!/bin/bash
defaults read /Library/Preferences/com.apple.HIToolbox.plist  AppleEnabledInputSources | grep -sq Swedish
[[ $? -eq 0 ]] && echo Swedish
like image 26
Mark Setchell Avatar answered Oct 26 '22 22:10

Mark Setchell