Skip to content

Commit 33569fa

Browse files
author
Daniel Kroening
committed
added a message color API
This enables colorful formatting of any message printed through the messaget API. Server-side implementation is provided for Windows and Unix consoles.
1 parent f06b563 commit 33569fa

File tree

4 files changed

+107
-5
lines changed

4 files changed

+107
-5
lines changed

src/util/cout_message.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ Author: Daniel Kroening, [email protected]
2121
#include <io.h>
2222
#include <cstdio>
2323
#include <util/pragma_pop.def>
24+
#else
25+
#include <unistd.h>
2426
#endif
2527

2628
#include "unicode.h"
@@ -35,6 +37,40 @@ cerr_message_handlert::cerr_message_handlert():
3537
{
3638
}
3739

40+
console_message_handlert::console_message_handlert(bool _always_flush)
41+
: always_flush(_always_flush), is_a_tty(false), use_SGR(false)
42+
{
43+
#ifdef _WIN32
44+
HANDLE out_handle=GetStdHandle(STD_OUTPUT_HANDLE);
45+
46+
DWORD consoleMode;
47+
if(GetConsoleMode(out_handle, &consoleMode))
48+
{
49+
is_a_tty = true;
50+
51+
#ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING
52+
consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
53+
if(SetConsoleMode(out_handle, consoleMode))
54+
use_SGR = true;
55+
#endif
56+
}
57+
#else
58+
is_a_tty = isatty(STDOUT_FILENO);
59+
use_SGR = is_a_tty;
60+
#endif
61+
}
62+
63+
/// Create an ECMA-48 SGR (Select Graphic Rendition) command with
64+
/// given code.
65+
/// \param c: ECMA-48 command code
66+
std::string console_message_handlert::command(unsigned c) const
67+
{
68+
if(!use_SGR)
69+
return std::string();
70+
71+
return "\x1b[" + std::to_string(c) + 'm';
72+
}
73+
3874
void console_message_handlert::print(
3975
unsigned level,
4076
const std::string &message)

src/util/cout_message.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,22 @@ class console_message_handlert : public message_handlert
3636

3737
virtual void flush(unsigned level) override;
3838

39-
console_message_handlert() : always_flush(false)
39+
console_message_handlert() : console_message_handlert(false)
4040
{
4141
}
4242

43-
explicit console_message_handlert(bool always_flush)
44-
: always_flush(always_flush)
45-
{
46-
}
43+
explicit console_message_handlert(bool always_flush);
44+
45+
std::string command(unsigned c) const override;
4746

4847
protected:
4948
const bool always_flush;
49+
50+
/// true if we are outputting to a proper console
51+
bool is_a_tty;
52+
53+
/// true if we use ECMA-48 SGR to render colors
54+
bool use_SGR;
5055
};
5156

5257
class gcc_message_handlert : public message_handlert

src/util/message.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ class message_handlert
6565
return message_count[level];
6666
}
6767

68+
/// \brief Create an ECMA-48 SGR (Select Graphic Rendition) command.
69+
/// The default behavior is no action.
70+
virtual std::string command(unsigned) const
71+
{
72+
return std::string();
73+
}
74+
6875
protected:
6976
unsigned verbosity;
7077
std::vector<std::size_t> message_count;
@@ -275,6 +282,52 @@ class messaget
275282
return m;
276283
}
277284

285+
/// \brief Create an ECMA-48 SGR (Select Graphic Rendition) command.
286+
std::string command(unsigned c) const
287+
{
288+
if(message_handler)
289+
return message_handler->command(c);
290+
else
291+
return std::string();
292+
}
293+
294+
/// return to default formatting,
295+
/// as defined by the terminal
296+
std::string reset() const
297+
{
298+
return command(0);
299+
}
300+
301+
/// render text with red foreground color
302+
std::string red() const
303+
{
304+
return command(31);
305+
}
306+
307+
/// render text with green foreground color
308+
std::string green() const
309+
{
310+
return command(32);
311+
}
312+
313+
/// render text with yellow foreground color
314+
std::string yellow() const
315+
{
316+
return command(33);
317+
}
318+
319+
/// render text with blue foreground color
320+
std::string blue() const
321+
{
322+
return command(34);
323+
}
324+
325+
/// render text with bold font
326+
std::string bold() const
327+
{
328+
return command(1);
329+
}
330+
278331
mstreamt &get_mstream(unsigned message_level) const
279332
{
280333
mstream.message_level=message_level;

src/util/ui_message.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ class ui_message_handlert : public message_handlert
8989
const source_locationt &location);
9090

9191
const char *level_string(unsigned level);
92+
93+
std::string command(unsigned c) const override
94+
{
95+
if(message_handler)
96+
return message_handler->command(c);
97+
else
98+
return std::string();
99+
}
92100
};
93101

94102
#define OPT_FLUSH "(flush)"

0 commit comments

Comments
 (0)