terminal: Vim cursor can't be changed

Environment

Windows build number: 10.0.19041.21
Windows Terminal version : 0.8.10091.0

Steps to reproduce

  • Open vim
  • Set options:
set background=dark
colorscheme desert
highlight Cursor guifg=white guibg=black

Expected behavior

In old terminal you know when you’re in normal mode

image

Actual behavior

Cursor can’t be changed, so it’s hard to work

image

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 12
  • Comments: 33 (8 by maintainers)

Commits related to this issue

Most upvoted comments

It worked, thanks!

I’m leaving this code for the lost souls that might search it

How to change cursor in vim in windows terminal

Works for vim in wsl (not powershell)

In this example, normal mode is a block, insert mode is a vertical bar

  " Cursor in terminal
  " https://vim.fandom.com/wiki/Configuring_the_cursor
  " 1 or 0 -> blinking block
  " 2 solid block
  " 3 -> blinking underscore
  " 4 solid underscore
  " Recent versions of xterm (282 or above) also support
  " 5 -> blinking vertical bar
  " 6 -> solid vertical bar
    
  if &term =~ '^xterm'
    " normal mode
    let &t_EI .= "\<Esc>[0 q"
    " insert mode
    let &t_SI .= "\<Esc>[6 q"
  endif

Ah, it looks like the documentation here is confusing. The guicursor settings are for GUI vim (gvim, xvim, mvim, etc.). You’ll want the ones at the bottom that mention xterm and rxvt, with the t_SI and t_EI control sequences.

There may be an issue in the regular expression. My configuration looks like this:

if &term =~ '^xterm'
  " solid underscore
  let &t_SI .= "\<Esc>[4 q"
  " solid block
  let &t_EI .= "\<Esc>[2 q"
  " 1 or 0 -> blinking block
  " 3 -> blinking underscore
  " Recent versions of xterm (282 or above) also support
  " 5 -> blinking vertical bar
  " 6 -> solid vertical bar
endif

I should note that for whatever reason using option 0 does not give blinking block in wsl and still outputs a vertical bar. So replace let &t_EI .= "\e[0 q" by let &t_EI .= "\e[1 q" and similarly when you exit vim. Here is the snippet that works for me.

if &term =~ '^xterm'
	" Cursor in terminal:
	" Link: https://vim.fandom.com/wiki/Configuring_the_cursor
	" 0 -> blinking block not working in wsl
	" 1 -> blinking block
	" 2 -> solid block
	" 3 -> blinking underscore
	" 4 -> solid underscore
	" Recent versions of xterm (282 or above) also support
	" 5 -> blinking vertical bar
	" 6 -> solid vertical bar

	" normal mode
	let &t_EI .= "\e[1 q" 	
	" insert mode
	let &t_SI .= "\e[5 q"	

	augroup windows_term
		autocmd!
		autocmd VimEnter * silent !echo -ne "\e[1 q" 
		autocmd VimLeave * silent !echo -ne "\e[5 q" 
	augroup END
endif

Closing this as solved is kind of frustrating, as the original issue was reported for Powershell sessions, while the “solution is” basically, “don’t use powershell, use linux”, which isn’t reaaally the answer I’d hope for. Ideally running vim in a powershell session would be comfortable without having to use WSL.

so this is the best solution:

if &term =~ '^xterm'
  " enter vim
  autocmd VimEnter * silent !echo -ne "\e[3 q"
  " oherwise
  let &t_EI .= "\<Esc>[3 q"
  " insert mode
  let &t_SI .= "\<Esc>[5 q"
  " 1 or 0 -> blinking block
  " 2 -> solid block
  " 3 -> blinking underscore
  " 4 -> solid underscore
  " Recent versions of xterm (282 or above) also support
  " 5 -> blinking vertical bar
  " 6 -> solid vertical bar
  " leave vim
  autocmd VimLeave * silent !echo -ne "\e[5 q"
endif

So the config posted by @eduardoarandah works in vim but appears to have the side effect of leaving the cursor in whatever state it was when Vim exited (most likely a block in normal mode), so the terminal ends up with a block cursor rather than the default.

(This is in ubuntu running in WSL)

I’ve been looking for the setting for Vim for Windows (cmd.exe and powershell version) but cannot find them. Could somebody tell me?

The use case permutations are very vast and most posters report on one instance only. Everybody posting solution is driven by good intention. However, please do bother to state what environment the solution you offer pertains to to save a brother an hour.

Solution

The following solution pertains to:

  • Windows OS
  • vim, not neovim
  • text interface, not gvim
  • windows process (vim.exe)
  • vim started with powershell 7.2.6, not cmd. Powershell standalone or through Windows Terminal (known problem for the latter, mentioned below)
  • assuming powershell cursor is vertical bar blinking
  • assumming the cursors you want in vim are normal:block, insert:vertical bar, replace:horizontal bar. None blinking
  • assumming Vim 9.0.0392 install, vim.exe available under C:\Program Files\Vim\vim90\vim.exe
  • assumming your username is Elmo and your home directory is C:\Users\Elmo

Create a file called .vimrc in your home directory C:\Users\Elmo with following content

let &t_SI = "\<Esc>[6 q"
let &t_SR = "\<Esc>[4 q"
let &t_EI = "\<Esc>[2 q"

6:vert-bar,4:underscore,2:block are the non-blinking cursors for the three vim modes.

This will make vim use the mode dependent cursors. Problem: upon exiting vim, the cursor you end up with in the Powershell prompt is block non-blinking. If that’s not what you want, edit your profile

notepad $profile or edit C:\Users\Elmo\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

Add the following function

