-*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
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|)
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
-*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
*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|
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()`.
-*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
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
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
+++ /dev/null
-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 :
{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},
// 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
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);
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;
&crv_status,
&u7_status,
&xcc_status,
+# ifdef FEAT_TERMINAL
+ &rfg_status,
+# endif
+ &rbg_status,
&rbm_status,
&rcs_status,
&winpos_status,
}
}
+/*
+ * 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
/*
}
}
+
+
/*
* Handle a response to T_CRV: {lead}{first}{x};{vers};{y}c
* Xterm and alike use '>' for {first}.
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;
/*
#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);
}
#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;
}
/*
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
test_plugin_tohtml \
test_plugin_tutor \
test_plugin_zip \
- test_plugin_colorresp \
test_plus_arg_edit \
test_popup \
test_popupwin \
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 \
+++ /dev/null
-" 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
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
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1757,
/**/
1756,
/**/