Hello,
short version>>>
When using inoremap <expr>, does vim throw away some part of state that
is kept when using a normal inoremap? Calling an <expr> function which
returns <C-x><C-n> results in different behaviour to doing a plain
inoremap to <C-x><C-n>.
full description>>>
I am writing a script for Japanese input in vim, making use of the
completion functionality so that I can select appropriate kanji from a
vim menu rather than using my OS-wide IME. My approach has been as
follows:
1. Simple transliteration of roman characters to kana (Japanese
phonetic characters) within vimscript
2. Write a completion function to take the kana input and return
a list of valid kanji utilising tools external to vim.
3. Override keymappings to be able to make use of the above
functionality naturally:
(i) Hook into CursorMovedI to do the kana transliteration
(ii) inoremap the <space> and <cr> keys to bring up the menu
and select a kanji.
This is modelled on most normal OS-wide IMEs, which all work pretty much
as described above: you type in the text, it is transliterated into kana
as you type, and then on pressing the space bar a menu comes up offering
you options. You can navigate this menu by pressing space repeatedly,
and select an option by pressing return. I would like to replicate this
functionality in vim.
My trouble is in step 3(ii). I am using the user completefunc, and if I
simply press <C-x><C-u> as usual the kanji options come up and I can
navigate them with <C-x><C-p>, <C-x><C-n>, and <C-x><C-u> as usual.
However when trying to remap this functionality to <space> and <cr> vim
exhibits strange behaviour while attempting to navigate the menu, as if
it's regenerating the menu every time rather than simply navigating the
existing menu.
My mapping is as follows:
inoremap <buffer> <expr> <space> vime#handle_input("\<space>")
inoremap <buffer> <expr> <cr> vime#handle_input("\<cr>")
(As you can see, I'm passing the key pressed as a parameter. The
documentation says that I should be able to read that from v:char, but
when I tried to do that it returned empty)
The handle_input function takes the key pressed and the current state of
the IME and uses it to determine what to do, returning the appropriate
keystrokes. It is implemented as follows:
function! vime#handle_input(input)
let current_pos = getpos('.')
let current_col = current_pos[2]
if a:input == "\<cr>"
if pumvisible() " 3. Accept selection and
close menu
echom "Menu up! Returning accept"
call vime#reset_startpoints()
return "\<C-x>\<C-y>"
endif
elseif a:input == "\<space>"
if pumvisible() " 2. Select next entry in
menu
echom "Menu up! Returning next"
return "\<C-x>\<C-n>"
elseif current_col > g:kanji_start_point " 1. Launch menu
echom "Menu not up! Opening menu"
return "\<C-x>\<C-u>"
endif
endif
return a:input
endfunction
The cases marked 1 and 3 above seem to work fine: I type a word, press
space, and the menu appears (case 1). If I press return at that point,
the word is accepted, and the IME starts tracking the next word (case
3). If I press space AGAIN, however, the menu is regenerated using the
currently selected word as its input. As well as that, the output from
:messages includes the line "Scanning tags.", which I am not printing.
My guess is that it is throwing away the current menu before doing the
<C-x><C-n> I'm returning, so that those keypresses then get interpreted
as if I had entered them outside of the context of there being an open
menu (as in :help i_CTRL-X_CTRL-N).
If I type <C-x><C-n> myself after pressing <space> the first time, it
works fine, so I think the problem is something to do either with the
remapping or the fact that I'm using an <expr> function to do it.
Any pointers would be very much appreciated!
-Dani.
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php