patch 9.1.1757: The colorresp plugin causes additional redraws

Problem:  The colorresp plugin causes additional redraws
          (Linwei, after v9.1.1703)
Solution: Move the code back into the C core and get rid of the vim
          plugin (Foxe Chen)

fixes: #18251
closes: #18279

Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Foxe Chen
2025-09-14 04:38:33 -04:00
committed by Christian Brabandt
parent c975d62473
commit c077f5e9d8
13 changed files with 251 additions and 170 deletions

View File

@ -1,4 +1,4 @@
*autocmd.txt* For Vim version 9.1. Last change: 2025 Sep 11
*autocmd.txt* For Vim version 9.1. Last change: 2025 Sep 14
VIM REFERENCE MANUAL by Bram Moolenaar
@ -1313,8 +1313,10 @@ TermResponseAll After the response to |t_RV|, |t_RC|, |t_RS|,
correspondingly, can be used. <amatch> will
be set to any of:
"ambiguouswidth" (|t_u7|),
"background" (|t_RB|),
"cursorblink" (|t_RC|),
"cursorshape" (|t_RS|),
"foreground" (|t_RF|),
"da1",
"osc",
"version" (|t_RV|)
@ -1322,15 +1324,6 @@ TermResponseAll After the response to |t_RV|, |t_RC|, |t_RS|,
executing another event, especially if file I/O,
a shell command or anything else that takes time
is involved.
Note: Traditionally, TermResponseAll was also
used for "foreground" and "background"
patterns. These are now handled as part of
the "osc" value. For backwards compatibility,
the $VIMRUNTIME/plugin/colorresp.vim plugin
will handle "osc" events and emit
TermResponseAll autocommand events when it
encounters "foreground" and "background"
values.
*TextChanged*
TextChanged After a change was made to the text in the
current buffer in Normal mode. That is after

View File

@ -1,4 +1,4 @@
*eval.txt* For Vim version 9.1. Last change: 2025 Aug 29
*eval.txt* For Vim version 9.1. Last change: 2025 Sep 14
VIM REFERENCE MANUAL by Bram Moolenaar
@ -2896,15 +2896,16 @@ v:termstyleresp The escape sequence returned by the terminal for the |t_RS|
*v:termrbgresp* *termrbgresp-variable*
v:termrbgresp The escape sequence returned by the terminal for the |t_RB|
termcap entry. This is used to find out what the terminal
background color is; see 'background'. This is set by the
$VIMRUNTIME/plugin/colorresp.vim plugin normally included with
Vim, but can be set manually if you know what you are doing.
Note that changing this will not do anything.
background color is; see 'background'. When this option is
set, the TermResponseAll autocommand event is fired, with
<amatch> set to "background".
*v:termrfgresp* *termrfgresp-variable*
v:termrfgresp The escape sequence returned by the terminal for the |t_RF|
termcap entry. This is used to find out what the terminal
foreground color is. Behaves the same as |v:termrbgresp|
foreground color is. When this option is set, the
TermResponseAll autocommand event is fired, with <amatch> set
to "foreground".
*v:termu7resp* *termu7resp-variable*
v:termu7resp The escape sequence returned by the terminal for the |t_u7|
@ -2923,9 +2924,7 @@ v:termda1 The escape sequence returned by a primary device attributes
v:termosc The escape sequence of the most recent OSC response received
from the terminal. When this variable is set, the
|TermResponseAll| autocommand event is fired, with <amatch>
set to "osc". Also used to set the |v:termrbgresp| and
|v:termrfgresp| via the $VIMRUNTIME/plugin/colorresp.vim
plugin
set to "osc".
*v:testing* *testing-variable*
v:testing Must be set before using `test_garbagecollect_now()`.

View File

@ -1,4 +1,4 @@
*version9.txt* For Vim version 9.1. Last change: 2025 Sep 13
*version9.txt* For Vim version 9.1. Last change: 2025 Sep 14
VIM REFERENCE MANUAL by Bram Moolenaar
@ -41759,9 +41759,6 @@ Others: ~
Command-line.
- |min()|/|max()| can handle all comparable data types.
- Vim triggers the |TermResponseAll| autocommand for any terminal OSC value.
- Vim includes the $VIMRUNTIME/plugins/colorresp.vim which parses the terminal
OSC response and can trigger a |TermResponseAll| with the "background" or
"foreground" value.
Platform specific ~
- MS-Winodws: Paths like "\Windows" and "/Windows" are now considered to be

View File

@ -3,7 +3,6 @@ The plugin directory is for standard Vim plugin scripts.
All files here ending in .vim will be sourced by Vim when it starts up.
Look in the file for hints on how it can be disabled without deleting it.
colorresp.vim used to detect terminal background and foreground colours
getscriptPlugin.vim get latest version of Vim scripts
gzip.vim edit compressed files
logiPat.vim logical operators on patterns

View File

@ -1,51 +0,0 @@
vim9script
# Vim plugin for setting the background and foreground colours depending on
# the terminal response.
#
# Maintainer: The Vim Project <https://github.com/vim/vim>
# Last Change: 2025 Sep 05
if exists("g:loaded_colorresp")
finish
endif
g:loaded_colorresp = 1
augroup ColorResp
au!
au TermResponseAll osc {
var parts: list<string> = matchlist(v:termosc, '\(\d\+\);rgb:\(\w\+\)/\(\w\+\)/\(\w\+\)')
if len(parts) >= 5
var type: string = parts[1]
var rval: number = str2nr(parts[2][: 1], 16)
var gval: number = str2nr(parts[3][: 1], 16)
var bval: number = str2nr(parts[4][: 1], 16)
if type == '11'
# Detect light or dark background by parsing OSC 11 RGB background reply
# from terminal. Sum the RGB values roughly; if bright enough, set
# 'background' to 'light', otherwise set it to 'dark'.
var new_bg_val: string = (3 * char2nr('6') < char2nr(parts[2]) + char2nr(parts[3]) + char2nr(parts[4])) ? "light" : "dark"
v:termrbgresp = v:termosc
&background = new_bg_val
# For backwards compatibility
if exists('#TermResponseAll#background')
doautocmd <nomodeline> TermResponseAll background
endif
else
v:termrfgresp = v:termosc
# For backwards compatibility
if exists('#TermResponseAll#foreground')
doautocmd <nomodeline> TermResponseAll foreground
endif
endif
endif
}
au VimEnter * ++once {
call echoraw(&t_RB)
call echoraw(&t_RF)
}
augroup END
# vim: set sw=2 sts=2 :

View File

@ -141,8 +141,8 @@ static struct vimvar
{VV_NAME("t_blob", VAR_NUMBER), NULL, VV_RO},
{VV_NAME("t_class", VAR_NUMBER), NULL, VV_RO},
{VV_NAME("t_object", VAR_NUMBER), NULL, VV_RO},
{VV_NAME("termrfgresp", VAR_STRING), NULL, 0},
{VV_NAME("termrbgresp", VAR_STRING), NULL, 0},
{VV_NAME("termrfgresp", VAR_STRING), NULL, VV_RO},
{VV_NAME("termrbgresp", VAR_STRING), NULL, VV_RO},
{VV_NAME("termu7resp", VAR_STRING), NULL, VV_RO},
{VV_NAME("termstyleresp", VAR_STRING), NULL, VV_RO},
{VV_NAME("termblinkresp", VAR_STRING), NULL, VV_RO},

View File

@ -883,6 +883,8 @@ vim_main2(void)
// Requesting the termresponse is postponed until here, so that a "-c q"
// argument doesn't make it appear in the shell Vim was started from.
may_req_termresponse();
may_req_bg_color();
#endif
// start in insert mode

View File

@ -59,6 +59,7 @@ void starttermcap(void);
void stoptermcap(void);
void may_req_termresponse(void);
void check_terminal_behavior(void);
void may_req_bg_color(void);
int swapping_screen(void);
void scroll_start(void);
void cursor_on_force(void);

View File

