lei4519 / blog

记录、分享
3 stars 1 forks source link

完善 Rime Vim Mode:支持 Linux & 自动切换回中文模式 #85

Open lei4519 opened 3 months ago

lei4519 commented 3 months ago

TL;DR

借助 lua_processor,自行实现 vim_mode 的中英文切换逻辑,使其支持:

这并不是一个完美的解决方案,可能达不到 100% 的使用效果,但是在普通的情况下已经足以使用

使用方法

可以参考此 feat: vim_model

引入 vim_mode.lua 文件

首先将 vim_mode.lua 文件放入自己的 lua 文件夹中,并在 rime.lua 中进行导出

vim_mode = require("vim_mode")  

加入 lua_processor

在自己的中文输入方案中,加入 lua_processor

比如我使用的是小鹤双拼,所以我修改 double_pinyin_flypy.custom.yaml,加入如下逻辑

patch:  
  # 加入 lua_processor  
  engine/processors/@before 0: lua_processor@vim_mode  
  # 默认关闭 vmode,只在对应的 app 中打开  
  switches/+:  
    - name: vmode  
      reset: 0  

配置 app_options

在对应平台的 .custom.yaml 中配置在什么应用下启用 vmode

比如 macOS 的 squirrel.custom.yaml

patch:  
  app_options:  
    org.alacritty:  
      ascii_mode: true  
      vmode: true  
    net.kovidgoyal.kitty:  
      ascii_mode: true  
      vmode: true  

实现思路与原因

起因

我觉得 vim_mode 的确是一个非常好的功能,尤其是我这种既要用 Obsidian,又要用 Terminal,偶尔还要用 VSCode 的人

虽然这些软件中都有类似 im-select 之类的切换插件,但是每个软件中都需要单独安装,且不同的操作系统,配置还可能不一样(比如我自己就在 macOS 和 Linux 下频繁切换)

所以如果能有一个 IM 级别的 vim_mode 切换解决方案,那真是再好不过了

可是目前的 vim_mode 有两个问题:

  1. 由前端实现,Linux 中不支持此功能
  2. 在中文模式下,切换到 normal mode,再进入 insert mode,会保持 ascii mode,而不会自动切换会中文模式
    • im-select 就会自动切换回中文模式

思路

搜索之后发现并没有一个现成的解决方案,但是却有大佬写过类似的逻辑,比如

稍微组合一下,就有了本文的解决方案


通过 switches 配置 vmode,再通过 app_options 配置在相应应用下打开 vmode ,即可实现原生的 vim_mode 在指定应用下开启的效果

利用 lua_processor 对按键输入进行处理,如果当前应用处于 vmode 下,就进行相关的逻辑处理

有考虑加入win端和macos端的vim mode · Issue #84 · fcitx/fcitx5-rime · GitHub 中所说,rime 是无法感知应用处于什么模式的(vim)
同样我们也无法知道应用处于什么模式,只能是根据 vim 的常规操作逻辑去大致的处理一下

思路如下:

在开启了 vmode 的应用中

Ref

lei4519 commented 1 month ago

@lei4519 问题已解决,ubuntu的包名就是apt或命令行用的包名,我把上面的配置放到对应输入方案下的配置文件中就可以生效了,ubuntu下squirrel.custom.yaml好像不能用?

linux 的配置文件要写在 fcitx5.custom.yaml 中(如果用的是 fcitx5)

不过 linux 中我遇到一个问题还没解决,就是 vim_mode.lua 这个 lua_processor 是配置在中文拼音里的,所以 esc 从中文切换到 ascii 是正常的,但在 ascii mode 中按 i/a/c/o 并不会重新进入中文模式

看起来是因为 Fcitx5 rime 的 ascii mode 根本不会执行配置在中文拼音中的 lua_processor 导致的,但是 macos 里就没有这个问题

如果可以给 ascii mode 也配置 lua_processor 就可以解决这个问题,不过一直也没时间去看

