Skip to content

Commit 279dd70

Browse files
committed
patch 9.1.1054: Vim doesn't work well with TERM=xterm-direct
Problem: Vim doesn't work well with TERM=xterm-direct (Andrea Pappacoda) Solution: detect if a terminal supports true-colors and enable termguicolors The terminfo database for xterm-direct contains both the (non-standard) termcap RGB capability and a number of colors == 0x1000000 so it seems either of those two options can be used to detect a terminal capable of displaying true colors. So set the termguicolor option automatically, when either of the two options is detected. (for some reasons, my debian xterm (v393) does not respond to XTGETTCAP query attempts, so falling back to the number of colors seems like a good compromize) fixes: #16327 closes: #16490 Signed-off-by: Christian Brabandt <[email protected]>
1 parent fb49e3c commit 279dd70

File tree

5 files changed

+85
-10
lines changed

5 files changed

+85
-10
lines changed

runtime/doc/options.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*options.txt* For Vim version 9.1. Last change: 2025 Jan 23
1+
*options.txt* For Vim version 9.1. Last change: 2025 Jan 26
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -8501,6 +8501,11 @@ A jump table for the options with a short description can be found at |Q_op|.
85018501
When on, uses |highlight-guifg| and |highlight-guibg| attributes in
85028502
the terminal (thus using 24-bit color).
85038503

8504+
Will automatically be enabled, if Vim detects that it runs in a
8505+
capable terminal (when the terminal supports the RGB terminfo
8506+
capability or when the number of colors |t_Co| supported by the
8507+
terminal is 0x1000000, e.g. with $TERM=xterm-direct).
8508+
85048509
Requires a ISO-8613-3 compatible terminal. If setting this option
85058510
does not work (produces a colorless UI) reading |xterm-true-color|
85068511
might help.

runtime/doc/version9.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*version9.txt* For Vim version 9.1. Last change: 2025 Jan 25
1+
*version9.txt* For Vim version 9.1. Last change: 2025 Jan 26
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -41628,6 +41628,8 @@ Changed~
4162841628
- New option value "nosort" for 'completeopt'
4162941629
- add |dist#vim9#Launch()| and |dist#vim9#Open()| to the |vim-script-library|
4163041630
and decouple it from |netrw|
41631+
- 'termguicolors' is automatically enabled if the terminal supports the RGB
41632+
terminfo capability or supports 0x1000000 colors
4163141633

4163241634
*added-9.2*
4163341635
Added ~

src/term.c

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,6 +1661,11 @@ set_color_count(int nr)
16611661
sprintf((char *)nr_colors, "%d", t_colors);
16621662
else
16631663
*nr_colors = NUL;
1664+
#ifdef FEAT_TERMGUICOLORS
1665+
// xterm-direct, enable termguicolors
1666+
if (t_colors == 0x1000000 && !p_tgc)
1667+
set_option_value((char_u *)"termguicolors", 1L, NULL, 0);
1668+
#endif
16641669
set_string_option_direct((char_u *)"t_Co", -1, nr_colors, OPT_FREE, 0);
16651670
}
16661671

