Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vim cursor can't be changed #4335

Closed
eduardoarandah opened this issue Jan 22, 2020 · 33 comments
Closed

Vim cursor can't be changed #4335

eduardoarandah opened this issue Jan 22, 2020 · 33 comments
Labels
Issue-Question For questions or discussion Needs-Tag-Fix Doesn't match tag requirements Resolution-Answered Related to questions that have been answered

Comments

@eduardoarandah
Copy link

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

@ghost ghost added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Jan 22, 2020
@DHowett-MSFT
Copy link
Contributor

It appears that Vim doesn't do this unless it's been explicitly configured to do so: vimwiki/Configuring the cursor. When I set the options for changing the cursor shape, it works properly.

image

image

Can you confirm the part of your vim config that exchanges the cursor options?

@DHowett-MSFT DHowett-MSFT added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Jan 22, 2020
@DHowett-MSFT
Copy link
Contributor

For what it's worth, I can't reproduce this issue even outside of Windows Terminal.

@eduardoarandah
Copy link
Author

  • I removed all my .vimrc confguration
  • copied the example config
  • closed vim and opened again in bash and powershell

Bash

image

Powershell

image

Vim information

In case something's wrong with vim:

:version output
image

In the old terminal

in the old terminal C:\Windows\System32\wsl.exe cursor is like this:

image

What other info might be useful?

@ghost ghost added Needs-Attention The core contributors need to come back around and look at this ASAP. and removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something labels Jan 22, 2020
@DHowett-MSFT
Copy link
Contributor

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

@DHowett-MSFT DHowett-MSFT added Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something and removed Needs-Attention The core contributors need to come back around and look at this ASAP. labels Jan 22, 2020
@DHowett-MSFT
Copy link
Contributor

And lastly, Windows vim (the one you're using from powershell) uses a different system to set the cursor. I think there's an open duplicate bug for that one not working 100% with Terminal. 😄

@eduardoarandah
Copy link
Author

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

@ghost ghost added Needs-Attention The core contributors need to come back around and look at this ASAP. and removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something labels Jan 22, 2020
@DHowett-MSFT
Copy link
Contributor

Thanks for following up! I'm going to close this one since it's answered.

@DHowett-MSFT DHowett-MSFT added Issue-Question For questions or discussion Resolution-Answered Related to questions that have been answered and removed Needs-Attention The core contributors need to come back around and look at this ASAP. Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting labels Jan 22, 2020
@lllama
Copy link

lllama commented Feb 26, 2020

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)

@heaths
Copy link
Member

heaths commented Mar 9, 2020

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).

@dennisjlee
Copy link

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"'

@chadmoore
Copy link

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.

@heaths
Copy link
Member

heaths commented Aug 5, 2020

@chadmoore while I agree with you, just wanted to add that you can do something similar in PowerShell if you overwrite your prompt function, but then that means taking responsibility for what it outputs.

The default is:

"PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) "

Based on https://docs.microsoft.com/windows/console/console-virtual-terminal-sequences#simple-cursor-positioning and using `e (PowerShell Core; see about_Special_Characters), something like this should work in your $profile:

function prompt {
"PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) `e[?12h"
}

I say should, but in testing the cursor didn't blink in Windows Terminal. Other cursor sequences worked, so this appears to be a bug in Windows Terminal.

@zadjii-msft
Copy link
Member

@chadmoore for the record, this thread was specifically tracking "setting the cursor in the WSL vim", not vim.exe. As @DHowett-MSFT mentioned above:

And lastly, Windows vim (the one you're using from powershell) uses a different system to set the cursor. I think there's an open duplicate bug for that one not working 100% with Terminal. 😄

I'm actually not sure that there's a duplicate for that issue, since I couldn't find it from some trivial searching. That should probably be moved out to it's own issue (which will likely end up as a bug on vim.exe)

@robertsk50
Copy link

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"

@gao-lex
Copy link

gao-lex commented Oct 10, 2020

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

@nickjj
Copy link

nickjj commented Oct 18, 2020

To follow up on this is there any way to have Vim use the MS Terminal vintage thick underline instead of the thin underline?

In practice I've found the block cursor in Vim with the MS Terminal to be not usable because the MS Terminal doesn't invert the color of the character under the block cursor so you often get into situations where you can't read the character under the block.

For now I've been using the vintage thick underline cursor but I haven't been able to find a code to set that. The thin underline is a bit too hard to see, especially when recording video tutorials.

@ngmy
Copy link

ngmy commented Oct 23, 2020

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>

@zeroxia
Copy link

zeroxia commented Dec 7, 2020

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.

@jclsn
Copy link

jclsn commented Dec 10, 2020

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).

