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"
13 #include "tools/gn/switches.h"
24 bool initialized
= false;
28 WORD default_attributes
;
30 bool is_console
= false;
32 void EnsureInitialized() {
37 const base::CommandLine
* cmdline
= base::CommandLine::ForCurrentProcess();
38 if (cmdline
->HasSwitch(switches::kNoColor
)) {
45 // On Windows, we can't force the color on. If the output handle isn't a
46 // console, there's nothing we can do about it.
47 hstdout
= ::GetStdHandle(STD_OUTPUT_HANDLE
);
48 CONSOLE_SCREEN_BUFFER_INFO info
;
49 is_console
= !!::GetConsoleScreenBufferInfo(hstdout
, &info
);
50 default_attributes
= info
.wAttributes
;
52 if (cmdline
->HasSwitch(switches::kColor
))
55 is_console
= isatty(fileno(stdout
));
59 void WriteToStdOut(const std::string
& output
) {
60 size_t written_bytes
= fwrite(output
.data(), 1, output
.size(), stdout
);
61 DCHECK_EQ(output
.size(), written_bytes
);
68 void OutputString(const std::string
& output
, TextDecoration dec
) {
75 ::SetConsoleTextAttribute(hstdout
, FOREGROUND_INTENSITY
);
78 ::SetConsoleTextAttribute(hstdout
,
79 FOREGROUND_RED
| FOREGROUND_INTENSITY
);
81 case DECORATION_GREEN
:
82 // Keep green non-bold.
83 ::SetConsoleTextAttribute(hstdout
, FOREGROUND_GREEN
);
86 ::SetConsoleTextAttribute(hstdout
,
87 FOREGROUND_BLUE
| FOREGROUND_INTENSITY
);
89 case DECORATION_YELLOW
:
90 ::SetConsoleTextAttribute(hstdout
,
91 FOREGROUND_RED
| FOREGROUND_GREEN
);
97 ::WriteFile(hstdout
, output
.c_str(), static_cast<DWORD
>(output
.size()),
101 ::SetConsoleTextAttribute(hstdout
, default_attributes
);
106 void OutputString(const std::string
& output
, TextDecoration dec
) {
110 case DECORATION_NONE
:
113 WriteToStdOut("\e[2m");
116 WriteToStdOut("\e[31m\e[1m");
118 case DECORATION_GREEN
:
119 WriteToStdOut("\e[32m");
121 case DECORATION_BLUE
:
122 WriteToStdOut("\e[34m\e[1m");
124 case DECORATION_YELLOW
:
125 WriteToStdOut("\e[33m\e[1m");
130 WriteToStdOut(output
.data());
132 if (is_console
&& dec
!= DECORATION_NONE
)
133 WriteToStdOut("\e[0m");
138 void PrintShortHelp(const std::string
& line
) {
139 size_t colon_offset
= line
.find(':');
140 size_t first_normal
= 0;
141 if (colon_offset
!= std::string::npos
) {
142 OutputString(" " + line
.substr(0, colon_offset
), DECORATION_YELLOW
);
143 first_normal
= colon_offset
;
146 // See if the colon is followed by a " [" and if so, dim the contents of [ ].
147 if (first_normal
> 0 &&
148 line
.size() > first_normal
+ 2 &&
149 line
[first_normal
+ 1] == ' ' && line
[first_normal
+ 2] == '[') {
150 size_t begin_bracket
= first_normal
+ 2;
152 first_normal
= line
.find(']', begin_bracket
);
153 if (first_normal
== std::string::npos
)
154 first_normal
= line
.size();
157 OutputString(line
.substr(begin_bracket
, first_normal
- begin_bracket
),
161 OutputString(line
.substr(first_normal
) + "\n");
164 void PrintLongHelp(const std::string
& text
) {
165 std::vector
<std::string
> lines
;
166 base::SplitStringDontTrim(text
, '\n', &lines
);
168 for (const auto& line
: lines
) {
169 // Check for a heading line.
170 if (!line
.empty() && line
[0] != ' ') {
171 // Highlight up to the colon (if any).
172 size_t chars_to_highlight
= line
.find(':');
173 if (chars_to_highlight
== std::string::npos
)
174 chars_to_highlight
= line
.size();
175 OutputString(line
.substr(0, chars_to_highlight
), DECORATION_YELLOW
);
176 OutputString(line
.substr(chars_to_highlight
) + "\n");
180 // Check for a comment.
181 TextDecoration dec
= DECORATION_NONE
;
182 for (const auto& elem
: line
) {
184 // Got a comment, draw dimmed.
185 dec
= DECORATION_DIM
;
187 } else if (elem
!= ' ') {
192 OutputString(line
+ "\n", dec
);