15

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

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

(我确实意识到系统首选项中有输入源的映射快捷方式,但是我更喜欢使用 Alfred 映射关键字)

4

6 回答 6

18

您可以使用文本输入服务 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 */;

第一行中的字典可以将其他属性用于选择输入源的其他标准。

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

于 2014-05-19T05:22:37.233 回答
8

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

不幸的是,非 GUI 脚本 shell 脚本/AppleScripting 解决方案不是一个选项:虽然可以更新反映当前所选输入源(键盘布局)的文件 -系统将忽略更改。*.plist~/Library/Preferences/com.apple.HIToolbox.plist

但是,以下GUI 脚本解决方案(基于this)虽然仍然涉及可见动作,但在我的机器上是健壮且相当的(大约 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
于 2014-05-19T15:44:15.937 回答
3

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

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

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

安装完成后,步骤如下:

  1. 创建一个名为whatever.m的文件
  2. 在what.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;
}
  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;
}

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

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

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

于 2020-08-03T15:23:51.757 回答
2

另一种选择是使用 Swift。它可以以类似脚本的方式使用(无需编译)。

  • 安装 Xcode 命令行工具
  • 从下面的代码创建一个脚本
  • 使用运行脚本swift script_file_name

代码:

import Carbon

let command = ProcessInfo.processInfo.arguments.dropFirst().last ?? ""
let filter = command == "list" ? nil : [kTISPropertyInputSourceID: command]

guard let cfSources = TISCreateInputSourceList(filter as CFDictionary?, false),
      let sources = cfSources.takeRetainedValue() as? [TISInputSource] else {
    print("Use \"list\" as an argument to list all enabled input sources.")
    exit(-1)
}

if filter == nil { // Print all sources
    print("Change input source by passing one of these names as an argument:")
    sources.forEach {
        let cfID = TISGetInputSourceProperty($0, kTISPropertyInputSourceID)!
        print(Unmanaged<CFString>.fromOpaque(cfID).takeUnretainedValue() as String)
    }
} else if let firstSource = sources.first { // Select this source
    exit(TISSelectInputSource(firstSource))
}

这详细说明了Ken Thomasessbnc.eu的答案。

于 2021-01-23T12:32:45.620 回答
1

在 AppleScript 上,您只能使用 cmd + "space" (或其他东西,用于更改键盘源)。

和所有你需要的:

    key code 49 using command down

49 - AppleScript ASCII 中的“空格”按钮代码。

PS:不要忘记在系统偏好设置中访问 AppleScript 实用程序。

于 2017-01-28T21:57:31.510 回答
0
tell application "System Events"
    key code 49 using control down
end tell

通过按键更改布局

于 2018-12-20T13:14:49.037 回答