Cursor shape in the console

138 views
Skip to first unread message

Tony Mechelynck

unread,
May 26, 2019, 6:39:21 PM5/26/19
to vim_use
In konsole 18.12.3, in a Big build of Vim (currently 8.1.1407) with
'ttybuiltin' on and 'term' set to "xterm-256color", ":set termcap"
tells me that t_SI, t_SR and t_EI are all unset, which explains why in
Console mode (i.e. invoked as "vim", "view", "vimdiff" etc., not
"gvim", "gview", "gvimdiff" etc.) the cursor never changes, it is
always a block. Is it possible (and how) to make the cursor become a
vertical bar when in Insert mode and an underscore in Replace mode
(while remaining a block in Normal mode)? ":help termcap-cursor-shape"
(which coincides with ":help termcap-cursor-color") actually gives an
example about how to change the cursor colour but not its shape but it
hints at how to do it… if only I knew the correct xterm bytecode to
make the cursor a block, a vertical bar or an underscore.

BTW, I couldn't find the required info in "man xterm" except maybe at
the very end where it says that xterm control sequences are described
by the file http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
…where I couldn't find where to look for the desired information. I
guess I've been corrupted by the clear and full online help provided
by Vim, I get lost in the ordinary, badly-written and confusing
manpages. ;-)

Best regards,
Tony.

Rob Foehl

unread,
May 28, 2019, 12:36:06 AM5/28/19
to vim_use
On Mon, 27 May 2019, Tony Mechelynck wrote:

> if only I knew the correct xterm bytecode to
> make the cursor a block, a vertical bar or an underscore.

Hi Tony,

Here's what I use for real xterm, and covering a pretty good span of Vim
releases (including those predating t_SR):

if has('cursorshape') && &term =~ '^xterm'
" Use a bar cursor in Insert mode

let &t_SI = "\<Esc>[6 q"

" Use a block cursor in Normal mode, and restore at Vim exit

let &t_EI = "\<Esc>[2 q"
let &t_te = &t_EI . substitute(&t_te, '\C' . &t_EI, '', 'g')

" Use t_SR for an underline cursor in Replace mode, if available (Vim
" 7.4.687 or newer); otherwise, change the value of t_SI when entering
" Insert or Replace mode, as appropriate.

if exists('&t_SR')
let &t_SR = "\<Esc>[4 q"
else
autocmd vimrc InsertChange,InsertEnter *
\ if v:insertmode == 'r' || v:insertmode == 'v' |
\ let &t_SI = "\<Esc>[4 q" |
\ else |
\ let &t_SI = "\<Esc>[6 q" |
\ endif
endif
endif


Those are the non-blinking variants in xterm. You'll probably need to
adjust that for non-xterm; there's a Vim wiki page[1] that suggests other
sequences for Konsole. Also note the &term test at the beginning.

-Rob


[1] https://vim.fandom.com/wiki/Change_cursor_shape_in_different_modes

Tony Mechelynck

unread,
May 28, 2019, 1:41:35 PM5/28/19
to vim_use
Thanks, I'll try those sequences. For the Linux non-X11 console (where
$TERM is "linux") it's probably hopeless indeed, and I'll add an "if
!has("gui_running") around the whole stuff because in gvim it already
works. It would probably still work without it, because starting the
GUI sets 'term' to "builtin_gui" and changes the whole termcap, but I
don't need to add unnecessary processing for the short time between
sourcing the vimrc and starting the GUI.

