Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Swap iTerm2 cursors in vim insert mode when using tmux
" tmux will only forward escape sequences to the terminal if surrounded by a DCS sequence
" http://sourceforge.net/mailarchive/forum.php?thread_name=AANLkTinkbdoZ8eNR1X2UobLTeww1jFrvfJxTMfKSq-L%2B%40mail.gmail.com&forum_name=tmux-users
if exists('$TMUX')
let &t_SI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=1\x7\<Esc>\\"
let &t_EI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=0\x7\<Esc>\\"
else
let &t_SI = "\<Esc>]50;CursorShape=1\x7"
let &t_EI = "\<Esc>]50;CursorShape=0\x7"
endif

forrest commented Mar 15, 2012

Thanks!

You, sir, are a gent and a scholar :)

this makes console vim so much better :)

jgeiger commented Jun 27, 2012

Just found this, thanks.

This works great for me if I first enter insert mode after opening a file.

But if I start editing in command mode it seems to really disturb my terminal, forcing me to :q! and open the file again.

Is anyone seeing this behavior and if so is there something I can do to prevent this besides always going into insert mode first?

Using tmux 1.6, iTerm2 Build 1.0.0.20120203 on Mountain Lion

Just a follow-up -- it seems to be an interaction with another part of my vim config as running vim -u minimal.vimrc where the above is the only thing in the vimrc works. However, I found an alternative method as follows that works without disabling my other configuration:

" switch cursor from block in insert mode
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" This enables iterm cursor changes from vim. In .tmux.conf you'll need:
" set-option -g terminal-overrides '*88col*:colors=88,*256col*:colors=256,xterm*:XT:Ms=\E]52;%p1%s;%p2%s\007:Cc=\E]12;%p1%s\007:Cr=\E]112\007:Cs=\E]50;CursorShape=%?%p1%{3}%<%t%{0}%e%p1%{2}%-%;%d\007'
"
" Source: https://github.com/Casecommons/casecommons_workstation/blob/master/templates/default/dot_tmux.conf.erb
"         https://github.com/Casecommons/vim-config/blob/master/init/tmux.vim
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
if exists('$ITERM_PROFILE')
  if exists('$TMUX')
    let &t_SI = "\<Esc>[3 q"
    let &t_EI = "\<Esc>[0 q"
  else
    let &t_SI = "\<Esc>]50;CursorShape=1\x7"
    let &t_EI = "\<Esc>]50;CursorShape=0\x7"
  endif
end

source: https://github.com/aaronjensen/vimfiles/blob/master/vimrc#L443-458

I have similar problem. My VIM start have problems with typing brackets ( ).

sheerun commented Jan 14, 2013

Thank you

Thanks!

iterion commented Apr 15, 2013

Oddly, this didn't work for me, but this plugin did. And, It seems to be doing roughly the same thing:
https://github.com/sjl/vitality.vim/

Is there any way to eliminate the lag going from insert mode to command mode? For me it's instant going into insert mode, but lags when coming out.

thanks a lot!

caipre commented Jan 24, 2014

@AdamBrodzinski: tmux has a delay for escape sequences. Try set-option -g escape-time 0.

rafi commented Jan 26, 2014

urxvt

/~.vimrc

" Changing cursor shape per mode
" 1 or 0 -> blinking block
" 2 -> solid block
" 3 -> blinking underscore
" 4 -> solid underscore
if exists('$TMUX')
    " tmux will only forward escape sequences to the terminal if surrounded by a DCS sequence
    let &t_SI .= "\<Esc>Ptmux;\<Esc>\<Esc>[4 q\<Esc>\\"
    let &t_EI .= "\<Esc>Ptmux;\<Esc>\<Esc>[2 q\<Esc>\\"
    autocmd VimLeave * silent !echo -ne "\033Ptmux;\033\033[0 q\033\\"
else
    let &t_SI .= "\<Esc>[4 q"
    let &t_EI .= "\<Esc>[2 q"
    autocmd VimLeave * silent !echo -ne "\033[0 q"
endif

~/.tmux.conf

set-option -sg escape-time 30

fwiw the much better way to do this is use tmux's terminal overrides to send the cursor changes on a per pane basis rather than for the entire terminal. It's a little bit more complicated, but it works much better:

This assumes tmux 1.9+, some things changed recently.

In your tmux.conf (explanation, but for older tmux)

set-option -g terminal-overrides '*88col*:colors=88,*256col*:colors=256,xterm*:XT:Ms=\E]52;%p1%s;%p2%s\007:Cs=\E]12;%p1%s\007:Cr=\E]112\007:Ss=\E]50;CursorShape=%?%p1%{3}%<%t%{0}%e%p1%{2}%-%;%d\007'

And in .vimrc:

if exists('$ITERM_PROFILE')
  if exists('$TMUX')
    let &t_SI = "\<Esc>[3 q"
    let &t_EI = "\<Esc>[0 q"
  else
    let &t_SI = "\<Esc>]50;CursorShape=1\x7"
    let &t_EI = "\<Esc>]50;CursorShape=0\x7"
  endif
