From: pancake Date: Thu, 18 Dec 2025 13:34:41 +0000 (+0100) Subject: Better color limit checks with TERM ##cons X-Git-Url: https://git.feebdaed.xyz/?a=commitdiff_plain;h=d76f20e143ce60ee8854bbe1064dd5d28b855010;p=0xmirror%2Fradare2.git Better color limit checks with TERM ##cons --- diff --git a/libr/cons/cons.c b/libr/cons/cons.c index 3934eb3482..8f2cbf3a9c 100644 --- a/libr/cons/cons.c +++ b/libr/cons/cons.c @@ -120,7 +120,7 @@ static void mark_free(RConsMark *m) { } /* - * Update the scrcolorlimit based on TERM environment variable. + * Update the color_limit based on TERM environment variable. * * This function provides a basic, hard-coded mapping from TERM values to * maximum color capabilities. It is intentionally simple and does not implement @@ -137,27 +137,31 @@ static void mark_free(RConsMark *m) { * - No consideration of terminal multiplexers (screen/tmux) capability passthrough * - No handling of terminal emulation compatibility layers */ -static void rcons_update_scrcolorlimit_from_term(RCons *cons) { +static void rcons_update_color_limit_from_term(RCons *cons) { char *term = r_sys_getenv ("TERM"); - int limit = COLOR_MODE_16M; // Default to no limit for unknown terminals + int limit = COLOR_MODE_16M; // Default to no limit + // alacritty, kitty, ghostty, wezterm, foot, konsole-256color, iterm2, .. if (R_STR_ISNOTEMPTY (term)) { if (!strcmp (term, "dumb")) { limit = COLOR_MODE_DISABLED; } else if (!strcmp (term, "vt100") || !strcmp (term, "vt102") || !strcmp (term, "vt220") || !strcmp (term, "vt200") || - !strncmp (term, "vt2", 3)) { + r_str_startswith (term, "vt2")) { limit = COLOR_MODE_DISABLED; } else if (!strcmp (term, "cons25")) { limit = COLOR_MODE_DISABLED; } else if (strstr (term, "16color")) { limit = COLOR_MODE_16; } else if (strstr (term, "256color")) { - limit = COLOR_MODE_256; + // requires extra check for COLORTERM=truecolor|24bit + // but it's the standard, and 99% of them support truecolor + // limit = COLOR_MODE_256; + limit = COLOR_MODE_16M; } else if (!strcmp (term, "ansi") || !strcmp (term, "screen")) { limit = COLOR_MODE_16; } } - cons->context->scrcolorlimit = limit; + cons->context->color_limit = limit; free (term); } @@ -181,13 +185,13 @@ static void init_cons_context(RCons *cons, RConsContext * R_NULLABLE parent) { if (parent) { ctx->color_mode = parent->color_mode; - ctx->scrcolorlimit = parent->scrcolorlimit; + ctx->color_limit = parent->color_limit; r_cons_pal_copy (cons, parent); } else { ctx->color_mode = COLOR_MODE_DISABLED; - ctx->scrcolorlimit = COLOR_MODE_16M; // Default to no limit + ctx->color_limit = COLOR_MODE_16M; // Default to no limit r_cons_pal_init (cons); - rcons_update_scrcolorlimit_from_term (cons); + rcons_update_color_limit_from_term (cons); } cons_grep_reset (&ctx->grep); } diff --git a/libr/core/cconfig.c b/libr/core/cconfig.c index 0c75c5318f..9b23b5afe0 100644 --- a/libr/core/cconfig.c +++ b/libr/core/cconfig.c @@ -1732,7 +1732,17 @@ static bool cb_scr_color_ophex(void *user, void *data) { static bool cb_color(void *user, void *data) { RCore *core = (RCore *)user; + const int limit = core->cons->context->color_limit; RConfigNode *node = (RConfigNode *)data; + if (*node->value == '?') { + r_cons_printf (core->cons, "Possible values:\n" + " 0 - disable colors\n" + " 1 - ansi 16 colors\n" + " 2 - 256 colors\n" + " 3 - 16 million colors (truecolor)\n" + "Maximum supported by your terminal: %d\n", limit); + return false; + } if (node->i_value) { core->print->flags |= R_PRINT_FLAGS_COLOR; } else { @@ -1743,11 +1753,13 @@ static bool cb_color(void *user, void *data) { } else if (!strcmp (node->value, "false")) { node->i_value = 0; } - int requested_mode = (node->i_value > COLOR_MODE_16M) - ? COLOR_MODE_16M - : node->i_value; - // Enforce scrcolorlimit: never exceed the terminal's capability - core->cons->context->color_mode = R_MIN (requested_mode, core->cons->context->scrcolorlimit); + int requested_mode = R_MIN (node->i_value, COLOR_MODE_16M); + if (requested_mode > limit) { + R_LOG_WARN ("Color mode %d requested but terminal only supports %d", requested_mode, limit); + // core->cons->context->color_mode = R_MIN (requested_mode, limit); + } + core->cons->context->color_mode = requested_mode; + r_cons_pal_reload (core->cons); // double flute r_print_set_flags (core->print, core->print->flags); r_log_set_colors (node->i_value); @@ -2666,6 +2678,13 @@ static bool cb_scrhighlight(void *user, void *data) { } #if R2__WINDOWS__ +static inline DWORD modevalue(DWORD mode, bool set) { + if (set) { + return mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING; + } + return mode & ~ENABLE_VIRTUAL_TERMINAL_PROCESSING & ~ENABLE_WRAP_AT_EOL_OUTPUT; +} + static bool scr_vtmode(void *user, void *data) { RCore *core = (RCore *)user; RConfigNode *node = (RConfigNode *)data; @@ -2687,18 +2706,10 @@ static bool scr_vtmode(void *user, void *data) { } HANDLE streams[] = { GetStdHandle (STD_OUTPUT_HANDLE), GetStdHandle (STD_ERROR_HANDLE) }; int i; - if (node->i_value > 0) { - for (i = 0; i < R_ARRAY_SIZE (streams); i++) { - GetConsoleMode (streams[i], &mode); - SetConsoleMode (streams[i], - mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING); - } - } else { - for (i = 0; i < R_ARRAY_SIZE (streams); i++) { - GetConsoleMode (streams[i], &mode); - SetConsoleMode (streams[i], - mode & ~ENABLE_VIRTUAL_TERMINAL_PROCESSING & ~ENABLE_WRAP_AT_EOL_OUTPUT); - } + bool set = (node->i_value > 0); + for (i = 0; i < R_ARRAY_SIZE (streams); i++) { + GetConsoleMode (streams[i], &mode); + SetConsoleMode (streams[i], modevalue (mode, set)); } return true; } @@ -4660,7 +4671,8 @@ R_API int r_core_config_init(RCore *core) { SETB ("scr.tts", "false", "use tts if available by a command (see ic)"); SETCB ("scr.prompt", "true", &cb_scrprompt, "show user prompt (used by r2 -q)"); SETICB ("scr.limit", 0, &cb_scr_limit, "stop printing after N bytes"); - SETICB ("scr.color", (core->print->flags & R_PRINT_FLAGS_COLOR)? COLOR_MODE_16: COLOR_MODE_DISABLED, &cb_color, "enable colors (0: none, 1: ansi, 2: 256 colors, 3: truecolor)"); + const int default_color = (core->print->flags & R_PRINT_FLAGS_COLOR)? core->cons->context->color_limit: COLOR_MODE_DISABLED; + SETICB ("scr.color", default_color, &cb_color, "enable colors (0: none, 1: ansi, 2: 256 colors, 3: truecolor)"); r_config_set_getter (cfg, "scr.color", (RConfigCallback)cb_color_getter); SETCB ("scr.color.grep", "false", &cb_scr_color_grep, "enable colors when using ~grep"); SETB ("scr.color.pipe", "false", "enable colors when using pipes"); diff --git a/libr/include/r_cons.h b/libr/include/r_cons.h index a76dfadb69..b91549411e 100644 --- a/libr/include/r_cons.h +++ b/libr/include/r_cons.h @@ -449,7 +449,7 @@ typedef struct r_cons_context_t { bool pageable; int color_mode; - int scrcolorlimit; // maximum color mode allowed based on TERM detection + int color_limit; // maximum mode based TERM envvar RConsPalette cpal; RConsPrintablePalette pal;