Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ See the [installation tutorial](https://gazebosim.org/api/common/5/install.html)

Please refer to the [examples directory](https://github.com/gazebosim/gz-common/tree/main/examples).

Console color output can be controlled with `GZ_CONSOLE_COLOR`:

* `yes`: always emit ANSI color codes.
* `no`: never emit ANSI color codes.

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README documents only yes/no, but the implementation is intended to address the broader “disable color output” use case (and the issue suggests gtest-like behavior). If you add support for 0/1 and/or auto, please document those here; otherwise consider explicitly stating that only yes/no are supported and that other values will be ignored with a warning.

Suggested change
Only the values `yes` and `no` are recognized; other values are ignored.

Copilot uses AI. Check for mistakes.
Only `yes` and `no` are recognized. Other values are ignored with a warning.

# Folder Structure

Refer to the following table for information about important directories and files in this repository.
Expand Down
38 changes: 36 additions & 2 deletions src/Console.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@
using namespace gz;
using namespace common;

#define CONSOLE_COLOR_ON 1
#define CONSOLE_COLOR_OFF 0

static int consoleColorMode = CONSOLE_COLOR_ON;

/////////////////////////////////////////////////
static void UpdateConsoleColorMode()
{
std::string consoleColor;
if (!env("GZ_CONSOLE_COLOR", consoleColor))
return;

const auto value = lowercase(trimmed(consoleColor));
if (value == "yes")
{
consoleColorMode = CONSOLE_COLOR_ON;
}
else if (value == "no")
{
consoleColorMode = CONSOLE_COLOR_OFF;
}
else
{
std::cerr << "Invalid value for GZ_CONSOLE_COLOR='" << consoleColor
<< "'. Valid values are: yes, no." << std::endl;
}
}


FileLogger common::Console::log("");

Expand Down Expand Up @@ -156,7 +184,11 @@ int Logger::Buffer::sync()
outstr.pop_back();

std::stringstream ss;
ss << "\033[1;" << this->color << "m" << outstr << "\033[0m";
if (consoleColorMode == CONSOLE_COLOR_OFF)
ss << outstr;
else
ss << "\033[1;" << this->color << "m" << outstr << "\033[0m";

if (lastNewLine)
ss << std::endl;

Expand Down Expand Up @@ -190,7 +222,7 @@ int Logger::Buffer::sync()

{
std::lock_guard<std::mutex> lk(this->syncMutex);
if (vtProcessing)
if (vtProcessing && consoleColorMode != CONSOLE_COLOR_OFF)
outStream << "\x1b[" << this->color << "m" << outstr << "\x1b[m";
else
outStream << outstr;
Expand Down Expand Up @@ -234,6 +266,8 @@ void FileLogger::Init(const std::string &_directory,
{
std::string logPath;

UpdateConsoleColorMode();

if (_directory.empty() ||
#ifndef _WIN32
_directory[0] != '/'
Expand Down
68 changes: 68 additions & 0 deletions src/Console_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -549,3 +549,71 @@ TEST_F(Console_TEST, NoInitAndLogNoHome)
// This should not throw
gzlog << "this is a test" << std::endl;
}

/////////////////////////////////////////////////
/// \brief Test Console color output with GZ_CONSOLE_COLOR=yes
TEST_F(Console_TEST, ConsoleColorYes)
{
common::Console::SetVerbosity(3);
EXPECT_TRUE(common::setenv("GZ_CONSOLE_COLOR", "yes"));

// Initialize
auto path = common::uuid();
gzLogInit(path, "test.log");

// stdout to check for ANSI codes
testing::internal::CaptureStdout();
gzmsg << "color yes test" << std::endl;
std::string output = testing::internal::GetCapturedStdout();

#ifndef _WIN32
// Check for ANSI escape sequence
EXPECT_TRUE(output.find("\033[") != std::string::npos);
#endif

EXPECT_TRUE(common::unsetenv("GZ_CONSOLE_COLOR"));
common::Console::SetVerbosity(1);
gzLogClose();
}

/////////////////////////////////////////////////
/// \brief Test Console color output with GZ_CONSOLE_COLOR=no
TEST_F(Console_TEST, ConsoleColorNo)
{
common::Console::SetVerbosity(3);
EXPECT_TRUE(common::setenv("GZ_CONSOLE_COLOR", "no"));

// Initialize
auto path = common::uuid();
gzLogInit(path, "test.log");

// stdout to check for no ANSI codes
testing::internal::CaptureStdout();
gzmsg << "color no test" << std::endl;
std::string output = testing::internal::GetCapturedStdout();

// Check for no ANSI escape sequence
EXPECT_TRUE(output.find("\033[") == std::string::npos);

EXPECT_TRUE(common::unsetenv("GZ_CONSOLE_COLOR"));
common::Console::SetVerbosity(1);
gzLogClose();
}

/////////////////////////////////////////////////
/// \brief Test invalid GZ_CONSOLE_COLOR value warning
TEST_F(Console_TEST, ConsoleColorInvalid)
{
EXPECT_TRUE(common::setenv("GZ_CONSOLE_COLOR", "maybe"));

// check stderr to check for warning message
testing::internal::CaptureStderr();
auto path = common::uuid();
gzLogInit(path, "test.log");
std::string output = testing::internal::GetCapturedStderr();

EXPECT_TRUE(output.find("Invalid value for GZ_CONSOLE_COLOR") != std::string::npos);

EXPECT_TRUE(common::unsetenv("GZ_CONSOLE_COLOR"));
gzLogClose();
}