Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vim: Adding cursorshape support over tmux + ssh

I like to change the cursor shape when in insert mode, but I'm having trouble configuring this correctly when ssh-ing through tmux. Here are my findings:

  • When I ssh outside of a local tmux session and I open Vim outside of a remote tmux session, cursor shape works (vertical bar in insert mode).
  • When I ssh outside of a local tmux session and I open Vim inside a remote tmux session, cursor shape works.
  • When I ssh inside of a local tmux session and I open Vim outside of a remote tmux session, cursor shape is broken (block in insert mode).
  • When I ssh inside of a local tmux session and I open Vim inside a remote tmux session (nested tmux; my preferred setup), cursor shape is broken.
  • When I open Vim locally inside of a local tmux session, cursorshape works (that is, something is going wrong with the combination of tmux and ssh; local tmux is fine locally).

My local machine is running OS X Sierra and my remote machine is CentOS 7. I think these are all the relevant dotfile settings, will post others if requested:

=== ~/.tmux.conf (on both local and remote machines) ===

set-option -g default-terminal "screen-256color"
set-option -g xterm-keys on

=== ~/.vimrc (on remote machine) ===

if empty($TMUX)
  let &t_SI = "\<Esc>]50;CursorShape=1\x7" " Vertical bar in insert mode
  let &t_EI = "\<Esc>]50;CursorShape=0\x7" " Block in normal mode
else
  let &t_SI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=1\x7\<Esc>\\"
  let &t_EI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=0\x7\<Esc>\\"
endif

if &term =~ '^screen'
  " tmux will send xterm-style keys when its xterm-keys option is on
  execute "set <xUp>=\e[1;*A"
  execute "set <xDown>=\e[1;*B"
  execute "set <xRight>=\e[1;*C"
  execute "set <xLeft>=\e[1;*D"
endif

As a side note, cursor shape never seems to work with mosh, in any of these cases. I think this is a mosh limitation, but if someone has a way of getting it to work with mosh that would be especially helpful.

like image 944
Kvass Avatar asked Feb 21 '17 21:02

Kvass


People also ask

How to change cursor shape for multiple tabs in Vim?

In multiple Vim tabs, cursor shape changes for all tabs, which agrees with the --INSERT--, --REPLACE-- or empty label in the command-line area. (FWIW I don't use any of those terminal multiplexers.)

How can I use tmux in multiple terminals?

In theory, the escape sequence could be used for tmux in any terminal. NOTE: These do not work with the default terminal. This works with multiple tabs and windows. Set IBeam shape in insert mode, underline shape in replace mode and block shape in normal mode. This makes your cursor change in all open terminals.

How to disable cursor blinking in Vim_use?

Add the following into .vimrc Above snippet disables cursor blinking. If you want cursor blink, just decrement all the 3 numbers above 2,4,6 by one each. VTE compatible terminals includes mate-terminal 1.18.1. In a vim_use thread on 31 March 2009, Matt Wozniski made the following comments :

How to change the shape of the cursor in different modes?

To change the shape of the cursor in different modes, you can add the following into your vimrc: In theory, the escape sequence could be used for tmux in any terminal. NOTE: These do not work with the default terminal.


1 Answers

First, you should use other escape codes. iTerm2 supports the xterm DECSCUSR extension to set the cursor shape, so there is no need to use proprietary escape codes. These three lines tell vim to use the xterm codes:

set t_SI=^[[6\ q
set t_SR=^[[4\ q
set t_EI=^[[2\ q

Important note: ^[ is one character. You can enter it by pressing Ctrl-V and then escape.

I have added t_SR to change the cursor in replace mode. tmux is aware of these cursor shape codes so you don't need to check if you are within a tmux session or not. In addition, tmux automatically keeps track of the cursor shape for different panes (which is not possible with proprietary codes). These codes also work with many other terminal emulators, for example all VTE based ones (gnome terminal, tilda, xfce terminal, ...).

After that, vim in your local tmux session should work as expected but you need some extra work to get it running over ssh. By default, tmux only accepts cursor shape changes if the outer terminal is xterm (or something similar like xterm-256color). On your local machine, everything is fine since iTerm2 is your outer terminal and sets $TERM to xterm-256color. When using ssh your local tmux session becomes the outer terminal and sets $TERM to screen-256color. Therefore, you have to tell tmux on your remote machine to pass cursor shape escape codes when a screen based terminal emulator is connected. For that, you can use the terminal-overrides option:

set -ga terminal-overrides ",screen*:Ss=^[[%p1%d q:Se=^[[2 q"

^[ is one character again.

Restart your tmux sessions and cursor shapes should change on both your local and your remote machine.

like image 146
IngoMeyer Avatar answered Oct 02 '22 17:10

IngoMeyer