Skip to content

Optin to VT100 style terminal codes on Windows #3004

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: devel
Choose a base branch
from

Conversation

Ext3h
Copy link

@Ext3h Ext3h commented Jul 21, 2025

Description

Enable VT100 terminal color codes on Windows too (if available) and use them by default.

GitHub Issues

Closes #3003

public:
// Store the streambuf from cout up-front because
// cout may get redirected when running tests
CoutStream() : m_os( Catch::cout().rdbuf() ) {}
CoutStream() : m_os( Catch::cout().rdbuf() ) {
m_isatty = true;
Copy link
Author

Choose a reason for hiding this comment

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

Too much Copy&Paste for my taste - and since Catch::cout() can be reimplemented, this is quite possibly probing the wrong file handles...


public: // IStream
std::ostream& stream() override { return m_os; }
bool isConsole() const override { return true; }
bool isConsole() const override { return m_isatty; }
Copy link
Author

Choose a reason for hiding this comment

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

This does not pass the tests. Now isConsole reports false in all of the unit tests when run in the CI - but its doing so rightfully.

Copy link
Author

Choose a reason for hiding this comment

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

Two options - injecting a proper terminal emulator for testing or changing the expected results?

m_isatty = m_isatty && enableVirtualTerminalSupport( STD_ERROR_HANDLE );
#endif
#if defined( CATCH_PLATFORM_MAC ) || defined( CATCH_PLATFORM_IPHONE )
m_isatty = m_isatty && !isDebuggerActive();
Copy link
Author

@Ext3h Ext3h Jul 21, 2025

Choose a reason for hiding this comment

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

Copy&Paste from original ANSIColourImpl code - unfortunately no comments, so what is this supposed to do? Is the debugger specifically not compatible with VT100 style sequences? Or does it not behave like a console in some other sense?

Copy link
Author

Choose a reason for hiding this comment

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

Does it even apply to stderr or is stderr not usable with debuggers on Mac/Iphone?

@@ -115,10 +114,13 @@ namespace {
}

static bool useImplementationForStream(IStream const& stream) {
Copy link
Author

Choose a reason for hiding this comment

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

We might just kick this one out of the auto-selection. Even the version check here is wonky, because it's easily thrown off guard by manifests or compatibility mode.

@Ext3h Ext3h force-pushed the ansi_colour_on_windows branch from fd44c79 to 43f577c Compare July 22, 2025 06:37
}

private:
void use( Colour::Code _colourCode ) const override {
auto setColour = [&out =
m_stream->stream()]( char const* escapeCode ) {
// The escape sequence must be flushed to console, otherwise
Copy link
Author

@Ext3h Ext3h Jul 22, 2025

Choose a reason for hiding this comment

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

That comment is partially a lie. std::cout, std::cerr and std::cin are all tied together. But they are (by default) not chained up correctly!

Problem is that while std::cerr and std::cin can cause an (implicit) flush of std::cout, std::cin doesn't do so on std::cerr, and neither does std::cout imply of flush of std::cerr.

Then again - it doesn't matter, because the terminal shouldn't apply escape sequences received on stderr to stdin in the first place, so this appears to be entirely incorrect after all?

And there's also std::flush explicitly throughout the entire codebase wherever necessary.

Copy link
Author

@Ext3h Ext3h Jul 22, 2025

Choose a reason for hiding this comment

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

Meanwhile, there are no tests actually setting up a stream-buffering that would have verified the necessity / correctness of the flushing in the first place.

I.e.:

setvbuf(stdout, NULL, _IOFBF, 3072);
setvbuf(stderr, NULL, _IOFBF, 3072);

That would quickly show where buffering is still broken.

The case where it does still break, is when configuring Catch2 to use std::cout as the output channel, while the code under test is utilizing std::cerr / stderr (but without explicit flushing and with output buffering explicitly enabled - which is NOT the default for stderr even when redirected!). But in that edge case, flushing std::cout still doesn't do anything about the un-flushed stderr.

@Ext3h Ext3h force-pushed the ansi_colour_on_windows branch from fd44c79 to 43f577c Compare July 22, 2025 06:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow/Default use of ANSI color codes on Windows
1 participant