通过终端或AppleScript以编程方式更改OSX键盘布局("输入源")?

max*_*gry 11 macos applescript alfred

我目前正在通过Alfred运行GUI AppleScript来切换输入源,并且GUI脚本有时可能需要1秒才能完成更改.它有时很烦人.

在终端/脚本中遇到了Determine OS X键盘布局("输入源").我想知道,因为如果有办法以编程方式更改输入源,我们可以找到当前的输入源吗?我试过覆盖com.apple.HIToolbox.plist但它没有改变输入.

(我确实知道系统偏好中有输入源的映射快捷方式,但我更喜欢用Alfred映射关键字)

Ken*_*ses 17

您可以使用文本输入服务API执行此操作:

NSArray* sources = CFBridgingRelease(TISCreateInputSourceList((__bridge CFDictionaryRef)@{ (__bridge NSString*)kTISPropertyInputSourceID : @"com.apple.keylayout.French" }, FALSE));
TISInputSourceRef source = (__bridge TISInputSourceRef)sources[0];
OSStatus status = TISSelectInputSource(source);
if (status != noErr)
    /* handle error */;
Run Code Online (Sandbox Code Playgroud)

第一行中的字典可以使用其他属性作为选择输入源的其他条件.

还有NSTextInputContext.它有一个selectedKeyboardInputSource可以设置为输入源ID以选择不同的输入源.问题在于,您需要一个可以使用的实例,NSTextInputContext并且只有当您有一个以文本视图作为其第一响应者的关键窗口时才存在其中一个实例.

  • 从 Xcode 6 开始构建它的步骤:`New Project` > `Command Line Tool` > 输入详细信息,在 `Language` 下选择 `Objective-C`。在`main.m`的顶部,添加`@import carbon;`。将代码粘贴到 `main()` 函数内的适当位置。 (2认同)

mkl*_*nt0 7

@Ken Thomases的解决方案可能是最强大的 - 但它需要创建一个命令行实用程序.

非GUI的脚本外壳脚本/ AppleScripting溶液是不幸的是一个选项:虽然它可以更新*.plist反映当前选择的输入源(键盘布局)文件- ~/Library/Preferences/com.apple.HIToolbox.plist-系统将忽略的变化.

但是,以下GUI脚本解决方案(基于)虽然仍然涉及可见操作,但在我的机器上运行稳定且速度相当(大约0.2秒):

(如果您只想循环安装布局,使用"系统偏好设置"中定义的键盘快捷键可能是您最好的选择; 解决方案的优势在于您可以定位特定的布局.)

请注意注释中提到的先决条件.

# Example call
my switchToInputSource("Spanish")

# Switches to the specified input source (keyboard layout) using GUI scripting.
# Prerequisites:
#   - The application running this script must be granted assisistive access.
#   - Showing the Input menu in the menu bar must be turned on 
# (System Preferences > Keyboard > Input Sources > Show Input menu in menu bar).
# Parameters:
#    name ... input source name, as displayed when you open the Input menu from
#             the menu bar; e.g.: "U.S."
# Example:
#   my switchToInputSource("Spanish")
on switchToInputSource(name)
    tell application "System Events" to tell process "SystemUIServer"
        tell (menu bar item 1 of menu bar 1 whose description is "text input")
            # !! Sadly, we must *visibly* select (open) the text-input menu-bar extra in order to
            # !! populate its menu with the available input sources.
            select
            tell menu 1
                # !! Curiously, using just `name` instead of `(get name)` didn't work: 'Access not allowed'.
                click (first menu item whose title = (get name))
            end tell
        end tell
    end tell
end switchToInputSource
Run Code Online (Sandbox Code Playgroud)


Gra*_*ain 5

使用 Xcode 命令行工具的解决方案

对于那些想要构建@Ken Thomases 的解决方案但不安装 Xcode 的人(它有几个 GiB,除非认真使用,否则花费这么多空间是完全没有用的),可以使用 Xcode 命令行工具来构建它。

互联网上有一些关于如何安装 Xcode 命令行工具的教程。这里的要点只是,与成熟的 Xcode 相比,它只占用一小部分空间。

安装完成后,请执行以下步骤:

  1. 创建一个名为whatever.m的文件
  2. 在whatever.m中输入以下内容:
#include <Carbon/Carbon.h>

int main (int argc, const char * argv[]) {
    NSArray* sources = CFBridgingRelease(TISCreateInputSourceList((__bridge CFDictionaryRef)@{ (__bridge NSString*)kTISPropertyInputSourceID : @"com.apple.keylayout.French" }, FALSE));
    TISInputSourceRef source = (__bridge TISInputSourceRef)sources[0];
    OSStatus status = TISSelectInputSource(source);
    if (status != noErr)
        return -1;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)
  1. 替换French为您想要的布局。
  2. 保存文件
  3. 在与whatever.m相同的文件夹中打开终端
  4. 运行这个命令: clang -framework Carbon whatever.m -o whatever

您的应用程序是whatever在同一文件夹中创建的,并且可以执行为: .\whatever

此外

我从未创建过任何 Objective-C 程序,因此这可能不是最理想的,但我想要一个可以将键盘布局作为命令行参数的可执行文件。对于任何感兴趣的人,这是我想出的解决方案:

在步骤 2 中使用以下代码:

#import <Foundation/Foundation.h>
#include <Carbon/Carbon.h>

int main (int argc, const char * argv[]) {
    NSArray *arguments = [[NSProcessInfo processInfo] arguments];

    NSArray* sources = CFBridgingRelease(TISCreateInputSourceList((__bridge CFDictionaryRef)@{ (__bridge NSString*)kTISPropertyInputSourceID : [@"com.apple.keylayout." stringByAppendingString:arguments[1]] }, FALSE));
    TISInputSourceRef source = (__bridge TISInputSourceRef)sources[0];
    OSStatus status = TISSelectInputSource(source);
    if (status != noErr)
        return -1;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在步骤 6 中,运行以下命令: clang -framework Carbon -framework Foundation whatever.m -o whatever

您现在可以从命令行切换到任何布局,例如: ./whatever British

注意:它只允许切换到系统上已配置的布局!