end

sblask commented Dec 2, 2014

@aaronjensen I just checked your explanation and wondered whether it would not have been possible to use the parameter directly (without if then else). So basically use something like \E]50;CursorShape=%p1%d\007 combined with:

let &t_SI = "\<Esc>[1 q"
let &t_SI = "\<Esc>[0 q"

Is there any good tutorial/documentation of this? The terminfo manpage is not great to understand what's going on...

@sblask, I just saw this and tried it out. It didn't work, but I may have done something wrong, though I vaguely remember having tried it in the past. TBH that whole thing is such a dark magic incantation that I did so long ago I'd just assume not touch it while it works 😉 The other problem w/ going [1 and [0 directly is that [3 and [0 actually work w/o the terminfo override, it's just a block and an underscore which is better than nothing.

oranki commented May 30, 2015

This works for both setting cursor colour and style per window/pane:

set -g terminal-overrides '*88col*:colors=88,*256col*:colors=256,xterm*:XT:Cs=\E]Pl%p1%s\E\\:Ss=\E]50;CursorShape=%d\007'

for setting cursor color:

printf '\033]12;%s\007' "rrggbb"

for setting cursor style:

printf '\033[%s q' "n"

rrggbb is 2-digit hex triplet specifying an RGB value, and n is digit 0, 1 or 2 (block, vertical bar, underline)

oranki commented May 31, 2015

This seemed to be a fairly common woe and it took me much too long to figure it out on my own, so I documented the problems and solutions with changing cursor color and style:

http://ass.kameli.org/cursor_tricks.html

@caipre, this didn't work for me:

@AdamBrodzinski: tmux has a delay for escape sequences. Try set-option -g escape-time 0.

@AdamBrodzinski, did you figure it out?

Thanks.

@ghost

ghost commented Aug 7, 2015

Exactly what I was looking for! Thank you for you help!

907th commented Nov 9, 2015

This awesome plugin handles cursor shapes in different situations

Adding this to my ~/.zshrc (or ~/.bashrc) fixed it using iterm (I'm not using tmux, also, I'm using neovim):

# Preserve Insert Cursor shape in nvim using iterm
export NVIM_TUI_ENABLE_CURSOR_SHAPE=1

mcmire commented Dec 1, 2015

+1 on using vim-togglecursor. Worked perfectly.

breerly commented Feb 2, 2016

+1 to NVIM_TUI_ENABLE_CURSOR_SHAPE - just add it to your ~/.config/nvim/init.vim like so:

:let $NVIM_TUI_ENABLE_CURSOR_SHAPE=1

breerly commented Feb 2, 2016

Wondering if the same thing can be achieved in ZSH...

I have something working in zsh/iterm, but not in tmux:

function zle-keymap-select zle-line-init
{
    case $KEYMAP in
        vicmd) # block cursor
            print -n -- "\E]50;CursorShape=0\C-G"
            ;;
        viins|main) # line cursor
            print -n -- "\E]50;CursorShape=1\C-G"
            fi
            ;;
    esac
    zle reset-prompt
    zle -R
}
function zle-line-finish
{
    print -n -- "\E]50;CursorShape=0\C-G"
}
zle -N zle-line-init
zle -N zle-line-finish
zle -N zle-keymap-select

Any help getting the above working in TMUX/ZSH would be greatly appreciated.

jcorbin commented Feb 2, 2016

@breerly here's an adapted copy of your functions that work under tmux using the DCS escape mentioned by OP: https://github.com/jcorbin/home/blob/master/.zsh/rc.d/vi-mode-cursor

breerly commented Feb 2, 2016

@jcorbin looks like it works, I'll try it on for awhile 👍

silesky commented Aug 17, 2016

@breerly here's an adapted copy of your functions that work under tmux using the DCS escape mentioned by OP: https://github.com/jcorbin/home/blob/master/.zsh/rc.d/vi-mode-cursor

@jcorbin ^ works on osx w/ zshell + tmux! thanks a lot! 👍

silesky commented Aug 19, 2016

@jcorbin I spoke too soon: it works well until you open up another pane. Switching between the two means that the cursor get's carried along, even if the pane you're switching to is in command mode. This leads to situations where you get the block cursor but you're actually in insert mode, and vice versa.

dlee commented Dec 8, 2016

@silesky, were you able to find a workaround for pane switching?

Thanks @jcorbin

nanoguo commented Feb 7, 2017

thanks

Thanks!

How can I get this working in the case of running ssh and opening vim on a remote machine from within a local tmux session?

https://stackoverflow.com/questions/42377945/vim-adding-cursorshape-support-over-tmux-ssh

orklann commented Apr 17, 2017

@AdamBrodzinski
Try adding this line to your .vimrc to get rid of the delay while switching between normal mode and insert mode

set timeoutlen=1000 ttimeoutlen=0

Thanks!

We should all get together for a drink some day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment