-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
base: devel
Are you sure you want to change the base?
Changes from 4 commits
100a554
84b9419
abad39e
43f577c
fd44c79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,15 +6,25 @@ | |
|
||
// SPDX-License-Identifier: BSL-1.0 | ||
|
||
#include <catch2/internal/catch_istream.hpp> | ||
#include <catch2/internal/catch_enforce.hpp> | ||
#include <catch2/internal/catch_debug_console.hpp> | ||
#include <catch2/internal/catch_unique_ptr.hpp> | ||
#include <catch2/internal/catch_enforce.hpp> | ||
#include <catch2/internal/catch_errno_guard.hpp> | ||
#include <catch2/internal/catch_istream.hpp> | ||
#include <catch2/internal/catch_stdstreams.hpp> | ||
#include <catch2/internal/catch_unique_ptr.hpp> | ||
#include <catch2/internal/catch_windows_h_proxy.hpp> | ||
|
||
#include <cstdio> | ||
#include <fstream> | ||
|
||
#if defined( CATCH_PLATFORM_LINUX ) || defined( CATCH_PLATFORM_MAC ) || \ | ||
defined( __GLIBC__ ) | ||
# define CATCH_INTERNAL_HAS_ISATTY | ||
# include <unistd.h> | ||
#elif defined( CATCH_PLATFORM_WINDOWS ) | ||
# include <io.h> | ||
#endif | ||
|
||
namespace Catch { | ||
|
||
Catch::IStream::~IStream() = default; | ||
|
@@ -86,29 +96,78 @@ namespace Detail { | |
|
||
/////////////////////////////////////////////////////////////////////////// | ||
|
||
#if defined( CATCH_PLATFORM_WINDOWS ) | ||
bool enableVirtualTerminalSupport( DWORD stdHandle ) { | ||
HANDLE outputHandle = GetStdHandle( stdHandle ); | ||
DWORD mode = 0; | ||
const DWORD requiredMode = ENABLE_PROCESSED_OUTPUT | | ||
ENABLE_VIRTUAL_TERMINAL_PROCESSING; | ||
if ( GetConsoleMode( outputHandle, &mode ) && | ||
( mode & requiredMode ) == requiredMode ) { | ||
// VT100 style sequence processing has to be enabled by | ||
// explicit opt-in. | ||
const DWORD newMode = mode | requiredMode; | ||
if( SetConsoleMode( outputHandle, newMode ) ) | ||
{ | ||
return true; | ||
} | ||
// Restore fail-safe state. | ||
SetConsoleMode( outputHandle, mode ); | ||
} | ||
return false; | ||
} | ||
#endif | ||
|
||
class CoutStream final : public IStream { | ||
std::ostream m_os; | ||
bool m_isatty; | ||
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Too much Copy&Paste for my taste - and since |
||
#if defined( CATCH_INTERNAL_HAS_ISATTY ) && \ | ||
!( defined( __DJGPP__ ) && defined( __STRICT_ANSI__ ) ) | ||
ErrnoGuard _; // for isatty | ||
m_isatty = m_isatty && isatty( STDOUT_FILENO ); | ||
#elif defined( CATCH_PLATFORM_WINDOWS ) | ||
m_isatty = m_isatty && _isatty( _fileno( stdout ) ); | ||
m_isatty = m_isatty && enableVirtualTerminalSupport( STD_OUTPUT_HANDLE ); | ||
#endif | ||
#if defined( CATCH_PLATFORM_MAC ) || defined( CATCH_PLATFORM_IPHONE ) | ||
m_isatty = m_isatty && !isDebuggerActive(); | ||
#endif | ||
} | ||
|
||
public: // IStream | ||
std::ostream& stream() override { return m_os; } | ||
bool isConsole() const override { return true; } | ||
bool isConsole() const override { return m_isatty; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does not pass the tests. Now There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? |
||
}; | ||
|
||
class CerrStream : public IStream { | ||
std::ostream m_os; | ||
|
||
bool m_isatty; | ||
public: | ||
// Store the streambuf from cerr up-front because | ||
// cout may get redirected when running tests | ||
CerrStream(): m_os( Catch::cerr().rdbuf() ) {} | ||
CerrStream(): m_os( Catch::cerr().rdbuf() ) { | ||
m_isatty = true; | ||
#if defined( CATCH_INTERNAL_HAS_ISATTY ) && \ | ||
!( defined( __DJGPP__ ) && defined( __STRICT_ANSI__ ) ) | ||
ErrnoGuard _; // for isatty | ||
m_isatty = m_isatty && isatty( STDERR_FILENO ); | ||
#elif defined( CATCH_PLATFORM_WINDOWS ) | ||
m_isatty = m_isatty && _isatty( _fileno( stderr ) ); | ||
m_isatty = m_isatty && enableVirtualTerminalSupport( STD_ERROR_HANDLE ); | ||
#endif | ||
#if defined( CATCH_PLATFORM_MAC ) || defined( CATCH_PLATFORM_IPHONE ) | ||
m_isatty = m_isatty && !isDebuggerActive(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copy&Paste from original There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it even apply to |
||
#endif | ||
} | ||
|
||
public: // IStream | ||
std::ostream& stream() override { return m_os; } | ||
bool isConsole() const override { return true; } | ||
bool isConsole() const override { return m_isatty; } | ||
}; | ||
|
||
/////////////////////////////////////////////////////////////////////////// | ||
|
There was a problem hiding this comment.
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.