function vim {
    & "C:\Program Files\Vim\vim90\vim.exe" $args && echo "`e[5 q"
}

That echo is a command to tell powershell to set the cursor to 5:blinking-vertical-bar in this case. Save. Exit.

Known Problem

When starting vim from Powershell through Windows Terminal the initial cursor should be block, non-blinking, however it’s the vertical bar blinking (whatever came from the prompt). Once you change modes, the expected vim cursors will be used. That is not the case if you use the standalone Powershell app.

Already Tried, Don’t Bother

Using the VimLeave event in .vimrc to execute set cursor

autocmd VimLeave * :!echo "`e[5 q"

Like to mark this useful.

I had the same problem @lllama and @heaths had (cursor stuck as block in terminal). The code below from stackoverflow allowed me to recover the cursor without modifying my .bashrc as @dennisjlee suggested.

autocmd VimLeave * silent !echo -ne "\e[6 q"

To follow up on @robertsk50 , it looks like when we enter vim for the first time, the cursor shows a vertical bar instead of block even though we enter in normal mode. Luckily, the link in @robertsk50 provides a solution:

autocmd VimEnter * silent !echo -ne "\e[0 q"

Here’s a workaround for resetting the cursor to a vertical bar after exiting vim.

Add this to your .bashrc so that it will set the cursor to a blinking bar every time it renders a prompt. (Other styles are listed in this StackOverflow answer)

export PROMPT_COMMAND='echo -e -n "\x1b[\x35 q"'

For me also none of the solutions work. This is the last issue I have with Vim on Windows (and well maybe that pasting from clipboard is not in line).

I encountered the problem that an escape sequence is output at starting Vim. I also encountered the problem that the terminal cursor even changed after suspending Vim with Ctrl+Z. I solved these problems by adding the following to previous solutions.

" HACK: Work around the problem that an escape sequence is output at startup.
"       https://vi.stackexchange.com/questions/19748
autocmd VimEnter * normal :startinsert
" suspend and resume vim
nnoremap <silent> <C-z> :execute 'silent !echo -en "\e[5 q"'<CR>:suspend<Bar>:execute 'silent !echo -en "\e[0 q"'<CR>

Confirmed what @lllama is seeing: when I exit vim from normal mode, the Terminal cursor is not a block cursor.

This works fine in conhost consoles (cmd, powershell, pwsh).

I had a specific setting for Command Prompt in Windows Terminal to use a Bar cursor. With this set the cursor in Vim for Windows was also always a vertical bar. I have now changed that setting to ‘Filled Box’. Now while the cursor is a flashing square block in the shell, in Vim for Windows it’s the same in Normal Mode and in Insert Mode it has changed to a flashing underscore. Not quite what it is set as (both modes flashing and underscore instead of vertical bar in Insert Mode), but at least there is a difference between Normal and Insert modes. This will do, as I don’t often use this version of vim anyway.

According to the Vim documentation, it should be applied after executing set termguicolors or set t_Co=256:

let &t_SI = "\e[6 q"
let &t_SR = "\e[4 q"
let &t_EI = "\e[2 q"
" when entering vim
let &t_ti ..= "\e[2 q"
" when leaving vim
let &t_te ..= "\e[5 q"

@iovuio Thank you for this information, but adding the following to my .vimrc doesn’t change the behavior of the cursor on Vim for Windows (run from cmd.exe or powershell).

let &t_SI = "\<Esc>[6 q"
let &t_SR = "\<Esc>[4 q"
let &t_EI = "\<Esc>[2 q"

It does change the cursor on Vim on Linux/WSL though (I had already had it set).

I just thought that my setup may differ because I use clink. Maybe this is having an effect? I can’t think of any reason why this setting wouldn’t work for me if it is the correct one to be used on Vim for Windows when using Windows Terminal.

The solution pasted by @gao-lex does not work for me, is it only for WSL?

I’m using PowerShell and cmd.exe: Windows version: Windows 10 Version 2004 (OS Build 19041.630) Windows Terminal version: Version: 1.4.3243.0 Vim is the official one for windows: 8.2, and I’d like to run vim inside the console, by typing vim.bat FILE

In PowerShell or cmd.exe, normal mode cursor is block, insert mode cursor is underscore. But even when I paste the content to my .vimrc, the cursor inside Windows Terminal is always a vertical bar. This is very confusing in Vim normal mode.

I can be sure that .vimrc is correctly located, and sourced by Vim when it launches.

This worked for me, I’m using PowerShell: https://github.com/microsoft/terminal/issues/68#issuecomment-418438517

@eduardoarandah

Environment

Windows build number: 10.0.19041.21
Windows Terminal version : 0.8.10091.0

Steps to reproduce

* Open vim

* Set options:
set background=dark
colorscheme desert
highlight Cursor guifg=white guibg=black

Expected behavior

In old terminal you know when you’re in normal mode

image

Actual behavior

Cursor can’t be changed, so it’s hard to work

image

I had the same issue. The easiest workaround is to set cursorShape under required profile inside settings.json. See this.

However, this will affect the entire profile instead of just vim.

The solution pasted by @gao-lex does not work for me, is it only for WSL?

I’m using PowerShell and cmd.exe: Windows version: Windows 10 Version 2004 (OS Build 19041.630) Windows Terminal version: Version: 1.4.3243.0 Vim is the official one for windows: 8.2, and I’d like to run vim inside the console, by typing vim.bat FILE

In PowerShell or cmd.exe, normal mode cursor is block, insert mode cursor is underscore. But even when I paste the content to my .vimrc, the cursor inside Windows Terminal is always a vertical bar. This is very confusing in Vim normal mode.

I can be sure that .vimrc is correctly located, and sourced by Vim when it launches.