@@ -49,12 +49,82 @@ func createDiagnosticReporter(sys System, options *core.CompilerOptions) diagnos
49
49
}
50
50
}
51
51
52
+ func defaultIsPretty (sys System ) bool {
53
+ return sys .WriteOutputIsTTY () && sys .GetEnvironmentVariable ("NO_COLOR" ) == ""
54
+ }
55
+
52
56
func shouldBePretty (sys System , options * core.CompilerOptions ) bool {
53
- if options == nil || options .Pretty .IsTrueOrUnknown () {
54
- // todo: return defaultIsPretty(sys);
55
- return true
57
+ if options == nil || options .Pretty .IsUnknown () {
58
+ return defaultIsPretty (sys )
59
+ }
60
+ return options .Pretty .IsTrue ()
61
+ }
62
+
63
+ type colors struct {
64
+ showColors bool
65
+
66
+ isWindows bool
67
+ isWindowsTerminal bool
68
+ isVSCode bool
69
+ supportsRicherColors bool
70
+ }
71
+
72
+ func createColors (sys System ) * colors {
73
+ if ! defaultIsPretty (sys ) {
74
+ return & colors {showColors : false }
75
+ }
76
+
77
+ os := sys .GetEnvironmentVariable ("OS" )
78
+ isWindows := strings .Contains (strings .ToLower (os ), "windows" )
79
+ isWindowsTerminal := sys .GetEnvironmentVariable ("WT_SESSION" ) != ""
80
+ isVSCode := sys .GetEnvironmentVariable ("TERM_PROGRAM" ) == "vscode"
81
+ supportsRicherColors := sys .GetEnvironmentVariable ("COLORTERM" ) == "truecolor" || sys .GetEnvironmentVariable ("TERM" ) == "xterm-256color"
82
+
83
+ return & colors {
84
+ showColors : true ,
85
+ isWindows : isWindows ,
86
+ isWindowsTerminal : isWindowsTerminal ,
87
+ isVSCode : isVSCode ,
88
+ supportsRicherColors : supportsRicherColors ,
89
+ }
90
+ }
91
+
92
+ func (c * colors ) bold (str string ) string {
93
+ if ! c .showColors {
94
+ return str
95
+ }
96
+ return "\x1b [1m" + str + "\x1b [22m"
97
+ }
98
+
99
+ func (c * colors ) blue (str string ) string {
100
+ if ! c .showColors {
101
+ return str
102
+ }
103
+
104
+ // Effectively Powershell and Command prompt users use cyan instead
105
+ // of blue because the default theme doesn't show blue with enough contrast.
106
+ if c .isWindows && ! c .isWindowsTerminal && ! c .isVSCode {
107
+ return c .brightWhite (str )
108
+ }
109
+ return "\x1b [94m" + str + "\x1b [39m"
110
+ }
111
+
112
+ func (c * colors ) blueBackground (str string ) string {
113
+ if ! c .showColors {
114
+ return str
115
+ }
116
+ if c .supportsRicherColors {
117
+ return "\x1B [48;5;68m" + str + "\x1B [39;49m"
118
+ } else {
119
+ return "\x1b [44m" + str + "\x1B [39;49m"
56
120
}
57
- return false
121
+ }
122
+
123
+ func (c * colors ) brightWhite (str string ) string {
124
+ if ! c .showColors {
125
+ return str
126
+ }
127
+ return "\x1b [97m" + str + "\x1b [39m"
58
128
}
59
129
60
130
func createReportErrorSummary (sys System , options * core.CompilerOptions ) func (diagnostics []* ast.Diagnostic ) {
@@ -134,43 +204,42 @@ func getOptionsForHelp(commandLine *tsoptions.ParsedCommandLine) []*tsoptions.Co
134
204
}
135
205
136
206
func getHeader (sys System , message string ) []string {
137
- // !!! const colors = createColors(sys);
138
- var header []string
139
- // !!! terminalWidth := sys.GetWidthOfTerminal?.() ?? 0
140
- const tsIconLength = 5
141
-
142
- // const tsIconFirstLine = colors.blueBackground("".padStart(tsIconLength));
143
- // const tsIconSecondLine = colors.blueBackground(colors.brightWhite("TS ".padStart(tsIconLength)));
144
- // // If we have enough space, print TS icon.
145
- // if (terminalWidth >= message.length + tsIconLength) {
146
- // // right align of the icon is 120 at most.
147
- // const rightAlign = terminalWidth > 120 ? 120 : terminalWidth;
148
- // const leftAlign = rightAlign - tsIconLength;
149
- // header.push(message.padEnd(leftAlign) + tsIconFirstLine + sys.newLine);
150
- // header.push("".padStart(leftAlign) + tsIconSecondLine + sys.newLine);
151
- // }
152
- // else {
153
- header = append (header , message + "\n " , "\n " )
154
- // }
207
+ colors := createColors (sys )
208
+ header := make ([]string , 0 , 3 )
209
+ terminalWidth := sys .GetWidthOfTerminal ()
210
+ const tsIcon = " "
211
+ const tsIconTS = " TS "
212
+ const tsIconLength = len (tsIcon )
213
+
214
+ tsIconFirstLine := colors .blueBackground (tsIcon )
215
+ tsIconSecondLine := colors .blueBackground (colors .brightWhite (tsIconTS ))
216
+ // If we have enough space, print TS icon.
217
+ if terminalWidth >= len (message )+ tsIconLength {
218
+ // right align of the icon is 120 at most.
219
+ rightAlign := core .IfElse (terminalWidth > 120 , 120 , terminalWidth )
220
+ leftAlign := rightAlign - tsIconLength
221
+ header = append (header , fmt .Sprintf ("%-*s" , leftAlign , message ), tsIconFirstLine , "\n " )
222
+ header = append (header , strings .Repeat (" " , leftAlign ), tsIconSecondLine , "\n " )
223
+ } else {
224
+ header = append (header , message , "\n " , "\n " )
225
+ }
155
226
return header
156
227
}
157
228
158
229
func printEasyHelp (sys System , simpleOptions []* tsoptions.CommandLineOption ) {
159
- // !!! const colors = createColors(sys);
230
+ colors : = createColors (sys )
160
231
var output []string
161
232
example := func (examples []string , desc * diagnostics.Message ) {
162
233
for _ , example := range examples {
163
- // !!! colors
164
- // output.push(" " + colors.blue(example) + sys.newLine);
165
- output = append (output , " " , example , "\n " )
234
+ output = append (output , " " , colors .blue (example ), "\n " )
166
235
}
167
236
output = append (output , " " , desc .Format (), "\n " , "\n " )
168
237
}
169
238
170
239
msg := diagnostics .X_tsc_Colon_The_TypeScript_Compiler .Format () + " - " + diagnostics .Version_0 .Format (core .Version ())
171
240
output = append (output , getHeader (sys , msg )... )
172
241
173
- output = append (output /* colors.bold(*/ , diagnostics .COMMON_COMMANDS .Format () /*)*/ , "\n " , "\n " )
242
+ output = append (output , colors .bold (diagnostics .COMMON_COMMANDS .Format ()) , "\n " , "\n " )
174
243
175
244
example ([]string {"tsc" }, diagnostics .Compiles_the_current_project_tsconfig_json_in_the_working_directory )
176
245
example ([]string {"tsc app.ts util.ts" }, diagnostics .Ignoring_tsconfig_json_compiles_the_specified_files_with_default_compiler_options )
@@ -192,10 +261,9 @@ func printEasyHelp(sys System, simpleOptions []*tsoptions.CommandLineOption) {
192
261
193
262
output = append (output , generateSectionOptionsOutput (sys , diagnostics .COMMAND_LINE_FLAGS .Format (), cliCommands /*subCategory*/ , false /*beforeOptionsDescription*/ , nil /*afterOptionsDescription*/ , nil )... )
194
263
264
+ // !!! locale formatMessage
195
265
after := diagnostics .You_can_learn_about_all_of_the_compiler_options_at_0 .Format ("https://aka.ms/tsc" )
196
- output = append (output , generateSectionOptionsOutput (sys , diagnostics .COMMON_COMPILER_OPTIONS .Format (), configOpts /*subCategory*/ , false /*beforeOptionsDescription*/ , nil ,
197
- // !!! locale formatMessage(Diagnostics.You_can_learn_about_all_of_the_compiler_options_at_0, "https://aka.ms/tsc")),
198
- & after )... )
266
+ output = append (output , generateSectionOptionsOutput (sys , diagnostics .COMMON_COMPILER_OPTIONS .Format (), configOpts /*subCategory*/ , false /*beforeOptionsDescription*/ , nil , & after )... )
199
267
200
268
for _ , chunk := range output {
201
269
fmt .Fprint (sys .Writer (), chunk )
@@ -211,8 +279,7 @@ func generateSectionOptionsOutput(
211
279
beforeOptionsDescription ,
212
280
afterOptionsDescription * string ,
213
281
) (output []string ) {
214
- // !!! color
215
- output = append (output /*createColors(sys).bold(*/ , sectionName /*)*/ , "\n " , "\n " )
282
+ output = append (output , createColors (sys ).bold (sectionName ), "\n " , "\n " )
216
283
217
284
if beforeOptionsDescription != nil {
218
285
output = append (output , * beforeOptionsDescription , "\n " , "\n " )
@@ -274,10 +341,10 @@ func generateGroupOptionOutput(sys System, optionsList []*tsoptions.CommandLineO
274
341
func generateOptionOutput (
275
342
sys System ,
276
343
option * tsoptions.CommandLineOption ,
277
- rightAlignOfLeftPart , leftAlignOfRightPart int ,
344
+ rightAlignOfLeft , leftAlignOfRight int ,
278
345
) []string {
279
346
var text []string
280
- // !!! const colors = createColors(sys);
347
+ colors : = createColors (sys )
281
348
282
349
// name and description
283
350
name := getDisplayNameTextOfOption (option )
@@ -298,27 +365,28 @@ func generateOptionOutput(
298
365
)
299
366
}
300
367
301
- var terminalWidth int
302
- // !!! const terminalWidth = sys.getWidthOfTerminal?.() ?? 0;
368
+ terminalWidth := sys .GetWidthOfTerminal ()
303
369
304
- // Note: child_process might return `terminalWidth` as undefined.
305
370
if terminalWidth >= 80 {
306
- // !!! let description = "";
307
- // !!! if (option.description) {
308
- // !!! description = getDiagnosticText(option.description);
309
- // !!! }
310
- // !!! text.push(...getPrettyOutput(name, description, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ true), sys.newLine);
311
- // !!! if (showAdditionalInfoOutput(valueCandidates, option)) {
312
- // !!! if (valueCandidates) {
313
- // !!! text.push(...getPrettyOutput(valueCandidates.valueType, valueCandidates.possibleValues, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ false), sys.newLine);
314
- // !!! }
315
- // !!! if (defaultValueDescription) {
316
- // !!! text.push(...getPrettyOutput(getDiagnosticText(Diagnostics.default_Colon), defaultValueDescription, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ false), sys.newLine);
317
- // !!! }
318
- // !!! }
319
- // !!! text.push(sys.newLine);
371
+ description := ""
372
+ if option .Description != nil {
373
+ description = option .Description .Format ()
374
+ }
375
+ text = append (text , getPrettyOutput (colors , name , description , rightAlignOfLeft , leftAlignOfRight , terminalWidth , true /*colorLeft*/ )... )
376
+ text = append (text , "\n " )
377
+ if showAdditionalInfoOutput (valueCandidates , option ) {
378
+ if valueCandidates != nil {
379
+ text = append (text , getPrettyOutput (colors , valueCandidates .valueType , valueCandidates .possibleValues , rightAlignOfLeft , leftAlignOfRight , terminalWidth , false /*colorLeft*/ )... )
380
+ text = append (text , "\n " )
381
+ }
382
+ if defaultValueDescription != "" {
383
+ text = append (text , getPrettyOutput (colors , diagnostics .X_default_Colon .Format (), defaultValueDescription , rightAlignOfLeft , leftAlignOfRight , terminalWidth , false /*colorLeft*/ )... )
384
+ text = append (text , "\n " )
385
+ }
386
+ }
387
+ text = append (text , "\n " )
320
388
} else {
321
- text = append (text /* !!! colors.blue(name) */ , name , "\n " )
389
+ text = append (text , colors .blue (name ), "\n " )
322
390
if option .Description != nil {
323
391
text = append (text , option .Description .Format ())
324
392
}
@@ -444,6 +512,33 @@ func getPossibleValues(option *tsoptions.CommandLineOption) string {
444
512
}
445
513
}
446
514
515
+ func getPrettyOutput (colors * colors , left string , right string , rightAlignOfLeft int , leftAlignOfRight int , terminalWidth int , colorLeft bool ) []string {
516
+ // !!! How does terminalWidth interact with UTF-8 encoding? Strada just assumed UTF-16.
517
+ res := make ([]string , 0 , 4 )
518
+ isFirstLine := true
519
+ remainRight := right
520
+ rightCharacterNumber := terminalWidth - leftAlignOfRight
521
+ for len (remainRight ) > 0 {
522
+ curLeft := ""
523
+ if isFirstLine {
524
+ curLeft = fmt .Sprintf ("%*s" , rightAlignOfLeft , left )
525
+ curLeft = fmt .Sprintf ("%-*s" , leftAlignOfRight , curLeft )
526
+ if colorLeft {
527
+ curLeft = colors .blue (curLeft )
528
+ }
529
+ } else {
530
+ curLeft = strings .Repeat (" " , leftAlignOfRight )
531
+ }
532
+
533
+ idx := min (rightCharacterNumber , len (remainRight ))
534
+ curRight := remainRight [:idx ]
535
+ remainRight = remainRight [idx :]
536
+ res = append (res , curLeft , curRight , "\n " )
537
+ isFirstLine = false
538
+ }
539
+ return res
540
+ }
541
+
447
542
func getDisplayNameTextOfOption (option * tsoptions.CommandLineOption ) string {
448
543
return "--" + option .Name + core .IfElse (option .ShortName != "" , ", -" + option .ShortName , "" )
449
544
}
0 commit comments