jszakmeister / vim-togglecursor

Toggle the cursor shape in the terminal for Vim.
http://www.vim.org/scripts/script.php?script_id=4403
119 stars 20 forks source link

[Bug] Vim cursor sometimes (always?) disappears on Vim startup when opening a file #19

Closed phongvcao closed 9 years ago

phongvcao commented 9 years ago

For some reasons my cursor keeps disappearing if I open a file in Vim (using vim /path/to/file command) inside gnome-terminal with tmux and powerline. When I change my mouse focus from gnome-terminal to another window (I am using Vim under terminal), OR replace vim-togglecursor with this snippet of Vimscript inside my .vimrc:

" Toggle cursor between block and ibeam shape in different modes (Insert,
" Normal, Visual, Replace. Also make them blink.
function! ToggleCursorByMode()
    if exists('$TMUX')
        if v:insertmode == 'r' || v:insertmode == 'v'
            let &t_SI = "\<Esc>Ptmux;\<Esc>\e[3 q\<Esc>\\"
        else
            let &t_SI = "\<Esc>Ptmux;\<Esc>\e[5 q\<Esc>\\"
        endif

        let &t_EI = "\<Esc>Ptmux;\<Esc>\e[0 q\<Esc>\\"

    else
        if v:insertmode == 'r' || v:insertmode == 'v'
            let &t_SI = "\e[3 q"
        else
            let &t_SI = "\e[5 q"
        endif

        let &t_EI = "\e[0 q"
    endif
endfunction

call ToggleCursorByMode()

augroup AutoCursor
    autocmd InsertEnter * :call ToggleCursorByMode()
autogroup END

Everything was working as expected. Without the above snippet of codes, sometimes even during cursor moving in Normal mode, my cursor disapearred and I had to move the mouse focus to another window beside gnome-terminal again and then move back.

I believe there is currently a problem of autocmd VimEnter * statement in plugin/togglecursor.vim unable to load <SID>ToggleCursorInit() at Vim startup, because as long as I replaced vim-togglecursor with the above code, OR tried to move focus to another window (which triggered FocusGained & FocusLost), the cursor started working again. So I guess you may want to add an autocmd BufWinEnter * OR invoking ToggleCursorInit() outside of autocmd (so it will be run when Vim sources the .vimrc file).

Here is my version information: OS: Arch Linux Shell: zsh 5.0.8 Multiplexor: tmux 2.0 Vim: VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Jul 11 2015 08:44:54) Included patches: 1-778 GNOME: Version 3.16.2

phongvcao commented 9 years ago

Okay I believe I found where the problem is: It is in this line of code in plugin/togglecursor.vim. When I commented it out, everything worked again as expected:

let &t_ti = s:GetEscapeCode(g:togglecursor_default) . &t_ti

The reason is this line of code makes &t_ti equal to ^[Ptmux;^[^[[2 q^[\^[Ptmux;^[^[[?1004h^[\^[[?1004h^[[?1049h while in fact &t_ti must be equal to ^[Ptmux;^[^[[?1004h^[\^[[?1004h^[[?1049h for the cursor to work in tmux and gnome-terminal.

So instead of using concatenation like above, you can either comment it out, or not using concatenation at all, or only using concatenation if we are inside Konsole:

if s:supported_terminal == 'cursorshape'
    let &t_ti = s:GetEscapeCode(g:togglecursor_default) . &t_ti
endif

@jszakmeister I just created a Pull Request with the above suggestion, which has worked fine for me. I am waiting for your opinion.

phongvcao commented 9 years ago

Oh I forgot to mention that I am using gnome-terminal with VTE version 4002 (0.40.2) on Arch Linux which is the newest (and not yet stable) version of VTE. If you use an older version it may still work but if you upgrade to VTE 4002, the cursor disappears on Vim startup regardless of whether you're inside Tmux session or not.

jszakmeister commented 9 years ago

The reason is this line of code makes &t_ti equal to ^[Ptmux;^[^[[2 q^[\^[Ptmux;^[^[[?1004h^[\^[[?1004h^[[?1049h while in fact &t_ti must be equal to ^[Ptmux;^[^[[?1004h^[\^[[?1004h^[[?1049h for the cursor to work in tmux and gnome-terminal.

Why is gnome-terminal different here? Doesn't this have more to do with tmux than gnome-terminal? I feel like I'm missing something here--I'm pretty certain this worked with tmux and gnome-terminal previously.

So instead of using concatenation like above, you can either comment it out, or not using concatenation at all, or only using concatenation if we are inside Konsole:

Why are the first two options? How does doing this maintain tmux support?

Oh I forgot to mention that I am using gnome-terminal with VTE version 4002 (0.40.2) on Arch Linux which is the newest (and not yet stable) version of VTE.

Ah, that might explain why I see something different. Still, I'm not sure it's my bug or VTE's.

jszakmeister commented 9 years ago

@phongvcao Give master a whirl and see what you think. I went about fixing the issue slightly different (I didn't like depending on the shape to know whether to prefix or not). It still works where I need it.

If you use an older version it may still work but if you upgrade to VTE 4002, the cursor disappears on Vim startup regardless of whether you're inside Tmux session or not.

I don't generally ride unstable builds... I don't have time to debug all the issues I run into from buggy upstream software--and I seem to have a knack for finding them. :-( I'd appreciate you giving the fix a whirl and reporting back though!

phongvcao commented 9 years ago

@jszakmeister Okay great I just updated vim-togglecursor and everything worked as expected. Thanks for the fix. I agree with everything you said so far.

jszakmeister commented 9 years ago

Great! Thanks for trying it out the new fix!

ph0ngp commented 9 years ago

after this fix, my cursor shape no longer changes to g:togglecursor_default when I enter Vim. It does change when I change the modes though. I am using iTerm 2.

phongvcao commented 9 years ago

@phphong so what shape does your cursor have when you enter Vim after this fix? Can you be more specific about your platform, what version of Vim, Tmux, etc.?

ph0ngp commented 9 years ago

My environment:

I have tried all 3 types of cursor (underline, box, vertical bar) and in all 3 cases the cursor shape just remains the same when I enter Vim

phongvcao commented 9 years ago

@phphong so when you removed the additional code from Pull Request #20 the cursor shape changed to the value you specify in g:togglecursor_default when starting Vim? Can you try these settings in your .vimrc?:

let g:togglecursor_force = 'xterm'
" can be 'underline' or whatever specified in the doc
let g:togglecursor_default = 'line'

My Vim on iTerm2 is working fine with this fix but I guess I will check things tonight after getting home from work.

ph0ngp commented 9 years ago

Yes, things works properly when I checkout commit 696ae70. I have tried your 2 lines (in my minimum vimrc) but it still does not work

jszakmeister commented 9 years ago

Heh, yeah, that's right: the t_ti hack was to enable the default cursor type to work. The Konsole specific bit was to put our bits first. It looks like I'm going to have to revert that change unless a better workaround can be found.

And just to be clear: the default cursor type is the cursor used in normal mode (not insert mode). It was to allow folks to have one setting at their normal terminal and use what makes sense within Vim.

phongvcao commented 9 years ago

@phphong okay please try out my branch for vim-togglecursor in your vimrc for now and see if it works:

I already issued Pull Request #23 to fix this issue (my branch contains the code in the Pull Request). I am waiting for your test result.

jszakmeister commented 9 years ago

@phongvcao Do you have a reproduction recipe for this? How did you make the problem happen? I need some details. I built tmux 2.0 and fired Vim up under gnome-terminal on F22 (using vte 0.40.2) and could not see the problem. Guarding t_ti this way (only selectively enabling or disabling it) prevents the default cursor from being set correctly. The better answer would be for us to figure out what is tickling vte 0.40.2. It also looks like it's not tmux related? You said this earlier:

If you use an older version it may still work but if you upgrade to VTE 4002, the cursor disappears on Vim startup regardless of whether you're inside Tmux session or not.

Is that correct? Is there an easy way to get an Arch Linux VM up and running? I really don't want to go through it's stupid install process.

phongvcao commented 9 years ago

@jszakmeister yes it is not tmux-related. Arch Linux is a unique distro though because it is based on rolling releases. Thus, all packages are updated to their latest. The exact version of my VTE is vte3 0.40.2-1 and the g:togglecursor_default option works fine with this Pull Request. With the result of your test I can no longer know what cause the problem beside VTE. GNOME? GTK? It is confusing.

But how about letting the users choose whether to set the &t_ti variable? Something like a g:togglecursor_prefix_ti variable. If this problem only happens on one distro of one operating systems (Arch Linux in this case), I think having an option for this would easily resolve the issue. Otherwise, I can set the &t_ti variable manually inside my .vimrc. What do you think?

phongvcao commented 9 years ago

@jszakmeister even if there exists a cause beside VTE (like in GNOME, GTK, etc.) I think it is too cumbersome for the plugin to detect it. Say it is some GNOME packages that conflict with VTE (like GTK3 for example) that produces this result. Then we have to check for GTK3 exact version through Vimscript? I think just having an option and let the users choose would ease future development pain.

jszakmeister commented 9 years ago

The exact version of my VTE is vte3 0.40.2-1 and the g:togglecursor_default option works fine with this Pull Request.

Meaning, if you do:

let g:togglecursor_default = 'underline'

in your .vimrc, Vim comes up with the normal mode cursor being an underline without any interaction from you? That's definitely not the behavior I saw.

I'd definitely consider adding an option, but it'd be really nice to understand why VTE is barfing on it. I suspect that with a small change in how it's being done, it could be made to work correctly.

phongvcao commented 9 years ago

@jszakmeister wait I think this time g:togglecursor_default no longer works in my Vim when I added the line you mentioned above. This is kinda strange to me because I used to use this option in my .vimrc after your fix of this issue and it worked fine.

The thing is when I move my mouse pointer away gnome-terminal (or any VTE-based terminal) into another window (say Firefox), the cursor appears again. This is kinda weird. It may be a &t_ti refreshing problem? I am not sure but maybe this bug is a bug of VTE and/or GNOME itself.

jszakmeister commented 9 years ago

How do you reproduce the problem? Anything special?

t_ti is only emitted once: when Vim starts up. IIRC, it's never emitted again by Vim.

phongvcao commented 9 years ago

@jszakmeister when I commented out the let &t_ti line, if I enter the insert mode and then back to normal mode, the g:togglecursor_default works correctly again.

It is very easy to reproduct this problem on Arch Linux but maybe not on Fedora. I don't know what the cause is after your test result.

jszakmeister commented 9 years ago

@jszakmeister when I commented out the let &t_ti line, if I enter the insert mode and then back to normal mode, the g:togglecursor_default works correctly again.

That's not working. The whole point of t_ti is to set the normal mode cursor when you first enter vim. If it's not correct when you first enter (without going into insert mode and back), then it's broken.

jszakmeister commented 9 years ago

@phongvcao I've tried to reproduce this locally, but am having no luck. In my testing, I've tried using gnome-terminal to firing up vim to edit a file, and the cursor never disappears. I've done this under tmux 1.9 and 2.0 as well. At this point, I feel like I'm out of options. FWIW, Neovim has seen a bug in the VTE widget that might be somewhat related (neovim/neovim#3110). I'd recommend getting this into a reproducible state, preferably using something like the script in 3110:

#!/usr/bin/env python
import sys
import time

time.sleep(2)
sys.stdout.write('\x1b[5 q')
sys.stdout.flush()
time.sleep(2)
sys.stdout.write('\x1b[2 q')
sys.stdout.flush()
time.sleep(2)

One of the Neovim devs filed a ticket in the GNOME bugtracker and got a pretty quick turnaround on it. Considering the Arch Linux is a rolling distro, that might be really good for you.

jszakmeister commented 9 years ago

@phongvcao I've added a new option (g:togglecursor_disable_default_init) to allow you to skip the modification of t_ti. It would be really swell if you could come up with a recipe for the GNOME guys and report the issue there though.

phongvcao commented 9 years ago

@jszakmeister okay great I will try a fresh re-installation of Arch Linux when I have time to test this thing out (see which package causes this, which config, etc.). Please keep this bug opened.

jszakmeister commented 9 years ago

@phongvcao I think this is probably the same bug you've been running into (which has been fixed in 0.41.90): https://github.com/GNOME/vte/commit/c1db666000f9c8e3d05930690926a6d7908e8e41

jszakmeister commented 9 years ago

BTW, I was able to reproduce the problem with:

sleep 1; printf '\e[4 q'; sleep 5; printf '\e[0 q'

You'll see the cursor disappear for 5 seconds and then reappear with the blinking block cursor at the end.

phongvcao commented 9 years ago

@jszakmeister wow you are right. When I set the g:togglecursor_default to 'blinking_block', the cursor appeared again even when g:togglecursor_disable_default_init was not set (so basically even when the &t_ti was set). I think we can close the bug here.

You can keep the g:togglecursor_disable_default_init variable in the next vim-togglecursor release or you can keep it. Also, I think we should set g:togglecursor_default to 'blinking_block' by default (instead of 'block' right now) in the plugin so users that still use 0.40.2 won't have the problem out of the box (and we should also mention this in the doc too, of why it is 'blinking_block' by default). As GNOME updates come in the next few months I expect quite a few amount of users will experience this bug.

That's just my opinion. Thank you for the fix and information. Problem solved!

phongvcao commented 9 years ago

Of course, we should set g:togglecursor_default to 'blinking_block' by default out of the box only on VTE4002+, because some terminals may not support blinking.

jszakmeister commented 9 years ago

You can keep the g:togglecursor_disable_default_init variable in the next vim-togglecursor release or you can keep it. Also, I think we should set g:togglecursor_default to 'blinking_block' by default in the plugin so users that still uses 0.40.2 won't have the problem and also mention this in the doc.

Just so I understand correctly: are you saying that you don't need the g:togglecursor_disable_default_init any more?

Also, I don't want to set that default for everyone. Many terminals use a non-blinking block cursor be default, so I think the current default is better. Perhaps there's something that can be done for affected versions of VTE 0.40.2 though. I'll have to think about it a bit more.

phongvcao commented 9 years ago

@jszakmeister I don't need the g:togglecursor_disable_default_init anymore. :+1:

If you don't want to make 'blinking_block' the current default then you should mention this in the doc, that with VTE4002 and above, if the cursor is not showing, users can try to set g:togglecursor_default to the blink_* ones.

I don't think it is very easy to alter the behavior of VTE4002 because the problem lays in VTE's underlying code. We can only create some sort of small hacks though.

jszakmeister commented 9 years ago

So, after thinking about this more, the intent of the plugin was to make terminal vim more like gvim, which does use blinking cursors by default. So I've changed the plugin to prefer blinking versions of all cursors, and fallback as necessary for various terminals. I also changed the default of g:togglecursor_leave to be a blinking block under VTE, and a plain block cursor otherwise--to match the defaults for most terminals and VTE. The new version has been tagged as v0.5.0.

I think I'm going to leave in g:togglecursor_disable_default_init for now, just in case someone else needs it, but the defaults should work better for VTE 0.40.2 users now.

phongvcao commented 9 years ago

@jszakmeister sounds very good to me :+1: