From c5b02d5a7a0a19b338ff2cbf610210058eac0a10 Mon Sep 17 00:00:00 2001 From: Mateusz Czaplinski Date: Sat, 2 Jul 2016 18:11:25 -0400 Subject: [PATCH 1/4] options: Set 't_Co' from unibilium + fix_terminfo. Closes #3428 References #4999 The Linux "virtual consoles" available on Alt-F1...Alt-F7 (i.e. tty1-tty7) support only 8 colors (actually, it's 16 colors when counted together with "bold/bright" attribute) and 8 background colors (those in some cases can be upped to 16 too, by using "blink" attribute - but this might be more risky, in case some legacy consoles really show it as blinking? I'm not sure about that.) This limit is buried deep in kernel sources for default tty drivers. Trying to use the Neovim's default 256 colors in this case gives totally bad colors, breaking all color schemes and sometimes rendering parts of the text invisible. A simple change enables code paths for handling 8/16 colors, which are still present in Neovim codebase. --- src/nvim/tui/tui.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 50558e644a..ea10130056 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -135,6 +135,8 @@ static void terminfo_start(UI *ui) data->ut = unibi_dummy(); } fix_terminfo(data); + // Set 't_Co' from the result of unibilium & fix_terminfo. + t_colors = unibi_get_num(data->ut, unibi_max_colors); // Enter alternate screen and clear unibi_out(ui, unibi_enter_ca_mode); unibi_out(ui, unibi_clear_screen); From fab62141c8bd10bc55d857e94e5b686434015d34 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 2 Jul 2016 18:08:25 -0400 Subject: [PATCH 2/4] options: Default t_Co to 256. This commit doesn't change any behavior, only moves the init out of main.c We _could_ move some initialization from tui.c:terminfo_start to an earlier phase, in order to avoid mis-reporting 't_Co' during startup. But this will be messy, and gains very little: TERM=linux works "good enough" as long as we correct t_Co in tui.c:terminfo_start (c5b02d5a7). --- src/nvim/globals.h | 2 +- src/nvim/main.c | 3 --- src/nvim/option.c | 1 + 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 42fde50bee..7f91903106 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -414,7 +414,7 @@ EXTERN int provider_call_nesting INIT(= 0); EXTERN char_u hash_removed; -EXTERN int t_colors INIT(= 0); /* int value of T_CCO */ +EXTERN int t_colors INIT(= 256); // int value of T_CCO /* * When highlight_match is TRUE, highlight a match, starting at the cursor diff --git a/src/nvim/main.c b/src/nvim/main.c index a876a0ad21..5cd1dbb467 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -276,7 +276,6 @@ int main(int argc, char **argv) printf(_("%d files to edit\n"), GARGCOUNT); full_screen = true; - t_colors = 256; check_tty(¶ms); /* @@ -1671,8 +1670,6 @@ static bool do_user_initialization(void) } /// Source startup scripts -/// -/// @param[in] static void source_startup_scripts(const mparm_T *const parmp) FUNC_ATTR_NONNULL_ALL { diff --git a/src/nvim/option.c b/src/nvim/option.c index 020a119fd3..a844c4ed80 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -4404,6 +4404,7 @@ bool get_tty_option(char *name, char **value) if (is_tty_option(name)) { if (value) { + // XXX: All other t_* options were removed in 3baba1e7. *value = xstrdup(""); } return true; From c00231078790e7f700b820a96f69387c42518a10 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 3 Jul 2016 01:17:26 -0400 Subject: [PATCH 3/4] tui: Assume 256 colors in most cases. Assume 256 colors if: - $TERM contains "xterm" or "256" - $COLORTERM contains "256" Closes #2912 --- src/nvim/tui/tui.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index ea10130056..d220df508a 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -788,6 +788,7 @@ static void fix_terminfo(TUIData *data) unibi_term *ut = data->ut; const char *term = os_getenv("TERM"); + const char *colorterm = os_getenv("COLORTERM"); if (!term) { goto end; } @@ -833,10 +834,10 @@ static void fix_terminfo(TUIData *data) #define XTERM_SETAB \ "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m" - if (os_getenv("COLORTERM") != NULL - && (!strcmp(term, "xterm") || !strcmp(term, "screen"))) { - // probably every modern terminal that sets TERM=xterm supports 256 - // colors(eg: gnome-terminal). Also do it when TERM=screen. + if ((colorterm && strstr(colorterm, "256")) + || strstr(term, "256") + || strstr(term, "xterm")) { + // Assume TERM~=xterm or COLORTERM~=256 supports 256 colors. unibi_set_num(ut, unibi_max_colors, 256); unibi_set_str(ut, unibi_set_a_foreground, XTERM_SETAF); unibi_set_str(ut, unibi_set_a_background, XTERM_SETAB); From 173d366a5b0b5f0784a1da8aef4fe5d0cab7e1ec Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 3 Jul 2016 01:13:48 -0400 Subject: [PATCH 4/4] test: TUI colors ('t_Co') --- test/functional/options/defaults_spec.lua | 6 +-- test/functional/terminal/tui_spec.lua | 60 +++++++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua index ed978cd17e..a36939b0bd 100644 --- a/test/functional/options/defaults_spec.lua +++ b/test/functional/options/defaults_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq +local eval, eq = helpers.eval, helpers.eq local execute = helpers.execute local function init_session(...) @@ -15,10 +15,6 @@ local function init_session(...) end describe('startup defaults', function() - before_each(function() - clear() - end) - describe(':filetype', function() local function expect_filetype(expected) local screen = Screen.new(48, 4) diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 91789d6575..4bae9a8d02 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -301,3 +301,63 @@ describe('tui focus event handling', function() ]]) end) end) + +-- These tests require `thelpers` because --headless/--embed +-- does not initialize the TUI. +describe("tui 't_Co' (terminal colors)", function() + local screen + + local function assert_term_colors(term, colorterm, maxcolors) + helpers.clear({env={TERM=term}, args={}}) + -- This is ugly because :term/termopen() forces TERM=xterm-256color. + -- TODO: Revisit this after jobstart/termopen accept `env` dict. + screen = thelpers.screen_setup(0, string.format( + [=[['sh', '-c', 'TERM=%s %s %s -u NONE -i NONE --cmd "silent set noswapfile"']]=], + term, + (colorterm ~= nil and "COLORTERM="..colorterm or ""), + helpers.nvim_prog)) + + thelpers.feed_data(":echo &t_Co\n") + screen:expect(string.format([[ + {1: } | + ~ | + ~ | + ~ | + [No Name] | + %-3s | + -- TERMINAL -- | + ]], tostring(maxcolors and maxcolors or ""))) + end + + it("unknown TERM sets empty 't_Co'", function() + assert_term_colors("yet-another-term", nil, nil) + end) + + it("unknown TERM with COLORTERM=screen-256color uses 256 colors", function() + assert_term_colors("yet-another-term", "screen-256color", 256) + end) + + it("TERM=linux uses 8 colors", function() + assert_term_colors("linux", nil, 8) + end) + + it("TERM=screen uses 8 colors", function() + assert_term_colors("screen", nil, 8) + end) + + it("TERM=screen COLORTERM=screen-256color uses 256 colors", function() + assert_term_colors("screen", "screen-256color", 256) + end) + + it("TERM=yet-another-term COLORTERM=screen-256color uses 256 colors", function() + assert_term_colors("screen", "screen-256color", 256) + end) + + it("TERM=xterm uses 256 colors", function() + assert_term_colors("xterm", nil, 256) + end) + + it("TERM=xterm-256color uses 256 colors", function() + assert_term_colors("xterm-256color", nil, 256) + end) +end)