forked from terrastruct/d2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
help.go
151 lines (122 loc) · 3.79 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
package main
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"oss.terrastruct.com/util-go/xmain"
"oss.terrastruct.com/d2/d2plugin"
)
func help(ms *xmain.State) {
fmt.Fprintf(ms.Stdout, `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:
%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 fmt file.d2 - Format file.d2
See more docs and the source code at https://oss.terrastruct.com/d2
`, filepath.Base(ms.Name), 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 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://oss.terrastruct.com/d2
`, 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
}