feat(defaults): enable 'termguicolors' by default when supported by terminal

Enable 'termguicolors' automatically when Nvim can detect that truecolor
is supported by the host terminal.

If $COLORTERM is set to "truecolor" or "24bit", or the terminal's
terminfo entry contains capabilities for Tc, RGB, or setrgbf and
setrgbb, then we assume that the terminal supports truecolor. Otherwise,
the terminal is queried (using both XTGETTCAP and SGR + DECRQSS). If the
terminal's response to these queries (if any) indicates that it supports
truecolor, then 'termguicolors' is enabled.
This commit is contained in:
Gregory Anders
2023-12-05 10:01:32 -08:00
parent 5b40a1c09d
commit 2613ba5000
11 changed files with 298 additions and 95 deletions

View File

@@ -8764,6 +8764,10 @@ return {
Enables 24-bit RGB color in the |TUI|. Uses "gui" |:highlight|
attributes instead of "cterm" attributes. |guifg|
Requires an ISO-8613-3 compatible terminal.
Nvim will automatically attempt to determine if the host terminal
supports 24-bit color and will enable this option if it does
(unless explicitly disabled by the user).
]=],
full_name = 'termguicolors',
redraw = { 'ui_option' },

View File

@@ -148,7 +148,8 @@ static bool cursor_style_enabled = false;
# include "tui/tui.c.generated.h"
#endif
void tui_start(TUIData **tui_p, int *width, int *height, char **term)
void tui_start(TUIData **tui_p, int *width, int *height, char **term, bool *rgb)
FUNC_ATTR_NONNULL_ALL
{
TUIData *tui = xcalloc(1, sizeof(TUIData));
tui->is_starting = true;
@@ -177,6 +178,7 @@ void tui_start(TUIData **tui_p, int *width, int *height, char **term)
*width = tui->width;
*height = tui->height;
*term = tui->term;
*rgb = tui->rgb;
}
void tui_set_key_encoding(TUIData *tui)
@@ -334,6 +336,9 @@ static void terminfo_start(TUIData *tui)
int konsolev = konsolev_env ? (int)strtol(konsolev_env, NULL, 10)
: (konsole ? 1 : 0);
// truecolor support must be checked before patching/augmenting terminfo
tui->rgb = term_has_truecolor(tui, colorterm);
patch_terminfo_bugs(tui, term, colorterm, vtev, konsolev, iterm_env, nsterm);
augment_terminfo(tui, term, vtev, konsolev, iterm_env, nsterm);
tui->can_change_scroll_region =
@@ -1439,7 +1444,7 @@ void tui_suspend(TUIData *tui)
tui_mouse_on(tui);
}
stream_set_blocking(tui->input.in_fd, false); // libuv expects this
ui_client_attach(tui->width, tui->height, tui->term);
ui_client_attach(tui->width, tui->height, tui->term, tui->rgb);
#endif
}
@@ -1752,6 +1757,44 @@ static int unibi_find_ext_bool(unibi_term *ut, const char *name)
return -1;
}
/// Determine if the terminal supports truecolor or not:
///
/// 1. If $COLORTERM is "24bit" or "truecolor", return true
/// 2. Else, check terminfo for Tc, RGB, setrgbf, or setrgbb capabilities. If
/// found, return true
/// 3. Else, return false
static bool term_has_truecolor(TUIData *tui, const char *colorterm)
{
// Check $COLORTERM
if (strequal(colorterm, "truecolor") || strequal(colorterm, "24bit")) {
return true;
}
// Check for Tc and RGB
for (size_t i = 0; i < unibi_count_ext_bool(tui->ut); i++) {
const char *n = unibi_get_ext_bool_name(tui->ut, i);
if (n && (!strcmp(n, "Tc") || !strcmp(n, "RGB"))) {
return true;
}
}
// Check for setrgbf and setrgbb
bool setrgbf = false;
bool setrgbb = false;
for (size_t i = 0; i < unibi_count_ext_str(tui->ut) && (!setrgbf || !setrgbb); i++) {
const char *n = unibi_get_ext_str_name(tui->ut, i);
if (n) {
if (!setrgbf && !strcmp(n, "setrgbf")) {
setrgbf = true;
} else if (!setrgbb && !strcmp(n, "setrgbb")) {
setrgbb = true;
}
}
}
return setrgbf && setrgbb;
}
/// Patches the terminfo records after loading from system or built-in db.
/// Several entries in terminfo are known to be deficient or outright wrong;
/// and several terminal emulators falsely announce incorrect terminal types.

View File

@@ -70,14 +70,14 @@ uint64_t ui_client_start_server(int argc, char **argv)
return channel->id;
}
void ui_client_attach(int width, int height, char *term)
void ui_client_attach(int width, int height, char *term, bool rgb)
{
MAXSIZE_TEMP_ARRAY(args, 3);
ADD_C(args, INTEGER_OBJ(width));
ADD_C(args, INTEGER_OBJ(height));
MAXSIZE_TEMP_DICT(opts, 9);
PUT_C(opts, "rgb", BOOLEAN_OBJ(true));
PUT_C(opts, "rgb", BOOLEAN_OBJ(rgb));
PUT_C(opts, "ext_linegrid", BOOLEAN_OBJ(true));
PUT_C(opts, "ext_termcolors", BOOLEAN_OBJ(true));
if (term) {
@@ -111,9 +111,10 @@ void ui_client_run(bool remote_ui)
ui_client_is_remote = remote_ui;
int width, height;
char *term;
tui_start(&tui, &width, &height, &term);
bool rgb;
tui_start(&tui, &width, &height, &term, &rgb);
ui_client_attach(width, height, term);
ui_client_attach(width, height, term, rgb);
// os_exit() will be invoked when the client channel detaches
while (true) {