gf/os/gcmd/gcmd_command_help.go

242 lines
5.7 KiB
Go

// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
//
package gcmd
import (
"bytes"
"context"
"fmt"
"io"
"os"
"github.com/gogf/gf/v2/text/gstr"
)
// Print prints help info to stdout for current command.
func (c *Command) Print() {
c.PrintTo(os.Stdout)
}
// PrintTo prints help info to custom io.Writer.
func (c *Command) PrintTo(writer io.Writer) {
var (
prefix = gstr.Repeat(" ", 4)
buffer = bytes.NewBuffer(nil)
arguments = make([]Argument, len(c.Arguments))
)
// Copy options for printing.
copy(arguments, c.Arguments)
// Add built-in help option, just for info only.
arguments = append(arguments, defaultHelpOption)
// Usage.
if c.Usage != "" || c.Name != "" {
buffer.WriteString("USAGE\n")
buffer.WriteString(prefix)
if c.Usage != "" {
buffer.WriteString(c.Usage)
} else {
var (
p = c
name = c.Name
)
for p.parent != nil {
name = p.parent.Name + " " + name
p = p.parent
}
buffer.WriteString(name)
if len(c.commands) > 0 {
buffer.WriteString(` COMMAND`)
}
if c.hasArgumentFromIndex() {
buffer.WriteString(` ARGUMENT`)
}
buffer.WriteString(` [OPTION]`)
}
buffer.WriteString("\n\n")
}
// Command.
if len(c.commands) > 0 {
buffer.WriteString("COMMAND\n")
var (
maxSpaceLength = 0
)
for _, cmd := range c.commands {
if len(cmd.Name) > maxSpaceLength {
maxSpaceLength = len(cmd.Name)
}
}
for _, cmd := range c.commands {
var (
spaceLength = maxSpaceLength - len(cmd.Name)
wordwrapPrefix = gstr.Repeat(" ", len(prefix+cmd.Name)+spaceLength+4)
)
c.printLineBrief(printLineBriefInput{
Buffer: buffer,
Name: cmd.Name,
Prefix: prefix,
Brief: gstr.Trim(cmd.Brief),
WordwrapPrefix: wordwrapPrefix,
SpaceLength: spaceLength,
})
}
buffer.WriteString("\n")
}
// Argument.
if c.hasArgumentFromIndex() {
buffer.WriteString("ARGUMENT\n")
var (
maxSpaceLength = 0
)
for _, arg := range arguments {
if !arg.IsArg {
continue
}
if len(arg.Name) > maxSpaceLength {
maxSpaceLength = len(arg.Name)
}
}
for _, arg := range arguments {
if !arg.IsArg {
continue
}
var (
spaceLength = maxSpaceLength - len(arg.Name)
wordwrapPrefix = gstr.Repeat(" ", len(prefix+arg.Name)+spaceLength+4)
)
c.printLineBrief(printLineBriefInput{
Buffer: buffer,
Name: arg.Name,
Prefix: prefix,
Brief: gstr.Trim(arg.Brief),
WordwrapPrefix: wordwrapPrefix,
SpaceLength: spaceLength,
})
}
buffer.WriteString("\n")
}
// Option.
if c.hasArgumentFromOption() {
buffer.WriteString("OPTION\n")
var (
nameStr string
maxSpaceLength = 0
)
for _, arg := range arguments {
if arg.IsArg {
continue
}
if arg.Short != "" {
nameStr = fmt.Sprintf("-%s,--%s", arg.Short, arg.Name)
} else {
nameStr = fmt.Sprintf("-/--%s", arg.Name)
}
if len(nameStr) > maxSpaceLength {
maxSpaceLength = len(nameStr)
}
}
for _, arg := range arguments {
if arg.IsArg {
continue
}
if arg.Short != "" {
nameStr = fmt.Sprintf("-%s, --%s", arg.Short, arg.Name)
} else {
nameStr = fmt.Sprintf("-/--%s", arg.Name)
}
var (
brief = gstr.Trim(arg.Brief)
spaceLength = maxSpaceLength - len(nameStr)
wordwrapPrefix = gstr.Repeat(" ", len(prefix+nameStr)+spaceLength+4)
)
c.printLineBrief(printLineBriefInput{
Buffer: buffer,
Name: nameStr,
Prefix: prefix,
Brief: brief,
WordwrapPrefix: wordwrapPrefix,
SpaceLength: spaceLength,
})
}
buffer.WriteString("\n")
}
// Example.
if c.Examples != "" {
buffer.WriteString("EXAMPLE\n")
for _, line := range gstr.SplitAndTrim(gstr.Trim(c.Examples), "\n") {
buffer.WriteString(prefix)
buffer.WriteString(gstr.WordWrap(gstr.Trim(line), maxLineChars, "\n"+prefix))
buffer.WriteString("\n")
}
buffer.WriteString("\n")
}
// Description.
if c.Description != "" {
buffer.WriteString("DESCRIPTION\n")
for _, line := range gstr.SplitAndTrim(gstr.Trim(c.Description), "\n") {
buffer.WriteString(prefix)
buffer.WriteString(gstr.WordWrap(gstr.Trim(line), maxLineChars, "\n"+prefix))
buffer.WriteString("\n")
}
buffer.WriteString("\n")
}
// Additional.
if c.Additional != "" {
lineStr := gstr.WordWrap(gstr.Trim(c.Additional), maxLineChars, "\n")
buffer.WriteString(lineStr)
buffer.WriteString("\n")
}
content := buffer.String()
content = gstr.Replace(content, "\t", " ")
_, _ = writer.Write([]byte(content))
}
type printLineBriefInput struct {
Buffer *bytes.Buffer
Name string
Prefix string
Brief string
WordwrapPrefix string
SpaceLength int
}
func (c *Command) printLineBrief(in printLineBriefInput) {
briefArray := gstr.SplitAndTrim(in.Brief, "\n")
if len(briefArray) == 0 {
// If command brief is empty, it just prints its command name.
briefArray = []string{""}
}
for i, line := range briefArray {
var lineStr string
if i == 0 {
lineStr = fmt.Sprintf(
"%s%s%s%s\n",
in.Prefix, in.Name, gstr.Repeat(" ", in.SpaceLength+4), line,
)
} else {
lineStr = fmt.Sprintf(
"%s%s%s%s\n",
in.Prefix, gstr.Repeat(" ", len(in.Name)), gstr.Repeat(" ", in.SpaceLength+4), line,
)
}
lineStr = gstr.WordWrap(lineStr, maxLineChars, "\n"+in.WordwrapPrefix)
in.Buffer.WriteString(lineStr)
}
}
func (c *Command) defaultHelpFunc(ctx context.Context, parser *Parser) error {
// Print command help info to stdout.
c.Print()
return nil
}