Skip to content

Commit 9bd3c93

Browse files
authored
Merge pull request #3015 from diffblue/console-colors
Console colors
2 parents 0914275 + d999a3e commit 9bd3c93

File tree

8 files changed

+154
-55
lines changed

8 files changed

+154
-55
lines changed

src/cbmc/all_properties.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,17 @@ void bmc_all_propertiest::report(const cover_goalst &cover_goals)
159159
result() << "\n** Results:" << eom;
160160

161161
for(const auto &goal_pair : goal_map)
162+
{
162163
result() << "[" << goal_pair.first << "] "
163-
<< goal_pair.second.description << ": "
164-
<< goal_pair.second.status_string()
165-
<< eom;
164+
<< goal_pair.second.description << ": ";
165+
166+
if(goal_pair.second.status == goalt::statust::SUCCESS)
167+
result() << green();
168+
else
169+
result() << red();
170+
171+
result() << goal_pair.second.status_string() << reset() << eom;
172+
}
166173

167174
if(bmc.options.get_bool_option("trace"))
168175
{

src/cbmc/bmc.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ bmct::run_decision_procedure(prop_convt &prop_conv)
153153

154154
void bmct::report_success()
155155
{
156-
result() << "VERIFICATION SUCCESSFUL" << eom;
156+
result() << bold() << "VERIFICATION SUCCESSFUL" << reset() << eom;
157157

158158
switch(ui_message_handler.get_ui())
159159
{
@@ -180,7 +180,7 @@ void bmct::report_success()
180180

181181
void bmct::report_failure()
182182
{
183-
result() << "VERIFICATION FAILED" << eom;
183+
result() << bold() << "VERIFICATION FAILED" << reset() << eom;
184184

185185
switch(ui_message_handler.get_ui())
186186
{

src/goto-analyzer/static_verifier.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,22 +232,22 @@ bool static_verifier(
232232

233233
if(e.is_true())
234234
{
235-
m.result() << "Success";
235+
m.result() << m.green() << "Success" << m.reset();
236236
pass++;
237237
}
238238
else if(e.is_false())
239239
{
240-
m.result() << "Failure (if reachable)";
240+
m.result() << m.red() << "Failure" << m.reset() << " (if reachable)";
241241
fail++;
242242
}
243243
else if(domain.is_bottom())
244244
{
245-
m.result() << "Success (unreachable)";
245+
m.result() << m.green() << "Success" << m.reset() << " (unreachable)";
246246
pass++;
247247
}
248248
else
249249
{
250-
m.result() << "Unknown";
250+
m.result() << m.yellow() << "Unknown" << m.reset();
251251
unknown++;
252252
}
253253

@@ -258,10 +258,11 @@ bool static_verifier(
258258
}
259259
}
260260

261-
m.status() << "Summary: "
261+
m.status() << m.bold() << "Summary: "
262262
<< pass << " pass, "
263263
<< fail << " fail if reachable, "
264-
<< unknown << " unknown\n";
264+
<< unknown << " unknown"
265+
<< m.reset() << messaget::eom;
265266

266267
return false;
267268
}

src/util/cout_message.cpp

Lines changed: 43 additions & 3 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)
@@ -118,14 +154,16 @@ void gcc_message_handlert::print(
118154
if(!function.empty())
119155
{
120156
if(!file.empty())
121-
dest+=id2string(file)+":";
157+
dest += command(1) + id2string(file) + ":" + command(0); // bold
122158
if(dest!="")
123159
dest+=' ';
124160
dest+="In function '"+id2string(function)+"':\n";
125161
}
126162

127163
if(!line.empty())
128164
{
165+
dest += command(1); // bold
166+
129167
if(!file.empty())
130168
dest+=id2string(file)+":";
131169

@@ -137,9 +175,11 @@ void gcc_message_handlert::print(
137175
dest+=id2string(column)+": ";
138176

139177
if(level==messaget::M_ERROR)
140-
dest+="error: ";
178+
dest += command(31) + "error: "; // red
141179
else if(level==messaget::M_WARNING)
142-
dest+="warning: ";
180+
dest += command(95) + "warning: "; // bright magenta
181+
182+
dest += command(0); // reset
143183
}
144184

145185
dest+=message;

src/util/cout_message.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,25 @@ 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

52-
class gcc_message_handlert : public message_handlert
57+
class gcc_message_handlert : public console_message_handlert
5358
{
5459
public:
5560
// aims to imitate the messages gcc prints

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.cpp

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@ Author: Daniel Kroening, [email protected]
1111
#include <fstream>
1212
#include <iostream>
1313

14-
#include "xml.h"
14+
#include "cmdline.h"
1515
#include "json.h"
16-
#include "xml_expr.h"
1716
#include "json_expr.h"
1817
#include "json_stream.h"
19-
#include "cout_message.h"
20-
#include "cmdline.h"
18+
#include "make_unique.h"
19+
#include "xml.h"
20+
#include "xml_expr.h"
2121

2222
ui_message_handlert::ui_message_handlert(
23-
message_handlert *message_handler,
23+
message_handlert *_message_handler,
2424
uit __ui,
2525
const std::string &program,
2626
bool always_flush,
2727
timestampert::clockt clock_type)
28-
: message_handler(message_handler),
28+
: message_handler(_message_handler),
2929
_ui(__ui),
3030
always_flush(always_flush),
3131
time(timestampert::make(clock_type)),
@@ -80,6 +80,12 @@ ui_message_handlert::ui_message_handlert(
8080
: timestampert::clockt::NONE
8181
: timestampert::clockt::NONE)
8282
{
83+
if(get_ui() == uit::PLAIN)
84+
{
85+
console_message_handler =
86+
util_make_unique<console_message_handlert>(always_flush);
87+
message_handler = &*console_message_handler;
88+
}
8389
}
8490

8591
ui_message_handlert::ui_message_handlert(message_handlert &message_handler)
@@ -132,19 +138,9 @@ void ui_message_handlert::print(
132138
std::stringstream ss;
133139
const std::string timestamp = time->stamp();
134140
ss << timestamp << (timestamp.empty() ? "" : " ") << message;
135-
if(message_handler)
136-
{
137-
message_handler->print(level, ss.str());
138-
if(always_flush)
139-
message_handler->flush(level);
140-
}
141-
else
142-
{
143-
console_message_handlert msg(always_flush);
144-
msg.print(level, ss.str());
145-
if(always_flush)
146-
msg.flush(level);
147-
}
141+
message_handler->print(level, ss.str());
142+
if(always_flush)
143+
message_handler->flush(level);
148144
}
149145
break;
150146

@@ -306,24 +302,12 @@ void ui_message_handlert::flush(unsigned level)
306302
switch(get_ui())
307303
{
308304
case uit::PLAIN:
309-
{
310-
if(message_handler)
311-
{
312-
message_handler->flush(level);
313-
}
314-
else
315-
{
316-
console_message_handlert msg(always_flush);
317-
msg.flush(level);
318-
}
319-
}
320-
break;
305+
message_handler->flush(level);
306+
break;
321307

322308
case uit::XML_UI:
323309
case uit::JSON_UI:
324-
{
325310
out << std::flush;
326-
}
327-
break;
311+
break;
328312
}
329313
}

src/util/ui_message.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Author: Daniel Kroening, [email protected]
1212

1313
#include <memory>
1414

15-
#include "message.h"
15+
#include "cout_message.h"
1616
#include "json_stream.h"
1717
#include "timestamper.h"
1818

@@ -41,6 +41,7 @@ class ui_message_handlert : public message_handlert
4141
}
4242

4343
protected:
44+
std::unique_ptr<console_message_handlert> console_message_handler;
4445
message_handlert *message_handler;
4546
uit _ui;
4647
const bool always_flush;
@@ -88,6 +89,14 @@ class ui_message_handlert : public message_handlert
8889
const source_locationt &location);
8990

9091
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+
}
91100
};
92101

93102
#define OPT_FLUSH "(flush)"

0 commit comments

Comments
 (0)