From 7227772045b5a8464a07f0caaa459ab15f8fb142 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sun, 30 Nov 2025 16:28:35 +0000 Subject: [PATCH] fix: only show console color when supported --- src/ImageConverter/ImageConverter.cpp | 2 + src/ImageConverter/ImageConverterArgs.cpp | 6 +- src/Linker/Linker.cpp | 2 + src/Linker/LinkerArgs.cpp | 6 +- src/ModMan/ModManArgs.cpp | 6 +- src/ModMan/main.cpp | 2 + src/RawTemplater/RawTemplater.cpp | 2 + src/RawTemplater/RawTemplaterArguments.cpp | 6 +- src/Unlinker/Unlinker.cpp | 2 + src/Unlinker/UnlinkerArgs.cpp | 6 +- src/Utils/Utils/Logging/Log.cpp | 66 ++++++++++++++++++- src/Utils/Utils/Logging/Log.h | 22 ++++--- .../ZoneCodeGenerator.cpp | 3 + .../ZoneCodeGeneratorArguments.cpp | 6 +- 14 files changed, 108 insertions(+), 29 deletions(-) diff --git a/src/ImageConverter/ImageConverter.cpp b/src/ImageConverter/ImageConverter.cpp index 22fa6090..2db2e011 100644 --- a/src/ImageConverter/ImageConverter.cpp +++ b/src/ImageConverter/ImageConverter.cpp @@ -35,6 +35,8 @@ namespace image_converter bool Start(const int argc, const char** argv) override { + con::init(); + auto shouldContinue = true; if (!m_args.ParseArgs(argc, argv, shouldContinue)) return false; diff --git a/src/ImageConverter/ImageConverterArgs.cpp b/src/ImageConverter/ImageConverterArgs.cpp index 1f9a7816..fad732b8 100644 --- a/src/ImageConverter/ImageConverterArgs.cpp +++ b/src/ImageConverter/ImageConverterArgs.cpp @@ -146,12 +146,12 @@ bool ImageConverterArgs::ParseArgs(const int argc, const char** argv, bool& shou // -v; --verbose if (m_argument_parser.IsOptionSpecified(OPTION_VERBOSE)) - con::globalLogLevel = con::LogLevel::DEBUG; + con::set_log_level(con::LogLevel::DEBUG); else - con::globalLogLevel = con::LogLevel::INFO; + con::set_log_level(con::LogLevel::INFO); // --no-color - con::globalUseColor = !m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR); + con::set_use_color(!m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR)); return true; } diff --git a/src/Linker/Linker.cpp b/src/Linker/Linker.cpp index b7dce2bd..e62109a5 100644 --- a/src/Linker/Linker.cpp +++ b/src/Linker/Linker.cpp @@ -432,6 +432,8 @@ class LinkerImpl final : public Linker public: bool Start(const int argc, const char** argv) override { + con::init(); + auto shouldContinue = true; if (!m_args.ParseArgs(argc, argv, shouldContinue)) return false; diff --git a/src/Linker/LinkerArgs.cpp b/src/Linker/LinkerArgs.cpp index d363c75c..654bda1f 100644 --- a/src/Linker/LinkerArgs.cpp +++ b/src/Linker/LinkerArgs.cpp @@ -203,12 +203,12 @@ bool LinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldContin // -v; --verbose if (m_argument_parser.IsOptionSpecified(OPTION_VERBOSE)) - con::globalLogLevel = con::LogLevel::DEBUG; + con::set_log_level(con::LogLevel::DEBUG); else - con::globalLogLevel = con::LogLevel::INFO; + con::set_log_level(con::LogLevel::INFO); // --no-color - con::globalUseColor = !m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR); + con::set_use_color(!m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR)); // b; --base-folder if (m_argument_parser.IsOptionSpecified(OPTION_BASE_FOLDER)) diff --git a/src/ModMan/ModManArgs.cpp b/src/ModMan/ModManArgs.cpp index b5b1f88c..b73d3c73 100644 --- a/src/ModMan/ModManArgs.cpp +++ b/src/ModMan/ModManArgs.cpp @@ -94,12 +94,12 @@ bool ModManArgs::ParseArgs(const int argc, const char** argv, bool& shouldContin // -v; --verbose if (m_argument_parser.IsOptionSpecified(OPTION_VERBOSE)) - con::globalLogLevel = con::LogLevel::DEBUG; + con::set_log_level(con::LogLevel::DEBUG); else - con::globalLogLevel = con::LogLevel::INFO; + con::set_log_level(con::LogLevel::INFO); // --no-color - con::globalUseColor = !m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR); + con::set_use_color(!m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR)); return true; } diff --git a/src/ModMan/main.cpp b/src/ModMan/main.cpp index fe8eeba1..4441853f 100644 --- a/src/ModMan/main.cpp +++ b/src/ModMan/main.cpp @@ -129,6 +129,8 @@ int main(int argc, const char** argv) g_set_application_name("OpenAssetTools ModMan"); #endif + con::init(); + ModManArgs args; auto shouldContinue = true; if (!args.ParseArgs(MODMAN_ARGC, MODMAN_ARGV, shouldContinue)) diff --git a/src/RawTemplater/RawTemplater.cpp b/src/RawTemplater/RawTemplater.cpp index 57465926..85554e28 100644 --- a/src/RawTemplater/RawTemplater.cpp +++ b/src/RawTemplater/RawTemplater.cpp @@ -46,6 +46,8 @@ public: int Run(const int argc, const char** argv) { + con::init(); + auto shouldContinue = true; if (!m_args.ParseArgs(argc, argv, shouldContinue)) return 1; diff --git a/src/RawTemplater/RawTemplaterArguments.cpp b/src/RawTemplater/RawTemplaterArguments.cpp index a933b425..743ba7a6 100644 --- a/src/RawTemplater/RawTemplaterArguments.cpp +++ b/src/RawTemplater/RawTemplaterArguments.cpp @@ -127,12 +127,12 @@ bool RawTemplaterArguments::ParseArgs(const int argc, const char** argv, bool& s // -v; --verbose if (m_argument_parser.IsOptionSpecified(OPTION_VERBOSE)) - con::globalLogLevel = con::LogLevel::DEBUG; + con::set_log_level(con::LogLevel::DEBUG); else - con::globalLogLevel = con::LogLevel::INFO; + con::set_log_level(con::LogLevel::INFO); // --no-color - con::globalUseColor = !m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR); + con::set_use_color(!m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR)); // -o; --output if (m_argument_parser.IsOptionSpecified(OPTION_OUTPUT_FOLDER)) diff --git a/src/Unlinker/Unlinker.cpp b/src/Unlinker/Unlinker.cpp index e1f6ee76..54192060 100644 --- a/src/Unlinker/Unlinker.cpp +++ b/src/Unlinker/Unlinker.cpp @@ -30,6 +30,8 @@ public: */ bool Start(const int argc, const char** argv) { + con::init(); + auto shouldContinue = true; if (!m_args.ParseArgs(argc, argv, shouldContinue)) return false; diff --git a/src/Unlinker/UnlinkerArgs.cpp b/src/Unlinker/UnlinkerArgs.cpp index 3ae9224f..86fc3486 100644 --- a/src/Unlinker/UnlinkerArgs.cpp +++ b/src/Unlinker/UnlinkerArgs.cpp @@ -303,12 +303,12 @@ bool UnlinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldCont // -v; --verbose if (m_argument_parser.IsOptionSpecified(OPTION_VERBOSE)) - con::globalLogLevel = con::LogLevel::DEBUG; + con::set_log_level(con::LogLevel::DEBUG); else - con::globalLogLevel = con::LogLevel::INFO; + con::set_log_level(con::LogLevel::INFO); // --no-color - con::globalUseColor = !m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR); + con::set_use_color(!m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR)); // -min; --minimal-zone m_minimal_zone_def = m_argument_parser.IsOptionSpecified(OPTION_MINIMAL_ZONE_FILE); diff --git a/src/Utils/Utils/Logging/Log.cpp b/src/Utils/Utils/Logging/Log.cpp index eee3d6d3..172810b2 100644 --- a/src/Utils/Utils/Logging/Log.cpp +++ b/src/Utils/Utils/Logging/Log.cpp @@ -3,10 +3,72 @@ #include #include +#ifdef _WIN32 +#include +#endif + +namespace +{ + bool logLevelSet = false; + + bool globalUseColor = true; + bool colorSet = false; + + bool CanUseColor() + { +#ifdef _WIN32 + DWORD dwMode = 0; + const auto stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleMode(stdoutHandle, &dwMode); + if (!(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + { + SetConsoleMode(stdoutHandle, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + dwMode = 0; + GetConsoleMode(stdoutHandle, &dwMode); + if (!(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + return false; + } + + const auto stderrHandle = GetStdHandle(STD_ERROR_HANDLE); + GetConsoleMode(stderrHandle, &dwMode); + if (!(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + { + SetConsoleMode(stderrHandle, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + dwMode = 0; + GetConsoleMode(stderrHandle, &dwMode); + if (!(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + return false; + } +#endif + + return true; + } +} // namespace + namespace con { - LogLevel globalLogLevel = LogLevel::INFO; - bool globalUseColor = true; + LogLevel _globalLogLevel = LogLevel::INFO; + + void init() + { + if (!logLevelSet) + set_log_level(LogLevel::INFO); + + if (!colorSet) + set_use_color(true); + } + + void set_log_level(const LogLevel value) + { + logLevelSet = true; + _globalLogLevel = value; + } + + void set_use_color(const bool value) + { + colorSet = true; + globalUseColor = value && CanUseColor(); + } void _debug_internal(const std::string& str) { diff --git a/src/Utils/Utils/Logging/Log.h b/src/Utils/Utils/Logging/Log.h index 2cd2f746..f6751e12 100644 --- a/src/Utils/Utils/Logging/Log.h +++ b/src/Utils/Utils/Logging/Log.h @@ -1,11 +1,12 @@ #pragma once +#include #include #include namespace con { - enum class LogLevel + enum class LogLevel : std::uint8_t { DEBUG = 0, INFO, @@ -13,8 +14,11 @@ namespace con ERROR }; - extern LogLevel globalLogLevel; - extern bool globalUseColor; + extern LogLevel _globalLogLevel; + + void init(); + void set_log_level(LogLevel value); + void set_use_color(bool value); void _debug_internal(const std::string& str); void _info_internal(const std::string& str); @@ -23,42 +27,42 @@ namespace con inline void debug(const std::string& str) { - if (static_cast(globalLogLevel) > static_cast(LogLevel::DEBUG)) + if (static_cast(_globalLogLevel) > static_cast(LogLevel::DEBUG)) return; _debug_internal(str); } template void debug(std::format_string fmt, Arg0&& arg0, OtherArgs&&... otherArgs) { - if (static_cast(globalLogLevel) > static_cast(LogLevel::DEBUG)) + if (static_cast(_globalLogLevel) > static_cast(LogLevel::DEBUG)) return; _debug_internal(std::vformat(fmt.get(), std::make_format_args(arg0, otherArgs...))); } inline void info(const std::string& str) { - if (static_cast(globalLogLevel) > static_cast(LogLevel::INFO)) + if (static_cast(_globalLogLevel) > static_cast(LogLevel::INFO)) return; _info_internal(str); } template void info(std::format_string fmt, Arg0&& arg0, OtherArgs&&... otherArgs) { - if (static_cast(globalLogLevel) > static_cast(LogLevel::INFO)) + if (static_cast(_globalLogLevel) > static_cast(LogLevel::INFO)) return; _info_internal(std::vformat(fmt.get(), std::make_format_args(arg0, otherArgs...))); } inline void warn(const std::string& str) { - if (static_cast(globalLogLevel) > static_cast(LogLevel::WARN)) + if (static_cast(_globalLogLevel) > static_cast(LogLevel::WARN)) return; _warn_internal(str); } template void warn(std::format_string fmt, Arg0&& arg0, OtherArgs&&... otherArgs) { - if (static_cast(globalLogLevel) > static_cast(LogLevel::WARN)) + if (static_cast(_globalLogLevel) > static_cast(LogLevel::WARN)) return; _warn_internal(std::vformat(fmt.get(), std::make_format_args(arg0, otherArgs...))); } diff --git a/src/ZoneCodeGeneratorLib/ZoneCodeGenerator.cpp b/src/ZoneCodeGeneratorLib/ZoneCodeGenerator.cpp index 506785a9..8039663e 100644 --- a/src/ZoneCodeGeneratorLib/ZoneCodeGenerator.cpp +++ b/src/ZoneCodeGeneratorLib/ZoneCodeGenerator.cpp @@ -6,6 +6,7 @@ #include "Persistence/IDataRepository.h" #include "Persistence/InMemory/InMemoryRepository.h" #include "Printing/PrettyPrinter.h" +#include "Utils/Logging/Log.h" #include "ZoneCodeGeneratorArguments.h" #include @@ -23,6 +24,8 @@ public: int Run(const int argc, const char** argv) override { + con::init(); + auto shouldContinue = true; if (!m_args.ParseArgs(argc, argv, shouldContinue)) return 1; diff --git a/src/ZoneCodeGeneratorLib/ZoneCodeGeneratorArguments.cpp b/src/ZoneCodeGeneratorLib/ZoneCodeGeneratorArguments.cpp index f508ba59..05d8d93d 100644 --- a/src/ZoneCodeGeneratorLib/ZoneCodeGeneratorArguments.cpp +++ b/src/ZoneCodeGeneratorLib/ZoneCodeGeneratorArguments.cpp @@ -173,12 +173,12 @@ bool ZoneCodeGeneratorArguments::ParseArgs(const int argc, const char** argv, bo // -v; --verbose if (m_argument_parser.IsOptionSpecified(OPTION_VERBOSE)) - con::globalLogLevel = con::LogLevel::DEBUG; + con::set_log_level(con::LogLevel::DEBUG); else - con::globalLogLevel = con::LogLevel::INFO; + con::set_log_level(con::LogLevel::INFO); // --no-color - con::globalUseColor = !m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR); + con::set_use_color(!m_argument_parser.IsOptionSpecified(OPTION_NO_COLOR)); // -p; --print if (m_argument_parser.IsOptionSpecified(OPTION_PRINT))