Files
vim-im-switch/vim-im-switch-select.vim
2026-07-06 14:20:29 +08:00

140 lines
3.9 KiB
VimL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

" 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:imselect_cmd = exepath('im-select')
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 = 'com.apple.inputmethod.SCIM.ITABC'
endif
" ---------------------------------------------------------------------
" Functions:
function! IMSelectCurrentIM() abort
return substitute(system(shellescape(s:imselect_cmd) . ' 2>/dev/null'), '[\r\n]', '', 'g')
endfunction
function! IMSelectSwitch(im) abort
if has('job')
silent! call job_start([s:imselect_cmd, a:im], {'out_io': 'null', 'err_io': 'null'})
else
silent! call system(shellescape(s:imselect_cmd) . ' ' . shellescape(a:im) . ' >/dev/null 2>&1 &')
endif
endfunction
function! IMSelectStart() abort
call IMSelectSwitch(g:imselect_english_im)
endfunction
function! IMSelectEnsureTarget(timer) abort
if g:imselect_last_insert_im_name != ''
call IMSelectSwitch(g:imselect_last_insert_im_name)
endif
endfunction
" 离开 Insert 模式前:保存当前输入法名称
function! IMSelectRemember() abort
let current_im = IMSelectCurrentIM()
if current_im != ''
let g:imselect_last_insert_im_name = current_im
endif
endfunction
" 离开 Insert 模式:切换到英文
function! IMSelect2en() abort
call IMSelectSwitch(g:imselect_english_im)
endfunction
" 恢复 Insert 模式输入法
function! IMSelectRestore(timer) abort
if g:imselect_last_insert_im_name == ''
let g:imselect_last_insert_im_name = g:imselect_chinese_im
endif
call IMSelectSwitch(g:imselect_last_insert_im_name)
call timer_start(200, function('IMSelectEnsureTarget'))
endfunction
" 进入 Insert 模式:延迟恢复保存的输入法
function! IMSelect2zh() abort
call timer_start(80, function('IMSelectRestore'))
endfunction
" ---------------------------------------------------------------------
" Autocmds:
" 绑定自动命令
function! BindIMSelectAu()
augroup IMSelect
autocmd!
" 离开 Insert 模式前:先保存输入法状态
autocmd InsertLeavePre * call IMSelectRemember()
" 离开 Insert 模式:切换到英文
autocmd InsertLeave * call IMSelect2en()
" 进入 Insert 模式:恢复上次的输入法状态
autocmd InsertEnter * call IMSelect2zh()
" Vim 启动后:切换到英文
autocmd VimEnter * call timer_start(100, {-> IMSelectStart()})
augroup END
endfunction
function! UnBindIMSelectAu()
augroup IMSelect
autocmd!
augroup END
endfunction
call BindIMSelectAu()
" 多光标支持:在选择多个光标前后的处理
function! IMSelect_multiple_cursors_before()
call UnBindIMSelectAu()
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