自从上次键盘换了控制器之后,基本上替代原先需要 Karabiner Elements 才能实现的功能,但是笔记本自带的键盘仍然需要这些配置,以保持两边一致的体验。所以我希望能够依据 MacBook Pro 是否有外接键盘自动切换到指定的配置,而无需手动切换。

不过这个功能网上已有成熟的模版,只要依自己的需要更改即可,下面以我的配置为例,参看题图。代码的大意是当发现指定 USB 设备时(这里是 HHKB mod),如果为连接(added)状态则执行 if 部分代码,如果是断开(removed)状态,则执行 elseif 部分代码。

我们主要区别是在于 if 语句里面的键盘名称,我们可以使用 Hammerspoon 提供一个 API 查看:

-- 打开 Hammerspoon 中的 console,输入下面的代码,获取已连接的键盘信息
-- 将会返回一个表格,包含所有连接的 USB 设备信息
hs.inspect(hs.usb.attachedDevices())

-- 找到连接的键盘
{
    productID = 16962,         -- 设备 ID
    productName = "HHKB mod",  -- 设备名称
    vendorID = 65261,          -- 品牌 ID
    vendorName = "t.m.k."      -- 品牌名称
  }

为了便于阅读及区分,一般都使用设备名称,即 productName,这里便可以完成第一部份代码:

function usbDeviceCallback(data)
    -- 当设备名称为 HHKB mod 时执行
    if (data["productName"] == "HHKB mod") then
    end
end

除了前面提到键盘的四个信息外,还有另外一个参数可用:

  • eventType
    • added:添加 / 接入
    • removed:删除 / 拔出

我们便可根据 eventType 来完成剩下的代码:

function usbDeviceCallback(data)
    -- 当设备名称为 HHKB mod 时执行
    if (data["productName"] == "HHKB mod") then
        if (data["eventType"] == "added")  then    -- 当键盘接入时
            hs.execute(cliPath.." --select-profile HHKB") -- 切换到 HHKB 配置
        elseif data["eventType"] == "removed" then -- 当键盘断开时
            hs.execute(cliPath.." --select-profile AiKeyboard")
        end
    end
end

这里为了便于阅读,去掉了题图中的提示代码。另外在目前使用的配置中多增加了一个蓝牙判断的代码,当断开外接键盘时,如果已连接蓝牙键盘,则配置不变,具体代码见 dotfiles/switch_karabiner_elements.lua。遗憾的是 Hammerspoon 目前并没有能主动观测指定蓝牙设备连接或断开的 API,所以当你开蓝牙键盘时并不能主动切换代码。

最后

总结一下需要的信息:

  • HHKB mod:从 hs.inspect(hs.usb.attachedDevices()) 得到的 productName,即键盘名称;
  • HHKB 和 AiKeyboard:在 Karabiner Elements Preferences -> Profiles 中显示的两个配置名称;

信息

版本

  • Hammerspoon:0.9.73
  • Karabiner-Elements:12.1.0
  • macOS Mojave:10.14.2

参考