Hello Vim developers,
I've written a user defined completion (via 'completefunc') that uses
normal y{motion}
to capture the completion matches. (I have some other completions that can use
getline() to extract the text; in those, the crash doesn't happen.)
If I use a straightforward mapping like
inoremap ... <C-o>:set completefunc=<SID>MotionComplete<CR><C-x><C-u>
to trigger the completion, everything is working fine. I've now appended some
<C-r>=pumvisible() ? "\<lt>Down>" : ""<CR> fragment to modify the popup menu
selection, and now observe Vim crashes whenever I invoke the augmented mapping.
In fact, any text after the <C-x><C-u> causes buffer corruptions and eventual
crashes.
I've whittled down my completion script to the attached version. With that, I
can reproduce crashes on the default (G)VIM 7.1 and 7.2 on Windows XP (but not
with 7.0, which works fine), and with the latest Vim 7.2.197 (Big version with
GTK2 GUI) on Ubuntu 8.04.
To reproduce (the completion is mapped to <F11>):
vim -N -u NONE -n -S CompleteAndTextMappingCrash.vim
ifoobar<CR>
foo<F11><CR> " No crash yet, but the '+' char after the mapping is lost
foo<F11>
Vim: Caught deadly signal SEGV
Vim: Finished.
Segmentation fault
You can check the original, correct behavior with:
vim -N -u NONE -n --cmd 'let nobug=1' -S CompleteAndTextMappingCrash.vim
Please let me know if you need any additional information.
-- regards, ingo
--
-- Ingo Karkat -- /^-- /^-- /^-- /^-- /^-- /^-- http://ingo-karkat.de/ --
-- http://vim.sourceforge.net/account/profile.php?user_id=9713 --
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---
function! s:FindMatchesInCurrentWindow( matches, pattern, matchTemplate,
options, isInCompletionBuffer )
let l:isBackward = has_key(a:options, 'backward_search')
let l:save_cursor = getpos('.')
let l:firstMatchPos = [0,0]
while ! complete_check()
let l:matchPos = searchpos( a:pattern, 'w' . (l:isBackward ? 'b' : '') )
if l:matchPos == [0,0] || l:matchPos == l:firstMatchPos
break
endif
if l:firstMatchPos == [0,0]
let l:firstMatchPos = l:matchPos
endif
let l:matchEndPos = searchpos( a:pattern, 'cen' )
if a:isInCompletionBuffer && (l:matchEndPos == l:save_cursor[1:2])
continue
endif
let l:matchObj = copy(a:matchTemplate)
let l:matchText = a:options.extractor(l:matchPos, l:matchEndPos,
l:matchObj)
let l:matchObj.word = l:matchText
if ! empty(l:matchText) && index(a:matches, l:matchObj) == -1
call add( a:matches, l:matchObj )
endif
endwhile
call setpos('.', l:save_cursor)
endfunction
function! MotionComplete_ExtractText( startPos, endPos, matchObj )
let l:save_cursor = getpos('.')
let @@ = ''
call setpos('.', [0, a:startPos[0], a:startPos[1], 0])
execute 'silent! normal y' . s:motion
let l:text = @@
call setpos('.', l:save_cursor)
return l:text
endfunction
function! s:LocateStartCol()
let l:startCol = searchpos('\k\+\%(\...@!.\)*\%#', 'bn', line('.'))[1]
if l:startCol == 0
let l:startCol = col('.')
endif
return l:startCol
endfunction
function! s:MotionComplete( findstart, base )
if a:findstart
return s:LocateStartCol() - 1 " Return byte index, not column.
else
let l:options = {}
let l:options.extractor = function('MotionComplete_ExtractText')
let l:matches = []
call s:FindMatchesInCurrentWindow( l:matches, '\V\<' . escape(a:base,
'\'), {}, l:options, 1 )
return l:matches
endif
endfunction
let s:motion = 'w'
inoremap <silent> <Plug>MotionComplete <C-o>:set
completefunc=<SID>MotionComplete<CR><C-x><C-u>
" The original mapping that caused the crash.
" In combination with an expression to select the first match in the popup menu
" (this is useful in combination with :set completeopt=menu,longest), Vim
" crashes.
"imap <F11> <Plug>MotionComplete<C-r>=pumvisible() ? "\<lt>Down>" : ""<CR>
" A simplified mapping that still causes the crash.
imap <F11> <Plug>MotionComplete+Some-More-Text
" The bare mapping works fine.
if exists('nobug')
imap <F11> <Plug>MotionComplete
endif