kovisoft / slimv

Official mirror of Slimv versions released on vim.org
454 stars 60 forks source link

Blinking cursor , flashing f^[ #2

Open dotmilk opened 10 years ago

dotmilk commented 10 years ago

Video of bug http://ge.tt/1tgt4481/v/0?c

Using spf13 + slimv

Steps to reproduce: Start vim edit a .lisp file ,c to start swank cursor begins blinking with f^[ being flashed in the bottom

kovisoft commented 10 years ago

I installed spf13 but unfortunately I was not able to reproduce the blinking. I guess the blinking occurs in the area of the status line where vim prints the keys typed when 'showcmd' is set.

Background: Slimv has a timer for continuous REPL update. This is done by feeding some 'innocent' keys into vim's typeahead buffer: starting a normal mode 'f' command followed by an Esc (=^[). I'm pretty sure that you see those characters reflected when the timer fires and puts them into the typeahead buffer.

Could you please test the following? Please locate the following line in function SlimvTimer() in ftplugin/slimv.vim:

    call feedkeys("f\e", 'n')

and wrap it the following way, so that 'showcmd' is temporarily disabled while feeding 'f\e':

    let save_sc = &showcmd
    set noshowcmd
    call feedkeys("f\e", 'n')
    let &showcmd = save_sc

Does it solve the problem?

dotmilk commented 10 years ago

Unfortunately it does not: http://ge.tt/7aqjh681/v/0?c

However i just now noticed that it does it in other buffers as well.

I'm working from a fresh spf13 as well, so it's strange it won't duplicate on your setup.

I'm on mountain lion, using iterm2 with zsh, though it does the same thing in macvim, so i'm assuming it's not a problem with my terminal session.

Maybe slowing down the timer?

kovisoft commented 10 years ago

Then it may be related to the speed of the terminal. Could you please perform another test? Let's disable 'showcmd' for the whole CursorHold event handling, please note the 'set noshowcmd' and 'set showcmd' lines added:

function! SlimvRefreshModeOn()
    if !exists( 'b:au_curhold_set' )
        let b:au_curhold_set = 1
        execute "au CursorHold   * :call SlimvTimer()"
        execute "au CursorHoldI  * :call SlimvTimer()"
        set noshowcmd
    endif
endfunction

" Switch refresh mode off
function! SlimvRefreshModeOff()
    set showcmd
    execute "au! CursorHold"
    execute "au! CursorHoldI"
    if exists( 'b:au_curhold_set' )
        unlet b:au_curhold_set
    endif
endfunction

If this still does not help then please redo your test with 'showcmd' just completely turned off in vim. Thanks for the assistance.

dotmilk commented 10 years ago

That works just fine, however the cursor is still blinking incredibly fast, it is much slower in macvim, so you are right about how fast the terminal is, any idea how to correct?

kovisoft commented 10 years ago

Please check the value of 'updatetime' and g:slimv_updatetime. The timer uses these settings for the re-trigger frequency (especially the second one during REPL refresh mode). Well, in case the cursor blinking is caused by the slimv timer and it is not a general vim setting.

Some notes on the original issue: My last code changes were not meant as a general fix for the problem. If we need a fix, we need to find a way that does not disable 'showcmd' for other users who don't have the blinking problem. A new option maybe?

dotmilk commented 10 years ago

updatetime=4000

Mainly it was the speed at which it was happening which caused the problem, very distracting blinking and putting the key combo there in the corner of my eye. So it's not as big of an issue if i can get it to slow down.

I know i can check something by 'set updatetime?' however that doesn't work for g:slimv_updatetime , how do check the current value?

And thank you for all the help.

kovisoft commented 10 years ago

You check options by 'set option?' and you check variables by 'echo variable'. So in this case:

set updatetime? echo g:slimv_updatetime

The latter one is 500 (=0.5 sec) by default. If you have updatetime=4000, that seems to be okay and that should not cause such a high frequency blinking. So I suppose something interferes with slimv's CursorHold handler.

Please check (during your test) this:

:au CursorHold

Does it print anything else than a single line of "* :call SlimvTimer()"?

BTW, does the whole problem happen without spf13? If no, then is it possible to temporarily disable some of the plugins installed by spf13? This way we could identify the one that may interfere with slimv.

dotmilk commented 10 years ago

Well after removing spf13 there was no problem, so it is definitely a conflict with spf13 that causes this, i'll get back with you after figuring out what conflicts. Results of :au CursorHold

:verbose au CursorHold
--- Auto-Commands ---
CursorHold
    *         call s:echo()
        Last set from ~/.spf13-vim-3/.vim/bundle/vim-bufferline/autoload/bufferline.vim
airline_whitespace  CursorHold
    *         unlet! b:airline_whitespace_check
        Last set from ~/.spf13-vim-3/.vim/bundle/vim-airline/autoload/airline/extensions/whitespace.
vim
TagbarAutoCmds  CursorHold
    __Tagbar__
              call s:ShowPrototype(1)
        Last set from ~/.spf13-vim-3/.vim/bundle/tagbar/autoload/tagbar.vim
    *         call s:AutoUpdate(fnamemodify(expand('<afile>'), ':p'), 0)
        Last set from ~/.spf13-vim-3/.vim/bundle/tagbar/autoload/tagbar.vim

The problem is gone after removing the tagbar plugin.

Should I open an issue with them, or shall we look at what their code is doing?

kovisoft commented 10 years ago

Thank you, that was a great help!

Let's try to identify the real root of the problem before opening an issue for another plugin, because it is possible that it's really slimv's fault.

I tried to check the code of the tagbar plugin, and I have some ideas. One idea is that maybe slimv should define an own group for autocommands. Please test these modified functions that define/remove augroup SlimvAutoCmds:

function! SlimvRefreshModeOn()
    if !exists( 'b:au_curhold_set' )
        let b:au_curhold_set = 1
        augroup SlimvAutoCmds
        execute "au CursorHold   * :call SlimvTimer()"
        execute "au CursorHoldI  * :call SlimvTimer()"
        augroup END
    endif
endfunction

" Switch refresh mode off
function! SlimvRefreshModeOff()
    execute "au! SlimvAutoCmds"
    if exists( 'b:au_curhold_set' )
        unlet b:au_curhold_set
    endif
endfunction

If this does not help then I think we should find the exact autocommand(s) of tagbar that interfere(s) with slimv. For this we could try to comment out some of the autocommands in tagbar for testing purposes:

(1) tagbar/autoload/tagbar.vim, line 967:

    autocmd CursorHold __Tagbar__ call s:ShowPrototype(1)

(2) tagbar/autoload/tagbar.vim, lines 984-985:

    autocmd BufReadPost,BufEnter,CursorHold,FileType * call
                \ s:AutoUpdate(fnamemodify(expand('<afile>'), ':p'), 0)

(3) tagbar/autoload/tagbar.vim, lines 968-969:

    autocmd WinEnter __Tagbar__ call s:SetStatusLine('current')
    autocmd WinLeave __Tagbar__ call s:SetStatusLine('noncurrent')

(4) tagbar/autoload/tagbar.vim, lines 975-978, :

    autocmd WinEnter * nested call s:QuitIfOnlyWindow()
    autocmd WinEnter * if bufwinnr('__Tagbar__') == -1 |
                     \ call s:ShrinkIfExpanded() |
                     \ endif

Sorry for adding so many tasks, I would do them myself if I could reproduce the problem. :( Thanks again!

dotmilk commented 10 years ago

augroup did not solve problem

When opening vim and

:e myfile.lisp

It is hit or miss as to whether there is a problem

New theory emerged: I have yet to get it to reproduce glitch while providing the file to be edited from shell, also i have noticed that the Airline plugin glitches out when i open .lisp files from inside vim (no other file type) causing the status bar to be blank.

Short video demonstrating the above: http://ge.tt/1jQ0wQ81/v/0

The following are the only lines in my .vimrc.local file that deals with lisp

augroup ft_lisp
    au!
    "Lisp no auto close
    au FileType lisp let b:AutoClosePairs = AutoClose#ParsePairs("\" ()")
    au FileType lisp let b:paredit_electric_return=0
augroup end

Is there a different start up order when file is opened from command line vs in vim?

There must be something different about the way it handles things when you open a file different ways.

dotmilk commented 10 years ago

Didn't realize i had closed this

kovisoft commented 10 years ago

Thanks for the detailed test report. TBH I'm a little clueless. :( Let's try another approach: checking what in slimv may interfere with others. I have two suspects:

(1) What happens if you comment out this line in function SlimvTimer() in slimv.vim?

call SlimvRefreshReplBuffer()

This way there will be no buffer switch, only CursorHold will be re-triggered.

(2) What happens if you comment out the 'call feedkeys(...)' lines in SlimvTimer(), but keep 'call SlimvRefreshReplBuffer()' uncommented? This way there will be no re-triggering, but there will be one buffer switch when CursorHold fires.

As a final resort we can enable vim's verbose logging:

Please send me the resulting 'test.log' file (you can find my email address in the slimv doc). Thanks.

dotmilk commented 10 years ago

Commenting out "call SlimvRefreshReplBuffer()" in SLimvTimer() removed the problem, I went ahead and put it back in and sent the test.log file for greater insight in to the problem.

Also following your second step commented out the feedkeys, leaving in the call to SlimvRefreshReplBuffer() also fixes the problem

feigaoxyz commented 7 years ago

Hi team.

Is there a solution for the problem now?

I am still experiencing this. As it eats my C-w if the following w|j|k... is typed not fast enough.

:verbose au CursorHold
--- Auto-Commands ---
gitgutter  CursorHold
    *         call gitgutter#process_buffer(bufnr(''), 1)
        Last set from ~/.dotfiles/vim/.vim/plugged/vim-gitgutter/plugin/gitgutter.vim
CursorHold
    *         unlet! b:airline_head
        Last set from ~/.dotfiles/vim/.vim/plugged/vim-airline/autoload/airline/extensions/branch.vim
airline_whitespace  CursorHold
    *         call <sid>ws_refresh()
        Last set from ~/.dotfiles/vim/.vim/plugged/vim-airline/autoload/airline/extensions/whitespace.vim
SlimvCursorHold  CursorHold
    *         :call SlimvTimer()
        Last set from ~/.dotfiles/vim/.vim/plugged/slimv/ftplugin/slimv.vim
kovisoft commented 7 years ago

Unfortunately I was (and still am) unable to reproduce the problem. I'm pretty sure it's somehow related with the interaction of the various CursorHold events of the plugins installed. I have just installed a fresh spf13 on linux, then added slimv, but for me the blinking just does not happen. I compared your list of CursorHold handlers to mine, the only difference I see is gitgutter (I don't have it), but I wouldn't want to say that gitgutter is causing the problem. Right now the only thing I can think of is to add a new option to disable or limit the feedkeys() calls in SlimvTimer(), please let me know if you think this makes any sense (I mean if e.g. commenting out feedkeys() solves the problem for you and slimv does not lose any functionality).

feigaoxyz commented 7 years ago

By commenting out call feedkeys("f\e", 'n') inside SlimvTimer(), things start moving smooth. But as I am just a newly lisp learner and slimv adaptor, I can not really say if there are other impacts on functionality.

Anyway I am glad to help if you want to hunt down this bug. To provide more info, I am using iTerm2 on macOS 10.12 with fish shell. I am not sure if I have spf13 installed, at least not aware of did so on purpose. I managed vim plugins via vim-plug, and the following is my vim version.

$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Jun 24 2017 12:45:56)
MacOS X (unix) version
Included patches: 1-666
Compiled by Homebrew
Huge version without GUI.  Features included (+) or not (-):
+acl             +file_in_path    +mouse_sgr       +tag_old_static
+arabic          +find_in_path    -mouse_sysmouse  -tag_any_white
+autocmd         +float           +mouse_urxvt     -tcl
-balloon_eval    +folding         +mouse_xterm     +termguicolors
-browse          -footer          +multi_byte      +terminfo
++builtin_terms  +fork()          +multi_lang      +termresponse
+byte_offset     -gettext         -mzscheme        +textobjects
+channel         -hangul_input    +netbeans_intg   +timers
+cindent         +iconv           +num64           +title
-clientserver    +insert_expand   +packages        -toolbar
+clipboard       +job             +path_extra      +user_commands
+cmdline_compl   +jumplist        +perl            +vertsplit
+cmdline_hist    +keymap          +persistent_undo +virtualedit
+cmdline_info    +lambda          +postscript      +visual
+comments        +langmap         +printer         +visualextra
+conceal         +libcall         +profile         +viminfo
+cryptv          +linebreak       +python          +vreplace
+cscope          +lispindent      -python3         +wildignore
+cursorbind      +listcmds        +quickfix        +wildmenu
+cursorshape     +localmap        +reltime         +windows
+dialog_con      -lua             +rightleft       +writebackup
+diff            +menu            +ruby            -X11
+digraphs        +mksession       +scrollbind      -xfontset
-dnd             +modify_fname    +signs           -xim
-ebcdic          +mouse           +smartindent     -xpm
+emacs_tags      -mouseshape      +startuptime     -xsmp
+eval            +mouse_dec       +statusline      -xterm_clipboard
+ex_extra        -mouse_gpm       -sun_workshop    -xterm_save
+extra_search    -mouse_jsbterm   +syntax          
+farsi           +mouse_netterm   +tag_binary      
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
  fall-back for $VIM: "/usr/local/share/vim"
Compilation: clang -c -I. -Iproto -DHAVE_CONFIG_H   -DMACOS_X_UNIX  -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1       
Linking: clang   -L. -fstack-protector -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/readline/lib  -L/usr/local/lib -o vim        -lncurses -liconv -framework Cocoa   -mmacosx-version-min=10.12 -fstack-protector-strong -L/usr/local/lib  -L/usr/local/Cellar/perl/5.26.0/lib/perl5/5.26.0/darwin-thread-multi-2level/CORE -lperl -lm -lutil -lc -F/usr/local/opt/python/Frameworks -framework Python   -lruby.2.4.1 -lobjc    
kovisoft commented 7 years ago

OK, thanks, so the problem seems to be that the CursorHold event triggers very frequently for some reason. Vim sends the CursorHold event when the user doesn't press any key for a while. This 'for a while' is defined by the updatetime vim option, you can check it with :set updatetime?. Normally this value should be a few hundreds or thousands (milliseconds), slimv sets it to 500 (half second) while waiting for the swank output. The feedkeys() call is used to re-trigger the CursorHold event (normally it is sent only once when updatetime elapsed). So that is the background. I suspect that another plugin sets a very short value for updatetime and this is causing the blinking. Another reason can be that updatetime is explicitly set to a short value in your .vimrc file, so I'd like you to verify this and also please execute the :set updatetime? command in vim when you experience the blinking.

feigaoxyz commented 7 years ago

I indeed manually set it in vimrc as vim-gitgutter recommended. After removing this, things work well, with only drawback I experiencing now is that visual hints on git status change (per line) in insert mode is delayed to 4000ms.

Another interesting observation during my experiment is that slimv save and load system updatetime every time REPL involved. A side-effect of these is that if I manually :set updatetime=10000, for example, during my vim editing, the slimv will still restore the value in my .vimrc (be 4000 or 250), instead of new value (10000).

Thank you for the insightful suggestion on updatetime. And thank you for your great plugin 👍

kovisoft commented 7 years ago

I did some changes, I'd like you to check it out. It should address two problems: (1) recognize changes done to updatetime after slimv started, (2) use g:slimv_updatetime while waiting for swank output. Could you please replace these two functions in your slimv.vim and check whether it solves the blinking problem? Thank you.

" Handle response coming from the SWANK listener
function! SlimvSwankResponse()
    let s:swank_ok_result = ''
    let s:refresh_disabled = 1
    silent execute s:py_cmd . 'swank_output(1)'
    let s:refresh_disabled = 0
    let s:swank_action = ''
    let s:swank_result = ''
    silent execute s:py_cmd . 'swank_response("")'

    if s:swank_action == ':describe-symbol' && s:swank_result != ''
        echo substitute(s:swank_result,'^\n*','','')
    elseif s:swank_ok_result != ''
        " Display the :ok result also in status bar in case the REPL buffer is not shown
        let s:swank_ok_result = substitute(s:swank_ok_result,"\<LF>",'','g')
        if s:swank_ok_result == ''
            call SlimvShortEcho( '=> OK' )
        else
            call SlimvShortEcho( '=> ' . s:swank_ok_result )
        endif
    endif
    if s:swank_actions_pending
        let s:last_update = -1
    elseif s:last_update < 0
        " Remember the time when all actions are processed
        let s:last_update = localtime()
    endif
    if s:swank_actions_pending == 0 && s:last_update >= 0 && s:last_update < localtime() - 2
        " All SWANK output handled long ago, restore original update frequency
        if &updatetime == g:slimv_updatetime
            let &updatetime = s:save_updatetime
        endif
    else
        " SWANK output still pending, keep higher update frequency
        if &updatetime != g:slimv_updatetime
            let s:save_updatetime = &updatetime
        endif
        let &updatetime = g:slimv_updatetime
    endif
endfunction

" Execute the given command and write its output at the end of the REPL buffer
function! SlimvCommand( cmd )
    silent execute a:cmd
    if &updatetime != g:slimv_updatetime
        let s:save_updatetime = &updatetime
    endif
    " Update more frequently until all swank responses processed
    let &updatetime = g:slimv_updatetime
    let s:last_update = -1
endfunction
feigaoxyz commented 7 years ago

It saves and loads correct updatetime value now.

kovisoft commented 7 years ago

OK, thanks, I committed these changes. Do you still have the blinking? Can it be solved by increasing updatetime and/or g:slimv_updatetime in your .vimrc?

feigaoxyz commented 7 years ago

I unset updatetime to its default value 4000 so it does not blink so frequently now.