update at 2025-12-05 13:34:29

This commit is contained in:
douboer@gmail.com
2025-12-05 13:34:29 +08:00
parent adc2cc6977
commit 8377047a36
6 changed files with 634 additions and 0 deletions

145
vim-im-switch-select.vim Normal file
View File

@@ -0,0 +1,145 @@
" vim-im-switch-select.vim - 智能记忆输入法状态 (使用 im-select)
" Author: Gavin Chan
" Modified by: codefalling, enhanced with smart IM state memory
" Version: 2.0.0
" Description: 记住退出 Insert 模式时的输入法状态,下次进入时自动恢复
" 使用 im-select 而不是 fcitx-remote 切换输入法
" ---------------------------------------------------------------------
" Load Once:
if exists('g:imselect_loaded')
finish
endif
if &ttimeoutlen <= 0 || &ttimeoutlen > 50
set ttimeoutlen=50
endif
if (has("win32") || has("win95") || has("win64") || has("win16"))
" Windows 下不要载入
finish
endif
if exists('$SSH_TTY')
finish
endif
if !executable("im-select")
finish
endif
let s:keepcpo = &cpo
let g:imselect_loaded = 1
set cpo&vim
" ---------------------------------------------------------------------
" 全局变量:记住上次 Insert 模式的输入法名称
let g:imselect_last_insert_im_name = ''
" 英文和中文输入法的 ID可以通过 im-select 获取)
if !exists('g:imselect_english_im')
let g:imselect_english_im = 'com.apple.keylayout.ABC'
endif
if !exists('g:imselect_chinese_im')
let g:imselect_chinese_im = 'auto-detect' " 将自动检测
endif
" ---------------------------------------------------------------------
" Functions:
" 离开 Insert 模式:保存当前输入法名称,然后切换到英文
function! IMSelect2en()
" 保存当前输入法名称
let current_im = substitute(system("im-select 2>/dev/null"), '\n', '', 'g')
let g:imselect_last_insert_im_name = current_im
" 切换到英文输入法(使用后台任务并重定向所有输出)
if has('job')
" Use nohup in a shell backgrounded process. Some Vim builds don't accept
" the 'detach' option; calling via sh -lc with nohup/& keeps process
" disassociated while avoiding unsupported job_start options.
call job_start(['sh', '-lc', 'nohup im-select ' . shellescape(g:imselect_english_im) . ' >/dev/null 2>&1 &'])
else
" Fallback: nohup in background
call system('nohup im-select ' . shellescape(g:imselect_english_im) . ' >/dev/null 2>&1 &')
endif
endfunction
" 进入 Insert 模式:根据保存的输入法名称恢复
function! IMSelect2zh()
" 如果上次保存的输入法名称为空,说明是第一次进入,保持英文
if g:imselect_last_insert_im_name == ''
return
endif
" 如果上次是英文输入法,保持英文(不需要做任何事)
if g:imselect_last_insert_im_name == g:imselect_english_im
return
endif
" 上次是中文输入法,恢复到那个输入法(使用后台任务并重定向所有输出)
if has('job')
call job_start(['sh', '-lc', 'nohup im-select ' . shellescape(g:imselect_last_insert_im_name) . ' >/dev/null 2>&1 &'])
else
call system('nohup im-select ' . shellescape(g:imselect_last_insert_im_name) . ' >/dev/null 2>&1 &')
endif
endfunction
" ---------------------------------------------------------------------
" Autocmds:
" 进入 Insert 模式一次后的处理
function! IMSelect2zhOnce()
call IMSelect2zh()
call UnBindIMSelectAu()
endfunction
function! BindIMSelectAu2zhOnce()
augroup IMSelect
au InsertEnter * call IMSelect2zhOnce()
augroup END
endfunction
" 绑定自动命令
function! BindIMSelectAu()
augroup IMSelect
" 离开 Insert 模式:保存输入法状态并切换到英文
au InsertLeave * call IMSelect2en()
" 进入 Insert 模式:恢复上次的输入法状态
au InsertEnter * call IMSelect2zh()
" Vim 启动时:切换到英文
au VimEnter * call IMSelect2en()
augroup END
endfunction
function! UnBindIMSelectAu()
au! IMSelect InsertLeave *
au! IMSelect InsertEnter *
endfunction
" 延迟初始化:首次进入 Insert 模式时才绑定自动命令
let g:imselect_called_bind = 0
function! IMSelectEchoBind()
if (g:imselect_called_bind==0)
call BindIMSelectAu()
endif
let g:imselect_called_bind = 1
endfunction
autocmd InsertEnter * call IMSelectEchoBind()
" 多光标支持:在选择多个光标前后的处理
function! IMSelect_multiple_cursors_before()
call UnBindIMSelectAu()
call BindIMSelectAu2zhOnce()
endfunction
function! IMSelect_multiple_cursors_after()
call IMSelect2en()
call BindIMSelectAu()
endfunction
" ---------------------------------------------------------------------
" Restoration And Modelines:
let &cpo=s:keepcpo
unlet s:keepcpo
let g:imselect_loaded = 1
" vim:fdm=expr:fde=getline(v\:lnum-1)=~'\\v"\\s*-{20,}'?'>1'\:1