Skip to content

Commit 4840bb9

Browse files
haoqixujakebailey
andauthored
Port part of tsc help from strada (#636)
Co-authored-by: Jake Bailey <[email protected]>
1 parent 368a8e5 commit 4840bb9

14 files changed

+424
-59
lines changed

internal/core/compileroptions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ type CompilerOptions struct {
134134
Watch Tristate `json:"watch,omitzero"`
135135
ShowConfig Tristate `json:"showConfig,omitzero"`
136136
TscBuild Tristate `json:"tscBuild,omitzero"`
137+
Help Tristate `json:"help,omitzero"`
138+
All Tristate `json:"all,omitzero"`
137139
}
138140

139141
func (options *CompilerOptions) GetEmitScriptTarget() ScriptTarget {

internal/execute/outputs.go

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package execute
22

33
import (
44
"fmt"
5+
"slices"
56
"strings"
67

78
"github.com/microsoft/typescript-go/internal/ast"
89
"github.com/microsoft/typescript-go/internal/compiler"
910
"github.com/microsoft/typescript-go/internal/compiler/diagnostics"
1011
"github.com/microsoft/typescript-go/internal/core"
1112
"github.com/microsoft/typescript-go/internal/diagnosticwriter"
13+
"github.com/microsoft/typescript-go/internal/tsoptions"
1214
"github.com/microsoft/typescript-go/internal/tspath"
1315
)
1416

@@ -85,3 +87,186 @@ func printVersion(sys System) {
8587
fmt.Fprint(sys.Writer(), diagnostics.Version_0.Format(core.Version)+sys.NewLine())
8688
sys.EndWrite()
8789
}
90+
91+
func printHelp(sys System, commandLine *tsoptions.ParsedCommandLine) {
92+
if commandLine.CompilerOptions().All.IsFalseOrUnknown() {
93+
printEasyHelp(sys, getOptionsForHelp(commandLine))
94+
} else {
95+
// !!! printAllHelp(sys, getOptionsForHelp(commandLine))
96+
}
97+
}
98+
99+
func getOptionsForHelp(commandLine *tsoptions.ParsedCommandLine) []*tsoptions.CommandLineOption {
100+
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
101+
opts := slices.Clone(tsoptions.OptionsDeclarations)
102+
opts = append(opts, &tsoptions.TscBuildOption)
103+
104+
if commandLine.CompilerOptions().All.IsTrue() {
105+
slices.SortFunc(opts, func(a, b *tsoptions.CommandLineOption) int {
106+
return strings.Compare(strings.ToLower(a.Name), strings.ToLower(b.Name))
107+
})
108+
return opts
109+
} else {
110+
return core.Filter(opts, func(opt *tsoptions.CommandLineOption) bool {
111+
return opt.ShowInSimplifiedHelpView
112+
})
113+
}
114+
}
115+
116+
func getHeader(sys System, message string) []string {
117+
// !!! const colors = createColors(sys);
118+
var header []string
119+
// !!! terminalWidth := sys.GetWidthOfTerminal?.() ?? 0
120+
const tsIconLength = 5
121+
122+
// const tsIconFirstLine = colors.blueBackground("".padStart(tsIconLength));
123+
// const tsIconSecondLine = colors.blueBackground(colors.brightWhite("TS ".padStart(tsIconLength)));
124+
// // If we have enough space, print TS icon.
125+
// if (terminalWidth >= message.length + tsIconLength) {
126+
// // right align of the icon is 120 at most.
127+
// const rightAlign = terminalWidth > 120 ? 120 : terminalWidth;
128+
// const leftAlign = rightAlign - tsIconLength;
129+
// header.push(message.padEnd(leftAlign) + tsIconFirstLine + sys.newLine);
130+
// header.push("".padStart(leftAlign) + tsIconSecondLine + sys.newLine);
131+
// }
132+
// else {
133+
header = append(header, message+sys.NewLine(), sys.NewLine())
134+
// }
135+
return header
136+
}
137+
138+
func printEasyHelp(sys System, simpleOptions []*tsoptions.CommandLineOption) {
139+
// !!! const colors = createColors(sys);
140+
var output []string
141+
example := func(examples []string, desc *diagnostics.Message) {
142+
for _, example := range examples {
143+
// !!! colors
144+
// output.push(" " + colors.blue(example) + sys.newLine);
145+
output = append(output, " ", example, sys.NewLine())
146+
}
147+
output = append(output, " ", desc.Format(), sys.NewLine(), sys.NewLine())
148+
}
149+
150+
msg := diagnostics.X_tsc_Colon_The_TypeScript_Compiler.Format() + " - " + diagnostics.Version_0.Format(core.Version)
151+
output = append(output, getHeader(sys, msg)...)
152+
153+
output = append(output /*colors.bold(*/, diagnostics.COMMON_COMMANDS.Format() /*)*/, sys.NewLine(), sys.NewLine())
154+
155+
example([]string{"tsc"}, diagnostics.Compiles_the_current_project_tsconfig_json_in_the_working_directory)
156+
example([]string{"tsc app.ts util.ts"}, diagnostics.Ignoring_tsconfig_json_compiles_the_specified_files_with_default_compiler_options)
157+
example([]string{"tsc -b"}, diagnostics.Build_a_composite_project_in_the_working_directory)
158+
example([]string{"tsc --init"}, diagnostics.Creates_a_tsconfig_json_with_the_recommended_settings_in_the_working_directory)
159+
example([]string{"tsc -p ./path/to/tsconfig.json"}, diagnostics.Compiles_the_TypeScript_project_located_at_the_specified_path)
160+
example([]string{"tsc --help --all"}, diagnostics.An_expanded_version_of_this_information_showing_all_possible_compiler_options)
161+
example([]string{"tsc --noEmit", "tsc --target esnext"}, diagnostics.Compiles_the_current_project_with_additional_settings)
162+
163+
var cliCommands []*tsoptions.CommandLineOption
164+
var configOpts []*tsoptions.CommandLineOption
165+
for _, opt := range simpleOptions {
166+
if opt.IsCommandLineOnly || opt.Category == diagnostics.Command_line_Options {
167+
cliCommands = append(cliCommands, opt)
168+
} else {
169+
configOpts = append(configOpts, opt)
170+
}
171+
}
172+
173+
output = append(output, generateSectionOptionsOutput(sys, diagnostics.COMMAND_LINE_FLAGS.Format(), cliCommands /*subCategory*/, false /*beforeOptionsDescription*/, nil /*afterOptionsDescription*/, nil)...)
174+
175+
after := diagnostics.You_can_learn_about_all_of_the_compiler_options_at_0.Format("https://aka.ms/tsc")
176+
output = append(output, generateSectionOptionsOutput(sys, diagnostics.COMMON_COMPILER_OPTIONS.Format(), configOpts /*subCategory*/, false /*beforeOptionsDescription*/, nil,
177+
// !!! locale formatMessage(Diagnostics.You_can_learn_about_all_of_the_compiler_options_at_0, "https://aka.ms/tsc")),
178+
&after)...)
179+
180+
for _, chunk := range output {
181+
fmt.Fprint(sys.Writer(), chunk)
182+
}
183+
sys.EndWrite()
184+
}
185+
186+
func generateSectionOptionsOutput(
187+
sys System,
188+
sectionName string,
189+
options []*tsoptions.CommandLineOption,
190+
subCategory bool,
191+
beforeOptionsDescription,
192+
afterOptionsDescription *string,
193+
) (output []string) {
194+
// !!! color
195+
output = append(output /*createColors(sys).bold(*/, sectionName /*)*/, sys.NewLine(), sys.NewLine())
196+
197+
if beforeOptionsDescription != nil {
198+
output = append(output, *beforeOptionsDescription, sys.NewLine(), sys.NewLine())
199+
}
200+
if !subCategory {
201+
output = append(output, generateGroupOptionOutput(sys, options)...)
202+
if afterOptionsDescription != nil {
203+
output = append(output, *afterOptionsDescription, sys.NewLine(), sys.NewLine())
204+
}
205+
return output
206+
}
207+
categoryMap := make(map[string][]*tsoptions.CommandLineOption)
208+
for _, option := range options {
209+
if option.Category == nil {
210+
continue
211+
}
212+
curCategory := option.Category.Format()
213+
categoryMap[curCategory] = append(categoryMap[curCategory], option)
214+
}
215+
for key, value := range categoryMap {
216+
output = append(output, "### ", key, sys.NewLine(), sys.NewLine())
217+
output = append(output, generateGroupOptionOutput(sys, value)...)
218+
}
219+
if afterOptionsDescription != nil {
220+
output = append(output, *afterOptionsDescription, sys.NewLine(), sys.NewLine())
221+
}
222+
223+
return output
224+
}
225+
226+
func generateGroupOptionOutput(sys System, optionsList []*tsoptions.CommandLineOption) []string {
227+
var maxLength int
228+
for _, option := range optionsList {
229+
curLenght := len(getDisplayNameTextOfOption(option))
230+
maxLength = max(curLenght, maxLength)
231+
}
232+
233+
// left part should be right align, right part should be left align
234+
235+
// assume 2 space between left margin and left part.
236+
rightAlignOfLeftPart := maxLength + 2
237+
// assume 2 space between left and right part
238+
leftAlignOfRightPart := rightAlignOfLeftPart + 2
239+
240+
var lines []string
241+
for _, option := range optionsList {
242+
tmp := generateOptionOutput(sys, option, rightAlignOfLeftPart, leftAlignOfRightPart)
243+
lines = append(lines, tmp...)
244+
}
245+
246+
// make sure always a blank line in the end.
247+
// !!! if lines[len(lines)-2] != sys.NewLine() {
248+
// !!! lines = append(lines, sys.NewLine())
249+
// !!! }
250+
251+
return lines
252+
}
253+
254+
func generateOptionOutput(
255+
sys System,
256+
option *tsoptions.CommandLineOption,
257+
rightAlignOfLeftPart, leftAlignOfRightPart int,
258+
) []string {
259+
var text []string
260+
// !!! const colors = createColors(sys);
261+
262+
// name and description
263+
// !!! name := getDisplayNameTextOfOption(option)
264+
265+
// !!!
266+
267+
return text
268+
}
269+
270+
func getDisplayNameTextOfOption(option *tsoptions.CommandLineOption) string {
271+
return "--" + option.Name + core.IfElse(option.ShortName != "", ", -"+option.ShortName, "")
272+
}

internal/execute/tsc.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@ func executeCommandLineWorker(sys System, cb cbType, commandLine *tsoptions.Pars
3434
return ExitStatusDiagnosticsPresent_OutputsSkipped, nil
3535
}
3636

37-
if commandLine.CompilerOptions().Init.IsTrue() ||
38-
// commandLine.CompilerOptions().Help != nil ||
39-
// commandLine.CompilerOptions().All != nil ||
40-
commandLine.CompilerOptions().Watch.IsTrue() && commandLine.CompilerOptions().ListFilesOnly.IsTrue() {
37+
if commandLine.CompilerOptions().Init.IsTrue() {
4138
return ExitStatusNotImplemented, nil
4239
}
4340

@@ -46,6 +43,15 @@ func executeCommandLineWorker(sys System, cb cbType, commandLine *tsoptions.Pars
4643
return ExitStatusSuccess, nil
4744
}
4845

46+
if commandLine.CompilerOptions().Help.IsTrue() || commandLine.CompilerOptions().All.IsTrue() {
47+
printHelp(sys, commandLine)
48+
return ExitStatusSuccess, nil
49+
}
50+
51+
if commandLine.CompilerOptions().Watch.IsTrue() && commandLine.CompilerOptions().ListFilesOnly.IsTrue() {
52+
return ExitStatusNotImplemented, nil
53+
}
54+
4955
if commandLine.CompilerOptions().Project != "" {
5056
if len(commandLine.FileNames()) != 0 {
5157
reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line))
@@ -76,7 +82,7 @@ func executeCommandLineWorker(sys System, cb cbType, commandLine *tsoptions.Pars
7682
reportDiagnostic(ast.NewCompilerDiagnostic(diagnostics.Cannot_find_a_tsconfig_json_file_at_the_current_directory_Colon_0, tspath.NormalizePath(sys.GetCurrentDirectory())))
7783
} else {
7884
printVersion(sys)
79-
// print help
85+
printHelp(sys, commandLine)
8086
}
8187
return ExitStatusDiagnosticsPresent_OutputsSkipped, nil
8288
}

internal/tsoptions/commandlineoption.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const (
1919
)
2020

2121
type CommandLineOption struct {
22-
Name, shortName string
22+
Name, ShortName string
2323
Kind CommandLineOptionKind
2424

2525
// used in parsing
@@ -30,7 +30,7 @@ type CommandLineOption struct {
3030
// used in output
3131
Description *diagnostics.Message
3232
DefaultValueDescription any
33-
showInSimplifiedHelpView bool
33+
ShowInSimplifiedHelpView bool
3434

3535
// used in output in serializing and generate tsconfig
3636
Category *diagnostics.Message

internal/tsoptions/declsbuild.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,37 @@ import (
88

99
var BuildOpts = slices.Concat(commonOptionsWithBuild, optionsForBuild)
1010

11-
var tscBuildOption = CommandLineOption{
11+
var TscBuildOption = CommandLineOption{
1212
Name: "build",
1313
Kind: "boolean",
14-
shortName: "b",
15-
showInSimplifiedHelpView: true,
14+
ShortName: "b",
15+
ShowInSimplifiedHelpView: true,
1616
Category: diagnostics.Command_line_Options,
1717
Description: diagnostics.Build_one_or_more_projects_and_their_dependencies_if_out_of_date,
1818
DefaultValueDescription: false,
1919
}
2020

2121
var optionsForBuild = []*CommandLineOption{
22-
&tscBuildOption,
22+
&TscBuildOption,
2323
{
2424
Name: "verbose",
25-
shortName: "v",
25+
ShortName: "v",
2626
Category: diagnostics.Command_line_Options,
2727
Description: diagnostics.Enable_verbose_logging,
2828
Kind: "boolean",
2929
DefaultValueDescription: false,
3030
},
3131
{
3232
Name: "dry",
33-
shortName: "d",
33+
ShortName: "d",
3434
Category: diagnostics.Command_line_Options,
3535
Description: diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
3636
Kind: "boolean",
3737
DefaultValueDescription: false,
3838
},
3939
{
4040
Name: "force",
41-
shortName: "f",
41+
ShortName: "f",
4242
Category: diagnostics.Command_line_Options,
4343
Description: diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
4444
Kind: "boolean",

0 commit comments

Comments
 (0)