在终端/脚本中确定OS X键盘布局(“输入源”)?

19

我想从终端确定OS X键盘布局(或者按照OS X的说法叫做"输入源"),以便在像tmux状态栏这样的地方显示它。

所以我想知道当前布局是"U.S."还是"Swedish - Pro",例如。

谷歌搜索对我毫无帮助。这是否可能?


https://apple.stackexchange.com/a/402868/282215 - HappyFace
6个回答

23

注意:@MarkSetchell应该得到荣誉,因为他想出了基本方法-从哪里(开始)查找以及使用什么工具。

经过进一步调查和在评论中来回讨论后,我想总结一下解决方案(截至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/'"

请注意,为了方便AppleScript确保只有\到达shell,需要将\转义为\\。如果您想要直接从shell执行相同的命令(作为一行),可以使用以下命令:
defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources | egrep -w 'KeyboardLayout Name' |sed -E 's/^.+ = \"?([^\"]+)\"?;$/\1/'

  • 当前选择的键盘布局存储在用户级别文件~/Library/Preferences/com.apple.HIToolbox.plist中,顶级键AppleSelectedInputSources,子键KeyboardLayout Name中。
  • defaults read确保读取当前设置(不幸的是,在OSX 10.9中,否则优越的/usr/libexec/PlistBuddy仅看到一个缓存版本,可能不同步)。
  • 由于defaults read无法返回单个键的值,因此必须通过egrepsed提取感兴趣的值 - 其中一个警告是defaults read有条件地在键名和字符串值周围使用双引号,具体取决于它们是否为单个单词(没有标点符号)。

更新:

事实证明,AppleScript 本身可以解析属性列表,但这有点像拔牙。而且,令人难以置信的是,潜在的不完全当前值问题也会影响AppleScript的解析。

以下是一个AppleScript处理程序,用于获取当前键盘布局; 它使用基于do shell script的解决方法来确保plist文件是当前的,但否则通过应用程序System EventsProperty List Suite使用AppleScript的属性列表功能。

注意:显然,上述基于shell的方法在这种情况下要简短得多,但是下面的代码演示了处理属性列表的一般技术。

# 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

Shell 单行代码(需要安装 ripgrep):defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources | command rg -e '"KeyboardLayout Name" = "([^"]*)"' --replace '$1' --only-matching --color never - HappyFace
谢谢,@HappyFace,但是一个 shell 的一行命令已经包含在答案中了(在第一个代码片段下面),它使用标准工具(并非每个人都有 rg)。 - mklement0

12

最近我用Objective-C编写了一个小型控制台实用程序(https://github.com/myshov/xkbswitch-macosx)来完成这个任务。它比基于脚本的解决方案要快得多。它既能获取当前输入布局,也能设置指定的输入布局。

获取当前布局:

$xkbswitch -ge
> US

设置给定的布局:

$xkbswith -se Russian

当执行 xkbswitch -ge 命令时,即 US% 输出结尾处为什么会有 % 符号呢?环境为:Apple Chip M1Pro,OSX 12.0。 - Jerry

7

我不确定这个答案是否正确,但是检查一下可能是值得的。如果你在文件中查找:

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

有一个叫做的变量

AppleCurrentKeyboardLayoutSourceID

我的设置是“英国”,而我在英国...

您可以使用以下脚本读取文件:

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

以下是示例输出:
(
    {
    InputSourceKind = "Keyboard Layout";
    "KeyboardLayout ID" = 2;
    "KeyboardLayout Name" = British;
}
)

那么,我想你的问题可以简单地回答为:
#!/bin/bash
defaults read /Library/Preferences/com.apple.HIToolbox.plist  AppleEnabledInputSources | grep -sq Swedish
[[ $? -eq 0 ]] && echo Swedish

1
+1 给侦探。由于“默认读取”显然只能针对_顶级_键,因此这里提供了一种使用PlistBuddy的替代方法,该方法专门提取“KeyboardLayout Name”键的值:/usr/libexec/PlistBuddy -c 'print "AppleSelectedInputSources:0:KeyboardLayout Name"' /Library/Preferences/com.apple.HIToolbox.plist - mklement0
如果我的回答解决了您的问题,能否请您接受它,这样我就可以得到一个可爱的大绿勾,请问还有什么需要补充或帮助的吗?我及比我聪明的人都会继续协助您! - Mark Setchell
3
答案在于(a)针对用户级别的 plist 文件:~/Library/Preferences/com.apple.HIToolbox.plist,而不是最初的“~”,以及(b)针对 AppleSelectedInputSources 键(而不是 AppleEnabledInputSources)。将它们结合起来:defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources | egrep -w 'KeyboardLayout Name' | sed -E 's/.+ = "?([^"]+)"?;/\1/'。注意:之所以使用 defaults read 是因为它 - 与 PlistBuddy 不同 - 确保读取的是当前值。 - mklement0
继续上文,需要进行 sed 操作的原因是 defaults read 命令只有在值需要时(即当它不是没有标点符号的单词时)才会使用双引号。 - mklement0
马克,我将@mklement0的答案设置为被接受的答案,因为它最清晰地总结了事情,并且在顶部有一些可运行的内容,似乎对我来说是最新的。但是你提出了基本的想法 - 非常感谢! - Henrik N
显示剩余5条评论

5

2

假设您有菜单栏输入菜单,我已经想出了如何使用AppleScript完成它。

在终端中运行以下命令:

osascript -e 'tell application "System Events" to tell process "SystemUIServer" to get the value of the first menu bar item of menu bar 1 whose description is "text input"'

即使只显示输入菜单作为旗帜图标,而没有输入源名称,也能正常工作。

在 Mavericks 中,第一次可能会提示您允许访问。在早期的 OS X 版本中,我认为您需要在辅助功能偏好设置中打开辅助设备支持。


1
我遇到了一个错误 73:157: execution error: System Events got an error: osascript is not allowed assistive access. (-1719) - Alex
@Alex 我认为这是答案最后一段描述的原因。在较新版本的 macOS 中可能会更加复杂。也许你可以尝试谷歌一下错误信息?例如,这个链接就有相关内容:http://techqa.info/programming/question/21913504/Accessibility-settings-for-non-GUI-apps-using-AppleScript-in-OSX-Mavericks- 请告诉我们你找到了什么。 - Henrik N

0
我在寻找解决键盘布局问题的答案时,发现了这篇文章。我在这里找到了解决方案,解决了我的问题。

Resolved Issues You might experience difficulty logging into your account because the keyboard layout may change unexpectedly at the Login window. (40821875)

Workaround: Log in to your account, launch Terminal, and execute the following command:

sudo rm -rf /var/db/securityagent/Library/Preferences/com.apple.HIToolbox.plist

这是苹果官方发布的Mojave版本说明


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接