1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "tools/gn/standard_out.h"
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "base/strings/string_split.h"
12 #include "build/build_config.h"
23 bool initialized
= false;
25 static const char kSwitchColor
[] = "color";
26 static const char kSwitchNoColor
[] = "nocolor";
30 WORD default_attributes
;
32 bool is_console
= false;
34 void EnsureInitialized() {
39 const base::CommandLine
* cmdline
= base::CommandLine::ForCurrentProcess();
40 if (cmdline
->HasSwitch(kSwitchNoColor
)) {
47 // On Windows, we can't force the color on. If the output handle isn't a
48 // console, there's nothing we can do about it.
49 hstdout
= ::GetStdHandle(STD_OUTPUT_HANDLE
);
50 CONSOLE_SCREEN_BUFFER_INFO info
;
51 is_console
= !!::GetConsoleScreenBufferInfo(hstdout
, &info
);
52 default_attributes
= info
.wAttributes
;
54 if (cmdline
->HasSwitch(kSwitchColor
))
57 is_console
= isatty(fileno(stdout
));
61 void WriteToStdOut(const std::string
& output
) {
62 size_t written_bytes
= fwrite(output
.data(), 1, output
.size(), stdout
);
63 DCHECK_EQ(output
.size(), written_bytes
);
70 void OutputString(const std::string
& output
, TextDecoration dec
) {
77 ::SetConsoleTextAttribute(hstdout
, FOREGROUND_INTENSITY
);
80 ::SetConsoleTextAttribute(hstdout
,
81 FOREGROUND_RED
| FOREGROUND_INTENSITY
);
83 case DECORATION_GREEN
:
84 // Keep green non-bold.
85 ::SetConsoleTextAttribute(hstdout
, FOREGROUND_GREEN
);
88 ::SetConsoleTextAttribute(hstdout
,
89 FOREGROUND_BLUE
| FOREGROUND_INTENSITY
);
91 case DECORATION_YELLOW
:
92 ::SetConsoleTextAttribute(hstdout
,
93 FOREGROUND_RED
| FOREGROUND_GREEN
);
99 ::WriteFile(hstdout
, output
.c_str(), static_cast<DWORD
>(output
.size()),
103 ::SetConsoleTextAttribute(hstdout
, default_attributes
);
108 void OutputString(const std::string
& output
, TextDecoration dec
) {
112 case DECORATION_NONE
:
115 WriteToStdOut("\e[2m");
118 WriteToStdOut("\e[31m\e[1m");
120 case DECORATION_GREEN
:
121 WriteToStdOut("\e[32m");
123 case DECORATION_BLUE
:
124 WriteToStdOut("\e[34m\e[1m");
126 case DECORATION_YELLOW
:
127 WriteToStdOut("\e[33m\e[1m");
132 WriteToStdOut(output
.data());
134 if (is_console
&& dec
!= DECORATION_NONE
)
135 WriteToStdOut("\e[0m");
140 void PrintShortHelp(const std::string
& line
) {
141 size_t colon_offset
= line
.find(':');
142 size_t first_normal
= 0;
143 if (colon_offset
!= std::string::npos
) {
144 OutputString(" " + line
.substr(0, colon_offset
), DECORATION_YELLOW
);
145 first_normal
= colon_offset
;
148 // See if the colon is followed by a " [" and if so, dim the contents of [ ].
149 if (first_normal
> 0 &&
150 line
.size() > first_normal
+ 2 &&
151 line
[first_normal
+ 1] == ' ' && line
[first_normal
+ 2] == '[') {
152 size_t begin_bracket
= first_normal
+ 2;
154 first_normal
= line
.find(']', begin_bracket
);
155 if (first_normal
== std::string::npos
)
156 first_normal
= line
.size();
159 OutputString(line
.substr(begin_bracket
, first_normal
- begin_bracket
),
163 OutputString(line
.substr(first_normal
) + "\n");
166 void PrintLongHelp(const std::string
& text
) {
167 std::vector
<std::string
> lines
;
168 base::SplitStringDontTrim(text
, '\n', &lines
);
170 for (const auto& line
: lines
) {
171 // Check for a heading line.
172 if (!line
.empty() && line
[0] != ' ') {
173 // Highlight up to the colon (if any).
174 size_t chars_to_highlight
= line
.find(':');
175 if (chars_to_highlight
== std::string::npos
)
176 chars_to_highlight
= line
.size();
177 OutputString(line
.substr(0, chars_to_highlight
), DECORATION_YELLOW
);
178 OutputString(line
.substr(chars_to_highlight
) + "\n");
182 // Check for a comment.
183 TextDecoration dec
= DECORATION_NONE
;
184 for (size_t char_i
= 0; char_i
< line
.size(); char_i
++) {
185 if (line
[char_i
] == '#') {
186 // Got a comment, draw dimmed.
187 dec
= DECORATION_DIM
;
189 } else if (line
[char_i
] != ' ') {
194 OutputString(line
+ "\n", dec
);