mirror of
https://github.com/catchorg/Catch2.git
synced 2025-08-03 13:55:39 +02:00
Refactor colour handling to prepare for per-reporter colour modes
This includes always compiling the ANSI and None colour implementations, as they don't need to touch any platform specific APIs, and removing their respective compile-time configuration options. Because the Win32 colour implementation requires Win32-specific APIs, it is still hidden behind a compile-time toggle, `CATCH_CONFIG_COLOUR_WIN32` (renamed from `..._COLOUR_WINDOWS`). The commandline options for colours were also changed. The option now uses different name, and allows to select between different implementations, rather than changing whether the compiled-in colour implementation is used through "yes/no/default" options.
This commit is contained in:
@@ -138,7 +138,7 @@ namespace Catch {
|
||||
uint32_t Config::rngSeed() const { return m_data.rngSeed; }
|
||||
unsigned int Config::shardCount() const { return m_data.shardCount; }
|
||||
unsigned int Config::shardIndex() const { return m_data.shardIndex; }
|
||||
UseColour Config::useColour() const { return m_data.useColour; }
|
||||
ColourMode Config::colourMode() const { return m_data.colourMode; }
|
||||
bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; }
|
||||
int Config::abortAfter() const { return m_data.abortAfter; }
|
||||
bool Config::showInvisibles() const { return m_data.showInvisibles; }
|
||||
|
@@ -66,7 +66,7 @@ namespace Catch {
|
||||
ShowDurations showDurations = ShowDurations::DefaultForReporter;
|
||||
double minDuration = -1;
|
||||
TestRunOrder runOrder = TestRunOrder::Declared;
|
||||
UseColour useColour = UseColour::Auto;
|
||||
ColourMode colourMode = ColourMode::PlatformDefault;
|
||||
WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
|
||||
|
||||
std::string defaultOutputFilename;
|
||||
@@ -114,7 +114,7 @@ namespace Catch {
|
||||
uint32_t rngSeed() const override;
|
||||
unsigned int shardCount() const override;
|
||||
unsigned int shardIndex() const override;
|
||||
UseColour useColour() const override;
|
||||
ColourMode colourMode() const override;
|
||||
bool shouldDebugBreak() const override;
|
||||
int abortAfter() const override;
|
||||
bool showInvisibles() const override;
|
||||
|
@@ -152,7 +152,8 @@ namespace Catch {
|
||||
|
||||
m_startupExceptions = true;
|
||||
auto errStream = makeStream( "%stderr" );
|
||||
auto colourImpl = makeColourImpl( &config(), errStream.get() );
|
||||
auto colourImpl = makeColourImpl(
|
||||
ColourMode::PlatformDefault, errStream.get() );
|
||||
auto guard = colourImpl->guardColour( Colour::Red );
|
||||
errStream->stream() << "Errors occurred during startup!" << '\n';
|
||||
// iterate over all exceptions and notify user
|
||||
@@ -197,7 +198,7 @@ namespace Catch {
|
||||
config();
|
||||
getCurrentMutableContext().setConfig(m_config.get());
|
||||
auto errStream = makeStream( "%stderr" );
|
||||
auto colour = makeColourImpl( &config(), errStream.get() );
|
||||
auto colour = makeColourImpl( ColourMode::PlatformDefault, errStream.get() );
|
||||
|
||||
errStream->stream()
|
||||
<< colour->guardColour( Colour::Red )
|
||||
|
@@ -32,7 +32,13 @@
|
||||
# error Cannot force ANDROID_LOGWRITE to both ON and OFF
|
||||
#endif
|
||||
|
||||
#cmakedefine CATCH_CONFIG_COLOUR_WIN32
|
||||
#cmakedefine CATCH_CONFIG_NO_COLOUR_WIN32
|
||||
|
||||
#if defined( CATCH_CONFIG_COLOUR_WIN32 ) && \
|
||||
defined( CATCH_CONFIG_NO_COLOUR_WIN32 )
|
||||
# error Cannot force COLOUR_WIN32 to be ON and OFF
|
||||
#endif
|
||||
|
||||
#cmakedefine CATCH_CONFIG_COUNTER
|
||||
#cmakedefine CATCH_CONFIG_NO_COUNTER
|
||||
@@ -159,9 +165,6 @@
|
||||
// ------
|
||||
|
||||
|
||||
#cmakedefine CATCH_CONFIG_COLOUR_ANSI
|
||||
#cmakedefine CATCH_CONFIG_COLOUR_NONE
|
||||
#cmakedefine CATCH_CONFIG_COLOUR_WINDOWS
|
||||
#cmakedefine CATCH_CONFIG_DISABLE_EXCEPTIONS
|
||||
#cmakedefine CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER
|
||||
#cmakedefine CATCH_CONFIG_DISABLE
|
||||
|
@@ -42,10 +42,15 @@ namespace Catch {
|
||||
LexicographicallySorted,
|
||||
Randomized
|
||||
};
|
||||
enum class UseColour {
|
||||
Auto,
|
||||
Yes,
|
||||
No
|
||||
enum class ColourMode : std::uint8_t {
|
||||
//! Let Catch2 pick implementation based on platform detection
|
||||
PlatformDefault,
|
||||
//! Use ANSI colour code escapes
|
||||
ANSI,
|
||||
//! Use Win32 console colour API
|
||||
Win32,
|
||||
//! Don't use any colour
|
||||
None
|
||||
};
|
||||
struct WaitForKeypress { enum When {
|
||||
Never,
|
||||
@@ -79,7 +84,7 @@ namespace Catch {
|
||||
virtual uint32_t rngSeed() const = 0;
|
||||
virtual unsigned int shardCount() const = 0;
|
||||
virtual unsigned int shardIndex() const = 0;
|
||||
virtual UseColour useColour() const = 0;
|
||||
virtual ColourMode colourMode() const = 0;
|
||||
virtual std::vector<std::string> const& getSectionsToRun() const = 0;
|
||||
virtual Verbosity verbosity() const = 0;
|
||||
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_reporter_registry.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
|
||||
#include <catch2/internal/catch_console_colour.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
@@ -95,19 +96,44 @@ namespace Catch {
|
||||
return ParserResult::runtimeError("Could not parse '" + seed + "' as seed");
|
||||
}
|
||||
};
|
||||
auto const setColourUsage = [&]( std::string const& useColour ) {
|
||||
auto mode = toLower( useColour );
|
||||
auto const setColourMode = [&]( std::string const&
|
||||
colourMode ) {
|
||||
auto mode = toLower( colourMode );
|
||||
|
||||
if( mode == "yes" )
|
||||
config.useColour = UseColour::Yes;
|
||||
else if( mode == "no" )
|
||||
config.useColour = UseColour::No;
|
||||
else if( mode == "auto" )
|
||||
config.useColour = UseColour::Auto;
|
||||
else
|
||||
return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" );
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
};
|
||||
if ( mode == "default" ) {
|
||||
if ( !isColourImplAvailable( ColourMode::PlatformDefault ) ) {
|
||||
return ParserResult::runtimeError(
|
||||
"colour mode 'default' is not supported in this "
|
||||
"binary" );
|
||||
}
|
||||
config.colourMode = ColourMode::PlatformDefault;
|
||||
} else if ( mode == "ansi" ) {
|
||||
if ( !isColourImplAvailable( ColourMode::ANSI ) ) {
|
||||
return ParserResult::runtimeError(
|
||||
"colour mode 'ansi' is not supported in this binary" );
|
||||
}
|
||||
config.colourMode = ColourMode::ANSI;
|
||||
} else if ( mode == "win32" ) {
|
||||
if ( !isColourImplAvailable( ColourMode::Win32 ) ) {
|
||||
return ParserResult::runtimeError(
|
||||
"colour mode 'win32' is not supported in this "
|
||||
"binary" );
|
||||
}
|
||||
config.colourMode = ColourMode::Win32;
|
||||
} else if ( mode == "none" ) {
|
||||
if ( !isColourImplAvailable( ColourMode::None ) ) {
|
||||
return ParserResult::runtimeError(
|
||||
"colour mode 'none' is not supported in this binary" );
|
||||
}
|
||||
config.colourMode = ColourMode::None;
|
||||
} else {
|
||||
return ParserResult::runtimeError(
|
||||
"colour mode must be one of: default, ansi, win32, "
|
||||
"or none. '" +
|
||||
colourMode + "' not recognised" );
|
||||
}
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
};
|
||||
auto const setWaitForKeypress = [&]( std::string const& keypress ) {
|
||||
auto keypressLc = toLower( keypress );
|
||||
if (keypressLc == "never")
|
||||
@@ -298,8 +324,8 @@ namespace Catch {
|
||||
| Opt( setRngSeed, "'time'|'random-device'|number" )
|
||||
["--rng-seed"]
|
||||
( "set a specific seed for random numbers" )
|
||||
| Opt( setColourUsage, "yes|no|auto" )
|
||||
["--use-colour"]
|
||||
| Opt( setColourMode, "ansi|win32|none|default" )
|
||||
["--colour-mode"]
|
||||
( "should output be colourised" )
|
||||
| Opt( config.libIdentify )
|
||||
["--libidentify"]
|
||||
|
@@ -116,7 +116,6 @@
|
||||
|
||||
#ifdef __OS400__
|
||||
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
|
||||
# define CATCH_CONFIG_COLOUR_NONE
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -164,7 +163,7 @@
|
||||
// Universal Windows platform does not support SEH
|
||||
// Or console colours (or console at all...)
|
||||
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||
# define CATCH_CONFIG_COLOUR_NONE
|
||||
# define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
|
||||
# else
|
||||
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
|
||||
# endif
|
||||
@@ -206,7 +205,7 @@
|
||||
#if defined(UNDER_RTSS) || defined(RTX64_BUILD)
|
||||
#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
|
||||
#define CATCH_INTERNAL_CONFIG_NO_ASYNC
|
||||
#define CATCH_CONFIG_COLOUR_NONE
|
||||
#define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
|
||||
#endif
|
||||
|
||||
#if !defined(_GLIBCXX_USE_C99_MATH_TR1)
|
||||
@@ -358,4 +357,12 @@
|
||||
#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||
#endif
|
||||
|
||||
#if defined( CATCH_PLATFORM_WINDOWS ) && \
|
||||
!defined( CATCH_CONFIG_COLOUR_WIN32 ) && \
|
||||
!defined( CATCH_CONFIG_NO_COLOUR_WIN32 ) && \
|
||||
!defined( CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 )
|
||||
# define CATCH_CONFIG_COLOUR_WIN32
|
||||
#endif
|
||||
|
||||
|
||||
#endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <catch2/internal/catch_platform.hpp>
|
||||
#include <catch2/internal/catch_debugger.hpp>
|
||||
#include <catch2/internal/catch_windows_h_proxy.hpp>
|
||||
#include <catch2/internal/catch_compiler_capabilities.hpp>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
@@ -31,20 +32,6 @@ namespace Catch {
|
||||
return ColourGuard(colourCode, this );
|
||||
}
|
||||
|
||||
namespace {
|
||||
//! A do-nothing implementation of colour, used as fallback for unknown
|
||||
//! platforms, and when the user asks to deactivate all colours.
|
||||
class NoColourImpl : public ColourImpl {
|
||||
public:
|
||||
NoColourImpl( IStream const* stream ): ColourImpl( stream ) {}
|
||||
static bool useColourOnPlatform() { return true; }
|
||||
|
||||
private:
|
||||
void use( Colour::Code ) const override {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void ColourImpl::ColourGuard::engageImpl( std::ostream& stream ) {
|
||||
assert( &stream == &m_colourImpl->m_stream->stream() &&
|
||||
"Engaging colour guard for different stream than used by the "
|
||||
@@ -92,18 +79,24 @@ namespace Catch {
|
||||
return CATCH_MOVE(*this);
|
||||
}
|
||||
|
||||
namespace {
|
||||
//! A do-nothing implementation of colour, used as fallback for unknown
|
||||
//! platforms, and when the user asks to deactivate all colours.
|
||||
class NoColourImpl : public ColourImpl {
|
||||
public:
|
||||
NoColourImpl( IStream const* stream ): ColourImpl( stream ) {}
|
||||
static bool useColourOnPlatform() { return true; }
|
||||
|
||||
private:
|
||||
void use( Colour::Code ) const override {}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
|
||||
# ifdef CATCH_PLATFORM_WINDOWS
|
||||
# define CATCH_CONFIG_COLOUR_WINDOWS
|
||||
# else
|
||||
# define CATCH_CONFIG_COLOUR_ANSI
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
|
||||
#if defined ( CATCH_CONFIG_COLOUR_WIN32 ) /////////////////////////////////////////
|
||||
|
||||
namespace Catch {
|
||||
namespace {
|
||||
@@ -174,13 +167,9 @@ namespace {
|
||||
namespace Catch {
|
||||
namespace {
|
||||
|
||||
// use POSIX/ ANSI console terminal codes
|
||||
// Thanks to Adam Strzelecki for original contribution
|
||||
// (http://github.com/nanoant)
|
||||
// https://github.com/philsquared/Catch/pull/131
|
||||
class PosixColourImpl : public ColourImpl {
|
||||
class ANSIColourImpl : public ColourImpl {
|
||||
public:
|
||||
PosixColourImpl( IStream const* stream ): ColourImpl( stream ) {}
|
||||
ANSIColourImpl( IStream const* stream ): ColourImpl( stream ) {}
|
||||
|
||||
static bool useColourOnPlatform(IStream const& stream) {
|
||||
// This is kinda messy due to trying to support a bunch of
|
||||
@@ -239,41 +228,50 @@ namespace {
|
||||
|
||||
namespace Catch {
|
||||
|
||||
Detail::unique_ptr<ColourImpl> makeColourImpl(IConfig const* config, IStream const* stream) {
|
||||
UseColour colourMode = config ? config->useColour() : UseColour::Auto;
|
||||
|
||||
bool createPlatformInstance = false;
|
||||
if ( colourMode == UseColour::No ) {
|
||||
createPlatformInstance = false;
|
||||
Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode implSelection,
|
||||
IStream const* stream ) {
|
||||
if ( implSelection == ColourMode::None ) {
|
||||
return Detail::make_unique<NoColourImpl>( stream );
|
||||
}
|
||||
|
||||
if ( colourMode == UseColour::Yes ) {
|
||||
createPlatformInstance = true;
|
||||
if ( implSelection == ColourMode::ANSI ) {
|
||||
return Detail::make_unique<ANSIColourImpl>( stream );
|
||||
}
|
||||
#if defined( CATCH_CONFIG_COLOUR_WIN32 )
|
||||
if ( implSelection == ColourMode::Win32 ) {
|
||||
return Detail::make_unique<Win32ColourImpl>( stream );
|
||||
}
|
||||
|
||||
if ( colourMode == UseColour::Auto ) {
|
||||
createPlatformInstance =
|
||||
#if defined( CATCH_CONFIG_COLOUR_ANSI )
|
||||
PosixColourImpl::useColourOnPlatform( *stream )
|
||||
#elif defined( CATCH_CONFIG_COLOUR_WINDOWS )
|
||||
Win32ColourImpl::useColourOnPlatform( *stream )
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
;
|
||||
|
||||
// todo: check win32 eligibility under ifdef, otherwise ansi
|
||||
if ( implSelection == ColourMode::PlatformDefault) {
|
||||
#if defined (CATCH_CONFIG_COLOUR_WIN32)
|
||||
if ( Win32ColourImpl::useColourOnPlatform( *stream ) ) {
|
||||
return Detail::make_unique<Win32ColourImpl>( stream );
|
||||
} else {
|
||||
return Detail::make_unique<NoColourImpl>( stream );
|
||||
}
|
||||
#endif
|
||||
if ( ANSIColourImpl::useColourOnPlatform( *stream ) ) {
|
||||
return Detail::make_unique<ANSIColourImpl>( stream );
|
||||
}
|
||||
return Detail::make_unique<NoColourImpl>( stream );
|
||||
}
|
||||
|
||||
if ( createPlatformInstance ) {
|
||||
return
|
||||
#if defined( CATCH_CONFIG_COLOUR_ANSI )
|
||||
Detail::make_unique<PosixColourImpl>(stream);
|
||||
#elif defined( CATCH_CONFIG_COLOUR_WINDOWS )
|
||||
Detail::make_unique<Win32ColourImpl>(stream);
|
||||
#else
|
||||
Detail::make_unique<NoColourImpl>(stream);
|
||||
CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(implSelection) );
|
||||
}
|
||||
|
||||
bool isColourImplAvailable( ColourMode colourSelection ) {
|
||||
switch ( colourSelection ) {
|
||||
#if defined( CATCH_CONFIG_COLOUR_WIN32 )
|
||||
case ColourMode::Win32:
|
||||
#endif
|
||||
case ColourMode::ANSI:
|
||||
case ColourMode::None:
|
||||
case ColourMode::PlatformDefault:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return Detail::make_unique<NoColourImpl>(stream);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -11,9 +11,11 @@
|
||||
#include <catch2/internal/catch_unique_ptr.hpp>
|
||||
|
||||
#include <iosfwd>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
enum class ColourMode : std::uint8_t;
|
||||
struct IConfig;
|
||||
class IStream;
|
||||
|
||||
@@ -128,7 +130,11 @@ namespace Catch {
|
||||
};
|
||||
|
||||
//! Provides ColourImpl based on global config and target compilation platform
|
||||
Detail::unique_ptr<ColourImpl> makeColourImpl( IConfig const* config, IStream const* stream );
|
||||
Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
|
||||
IStream const* stream );
|
||||
|
||||
//! Checks if specific colour impl has been compiled into the binary
|
||||
bool isColourImplAvailable( ColourMode colourSelection );
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
|
@@ -9,10 +9,21 @@
|
||||
#include <catch2/reporters/catch_reporter_common_base.hpp>
|
||||
|
||||
#include <catch2/reporters/catch_reporter_helpers.hpp>
|
||||
#include <catch2/internal/catch_console_colour.hpp>
|
||||
#include <catch2/internal/catch_stream.hpp>
|
||||
|
||||
|
||||
namespace Catch {
|
||||
ReporterBase::ReporterBase( ReporterConfig const& config ):
|
||||
IEventListener( config.fullConfig() ),
|
||||
m_wrapped_stream( config.stream() ),
|
||||
m_stream( m_wrapped_stream->stream() ),
|
||||
m_colour( makeColourImpl( m_config->colourMode(), m_wrapped_stream ) ) {}
|
||||
|
||||
void ReporterBase::listReporters(std::vector<ReporterDescription> const& descriptions) {
|
||||
ReporterBase::~ReporterBase() = default;
|
||||
|
||||
void ReporterBase::listReporters(
|
||||
std::vector<ReporterDescription> const& descriptions ) {
|
||||
defaultListReporters(m_stream, descriptions, m_config->verbosity());
|
||||
}
|
||||
|
||||
|
@@ -9,10 +9,10 @@
|
||||
#define CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
|
||||
|
||||
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
|
||||
#include <catch2/internal/catch_stream.hpp>
|
||||
#include <catch2/internal/catch_console_colour.hpp>
|
||||
|
||||
namespace Catch {
|
||||
class ColourImpl;
|
||||
|
||||
/**
|
||||
* This is the base class for all reporters.
|
||||
*
|
||||
@@ -33,12 +33,8 @@ namespace Catch {
|
||||
Detail::unique_ptr<ColourImpl> m_colour;
|
||||
|
||||
public:
|
||||
ReporterBase( ReporterConfig const& config ):
|
||||
IEventListener( config.fullConfig() ),
|
||||
m_wrapped_stream( config.stream() ),
|
||||
m_stream( m_wrapped_stream->stream() ),
|
||||
m_colour( makeColourImpl( config.fullConfig(), m_wrapped_stream ) ) {}
|
||||
|
||||
ReporterBase( ReporterConfig const& config );
|
||||
~ReporterBase() override; // = default;
|
||||
|
||||
/**
|
||||
* Provides a simple default listing of reporters.
|
||||
|
Reference in New Issue
Block a user