@ -131,6 +131,19 @@ static termrequest_T u7_status = TERMREQUEST_INIT;
static termrequest_T xcc_status = TERMREQUEST_INIT;
#ifdef FEAT_TERMRESPONSE
# ifdef FEAT_TERMINAL
// Request foreground color report:
static termrequest_T rfg_status = TERMREQUEST_INIT;
static int fg_r = 0;
static int fg_g = 0;
static int fg_b = 0;
static int bg_r = 255;
static int bg_g = 255;
static int bg_b = 255;
# endif
// Request background color report:
static termrequest_T rbg_status = TERMREQUEST_INIT;
// Request cursor blinking mode report:
static termrequest_T rbm_status = TERMREQUEST_INIT;
@ -145,6 +158,10 @@ static termrequest_T *all_termrequests[] = {
&crv_status,
&u7_status,
&xcc_status,
# ifdef FEAT_TERMINAL
&rfg_status,
# endif
&rbg_status,
&rbm_status,
&rcs_status,
&winpos_status,
@ -4190,6 +4207,49 @@ check_terminal_behavior(void)
}
}
/*
* Similar to requesting the version string: Request the terminal background
* color when it is the right moment.
*/
void
may_req_bg_color(void)
{
if (can_get_termresponse() && starting == 0)
{
int didit = FALSE;
# ifdef FEAT_TERMINAL
// Only request foreground if t_RF is set.
if (rfg_status.tr_progress == STATUS_GET && *T_RFG != NUL)
{
MAY_WANT_TO_LOG_THIS;
LOG_TR1("Sending FG request");
out_str(T_RFG);
termrequest_sent(&rfg_status);
didit = TRUE;
}
# endif
// Only request background if t_RB is set.
if (rbg_status.tr_progress == STATUS_GET && *T_RBG != NUL)
{
MAY_WANT_TO_LOG_THIS;
LOG_TR1("Sending BG request");
out_str(T_RBG);
termrequest_sent(&rbg_status);
didit = TRUE;
}
if (didit)
{
// check for the characters now, otherwise they might be eaten by
// get_keystroke()
out_flush();
(void)vpeekc_nomap();
}
}
}
#endif
/*
@ -4983,6 +5043,8 @@ handle_u7_response(int *arg, char_u *tp UNUSED, int csi_len UNUSED)
}
}
/*
* Handle a response to T_CRV: {lead}{first}{x};{vers};{y}c
* Xterm and alike use '>' for {first}.
@ -5743,6 +5805,93 @@ handle_csi(
return 0;
}
static void
check_for_color_response(char_u *resp, int len)
{
int i, j;
char_u *argp;
j = 1 + (resp[0] == ESC);
argp = resp + j;
if (len >= j + 3 && (argp[0] != '1'
|| (argp[1] != '1' && argp[1] != '0')
|| argp[2] != ';'))
i = 0; // no match
else
{
for (i = j; i < len; ++i)
if (resp[i] == '\007' || (resp[0] == OSC ? resp[i] == STERM
: (resp[i] == ESC && i + 1 < len && resp[i + 1] == '\\')))
{
int is_bg = argp[1] == '1';
int is_4digit = i - j >= 21 && resp[j + 11] == '/'
&& resp[j + 16] == '/';
if (i - j >= 15 && STRNCMP(resp + j + 3, "rgb:", 4) == 0
&& (is_4digit
|| (resp[j + 9] == '/' && resp[j + 12] == '/')))
{
char_u *tp_r = resp + j + 7;
char_u *tp_g = resp + j + (is_4digit ? 12 : 10);
char_u *tp_b = resp + j + (is_4digit ? 17 : 13);
#if defined(FEAT_TERMRESPONSE) && defined(FEAT_TERMINAL)
int rval, gval, bval;
rval = hexhex2nr(tp_r);
gval = hexhex2nr(tp_g);
bval = hexhex2nr(tp_b);
#endif
if (is_bg)
{
char *new_bg_val = (3 * '6' < *tp_r + *tp_g +
*tp_b) ? "light" : "dark";
LOG_TRN("Received RBG response: %s", tp);
#ifdef FEAT_TERMRESPONSE
rbg_status.tr_progress = STATUS_GOT;
# ifdef FEAT_TERMINAL
bg_r = rval;
bg_g = gval;
bg_b = bval;
# endif
#endif
if (!option_was_set((char_u *)"bg")
&& STRCMP(p_bg, new_bg_val) != 0)
{
// value differs, apply it
set_option_value_give_err((char_u *)"bg",
0L, (char_u *)new_bg_val, 0);
reset_option_was_set((char_u *)"bg");
redraw_asap(UPD_CLEAR);
}
}
#if defined(FEAT_TERMRESPONSE) && defined(FEAT_TERMINAL)
else
{
LOG_TRN("Received RFG response: %s", tp);
rfg_status.tr_progress = STATUS_GOT;
fg_r = rval;
fg_g = gval;
fg_b = bval;
}
#endif
}
#ifdef FEAT_EVAL
set_vim_var_string(is_bg ? VV_TERMRBGRESP
: VV_TERMRFGRESP, resp, len);
#endif
apply_autocmds(EVENT_TERMRESPONSEALL,
is_bg ? (char_u *)"background" : (char_u *)"foreground",
NULL, FALSE, curbuf);
break;
}
}
if (i == len)
LOG_TR1("not enough characters for RB");
}
static oscstate_T osc_state;
/*
@ -5803,6 +5952,9 @@ handle_osc(char_u *tp, int len, char_u *key_name, int *slen)
#ifdef FEAT_EVAL
set_vim_var_string_direct(VV_TERMOSC, osc_state.buf.ga_data);
#endif
// Check for background/foreground colour response
check_for_color_response(osc_state.buf.ga_data, osc_state.buf.ga_len - 1);
char_u savebg = *p_bg;
apply_autocmds(EVENT_TERMRESPONSEALL, (char_u *)"osc",
NULL, FALSE, curbuf);
@ -6584,28 +6736,18 @@ handle_osc:
}
#if (defined(FEAT_TERMINAL) && defined(FEAT_TERMRESPONSE)) || defined(PROTO)
static void
term_get_color(char_u *str, char_u *r, char_u *g, char_u *b)
{
char_u rn[3], gn[3], bn[3];
if (sscanf((char *)str, "%*[^:]:%2s%*[^/]/%2s%*[^/]/%2s",
(char *)&rn, (char *)&gn, (char *)&bn) != 3)
return;
*r = hexhex2nr(rn);
*g = hexhex2nr(gn);
*b = hexhex2nr(bn);
}
/*
* Get the text foreground color, if known.
*/
void
term_get_fg_color(char_u *r, char_u *g, char_u *b)
{
term_get_color(get_vim_var_str(VV_TERMRFGRESP), r, g, b);
if (rfg_status.tr_progress != STATUS_GOT)
return;
*r = fg_r;
*g = fg_g;
*b = fg_b;
}
/*
@ -6614,7 +6756,12 @@ term_get_fg_color(char_u *r, char_u *g, char_u *b)
void
term_get_bg_color(char_u *r, char_u *g, char_u *b)
{
term_get_color(get_vim_var_str(VV_TERMRBGRESP), r, g, b);
if (rbg_status.tr_progress != STATUS_GOT)
return;
*r = bg_r;
*g = bg_g;
*b = bg_b;
}
#endif

View File

@ -252,7 +252,6 @@ NEW_TESTS = \
test_plugin_tohtml \
test_plugin_tutor \
test_plugin_zip \
test_plugin_colorresp \
test_plus_arg_edit \
test_popup \
test_popupwin \
@ -526,7 +525,6 @@ NEW_TESTS_RES = \
test_plugin_tohtml.res \
test_plugin_tutor.res \
test_plugin_zip.res \
test_plugin_colorresp.res \
test_plus_arg_edit.res \
test_popup.res \
test_popupwin.res \

View File

@ -1,74 +0,0 @@
" Test for the colorresp plugin
CheckNotGui
CheckUnix
runtime plugin/colorresp.vim
func Test_colorresp()
set t_RF=x
set t_RB=y
" response to t_RF, 4 digits
let red = 0x12
let green = 0x34
let blue = 0x56
let seq = printf("\<Esc>]10;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrfgresp)
" call WaitForAssert({-> assert_equal(seq, v:termrfgresp)})
" response to t_RF, 2 digits
let red = 0x78
let green = 0x9a
let blue = 0xbc
let seq = printf("\<Esc>]10;rgb:%02x/%02x/%02x\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrfgresp)
" response to t_RB, 4 digits, dark
set background=light
call test_option_not_set('background')
let red = 0x29
let green = 0x4a
let blue = 0x6b
let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrbgresp)
call assert_equal('dark', &background)
" response to t_RB, 4 digits, light
set background=dark
call test_option_not_set('background')
let red = 0x81
let green = 0x63
let blue = 0x65
let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrbgresp)
call assert_equal('light', &background)
" response to t_RB, 2 digits, dark
set background=light
call test_option_not_set('background')
let red = 0x47
let green = 0x59
let blue = 0x5b
let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrbgresp)
call assert_equal('dark', &background)
" response to t_RB, 2 digits, light
set background=dark
call test_option_not_set('background')
let red = 0x83
let green = 0xa4
let blue = 0xc2
let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrbgresp)
call assert_equal('light', &background)
set t_RF= t_RB=
endfunc

View File

@ -2790,4 +2790,72 @@ func Test_term_response_osc()
call assert_equal("\<Esc>]15;hello world!\x07", v:termosc)
endfunc
" This only checks if the sequence is recognized.
func Test_term_rgb_response()
set t_RF=x
set t_RB=y
" response to t_RF, 4 digits
let red = 0x12
let green = 0x34
let blue = 0x56
let seq = printf("\<Esc>]10;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrfgresp)
" response to t_RF, 2 digits
let red = 0x78
let green = 0x9a
let blue = 0xbc
let seq = printf("\<Esc>]10;rgb:%02x/%02x/%02x\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrfgresp)
" response to t_RB, 4 digits, dark
set background=light
eval 'background'->test_option_not_set()
let red = 0x29
let green = 0x4a
let blue = 0x6b
let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrbgresp)
call assert_equal('dark', &background)
" response to t_RB, 4 digits, light
set background=dark
call test_option_not_set('background')
let red = 0x81
let green = 0x63
let blue = 0x65
let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrbgresp)
call assert_equal('light', &background)
" response to t_RB, 2 digits, dark
set background=light
call test_option_not_set('background')
let red = 0x47
let green = 0x59
let blue = 0x5b
let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrbgresp)
call assert_equal('dark', &background)
" response to t_RB, 2 digits, light
set background=dark
call test_option_not_set('background')
let red = 0x83
let green = 0xa4
let blue = 0xc2
let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termrbgresp)
call assert_equal('light', &background)
set t_RF= t_RB=
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -724,6 +724,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1757,
/**/
1756,
/**/