IC-killer commented 1 month ago

@lei4519 ubuntu ibus 下,app_options不生效,好像没有支持?https://github.com/rime/ibus-rime/issues/96 你的可以识别应用吗,我的好像不行

IC-killer commented 1 month ago

默认英文,先删除vmode变量全局使用了。。

lei4519 commented 1 month ago

@IC-killer 没有试过 ibus,Fcitx5 里是可以的

IC-killer commented 1 month ago

全局使用esc回到英文,只保留以下脚本就可以,这似乎对我来说已经足够了,app_options是锦上添花

local function vim_mode(key, env)
    if key.keycode == 65307 then
        env.engine.context:set_option("ascii_mode", true)
    end
    return 2
end
return vim_mode

如果我想实现按下jk回到ascii_mode应该怎么做,, 发现这个脚本似乎只有在esc alt shift这些按键按下时才会触发,按下普通的字母键,比如i a,会优先弹出候选框,而这个脚本我只能通过+加载,不清楚是否是加载顺序必须要在最前面的@before 0,但是before 0又会出错。。。

IC-killer commented 1 month ago

可以通过@before 0正常加载了,是写法错误,, engine/processors/https://github.com/before 0: lua_processor@*vim_mode

lei4519 commented 1 month ago

全局使用esc回到英文,只保留以下脚本就可以,这似乎对我来说已经足够了,app_options是锦上添花

local function vim_mode(key, env)
  if key.keycode == 65307 then
      env.engine.context:set_option("ascii_mode", true)
  end
  return 2
end
return vim_mode

如果我想实现按下jk回到ascii_mode应该怎么做,, 发现这个脚本似乎只有在esc alt shift这些按键按下时才会触发,按下普通的字母键,比如i a,会优先弹出候选框,而这个脚本我只能通过+加载,不清楚是否是加载顺序必须要在最前面的@before 0,但是before 0又会出错。。。

+ 等于 push, 会放在 processors 的末尾才会被执行到,如果想一开始就执行,只能用 before 0,语法报错的话把 rime 升级到最新的试试呢

全局 esc 切英文可以直接配置 ascii_composer.switch_key 实现吧,相当于把 esc 映射成 shift?

jk 切换可以试试 key:repr() == "j+k" 行不行

PromethiumL commented 3 weeks ago

可以通过@before 0正常加载了,是写法错误,, engine/processors/https://github.com/before 0: lua_processor@*vim_mode

可以放在代码块里吗,这个星号有点看不懂

PromethiumL commented 3 weeks ago

可以通过@before 0正常加载了,是写法错误,, engine/processors/https://github.com/before 0: lua_processor@*vim_mode

可以放在代码块里吗,这个星号有点看不懂

我看了一下 API 总算解决 jk 的问题了。不过我没放在 before 0 也能用

local function jk_processor(key, env)
  local input = env.engine.context.input
  local cxt = env.engine.context
  local k = 107

  if input == 'j' and key.keycode == k then
    -- os.execute("osascript -e 'display notification\"" .. 'JK' .. ' " with title "Event"\'')
    cxt:clear()

    env.engine:commit_text('jk')
    cxt:set_option("ascii_mode", true)
    return 1
  end

  return 2
end

return jk_processor
LLMChild commented 1 day ago

在iterm2上使用正常,转到wezterm上有问题。 具体问题表现为: 在ascill_mode下一切正常,转中文输入并使用esc退出后也能正常转为normal mode并切换到ascill_mode 但是使用i|o|a等按键时候,无法进入vim的insert mode,而输入法正常转为了中文输入

LLMChild commented 1 day ago
if prev_is_cn_mode then
     env.engine.context:clear()
     env.engine:commit_text(string.char(key.keycode))
     -- set_option前把context clear掉并把对应keycode上屏就可以解决wezterm的问题
     env.engine.context:set_option("ascii_mode", false)
return 1