@lk-hang
Copy link

lk-hang commented Jan 1, 2021

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

@KalleOlaviNiemitalo
Copy link

I should note that for whatever reason using option 0 does not give blinking block in wsl and still outputs a vertical bar.

There was a long discussion about cursor style 0 vs. 1 vs. empty, in #1604.

@jclsn
Copy link

jclsn commented Jan 2, 2021

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.

Doesn't work for me :(

@Apreche
Copy link

Apreche commented Jan 5, 2021

Sometimes I use wsl with VcXsrv, and that means everything works fine. Sometimes I use wsl inside of Windows Terminal. It's the same vimrc either way. I can't use if &term =~ '^xterm' to enable the cursor fix because it's always true. That will mess up my cursor that works perfectly when using a Linux terminal emulator under VcXsrv. I need some way to detect Windows Terminal specifically. Maybe is there a way to put an environment variable like WINDOWS_TERMINAL=true or something like that?

My vim has a light color scheme, and it fails to change the color or shape of the Windows terminal cursor. So the cursor becomes literally 100% invisible when using vim. The situation is pretty dire.

@CRTejaswi
Copy link

CRTejaswi commented Jan 18, 2021

@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.

@devhashtag
Copy link

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:
#68 (comment)

neninja added a commit to neninja/dotfiles that referenced this issue Jun 1, 2021
PrashanthaTP added a commit to PrashanthaTP/dotfiles that referenced this issue Aug 21, 2021
(Issue) cursor does not reset on exiting from vim
    - microsoft/terminal#4335

(Issue : #5)
PrashanthaTP added a commit to PrashanthaTP/dotfiles that referenced this issue Aug 21, 2021
(Issue) cursor does not reset on exiting from vim
    - microsoft/terminal#4335
PrashanthaTP added a commit to PrashanthaTP/dotfiles that referenced this issue Aug 29, 2021
why:
to distinguish between command and normal modes of vi mode in
powershell

how:
using VimLeave event and guicursor option

misc:
see :help guicursor

links:
- neovim/neovim#4867
- microsoft/terminal#4335

tags:
cursor,cursor-shape

fixes #5
PrashanthaTP added a commit to PrashanthaTP/dotfiles that referenced this issue Aug 29, 2021
why:
to distinguish between command and normal modes of vi mode in
powershell

how:
using VimLeave event and guicursor option

misc:
see :help guicursor

links:
- neovim/neovim#4867
- microsoft/terminal#4335

tags:
cursor,cursor-shape

fixes #5
@younger-1
Copy link

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: #68 (comment)

It works, but vim does not attempt to restore cursor shape on exit.
neovim could restore cursor shape on exit by autocmd VimLeave * set guicursor=a:ver25.
How about vim?

@ABD-01
Copy link

ABD-01 commented Jun 17, 2022

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

@gao-lex Thanks a Lot for this One 🫂

@eggbean
Copy link

eggbean commented Sep 6, 2022

And lastly, Windows vim (the one you're using from powershell) uses a different system to set the cursor. I think there's an open duplicate bug for that one not working 100% with Terminal. 😄

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

I have this set for Vim on Linux/WSL, and it works, but not on Windows Terminal cmd.exe or powershell.

" Change cursor depending on mode, like in nvim
let &t_SI = "\<Esc>[6 q"
let &t_SR = "\<Esc>[4 q"
let &t_EI = "\<Esc>[2 q"

@parml
Copy link

parml commented Sep 7, 2022

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.

@eggbean
Copy link

eggbean commented Sep 8, 2022

@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.

@eggbean
Copy link

eggbean commented Sep 8, 2022

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.

@haakuya
Copy link

haakuya commented Feb 18, 2024

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"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Question For questions or discussion Needs-Tag-Fix Doesn't match tag requirements Resolution-Answered Related to questions that have been answered
Projects
None yet
Development

No branches or pull requests