forked from terrastruct/d2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhelp.go
161 lines (131 loc) · 4.19 KB
/
help.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package d2cli
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"oss.terrastruct.com/util-go/xmain"
"oss.terrastruct.com/d2/d2plugin"
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
"oss.terrastruct.com/d2/lib/version"
)
func help(ms *xmain.State) {
fmt.Fprintf(ms.Stdout, `%[1]s %[2]s
Usage:
%[1]s [--watch=false] [--theme=0] file.d2 [file.svg | file.png]
%[1]s layout [name]
%[1]s fmt file.d2 ...
%[1]s compiles and renders file.d2 to file.svg | file.png
It defaults to file.svg if an output path is not provided.
Use - to have d2 read from stdin or write to stdout.
See man d2 for more detailed docs.
Flags:
%[3]s
Subcommands:
%[1]s layout - Lists available layout engine options with short help
%[1]s layout [name] - Display long help for a particular layout engine, including its configuration options
%[1]s themes - Lists available themes
%[1]s fmt file.d2 ... - Format passed files
See more docs and the source code at https://oss.terrastruct.com/d2.
Hosted icons at https://icons.terrastruct.com.
Playground runner at https://play.d2lang.com.
`, filepath.Base(ms.Name), version.Version, ms.Opts.Defaults())
}
func layoutCmd(ctx context.Context, ms *xmain.State, ps []d2plugin.Plugin) error {
if len(ms.Opts.Flags.Args()) == 1 {
return shortLayoutHelp(ctx, ms, ps)
} else if len(ms.Opts.Flags.Args()) == 2 {
return longLayoutHelp(ctx, ms, ps)
} else {
return pluginSubcommand(ctx, ms, ps)
}
}
func themesCmd(ctx context.Context, ms *xmain.State) {
fmt.Fprintf(ms.Stdout, "Available themes:\n%s", d2themescatalog.CLIString())
}
func shortLayoutHelp(ctx context.Context, ms *xmain.State, ps []d2plugin.Plugin) error {
var pluginLines []string
pinfos, err := d2plugin.ListPluginInfos(ctx, ps)
if err != nil {
return err
}
for _, p := range pinfos {
var l string
if p.Type == "bundled" {
l = fmt.Sprintf("%s (bundled) - %s", p.Name, p.ShortHelp)
} else {
l = fmt.Sprintf("%s (%s) - %s", p.Name, humanPath(p.Path), p.ShortHelp)
}
pluginLines = append(pluginLines, l)
}
fmt.Fprintf(ms.Stdout, `Available layout engines found:
%s
Usage:
To use a particular layout engine, set the environment variable D2_LAYOUT=[name] or flag --layout=[name].
Example:
D2_LAYOUT=dagre d2 in.d2 out.svg
Subcommands:
%s layout [layout name] - Display long help for a particular layout engine, including its configuration options
See more docs at https://d2lang.com/tour/layouts
`, strings.Join(pluginLines, "\n"), ms.Name)
return nil
}
func longLayoutHelp(ctx context.Context, ms *xmain.State, ps []d2plugin.Plugin) error {
layout := ms.Opts.Flags.Arg(1)
plugin, err := d2plugin.FindPlugin(ctx, ps, layout)
if err != nil {
if errors.Is(err, exec.ErrNotFound) {
return layoutNotFound(ctx, ps, layout)
}
return err
}
pinfo, err := plugin.Info(ctx)
if err != nil {
return err
}
plocation := pinfo.Type
if pinfo.Type == "binary" {
plocation = fmt.Sprintf("executable plugin at %s", humanPath(pinfo.Path))
}
if !strings.HasSuffix(pinfo.LongHelp, "\n") {
pinfo.LongHelp += "\n"
}
fmt.Fprintf(ms.Stdout, `%s (%s):
%s`, pinfo.Name, plocation, pinfo.LongHelp)
return nil
}
func layoutNotFound(ctx context.Context, ps []d2plugin.Plugin, layout string) error {
pinfos, err := d2plugin.ListPluginInfos(ctx, ps)
if err != nil {
return err
}
var names []string
for _, p := range pinfos {
names = append(names, p.Name)
}
return xmain.UsageErrorf(`D2_LAYOUT "%s" is not bundled and could not be found in your $PATH.
The available options are: %s. For details on each option, run "d2 layout".
For more information on setup, please visit https://github.com/terrastruct/d2.`,
layout, strings.Join(names, ", "))
}
func pluginSubcommand(ctx context.Context, ms *xmain.State, ps []d2plugin.Plugin) error {
layout := ms.Opts.Flags.Arg(1)
plugin, err := d2plugin.FindPlugin(ctx, ps, layout)
if err != nil {
if errors.Is(err, exec.ErrNotFound) {
return layoutNotFound(ctx, ps, layout)
}
return err
}
ms.Opts.Args = ms.Opts.Flags.Args()[2:]
return d2plugin.Serve(plugin)(ctx, ms)
}
func humanPath(fp string) string {
if strings.HasPrefix(fp, os.Getenv("HOME")) {
return filepath.Join("~", strings.TrimPrefix(fp, os.Getenv("HOME")))
}
return fp
}