If the codes for "real xterm" don't work in konsole, AFAIK I'll have
to place the whole stuff at the TermResponse event (which is fired in
both), because in konsole I have a $TERM starting with xterm but a
different v:termresponse (ESC [>0;115;0c in konsole but ESC
[>41;330;0c in xterm, IOW konsole tries to emulate xterm in vt100 but
I don't know what "terminal type 41" means in a real xterm). I notice
that in both cases, and contrary to what is said at ":help
v:termresponse", the first character after ESC [ is a greater-than
sign which is none of a digit, semicolon or period.

To restore the block cursor at Vim exit I suppose it is enough to use
(not yet tested)
au VimLeave * exe "normal \<C-\\>\<C-N>"
to put Vim in Normal mode; however "leaving Vim normally" is by means
of a :qa or :xa command, which is started from Normal mode and leaves
Vim in it so that autocommand would only matter for "abnormal exits".

Best regards,
Tony.

Tony Mechelynck

unread,
May 28, 2019, 4:00:27 PM5/28/19
to vim_use
The following works in xterm. I'm investigating further for konsole:

" try to change cursor shape in Console mode in xterm-like terminals
" ESC [2 q = █ (Normal)
" ESC [4 q = _ (Replace)
" ESC [6 q = | (Insert)
" ESC [5m = blink (all modes)
if !has('gui_running') && has('termresponse') && has('cursorshape') &&
has('autocmd')
func CursorU(mode)
if a:mode == 'r' || a:mode == 'v'
let &t_SI = "\<ESC>[4 q"
else
let &t_SI = "\<Esc>[6 q"
endif
endfunc
augroup consCursor
au TermResponse *
\ if &t_EI == '' | let &t_EI = "\<Esc>[2 q" | endif
\| if &t_SI == '' | let &t_SI = "\<Esc>[6 q" | endif
\| if exists('&t_SR')
\| if &t_SR == '' | let &t_SR = "\<Esc>[4 q" | endif
\| else
\| au InsertChange,InsertEnter * call CursorU(v:insertmode)
\| endif
au VimLeave exe "normal \<C-\\>\<C-N>"
augroup END
endif


Best regards,
Tony.

Tony Mechelynck

unread,
May 28, 2019, 5:31:17 PM5/28/19
to vim_use
This simpler version works in konsole but does nothing in xterm and in
the Linux console. I haven't found how to make it work in both konsole
and xterm but I'm giving up, I don't use Vim in xterm that much. Also
I left out the test on exists('&t_SR') because I on't use Vim 7 (or
earlier) anymore at all.

if !has('gui_running') && has('cursorshape')
let &t_EI = "\<Esc>]50;CursorShape=0\x7"
let &t_SI = "\<Esc>]50;CursorShape=1\x7"
let &t_SR = "\<Esc>]50;CursorShape=2\x7"
endif


Best regards,
Tony.

tooth pik

unread,
May 28, 2019, 5:43:16 PM5/28/19
to vim...@googlegroups.com
cool beans tony, thanx! i didn't know terminal vim in konsole could do that!

tp

Tony Mechelynck

unread,
May 28, 2019, 6:56:23 PM5/28/19
to vim_use
On Tue, May 28, 2019 at 11:43 PM tooth pik <toot...@gmail.com> wrote:
[...]
> cool beans tony, thanx! i didn't know terminal vim in konsole could do that!
>
> tp

I pasted this code from the wiki page linked to by Rob Foehl in his
answer above; in that same wiki page you'll find escape sequences for
various kinds of terminal emulators. What I haven't found is how to
fashion a well-thought-of conditional statement to change the cursor
shape the right way in various incompatible terminals while using a
single vimrc.

Best regards,
Tony.

John Little

unread,
May 31, 2019, 12:45:51 AM5/31/19
to vim_use
On Wednesday, May 29, 2019 at 9:31:17 AM UTC+12, Tony Mechelynck wrote:
> ... I haven't found how to make it work in both konsole
> and xterm ...

I use the XTERM_VERSION environment variable. xterm defines it, konsole doesn't.

Note that if xterm is started with -bc for a blinking cursor, the effects of the 5 and 6 are reversed, so that 5 is steady and 6 blinking.

Also, I sometimes use the "Set Text Parameters" sequence to change the colour of the cursor; so

if $XTERM_VERSION =~? "xterm"
let &t_SI = "\<Esc>]12;green\x7"
let &t_EI = "\<Esc>]12;red\x7"
endif

Tony Mechelynck

unread,
May 31, 2019, 3:31:46 AM5/31/19
to vim_use
On Fri, May 31, 2019 at 6:45 AM John Little <john.b...@gmail.com> wrote:
>
> On Wednesday, May 29, 2019 at 9:31:17 AM UTC+12, Tony Mechelynck wrote:
> > ... I haven't found how to make it work in both konsole
> > and xterm ...
>
> I use the XTERM_VERSION environment variable. xterm defines it, konsole doesn't.

Ah, interesting. Yes, indeed, in bash in xterm, "echo $XTERM_VERSION"
answers Xterm(330) but in konsole the answer is empty. Thanks!
>
> Note that if xterm is started with -bc for a blinking cursor, the effects of the 5 and 6 are reversed, so that 5 is steady and 6 blinking.

IOW, if the cursor is blinking in bash in xterm, with the "even" codes
it wil remain blinking in Vim.

Thanks to you, my problem is solved in both xterm and konsole, with
the folowing code:

" try to change cursor shape in Console mode in xterm-like terminals
" t_EI = █ (Normal)
" t_SR = _ (Replace)
" t_SI = | (Insert)
if !has('gui_running') && has('cursorshape')
if $XTERM_VERSION =~? '^xterm' " a «real» xterm
let &t_EI = "\<Esc>[2 q"
let &t_SI = "\<Esc>[6 q"
let &t_SR = "\<Esc>[4 q"
else " assume konsole
let &t_EI = "\<Esc>]50;CursorShape=0\x7"
let &t_SI = "\<Esc>]50;CursorShape=1\x7"
let &t_SR = "\<Esc>]50;CursorShape=2\x7"
endif
endif


Best regards,
Tony.
Reply all
Reply to author
Forward
0 new messages