From 67a79084209a3e6091ae5853730392f080824325 Mon Sep 17 00:00:00 2001 From: VimWei Date: Fri, 3 Jul 2026 09:59:56 +0800 Subject: [PATCH 1/3] feat(im_select): add im-control mode and fix gvim condition - Integrate external im-control command for input method switching on events. - Correct gvim early-exit condition to only apply on macOS. --- autoload/im_select.vim | 52 ++++++++++++++++++++++++++++++++++++++++++ plugin/im_select.vim | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/autoload/im_select.vim b/autoload/im_select.vim index 730f444..4980fd5 100644 --- a/autoload/im_select.vim +++ b/autoload/im_select.vim @@ -185,6 +185,10 @@ endfunction function! im_select#on_insert_enter() abort " let s:insert_enter_count += 1 " echomsg 'InsertEnter: ' . s:insert_enter_count . ', mode: ' . mode() . ', event: ' . string(v:event) + if get(g:, 'im_control_enabled', 1) && exists('g:im_control_command') + call im_select#im_control_on_insert_enter() + return + endif if s:focus_event_enabled if g:im_select_prev_im != '' call im_select#set_im(g:im_select_prev_im) @@ -204,6 +208,10 @@ endfunction function! im_select#on_insert_leave() abort " let s:insert_leave_count += 1 " echomsg 'InsertLeave: ' . s:insert_leave_count . ', mode: ' . mode() . ', event: ' . string(v:event) + if get(g:, 'im_control_enabled', 1) && exists('g:im_control_command') + call im_select#im_control_on_insert_leave() + return + endif if s:focus_event_enabled let j = im_select#get_and_set_prev_im('im_select#on_insert_leave_get_im_callback') endif @@ -219,6 +227,10 @@ endfunction function! im_select#on_focus_gained() abort " let s:focus_gained_count += 1 " echomsg 'FocusGained: ' . s:focus_gained_count + if get(g:, 'im_control_enabled', 1) && exists('g:im_control_command') + call im_select#im_control_on_focus_gained() + return + endif if s:focus_event_enabled if match(mode(), '^\(c\|i\|R\|s\|S\|t\|CTRL\-S\)') < 0 let j = im_select#get_and_set_prev_im('im_select#on_focus_gained_get_im_callback') @@ -230,6 +242,9 @@ endfunction function! im_select#on_focus_lost() abort " let s:focus_lost_count += 1 " echomsg 'FocusLost: ' . s:focus_lost_count + if get(g:, 'im_control_enabled', 1) && exists('g:im_control_command') + return + endif if s:focus_event_enabled if match(mode(), '^\(c\|i\|R\|s\|S\|t\|CTRL\-S\)') < 0 if g:im_select_prev_im != '' @@ -242,6 +257,10 @@ function! im_select#on_focus_lost() abort endfunction function! im_select#on_vim_leave_pre() abort + if get(g:, 'im_control_enabled', 1) && exists('g:im_control_command') + call im_select#im_control_on_vim_leave_pre() + return + endif if s:gui if match(mode(), '^\(c\|i\|R\|s\|S\|t\|CTRL\-S\)') < 0 if g:im_select_prev_im != '' @@ -253,4 +272,37 @@ function! im_select#on_vim_leave_pre() abort endif endfunction +" ===== im-control mode ===== {{{1 + +function! im_select#im_control_set_mode(chinese) abort + if a:chinese + let cmd = [g:im_control_command, '-k', 'open', '-c', 'native'] + else + let cmd = [g:im_control_command, '-k', 'open', '-c', 'alphanumeric'] + endif + return s:ImSetJob.new(cmd) +endfunction + +function! im_select#im_control_on_insert_enter() abort + call im_select#im_control_set_mode(v:false) +endfunction + +function! im_select#im_control_on_insert_leave() abort + if s:focus_event_enabled + call im_select#im_control_set_mode(v:false) + endif +endfunction + +function! im_select#im_control_on_focus_gained() abort + if s:focus_event_enabled + if match(mode(), '^\(c\|i\|R\|s\|S\|t\|CTRL\-S\)') < 0 + call im_select#im_control_set_mode(v:false) + endif + endif +endfunction + +function! im_select#im_control_on_vim_leave_pre() abort + call im_select#im_control_set_mode(v:false) +endfunction + " vim: ts=8 sts=4 sw=4 et diff --git a/plugin/im_select.vim b/plugin/im_select.vim index 49fae36..06c6daf 100644 --- a/plugin/im_select.vim +++ b/plugin/im_select.vim @@ -18,7 +18,7 @@ endif let g:im_select_enable_for_gvim = get(g:, 'im_select_enable_for_gvim', 0) -if !has('nvim') && has('gui_running') && (has('win32') || has('win64') || has('gui_mavim')) && !g:im_select_enable_for_gvim +if !has('nvim') && has('gui_running') && has('gui_mavim') && !g:im_select_enable_for_gvim finish endif From b375d4219d929692028de872ab84a38f628995c1 Mon Sep 17 00:00:00 2001 From: VimWei Date: Wed, 8 Jul 2026 17:52:28 +0800 Subject: [PATCH 2/3] fix(vim): add missing callbacks and simplify Windows IM command - Add empty on_stdout and on_stderr for Neovim job object. - Add empty out_cb and err_cb for Vim job object and pass to job_start. - Simplify Windows/WSL configuration to use fixed command. --- autoload/im_select.vim | 14 ++++++++++++++ plugin/im_select.vim | 18 +++--------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/autoload/im_select.vim b/autoload/im_select.vim index 4980fd5..40ae1b4 100644 --- a/autoload/im_select.vim +++ b/autoload/im_select.vim @@ -37,6 +37,12 @@ endfunction if has('nvim') let s:ImSetJob = {} + function s:ImSetJob.on_stdout(job_id, data, event) abort + endfunction + + function s:ImSetJob.on_stderr(job_id, data, event) abort + endfunction + function s:ImSetJob.wait() abort call jobwait([self.id]) endfunction @@ -82,6 +88,12 @@ if has('nvim') else let s:ImSetJob = {} + function s:ImSetJob.out_cb(channel, msg) abort + endfunction + + function s:ImSetJob.err_cb(channel, msg) abort + endfunction + function s:ImSetJob.exit_cb(job, status) abort let self.is_running = 0 endfunction @@ -96,6 +108,8 @@ else let object = copy(s:ImSetJob) let object.cmd = a:cmd let object.id = job_start(object.cmd, { + \ 'out_cb': object.out_cb, + \ 'err_cb': object.err_cb, \ 'exit_cb': object.exit_cb \ }) let object.is_running = 1 diff --git a/plugin/im_select.vim b/plugin/im_select.vim index 06c6daf..acab137 100644 --- a/plugin/im_select.vim +++ b/plugin/im_select.vim @@ -25,21 +25,9 @@ endif " OS and IM detection if !exists('g:im_select_get_im_cmd') || !exists('g:ImSelectSetImCmd') if has('win32') || has('win64') || has('win32unix') || has('wsl') || $PATH =~ '/mnt/c/WINDOWS' - if !exists('g:im_select_command') - " let cmd = exepath('im-select.exe') - " if cmd == '' - " echohl ErrorMsg | echomsg 'im-select.exe is not found on your system. Please refer to https://github.com/daipeihust/im-select' | echohl None - " finish - " endif - let cmd = 'im-select.exe' - let g:im_select_command = cmd - endif - - if !exists('g:im_select_default') - let g:im_select_default = '1033' - endif - let g:im_select_get_im_cmd = [g:im_select_command] - let g:ImSelectSetImCmd = {key -> [g:im_select_command, key]} + let g:im_select_default = '1033' + let g:im_select_get_im_cmd = ['cmd', '/c', 'echo', '1033'] + let g:ImSelectSetImCmd = {key -> ['cmd', '/c', 'echo', '1033']} elseif has('mac') || has('macunix') || has('osx') || has('osxdarwin') if !exists('g:im_select_command') " let cmd = exepath('im-select') From df0968e30a920d09d27ed710807669688ba85117 Mon Sep 17 00:00:00 2001 From: VimWei Date: Thu, 9 Jul 2026 09:50:36 +0800 Subject: [PATCH 3/3] fix: drop -k open from im-control calls to decouple compartments OPENCLOSE and CONVERSION compartments have separate responsibilities: OPENCLOSE manages IME enable/disable, CONVERSION manages Chinese/English. Sending -k open on every insert enter/leave was redundant (OPENCLOSE is already open during normal editing) and could trigger Weasel's OPENCLOSE handler blind-toggle of ascii_mode on Windows 11, racing with the CONVERSION handler. Now only -c is sent. The CONVERSION handler alone switches mode, matching the compartment separation principle. --- autoload/im_select.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/im_select.vim b/autoload/im_select.vim index 40ae1b4..6a21e5d 100644 --- a/autoload/im_select.vim +++ b/autoload/im_select.vim @@ -290,9 +290,9 @@ endfunction function! im_select#im_control_set_mode(chinese) abort if a:chinese - let cmd = [g:im_control_command, '-k', 'open', '-c', 'native'] + let cmd = [g:im_control_command, '-c', 'native'] else - let cmd = [g:im_control_command, '-k', 'open', '-c', 'alphanumeric'] + let cmd = [g:im_control_command, '-c', 'alphanumeric'] endif return s:ImSetJob.new(cmd) endfunction