junegunn / vader.vim

A simple Vimscript test framework
589 stars 40 forks source link

README incorrectly states that not updated search history is a Vim bug #62

Open ZyX-I opened 8 years ago

ZyX-I commented 8 years ago

Unlike absense of CursorMoved event which is either a bug or feature without documentation I know about, search history is intentionally not updated: :h function-search-undo. README should not mention this as being “likely a bug of Vim”.


If you want to fix this you need to run Do blocks outside of a function which will get messy because function looking like

function Foo() abort
    " Do something
    normal test
    " Do something else
endfunction

needs to be converted into

function FooStart() abort
    " Do something
    call feedkeys("test\<C-\><C-n>:call FooEnd()\n", "t")
endfunction
function FooEnd() abort
    " Do something else
endfunction

which looks easy only as long as Foo is called at the top level and not by other function and does not contain any kinds of conditional/cyclic execution: both is not your case. But this conversion may appear to fix problems with events (did not actually test), search history (very much likely to fix), and also allows creating workaround for “inability to use feedkeys()” problem: use FooEndRunner() function that may delay FooEnd run:

function FooStart() abort
    " Do something
    call feedkeys("test\<Plug>(VaderRunFooEnd)", "t")
endfunction
function FooEndRunner() abort
    if getchar(1) isnot 0
        call feedkeys("\<Plug>(VaderRunFooEnd)", "t") " Delay running FooEnd until there is no output
        return ""
    endif
    return "\<C-\>\<C-n>:call FooEnd()\n"
endfunction
map <expr> <Plug>(VaderRunFooEnd) FooEndRunner()
map! <expr> <Plug>(VaderRunFooEnd) FooEndRunner()

(looks ugly, which is why I would never use test frameworks written in VimL: ugly hacks either in your code or in framework code are necessary in many complex cases).


There is also another unmentioned issue with <expr> mappings: column position is updated not when you expect:

:let @a='i|jj'
:inoremap <expr> jj col('.')
:normal! @a

yields |1. Change <expr> jj col('.') to jj <C-r>=col('.')<CR> and this will yield |2. Do not change anything, but in place of using macros type i|jj, you will see |2 again. feedkeys(@a, "t") is not helpful here as well, so my workaround will not fix this issue. (Issue was actually found when creating tests for translit3 plugin; those tests have nothing to do with vader.vim, but issue will also definitely hit your users should they need cursor position inside an <expr> mapping for whatever reason. Do not remember whether I did report it to vim-dev.)

junegunn commented 8 years ago

Thanks for the writeup. I'll update the README. Writing a non-trivial vim plugin has become increasingly frustrating for me due to some incomprehensible bugs and extremely unintuitive subtleties that require truly horrible hacks :( It's really great to see that you're tracking down those problems and actively contributing to improve the situation. Keep up the good work!