简体   繁体   中英

Cursor color in xterm; change accordingly to the syntax in vim

In gnome-terminal and konsole, my cursor color changes according to the selected foreground color in vim (if I'm on red text, my cursor is red). In xterm, my cursor is ALWAYS white. How can I set xterm to the same behaviour than gnome-terminal or konsole?

Thanks a lot.

Actually, xterm's manual is not so simple, and there is no suitable tutorial for just this feature. Quoting from the manual:

cursorColor (class CursorColor )

Specifies the color to use for the text cursor. The default is "XtDefaultForeground". By default, xterm attempts to keep this color from being the same as the background color, since it draws the cursor by filling the background of a text cell. The same restriction applies to control sequences which may change this color.

Setting this resource overrides most of xterm's adjustments to cursor color. It will still use reverse-video to disallow some cases, such as a black cursor on a black background.

Also, highlighting can be treated specially (quoting from the description of a command-line option);

-hm

Tells xterm to use highlightTextColor and highlightColor to override the reversed foreground/background colors in a selection. It sets the highlightColorMode resource to "true".

That alludes to a few cases:

  • the cursor color can be set using command-line option or resource. If it is set in this manner (and unless overridden by the dynamic colors escape sequence to change the color), xterm uses this color.
  • if it is not constrained, xterm attempts to keep the cursor visible by using the reverse of the foreground and background colors set by "ANSI" control sequences for colors 0-7, as well as the non-ANSI controls for colors 8-255.
  • occasionally, an application sets foreground and background colors to the same value (xterm attempts to choose a suitable cursor color for this case as well).
  • colors can be set separately for highlighting.

Now... xterm basically makes the cursor visible (unless overridden) by choosing colors which are the reversed foreground vs background. Gnome-terminal does something like that, but not really: it chooses opposite items from the color palette, which can (reading an example now) make the cursor less visible, since the palette it uses is less luminous. (In particular, I notice that the "reverse" of yellow text becomes a dull orange). Konsole's palettes as a rule give even poorer visibility (though yellow is reversed like xterm, red text is indistinct against a black background).

XTerm:

在此处输入图片说明

Gnome-terminal:

在此处输入图片说明

Konsole

在此处输入图片说明

In short: it sounds as if the OP's xterm is configured to set the cursor color to a specific value, and the fix would be to eliminate the setting. But the appearance of the cursor on the text will differ unless some care is given to configuring the colors (for all three terminals).

To ensure the cursor color is always the color of the foreground, add this to .Xresources for yourself or to /etc/X11/app-defaults/XTerm for the whole machine. Location of the second can vary from OS to OS.

xterm*cursorColor:      *XtDefaultForeground

According to Xterm Control Sequences , you can use Control Sequence Introducer and Operating System Command , CSI / OSC for short.

Interesting OSC :

OSC Ps ; Pt BEL
...
Ps = 1 2 ⇒  Change text cursor color to Pt.

Using this OSC we can change text cursor to any desired color, it accepts color names, like red , green etc. or something like: rgb:RR/GG/BB see XParseColor

Interesting CSI :

CSI Ps SP q
          Set cursor style (DECSCUSR), VT520.
            Ps = 0  ⇒  blinking block.
            Ps = 1  ⇒  blinking block (default).
            Ps = 2  ⇒  steady block.
            Ps = 3  ⇒  blinking underline.
            Ps = 4  ⇒  steady underline.
            Ps = 5  ⇒  blinking bar, xterm.
            Ps = 6  ⇒  steady bar, xterm.

Now using vim's t_SI and t_EI and these CSI / OSC we can do something like that:

let &t_SI="\<Esc>[5 q\<Esc>]12;" . rgb_or_name_color . "\x7"
let &t_EI="\<Esc>[5 q\<Esc>]12;" . rgb_or_name_color_for_not_insert_mode . "\x7"    

Here is a function that parses current color scheme's Cursor and Type hi groups for guifg (useful with set termguicolors )/ ctermfg colors, and then sets the t_SI and t_EI according to these colors:

fun! UpdateTermCursor()
  if &term =~ "xterm\\|rxvt"
    fun! s:cologet(gr) 
      let cc = execute('hi ' . a:gr)
      let color = matchstr(cc, 'guifg=\zs[^ ]*')
      if color == 'bg'
        let color = matchstr(cc, 'guibg=\zs[^ ]*')
      endif
      if color == ''
        let color = matchstr(cc, 'ctermfg=\zs[^ ]*')
      endif
      if color[0] == '#'
        let color = 'rgb:' . substitute(color[1:-1], '..', '\0\/', 'g')[0:-2]
      endif
      return color
    endfun
    let cur = s:cologet('Cursor') 
    " You can change group, for example CursorLineNr, Special, NonText etc.
    let curb = s:cologet('Type')
    let &t_SI="\<Esc>[5 q\<Esc>]12;" . curb . "\x7"
    let &t_EI="\<Esc>[1 q\<Esc>]12;" . cur . "\x7"
    " Redraw 
    :call feedkeys("i\<C-O>:stopinsert\<CR>")
    " silent! exe ':redraw!'
    " :call feedkeys("i\<Esc>l")
    " Restore cursor to I when leaving vim
    augroup TermCursorLeave
      autocmd!
      autocmd VimLeave * silent !echo -ne "\e[5 q"
    augroup END
  endif
endfun

After you change colorscheme using :colorscheme , execute :call UpdateTermCursor() , here is example:

vim 术语光标颜色

According to Xterm's manual , it will automatically highlight text cursor. Gnome-terminal has inherited that characteristic from Xterm, that's why the cursor color changes in vim.

In my case, xterm just work the same as gnome-terminal with respect to cursor highlight.

Are you using a real xterm, so just some other term setting the $TERM as 'xterm'?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM