From d7a22c236504ca3d2ba7b9d760cc39932fafe07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigbj=C3=B8rn=20Skj=C3=A6ret?= Date: Sat, 6 Dec 2025 16:15:22 +0100 Subject: [PATCH] change --color to accept on/off/auto, default to auto --- common/arg.cpp | 24 ++++++++++++++++++------ common/common.cpp | 26 ++++++++++++++++++++++++++ common/common.h | 7 +++++++ common/log.cpp | 29 +++-------------------------- 4 files changed, 54 insertions(+), 32 deletions(-) diff --git a/common/arg.cpp b/common/arg.cpp index 9e062ee7a1b..4203da4a0a6 100644 --- a/common/arg.cpp +++ b/common/arg.cpp @@ -708,6 +708,8 @@ common_params_context common_params_parser_init(common_params & params, llama_ex params.use_jinja = true; } + params.use_color = tty_can_use_colors(); + // load dynamic backends ggml_backend_load_all(); @@ -790,10 +792,20 @@ common_params_context common_params_parser_init(common_params & params, llama_ex } ).set_examples({LLAMA_EXAMPLE_MAIN})); add_opt(common_arg( - {"-co", "--color"}, - string_format("colorise output to distinguish prompt and user input from generations (default: %s)", params.use_color ? "true" : "false"), - [](common_params & params) { - params.use_color = true; + {"-co", "--color"}, "[on|off|auto]", + "Colorize output to distinguish prompt and user input from generations ('on', 'off', or 'auto', default: 'auto')\n" + "'auto' enables colors when output is to a terminal", + [](common_params & params, const std::string & value) { + if (is_truthy(value)) { + params.use_color = true; + } else if (is_falsey(value)) { + params.use_color = false; + } else if (is_autoy(value)) { + params.use_color = tty_can_use_colors(); + } else { + throw std::invalid_argument( + string_format("error: unknown value for --color: '%s'\n", value.c_str())); + } } ).set_examples({LLAMA_EXAMPLE_MAIN, LLAMA_EXAMPLE_SPECULATIVE, LLAMA_EXAMPLE_LOOKUP})); add_opt(common_arg( @@ -1022,7 +1034,7 @@ common_params_context common_params_parser_init(common_params & params, llama_ex params.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_AUTO; } else { throw std::runtime_error( - string_format("error: unkown value for --flash-attn: '%s'\n", value.c_str())); + string_format("error: unknown value for --flash-attn: '%s'\n", value.c_str())); } }).set_env("LLAMA_ARG_FLASH_ATTN")); add_opt(common_arg( @@ -2696,7 +2708,7 @@ common_params_context common_params_parser_init(common_params & params, llama_ex common_log_set_colors(common_log_main(), LOG_COLORS_AUTO); } else { throw std::invalid_argument( - string_format("error: unkown value for --log-colors: '%s'\n", value.c_str())); + string_format("error: unknown value for --log-colors: '%s'\n", value.c_str())); } } ).set_env("LLAMA_LOG_COLORS")); diff --git a/common/common.cpp b/common/common.cpp index a42f4884359..0497f90a280 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -982,6 +982,32 @@ std::vector fs_list(const std::string & path, bool include_dir return files; } +// +// TTY utils +// + +bool tty_can_use_colors() { + // Check NO_COLOR environment variable (https://no-color.org/) + if (const char * no_color = std::getenv("NO_COLOR")) { + if (no_color[0] != '\0') { + return false; + } + } + + // Check TERM environment variable + if (const char * term = std::getenv("TERM")) { + if (std::strcmp(term, "dumb") == 0) { + return false; + } + } + + // Check if stdout and stderr are connected to a terminal + // We check both because log messages can go to either + bool stdout_is_tty = isatty(fileno(stdout)); + bool stderr_is_tty = isatty(fileno(stderr)); + + return stdout_is_tty || stderr_is_tty; +} // // Model utils diff --git a/common/common.h b/common/common.h index 179113a4dbf..d28e48991c3 100644 --- a/common/common.h +++ b/common/common.h @@ -655,6 +655,13 @@ struct common_file_info { }; std::vector fs_list(const std::string & path, bool include_directories); +// +// TTY utils +// + +// Auto-detect if colors can be enabled based on terminal and environment +bool tty_can_use_colors(); + // // Model utils // diff --git a/common/log.cpp b/common/log.cpp index b6c9ff79a43..00a03f158d3 100644 --- a/common/log.cpp +++ b/common/log.cpp @@ -1,3 +1,4 @@ +#include "common.h" #include "log.h" #include @@ -26,30 +27,6 @@ void common_log_set_verbosity_thold(int verbosity) { common_log_verbosity_thold = verbosity; } -// Auto-detect if colors should be enabled based on terminal and environment -static bool common_log_should_use_colors_auto() { - // Check NO_COLOR environment variable (https://no-color.org/) - if (const char * no_color = std::getenv("NO_COLOR")) { - if (no_color[0] != '\0') { - return false; - } - } - - // Check TERM environment variable - if (const char * term = std::getenv("TERM")) { - if (std::strcmp(term, "dumb") == 0) { - return false; - } - } - - // Check if stdout and stderr are connected to a terminal - // We check both because log messages can go to either - bool stdout_is_tty = isatty(fileno(stdout)); - bool stderr_is_tty = isatty(fileno(stderr)); - - return stdout_is_tty || stderr_is_tty; -} - static int64_t t_us() { return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); } @@ -391,7 +368,7 @@ struct common_log * common_log_main() { static std::once_flag init_flag; std::call_once(init_flag, [&]() { // Set default to auto-detect colors - log.set_colors(common_log_should_use_colors_auto()); + log.set_colors(tty_can_use_colors()); }); return &log; @@ -422,7 +399,7 @@ void common_log_set_file(struct common_log * log, const char * file) { void common_log_set_colors(struct common_log * log, log_colors colors) { if (colors == LOG_COLORS_AUTO) { - log->set_colors(common_log_should_use_colors_auto()); + log->set_colors(tty_can_use_colors()); return; }