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 (size_t i = 0; i < lines.size(); i++) {
171 const std::string& line = lines[i];
173 // Check for a heading line.
174 if (!line.empty() && line[0] != ' ') {
175 // Highlight up to the colon (if any).
176 size_t chars_to_highlight = line.find(':');
177 if (chars_to_highlight == std::string::npos)
178 chars_to_highlight = line.size();
179 OutputString(line.substr(0, chars_to_highlight), DECORATION_YELLOW);
180 OutputString(line.substr(chars_to_highlight) + "\n");
184 // Check for a comment.
185 TextDecoration dec = DECORATION_NONE;
186 for (size_t char_i = 0; char_i < line.size(); char_i++) {
187 if (line[char_i] == '#') {
188 // Got a comment, draw dimmed.
189 dec = DECORATION_DIM;
191 } else if (line[char_i] != ' ') {
196 OutputString(line + "\n", dec);