@@ -1694,8 +1699,9 @@ may_adjust_color_count(int val)
16941699
static char *(key_names[]) =
16951700
{
16961701
# ifdef FEAT_TERMRESPONSE
1697-
// Do this one first, it may cause a screen redraw.
1702+
// Do those ones first, both may cause a screen redraw.
16981703
"Co",
1704+
"RGB",
16991705
# endif
17001706
"ku", "kd", "kr", "kl",
17011707
"#2", "#4", "%i", "*7",
@@ -5854,6 +5860,7 @@ handle_dcs(char_u *tp, char_u *argp, int len, char_u *key_name, int *slen)
58545860
{
58555861
int i, j;
58565862

5863+
LOG_TR(("Received DCS response: %s", (char*)tp));
58575864
j = 1 + (tp[0] == ESC);
58585865
if (len < j + 3)
58595866
i = len; // need more chars
@@ -7100,7 +7107,7 @@ req_codes_from_term(void)
71007107
static void
71017108
req_more_codes_from_term(void)
71027109
{
7103-
char buf[23]; // extra size to shut up LGTM
7110+
char buf[32]; // extra size to shut up LGTM
71047111
int old_idx = xt_index_out;
71057112

71067113
// Don't do anything when going to exit.
@@ -7115,7 +7122,10 @@ req_more_codes_from_term(void)
71157122

71167123
MAY_WANT_TO_LOG_THIS;
71177124
LOG_TR(("Requesting XT %d: %s", xt_index_out, key_name));
7118-
sprintf(buf, "\033P+q%02x%02x\033\\", key_name[0], key_name[1]);
7125+
if (key_name[2] != NUL)
7126+
sprintf(buf, "\033P+q%02x%02x%02x\033\\", key_name[0], key_name[1], key_name[2]);
7127+
else
7128+
sprintf(buf, "\033P+q%02x%02x\033\\", key_name[0], key_name[1]);
71197129
out_str_nf((char_u *)buf);
71207130
++xt_index_out;
71217131
}
@@ -7135,21 +7145,24 @@ req_more_codes_from_term(void)
71357145
got_code_from_term(char_u *code, int len)
71367146
{
71377147
#define XT_LEN 100
7138-
char_u name[3];
7148+
char_u name[4];
71397149
char_u str[XT_LEN];
71407150
int i;
71417151
int j = 0;
71427152
int c;
71437153

71447154
// A '1' means the code is supported, a '0' means it isn't.
71457155
// When half the length is > XT_LEN we can't use it.
7146-
// Our names are currently all 2 characters.
7147-
if (code[0] == '1' && code[7] == '=' && len / 2 < XT_LEN)
7156+
if (code[0] == '1' && (code[7] || code[9] == '=') && len / 2 < XT_LEN)
71487157
{
71497158
// Get the name from the response and find it in the table.
71507159
name[0] = hexhex2nr(code + 3);
71517160
name[1] = hexhex2nr(code + 5);
7152-
name[2] = NUL;
7161+
if (code[9] == '=')
7162+
name[2] = hexhex2nr(code + 7);
7163+
else
7164+
name[2] = NUL;
7165+
name[3] = NUL;
71537166
for (i = 0; key_names[i] != NULL; ++i)
71547167
{
71557168
if (STRCMP(key_names[i], name) == 0)
@@ -7163,7 +7176,8 @@ got_code_from_term(char_u *code, int len)
71637176

71647177
if (key_names[i] != NULL)
71657178
{
7166-
for (i = 8; (c = hexhex2nr(code + i)) >= 0; i += 2)
7179+
i = (code[7] == '=') ? 8 : 10;
7180+
for (; (c = hexhex2nr(code + i)) >= 0; i += 2)
71677181
str[j++] = c;
71687182
str[j] = NUL;
71697183
if (name[0] == 'C' && name[1] == 'o')
@@ -7180,6 +7194,22 @@ got_code_from_term(char_u *code, int len)
71807194
#endif
71817195
may_adjust_color_count(val);
71827196
}
7197+
#ifdef FEAT_TERMGUICOLORS
7198+
// when RGB result comes back, it is supported when the result contains an '='
7199+
else if (name[0] == 'R' && name[1] == 'G' && name[2] == 'B' && code[9] == '=')
7200+
{
7201+
int val = atoi((char *)str);
7202+
// 8 bits per color channel
7203+
if (val == 8)
7204+
{
7205+
#ifdef FEAT_EVAL
7206+
ch_log(NULL, "got_code_from_term(RGB): xterm-direct colors detected");
7207+
#endif
7208+
// RGB capability set, enable termguicolors
7209+
set_option_value((char_u *)"termguicolors", 1L, NULL, 0);
7210+
}
7211+
}
7212+
#endif
71837213
else
71847214
{
71857215
i = find_term_bykeys(str);

src/testdir/test_termcodes.vim

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2739,4 +2739,40 @@ func Test_terminal_builtin_without_gui()
27392739
call assert_notequal(-1, index(output, 'builtin_dumb'))
27402740
endfunc
27412741

2742+
func Test_xterm_direct_enables_termguicolors()
2743+
" TERM=xterm-direct enables termguicolors
2744+
CheckNotMSWindows
2745+
if !CanRunVimInTerminal()
2746+
throw 'Skipped: cannot make screendumps'
2747+
endif
2748+
if !executable('tput')
2749+
throw "Skipped: tput not executable!"
2750+
endif
2751+
if has("gui_running")
2752+
throw "Skipped: does not work in GUI mode"
2753+
endif
2754+
call system('tput -Txterm-direct RGB 2>/dev/null')
2755+
if v:shell_error
2756+
throw "Skipped: xterm-direct $TERM has no RGB capability"
2757+
endif
2758+
let colors = systemlist('tput -Txterm-direct colors')[0]
2759+
defer delete('XTerm-direct.txt')
2760+
2761+
let buf = RunVimInTerminal('--cmd ":set noswapfile" --clean XTerm-direct.txt',
2762+
\ {'rows': 10, 'env': {'TERM': 'xterm-direct'}})
2763+
call TermWait(buf)
2764+
call term_sendkeys(buf, ":$put ='TERM: ' .. &term\<cr>")
2765+
" doesn't work. Vim cannot query xterm colors in the embedded terminal?
2766+
"call term_sendkeys(buf, ":$put ='Colors: ' .. &t_Co\<cr>")
2767+
call term_sendkeys(buf, ":$put ='Termguicolors: ' .. &tgc\<cr>")
2768+
call term_sendkeys(buf, ":wq\<cr>")
2769+
call TermWait(buf)
2770+
2771+
let result=readfile('XTerm-direct.txt')
2772+
" call assert_equal(['', 'TERM: xterm-direct', 'Colors: ' .. colors, 'Termguicolors: 1'], result)
2773+
call assert_equal(['', 'TERM: xterm-direct', 'Termguicolors: 1'], result)
2774+
" cleanup
2775+
bw!
2776+
endfunc
2777+
27422778
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ static char *(features[]) =
704704

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
1054,
707709
/**/
708710
1053,
709711
/**/

0 commit comments

Comments
 (0)