V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
jerommix
V2EX  ›  程序员

解决了我在 MacOS 下输入法和 Vim Mode 的烦恼

  •  
  •   jerommix · 175 天前 · 1295 次点击
    这是一个创建于 175 天前的主题,其中的信息可能已经有所发展或是发生改变。

    MacOS 下切换输入法一直很恼人,特别是在 vim mode 下。

    利用 Harmmerspoon 今天终于达到自己满意的效果了,实现逻辑 AppGroup1 默认开启英文输入法,AppGroup2 在 ESC 或 Ctrl [ 后切换为英文输入。参考实现如下:

    
    local function switchToABC()
        hs.keycodes.currentSourceID("com.apple.keylayout.ABC")
    end
    
    local targetAppsGroup1 = {
        "com.runningwithcrayons.Alfred",
        "com.apple.finder",
        "org.hammerspoon.Hammerspoon",
        "com.apple.Safari",
        "com.mitchellh.ghostty",
        "com.todesktop.230313mzl4w4u92", -- Cursor
        "com.microsoft.VSCode",
        "com.apple.dt.Xcode",
        "com.apple.Terminal",
        "org.vim.MacVim",
    }
    
    local targetAppsGroup2 = { -- 在这些应用中按下 Esc 或 Ctrl+[ 时切换为 ABC
        "com.apple.Terminal",
        "com.apple.dt.Xcode",
        "com.jetbrains.intellij",
        "com.microsoft.VSCode",
        "com.mitchellh.ghostty",
        "com.todesktop.230313mzl4w4u92", -- Cursor
        "org.vim.MacVim",
    }
    
    -- 监听应用切换事件
    local function handleAppSwitch(appName, eventType, app)
        if eventType == hs.application.watcher.activated then
            local bundleID = app:bundleID()
            -- 检查是否在 Group 1 中
            for _, appID in ipairs(targetAppsGroup1) do
                if bundleID == appID then
                    switchToABC()
                    break
                end
            end
        end
    end
    
    -- 创建应用切换监听器
    local appWatcher = hs.application.watcher.new(handleAppSwitch)
    appWatcher:start()
    
    -- 监听键盘事件( Esc 和 Ctrl+[)
    local eventTap = hs.eventtap.new({hs.eventtap.event.types.keyDown}, function(event)
        local keyCode = event:getKeyCode()
        local modifiers = event:getFlags()
        local isEsc = (keyCode == hs.keycodes.map.escape) -- Esc 键
        local isCtrlOpenBracket = (keyCode == hs.keycodes.map["["] and modifiers.ctrl) -- Ctrl+[
    
        if isEsc or isCtrlOpenBracket then
            local frontmostApp = hs.application.frontmostApplication()
            local bundleID = frontmostApp:bundleID()
            -- 检查是否在 Group 2 中
            for _, appID in ipairs(targetAppsGroup2) do
                if bundleID == appID then
                    switchToABC() -- 切换输入法
                    break
                end
            end
        end
    
        return false -- 允许事件继续传递
    end)
    
    eventTap:start() -- 启动监听
    
    
    6 条回复    2025-04-27 16:59:39 +08:00
    shinonome
        1
    shinonome  
       175 天前
    挺好的, 不过小狼毫有 vim_mode 也能满足
    jerommix
        2
    jerommix  
    OP
       175 天前
    @shinonome 鼠须管用户折腾了一圈发现不太完美 😄
    jqtmviyu
        3
    jqtmviyu  
       174 天前
    我在用 rime, 但 macos 版缺少查询当前中英文状态的 api
    jerommix
        4
    jerommix  
    OP
       174 天前
    @jqtmviyu 是的,所以粗暴一些,切换应用或按下 esc 时 fallback 回英文状态。
    jqtmviyu
        5
    jqtmviyu  
       174 天前
    @jerommix #4 哈哈, 刚看了眼 Karabiner 配置, 其实有相同困扰的 v2exer 不少, https://www.v2ex.com/t/565667

    这个 19 年的帖子也是解决同样的问题. shift 轮换输入法, esc 切换英文.
    dbing
        6
    dbing  
       127 天前
    我的解决方案是中文只用鼠须管,英文用系统自带的 ABC ,使用是 karabiner 将 caps lock 映射成超级按键,单独按下切换式鼠须管或者 ABC ,这个按键配合其他键 用于实现其他功能
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3790 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 485ms · UTC 00:47 · PVG 08:47 · LAX 17:47 · JFK 20:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.