2022-11-16 10:33:57PM
This commit is contained in:
parent
7d9ace3ae4
commit
052b461b03
3 changed files with 134 additions and 24 deletions
|
|
@ -28,7 +28,7 @@ Subcommands:
|
||||||
%[1]s layout [layout name] - Display long help for a particular layout engine
|
%[1]s layout [layout name] - Display long help for a particular layout engine
|
||||||
|
|
||||||
See more docs and the source code at https://oss.terrastruct.com/d2
|
See more docs and the source code at https://oss.terrastruct.com/d2
|
||||||
`, ms.Name, ms.Opts.Help())
|
`, ms.Name, ms.Opts.Defaults())
|
||||||
}
|
}
|
||||||
|
|
||||||
func layoutHelp(ctx context.Context, ms *xmain.State) error {
|
func layoutHelp(ctx context.Context, ms *xmain.State) error {
|
||||||
|
|
|
||||||
45
lib/xmain/flag_helpers.go
Normal file
45
lib/xmain/flag_helpers.go
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
// flag_helpers.go are private functions from pflag/flag.go
|
||||||
|
package xmain
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
func wrap(i, w int, s string) string {
|
||||||
|
if w == 0 {
|
||||||
|
return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1)
|
||||||
|
}
|
||||||
|
wrap := w - i
|
||||||
|
var r, l string
|
||||||
|
if wrap < 24 {
|
||||||
|
i = 16
|
||||||
|
wrap = w - i
|
||||||
|
r += "\n" + strings.Repeat(" ", i)
|
||||||
|
}
|
||||||
|
if wrap < 24 {
|
||||||
|
return strings.Replace(s, "\n", r, -1)
|
||||||
|
}
|
||||||
|
slop := 5
|
||||||
|
wrap = wrap - slop
|
||||||
|
l, s = wrapN(wrap, slop, s)
|
||||||
|
r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1)
|
||||||
|
for s != "" {
|
||||||
|
var t string
|
||||||
|
t, s = wrapN(wrap, slop, s)
|
||||||
|
r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapN(i, slop int, s string) (string, string) {
|
||||||
|
if i+slop > len(s) {
|
||||||
|
return s, ""
|
||||||
|
}
|
||||||
|
w := strings.LastIndexAny(s[:i], " \t\n")
|
||||||
|
if w <= 0 {
|
||||||
|
return s, ""
|
||||||
|
}
|
||||||
|
nlPos := strings.LastIndex(s[:i], "\n")
|
||||||
|
if nlPos > 0 && nlPos < w {
|
||||||
|
return s[:nlPos], s[nlPos+1:]
|
||||||
|
}
|
||||||
|
return s[:w], s[w+1:]
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package xmain
|
package xmain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
@ -17,7 +18,7 @@ type Opts struct {
|
||||||
env *xos.Env
|
env *xos.Env
|
||||||
log *cmdlog.Logger
|
log *cmdlog.Logger
|
||||||
|
|
||||||
registeredEnvs []string
|
flagEnv map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOpts(env *xos.Env, log *cmdlog.Logger, args []string) *Opts {
|
func NewOpts(env *xos.Env, log *cmdlog.Logger, args []string) *Opts {
|
||||||
|
|
@ -30,38 +31,102 @@ func NewOpts(env *xos.Env, log *cmdlog.Logger, args []string) *Opts {
|
||||||
Flags: flags,
|
Flags: flags,
|
||||||
env: env,
|
env: env,
|
||||||
log: log,
|
log: log,
|
||||||
|
flagEnv: make(map[string]string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Opts) Help() string {
|
// Mostly copy pasted pasted from pflag.FlagUsagesWrapped
|
||||||
b := &strings.Builder{}
|
// with modifications for env var
|
||||||
o.Flags.SetOutput(b)
|
func (o *Opts) Defaults() string {
|
||||||
o.Flags.PrintDefaults()
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
if len(o.registeredEnvs) > 0 {
|
var lines []string
|
||||||
b.WriteString("\nYou may persistently set the following as environment variables (flags take precedent):\n")
|
|
||||||
for i, e := range o.registeredEnvs {
|
maxlen := 0
|
||||||
s := fmt.Sprintf("- $%s", e)
|
maxEnvLen := 0
|
||||||
if i != len(o.registeredEnvs)-1 {
|
o.Flags.VisitAll(func(flag *pflag.Flag) {
|
||||||
s += "\n"
|
if flag.Hidden {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
b.WriteString(s)
|
|
||||||
|
line := ""
|
||||||
|
if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
|
||||||
|
line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name)
|
||||||
|
} else {
|
||||||
|
line = fmt.Sprintf(" --%s", flag.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
varname, usage := pflag.UnquoteUsage(flag)
|
||||||
|
if varname != "" {
|
||||||
|
line += " " + varname
|
||||||
|
}
|
||||||
|
if flag.NoOptDefVal != "" {
|
||||||
|
switch flag.Value.Type() {
|
||||||
|
case "string":
|
||||||
|
line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
|
||||||
|
case "bool":
|
||||||
|
if flag.NoOptDefVal != "true" {
|
||||||
|
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||||
|
}
|
||||||
|
case "count":
|
||||||
|
if flag.NoOptDefVal != "+1" {
|
||||||
|
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.String()
|
line += "\x00"
|
||||||
|
|
||||||
|
if len(line) > maxlen {
|
||||||
|
maxlen = len(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
if e, ok := o.flagEnv[flag.Name]; ok {
|
||||||
|
line += fmt.Sprintf("$%s", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
line += "\x01"
|
||||||
|
|
||||||
|
if len(line) > maxEnvLen {
|
||||||
|
maxEnvLen = len(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
line += usage
|
||||||
|
if flag.Value.Type() == "string" {
|
||||||
|
line += fmt.Sprintf(" (default %q)", flag.DefValue)
|
||||||
|
} else {
|
||||||
|
line += fmt.Sprintf(" (default %s)", flag.DefValue)
|
||||||
|
}
|
||||||
|
if len(flag.Deprecated) != 0 {
|
||||||
|
line += fmt.Sprintf(" (DEPRECATED: %s)", flag.Deprecated)
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, line)
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
sidx1 := strings.Index(line, "\x00")
|
||||||
|
sidx2 := strings.Index(line, "\x01")
|
||||||
|
spacing1 := strings.Repeat(" ", maxlen-sidx1)
|
||||||
|
spacing2 := strings.Repeat(" ", (maxEnvLen-maxlen)-sidx2+sidx1)
|
||||||
|
fmt.Fprintln(buf, line[:sidx1], spacing1, line[sidx1+1:sidx2], spacing2, wrap(maxEnvLen+3, 0, line[sidx2+1:]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Opts) getEnv(k string) string {
|
func (o *Opts) getEnv(flag, k string) string {
|
||||||
if k != "" {
|
if k != "" {
|
||||||
o.registeredEnvs = append(o.registeredEnvs, k)
|
o.flagEnv[flag] = k
|
||||||
return o.env.Getenv(k)
|
return o.env.Getenv(k)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Opts) Int64(envKey, flag, shortFlag string, defaultVal int64, usage string) (*int64, error) {
|
func (o *Opts) Int64(envKey, flag, shortFlag string, defaultVal int64, usage string) (*int64, error) {
|
||||||
if env := o.getEnv(envKey); env != "" {
|
if env := o.getEnv(flag, envKey); env != "" {
|
||||||
envVal, err := strconv.ParseInt(env, 10, 64)
|
envVal, err := strconv.ParseInt(env, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(`invalid environment variable %s. Expected int64. Found "%v".`, envKey, envVal)
|
return nil, fmt.Errorf(`invalid environment variable %s. Expected int64. Found "%v".`, envKey, envVal)
|
||||||
|
|
@ -73,7 +138,7 @@ func (o *Opts) Int64(envKey, flag, shortFlag string, defaultVal int64, usage str
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Opts) String(envKey, flag, shortFlag string, defaultVal, usage string) *string {
|
func (o *Opts) String(envKey, flag, shortFlag string, defaultVal, usage string) *string {
|
||||||
if env := o.getEnv(envKey); env != "" {
|
if env := o.getEnv(flag, envKey); env != "" {
|
||||||
defaultVal = env
|
defaultVal = env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +146,7 @@ func (o *Opts) String(envKey, flag, shortFlag string, defaultVal, usage string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Opts) Bool(envKey, flag, shortFlag string, defaultVal bool, usage string) (*bool, error) {
|
func (o *Opts) Bool(envKey, flag, shortFlag string, defaultVal bool, usage string) (*bool, error) {
|
||||||
if env := o.getEnv(envKey); env != "" {
|
if env := o.getEnv(flag, envKey); env != "" {
|
||||||
if !boolyEnv(env) {
|
if !boolyEnv(env) {
|
||||||
return nil, fmt.Errorf(`invalid environment variable %s. Expected bool. Found "%s".`, envKey, env)
|
return nil, fmt.Errorf(`invalid environment variable %s. Expected bool. Found "%s".`, envKey, env)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue