Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
catch_console_colour.cpp
Go to the documentation of this file.
1/*
2 * Created by Phil on 25/2/2012.
3 * Copyright 2012 Two Blue Cubes Ltd. All rights reserved.
4 *
5 * Distributed under the Boost Software License, Version 1.0. (See accompanying
6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 */
8
9
10#if defined(__clang__)
11# pragma clang diagnostic push
12# pragma clang diagnostic ignored "-Wexit-time-destructors"
13#endif
14
15
17#include "catch_enforce.h"
18#include "catch_errno_guard.h"
20#include "catch_stream.h"
21#include "catch_context.h"
22#include "catch_platform.h"
23#include "catch_debugger.h"
25
26#include <sstream>
27
28namespace Catch {
29 namespace {
30
31 struct IColourImpl {
32 virtual ~IColourImpl() = default;
33 virtual void use( Colour::Code _colourCode ) = 0;
34 };
35
36 struct NoColourImpl : IColourImpl {
37 void use( Colour::Code ) {}
38
39 static IColourImpl* instance() {
40 static NoColourImpl s_instance;
41 return &s_instance;
42 }
43 };
44
45 } // anon namespace
46} // namespace Catch
47
48#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
49# ifdef CATCH_PLATFORM_WINDOWS
50# define CATCH_CONFIG_COLOUR_WINDOWS
51# else
52# define CATCH_CONFIG_COLOUR_ANSI
53# endif
54#endif
55
56
57#if defined ( CATCH_CONFIG_COLOUR_WINDOWS )
58
59namespace Catch {
60namespace {
61
62 class Win32ColourImpl : public IColourImpl {
63 public:
64 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
65 {
66 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
67 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
68 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
69 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
70 }
71
72 void use( Colour::Code _colourCode ) override {
73 switch( _colourCode ) {
74 case Colour::None: return setTextAttribute( originalForegroundAttributes );
75 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
76 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
77 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
78 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
79 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
80 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
81 case Colour::Grey: return setTextAttribute( 0 );
82
83 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
84 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
85 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
86 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
87 case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
88
89 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
90
91 default:
92 CATCH_ERROR( "Unknown colour requested" );
93 }
94 }
95
96 private:
97 void setTextAttribute( WORD _textAttribute ) {
98 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
99 }
100 HANDLE stdoutHandle;
101 WORD originalForegroundAttributes;
102 WORD originalBackgroundAttributes;
103 };
104
105 IColourImpl* platformColourInstance() {
106 static Win32ColourImpl s_instance;
107
109 UseColour::YesOrNo colourMode = config
110 ? config->useColour()
112 if( colourMode == UseColour::Auto )
113 colourMode = UseColour::Yes;
114 return colourMode == UseColour::Yes
115 ? &s_instance
116 : NoColourImpl::instance();
117 }
118
119} // end anon namespace
120} // end namespace Catch
121
122#elif defined( CATCH_CONFIG_COLOUR_ANSI )
123
124#include <unistd.h>
125
126namespace Catch {
127namespace {
128
129 // use POSIX/ ANSI console terminal codes
130 // Thanks to Adam Strzelecki for original contribution
131 // (http://github.com/nanoant)
132 // https://github.com/philsquared/Catch/pull/131
133 class PosixColourImpl : public IColourImpl {
134 public:
135 void use( Colour::Code _colourCode ) override {
136 switch( _colourCode ) {
137 case Colour::None:
138 case Colour::White: return setColour( "[0m" );
139 case Colour::Red: return setColour( "[0;31m" );
140 case Colour::Green: return setColour( "[0;32m" );
141 case Colour::Blue: return setColour( "[0;34m" );
142 case Colour::Cyan: return setColour( "[0;36m" );
143 case Colour::Yellow: return setColour( "[0;33m" );
144 case Colour::Grey: return setColour( "[1;30m" );
145
146 case Colour::LightGrey: return setColour( "[0;37m" );
147 case Colour::BrightRed: return setColour( "[1;31m" );
148 case Colour::BrightGreen: return setColour( "[1;32m" );
149 case Colour::BrightWhite: return setColour( "[1;37m" );
150 case Colour::BrightYellow: return setColour( "[1;33m" );
151
152 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
153 default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
154 }
155 }
156 static IColourImpl* instance() {
157 static PosixColourImpl s_instance;
158 return &s_instance;
159 }
160
161 private:
162 void setColour( const char* _escapeCode ) {
163 getCurrentContext().getConfig()->stream()
164 << '\033' << _escapeCode;
165 }
166 };
167
168 bool useColourOnPlatform() {
169 return
170#ifdef CATCH_PLATFORM_MAC
171 !isDebuggerActive() &&
172#endif
173#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
174 isatty(STDOUT_FILENO)
175#else
176 false
177#endif
178 ;
179 }
180 IColourImpl* platformColourInstance() {
181 ErrnoGuard guard;
183 UseColour::YesOrNo colourMode = config
184 ? config->useColour()
186 if( colourMode == UseColour::Auto )
187 colourMode = useColourOnPlatform()
190 return colourMode == UseColour::Yes
191 ? PosixColourImpl::instance()
192 : NoColourImpl::instance();
193 }
194
195} // end anon namespace
196} // end namespace Catch
197
198#else // not Windows or ANSI ///////////////////////////////////////////////
199
200namespace Catch {
201
202 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
203
204} // end namespace Catch
205
206#endif // Windows/ ANSI/ None
207
208namespace Catch {
209
210 Colour::Colour( Code _colourCode ) { use( _colourCode ); }
211 Colour::Colour( Colour&& rhs ) noexcept {
212 m_moved = rhs.m_moved;
213 rhs.m_moved = true;
214 }
215 Colour& Colour::operator=( Colour&& rhs ) noexcept {
216 m_moved = rhs.m_moved;
217 rhs.m_moved = true;
218 return *this;
219 }
220
221 Colour::~Colour(){ if( !m_moved ) use( None ); }
222
223 void Colour::use( Code _colourCode ) {
224 static IColourImpl* impl = platformColourInstance();
225 impl->use( _colourCode );
226 }
227
228 std::ostream& operator << ( std::ostream& os, Colour const& ) {
229 return os;
230 }
231
232} // end namespace Catch
233
234#if defined(__clang__)
235# pragma clang diagnostic pop
236#endif
237
#define CATCH_INTERNAL_ERROR(msg)
#define CATCH_ERROR(msg)
os_t os
IContext & getCurrentContext()
std::shared_ptr< IConfig const > IConfigPtr
bool isDebuggerActive()
auto operator<<(std::ostream &os, LazyExpression const &lazyExpr) -> std::ostream &
Colour(Code _colourCode)
static void use(Code _colourCode)
Colour & operator=(Colour &&other) noexcept
virtual IConfigPtr const & getConfig() const =0
Definition bench.cpp:18