Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: tools/gn/standard_out.cc

Issue 1024783002: Add a --markdown flag to GN to be able to output help in markdown. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gn_all_help
Patch Set: update w/ review feedback, merge to head, fix highlighting of comments Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/docs/reference.md ('k') | tools/gn/switches.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/standard_out.h" 5 #include "tools/gn/standard_out.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 11 matching lines...) Expand all
22 namespace { 22 namespace {
23 23
24 bool initialized = false; 24 bool initialized = false;
25 25
26 #if defined(OS_WIN) 26 #if defined(OS_WIN)
27 HANDLE hstdout; 27 HANDLE hstdout;
28 WORD default_attributes; 28 WORD default_attributes;
29 #endif 29 #endif
30 bool is_console = false; 30 bool is_console = false;
31 31
32 bool is_markdown = false;
33
32 void EnsureInitialized() { 34 void EnsureInitialized() {
33 if (initialized) 35 if (initialized)
34 return; 36 return;
35 initialized = true; 37 initialized = true;
36 38
37 const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); 39 const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
40 if (cmdline->HasSwitch(switches::kMarkdown)) {
41 // output help in Markdown's syntax, not color-highlighted.
brettw 2015/04/17 02:38:56 Capitalize "output"
42 is_markdown = true;
43 }
44
38 if (cmdline->HasSwitch(switches::kNoColor)) { 45 if (cmdline->HasSwitch(switches::kNoColor)) {
39 // Force color off. 46 // Force color off.
40 is_console = false; 47 is_console = false;
41 return; 48 return;
42 } 49 }
43 50
44 #if defined(OS_WIN) 51 #if defined(OS_WIN)
45 // On Windows, we can't force the color on. If the output handle isn't a 52 // 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. 53 // console, there's nothing we can do about it.
47 hstdout = ::GetStdHandle(STD_OUTPUT_HANDLE); 54 hstdout = ::GetStdHandle(STD_OUTPUT_HANDLE);
48 CONSOLE_SCREEN_BUFFER_INFO info; 55 CONSOLE_SCREEN_BUFFER_INFO info;
49 is_console = !!::GetConsoleScreenBufferInfo(hstdout, &info); 56 is_console = !!::GetConsoleScreenBufferInfo(hstdout, &info);
50 default_attributes = info.wAttributes; 57 default_attributes = info.wAttributes;
51 #else 58 #else
52 if (cmdline->HasSwitch(switches::kColor)) 59 if (cmdline->HasSwitch(switches::kColor))
53 is_console = true; 60 is_console = true;
54 else 61 else
55 is_console = isatty(fileno(stdout)); 62 is_console = isatty(fileno(stdout));
56 #endif 63 #endif
57 } 64 }
58 65
59 void WriteToStdOut(const std::string& output) { 66 void WriteToStdOut(const std::string& output) {
60 size_t written_bytes = fwrite(output.data(), 1, output.size(), stdout); 67 size_t written_bytes = fwrite(output.data(), 1, output.size(), stdout);
61 DCHECK_EQ(output.size(), written_bytes); 68 DCHECK_EQ(output.size(), written_bytes);
62 } 69 }
63 70
71 void OutputMarkdownDec(TextDecoration dec) {
72 // The markdown rendering turns "dim" text to italics and any
73 // other colored text to bold.
74
75 #if defined(OS_WIN)
76 if (dec == DECORATION_DIM)
77 ::WriteFile(hstdout, "*", 1), &written, nullptr);
78 else if (dec != DECORATION_NONE)
79 ::WriteFile(hstdout, "**", 2), &written, nullptr);
80 #else
81 if (dec == DECORATION_DIM)
82 WriteToStdOut("*");
83 else if (dec != DECORATION_NONE)
84 WriteToStdOut("**");
85 #endif
86 }
87
64 } // namespace 88 } // namespace
65 89
66 #if defined(OS_WIN) 90 #if defined(OS_WIN)
67 91
68 void OutputString(const std::string& output, TextDecoration dec) { 92 void OutputString(const std::string& output, TextDecoration dec) {
69 EnsureInitialized(); 93 EnsureInitialized();
70 if (is_console) { 94 DWORD written = 0;
95
96 if (is_markdown) {
97 OutputMarkdownDec(dec);
98 } else if (is_console) {
71 switch (dec) { 99 switch (dec) {
72 case DECORATION_NONE: 100 case DECORATION_NONE:
73 break; 101 break;
74 case DECORATION_DIM: 102 case DECORATION_DIM:
75 ::SetConsoleTextAttribute(hstdout, FOREGROUND_INTENSITY); 103 ::SetConsoleTextAttribute(hstdout, FOREGROUND_INTENSITY);
76 break; 104 break;
77 case DECORATION_RED: 105 case DECORATION_RED:
78 ::SetConsoleTextAttribute(hstdout, 106 ::SetConsoleTextAttribute(hstdout,
79 FOREGROUND_RED | FOREGROUND_INTENSITY); 107 FOREGROUND_RED | FOREGROUND_INTENSITY);
80 break; 108 break;
81 case DECORATION_GREEN: 109 case DECORATION_GREEN:
82 // Keep green non-bold. 110 // Keep green non-bold.
83 ::SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN); 111 ::SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN);
84 break; 112 break;
85 case DECORATION_BLUE: 113 case DECORATION_BLUE:
86 ::SetConsoleTextAttribute(hstdout, 114 ::SetConsoleTextAttribute(hstdout,
87 FOREGROUND_BLUE | FOREGROUND_INTENSITY); 115 FOREGROUND_BLUE | FOREGROUND_INTENSITY);
88 break; 116 break;
89 case DECORATION_YELLOW: 117 case DECORATION_YELLOW:
90 ::SetConsoleTextAttribute(hstdout, 118 ::SetConsoleTextAttribute(hstdout,
91 FOREGROUND_RED | FOREGROUND_GREEN); 119 FOREGROUND_RED | FOREGROUND_GREEN);
92 break; 120 break;
93 } 121 }
94 } 122 }
95 123
96 DWORD written = 0;
97 ::WriteFile(hstdout, output.c_str(), static_cast<DWORD>(output.size()), 124 ::WriteFile(hstdout, output.c_str(), static_cast<DWORD>(output.size()),
98 &written, nullptr); 125 &written, nullptr);
99 126
100 if (is_console) 127 if (is_markdown) {
128 OutputMarkdownDec(dec);
129 } else if (is_console) {
101 ::SetConsoleTextAttribute(hstdout, default_attributes); 130 ::SetConsoleTextAttribute(hstdout, default_attributes);
131 }
102 } 132 }
103 133
104 #else 134 #else
105 135
106 void OutputString(const std::string& output, TextDecoration dec) { 136 void OutputString(const std::string& output, TextDecoration dec) {
107 EnsureInitialized(); 137 EnsureInitialized();
108 if (is_console) { 138 if (is_markdown) {
139 OutputMarkdownDec(dec);
140 } else if (is_console) {
109 switch (dec) { 141 switch (dec) {
110 case DECORATION_NONE: 142 case DECORATION_NONE:
111 break; 143 break;
112 case DECORATION_DIM: 144 case DECORATION_DIM:
113 WriteToStdOut("\e[2m"); 145 WriteToStdOut("\e[2m");
114 break; 146 break;
115 case DECORATION_RED: 147 case DECORATION_RED:
116 WriteToStdOut("\e[31m\e[1m"); 148 WriteToStdOut("\e[31m\e[1m");
117 break; 149 break;
118 case DECORATION_GREEN: 150 case DECORATION_GREEN:
119 WriteToStdOut("\e[32m"); 151 WriteToStdOut("\e[32m");
120 break; 152 break;
121 case DECORATION_BLUE: 153 case DECORATION_BLUE:
122 WriteToStdOut("\e[34m\e[1m"); 154 WriteToStdOut("\e[34m\e[1m");
123 break; 155 break;
124 case DECORATION_YELLOW: 156 case DECORATION_YELLOW:
125 WriteToStdOut("\e[33m\e[1m"); 157 WriteToStdOut("\e[33m\e[1m");
126 break; 158 break;
127 } 159 }
128 } 160 }
129 161
130 WriteToStdOut(output.data()); 162 WriteToStdOut(output.data());
131 163
132 if (is_console && dec != DECORATION_NONE) 164 if (is_markdown) {
165 OutputMarkdownDec(dec);
166 } else if (is_console && dec != DECORATION_NONE) {
133 WriteToStdOut("\e[0m"); 167 WriteToStdOut("\e[0m");
168 }
134 } 169 }
135 170
136 #endif 171 #endif
137 172
138 void PrintShortHelp(const std::string& line) { 173 void PrintShortHelp(const std::string& line) {
174 EnsureInitialized();
175
139 size_t colon_offset = line.find(':'); 176 size_t colon_offset = line.find(':');
140 size_t first_normal = 0; 177 size_t first_normal = 0;
141 if (colon_offset != std::string::npos) { 178 if (colon_offset != std::string::npos) {
142 OutputString(" " + line.substr(0, colon_offset), DECORATION_YELLOW); 179 OutputString(" " + line.substr(0, colon_offset), DECORATION_YELLOW);
143 first_normal = colon_offset; 180 first_normal = colon_offset;
144 } 181 }
145 182
146 // See if the colon is followed by a " [" and if so, dim the contents of [ ]. 183 // See if the colon is followed by a " [" and if so, dim the contents of [ ].
147 if (first_normal > 0 && 184 if (first_normal > 0 &&
148 line.size() > first_normal + 2 && 185 line.size() > first_normal + 2 &&
149 line[first_normal + 1] == ' ' && line[first_normal + 2] == '[') { 186 line[first_normal + 1] == ' ' && line[first_normal + 2] == '[') {
150 size_t begin_bracket = first_normal + 2; 187 size_t begin_bracket = first_normal + 2;
151 OutputString(": "); 188 OutputString(": ");
152 first_normal = line.find(']', begin_bracket); 189 first_normal = line.find(']', begin_bracket);
153 if (first_normal == std::string::npos) 190 if (first_normal == std::string::npos)
154 first_normal = line.size(); 191 first_normal = line.size();
155 else 192 else
156 first_normal++; 193 first_normal++;
157 OutputString(line.substr(begin_bracket, first_normal - begin_bracket), 194 OutputString(line.substr(begin_bracket, first_normal - begin_bracket),
158 DECORATION_DIM); 195 DECORATION_DIM);
159 } 196 }
160 197
161 OutputString(line.substr(first_normal) + "\n"); 198 OutputString(line.substr(first_normal) + "\n");
162 } 199 }
163 200
164 void PrintLongHelp(const std::string& text) { 201 void PrintLongHelp(const std::string& text) {
202 EnsureInitialized();
203
165 std::vector<std::string> lines; 204 std::vector<std::string> lines;
166 base::SplitStringDontTrim(text, '\n', &lines); 205 base::SplitStringDontTrim(text, '\n', &lines);
167 206
207 bool first_header = true;
208 bool in_body = false;
168 for (const auto& line : lines) { 209 for (const auto& line : lines) {
169 // Check for a heading line. 210 // Check for a heading line.
170 if (!line.empty() && line[0] != ' ') { 211 if (!line.empty() && line[0] != ' ') {
212 if (is_markdown) {
213 // GN's block-level formatting is converted to markdown as follows:
214 // * The first heading is treated as an H2.
215 // * Subsequent heading are treated as H3s.
216 // * Any other text is wrapped in a code block and displayed as-is.
217 //
218 // Span-level formatting (the decorations) is converted inside
219 // OutputString().
220 if (in_body) {
221 OutputString("```\n\n", DECORATION_NONE);
222 in_body = false;
223 }
224
225 if (first_header) {
226 OutputString("## ", DECORATION_NONE);
227 first_header = false;
228 } else {
229 OutputString("### ", DECORATION_NONE);
230 }
231 }
232
171 // Highlight up to the colon (if any). 233 // Highlight up to the colon (if any).
172 size_t chars_to_highlight = line.find(':'); 234 size_t chars_to_highlight = line.find(':');
173 if (chars_to_highlight == std::string::npos) 235 if (chars_to_highlight == std::string::npos)
174 chars_to_highlight = line.size(); 236 chars_to_highlight = line.size();
237
175 OutputString(line.substr(0, chars_to_highlight), DECORATION_YELLOW); 238 OutputString(line.substr(0, chars_to_highlight), DECORATION_YELLOW);
176 OutputString(line.substr(chars_to_highlight) + "\n"); 239 OutputString(line.substr(chars_to_highlight) + "\n");
177 continue; 240 continue;
241 } else if (!line.empty() && !in_body) {
242 OutputString("```\n", DECORATION_NONE);
243 in_body = true;
178 } 244 }
179 245
180 // Check for a comment. 246 // Check for a comment.
181 TextDecoration dec = DECORATION_NONE; 247 TextDecoration dec = DECORATION_NONE;
182 for (const auto& elem : line) { 248 for (const auto& elem : line) {
183 if (elem == '#') { 249 if (elem == '#' && !is_markdown) {
184 // Got a comment, draw dimmed. 250 // Got a comment, draw dimmed.
185 dec = DECORATION_DIM; 251 dec = DECORATION_DIM;
186 break; 252 break;
187 } else if (elem != ' ') { 253 } else if (elem != ' ') {
188 break; 254 break;
189 } 255 }
190 } 256 }
191 257
192 OutputString(line + "\n", dec); 258 OutputString(line + "\n", dec);
193 } 259 }
260
261 if (is_markdown && in_body) {
brettw 2015/04/17 02:38:56 No {}
262 OutputString("\n```\n");
263 }
194 } 264 }
195 265
OLDNEW
« no previous file with comments | « tools/gn/docs/reference.md ('k') | tools/gn/switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698