github.com/gogf/gf/v2@v2.7.4/os/gcmd/gcmd_command_help.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  //
     7  
     8  package gcmd
     9  
    10  import (
    11  	"bytes"
    12  	"context"
    13  	"fmt"
    14  	"io"
    15  	"os"
    16  
    17  	"github.com/gogf/gf/v2/text/gstr"
    18  )
    19  
    20  // Print prints help info to stdout for current command.
    21  func (c *Command) Print() {
    22  	c.PrintTo(os.Stdout)
    23  }
    24  
    25  // PrintTo prints help info to custom io.Writer.
    26  func (c *Command) PrintTo(writer io.Writer) {
    27  	var (
    28  		prefix    = gstr.Repeat(" ", 4)
    29  		buffer    = bytes.NewBuffer(nil)
    30  		arguments = make([]Argument, len(c.Arguments))
    31  	)
    32  	// Copy options for printing.
    33  	copy(arguments, c.Arguments)
    34  	// Add built-in help option, just for info only.
    35  	arguments = append(arguments, defaultHelpOption)
    36  
    37  	// Usage.
    38  	if c.Usage != "" || c.Name != "" {
    39  		buffer.WriteString("USAGE\n")
    40  		buffer.WriteString(prefix)
    41  		if c.Usage != "" {
    42  			buffer.WriteString(c.Usage)
    43  		} else {
    44  			var (
    45  				p    = c
    46  				name = c.Name
    47  			)
    48  			for p.parent != nil {
    49  				name = p.parent.Name + " " + name
    50  				p = p.parent
    51  			}
    52  			buffer.WriteString(name)
    53  			if len(c.commands) > 0 {
    54  				buffer.WriteString(` COMMAND`)
    55  			}
    56  			if c.hasArgumentFromIndex() {
    57  				buffer.WriteString(` ARGUMENT`)
    58  			}
    59  			buffer.WriteString(` [OPTION]`)
    60  		}
    61  		buffer.WriteString("\n\n")
    62  	}
    63  	// Command.
    64  	if len(c.commands) > 0 {
    65  		buffer.WriteString("COMMAND\n")
    66  		var (
    67  			maxSpaceLength = 0
    68  		)
    69  		for _, cmd := range c.commands {
    70  			if len(cmd.Name) > maxSpaceLength {
    71  				maxSpaceLength = len(cmd.Name)
    72  			}
    73  		}
    74  		for _, cmd := range c.commands {
    75  			var (
    76  				spaceLength    = maxSpaceLength - len(cmd.Name)
    77  				wordwrapPrefix = gstr.Repeat(" ", len(prefix+cmd.Name)+spaceLength+4)
    78  			)
    79  			c.printLineBrief(printLineBriefInput{
    80  				Buffer:         buffer,
    81  				Name:           cmd.Name,
    82  				Prefix:         prefix,
    83  				Brief:          gstr.Trim(cmd.Brief),
    84  				WordwrapPrefix: wordwrapPrefix,
    85  				SpaceLength:    spaceLength,
    86  			})
    87  		}
    88  		buffer.WriteString("\n")
    89  	}
    90  
    91  	// Argument.
    92  	if c.hasArgumentFromIndex() {
    93  		buffer.WriteString("ARGUMENT\n")
    94  		var (
    95  			maxSpaceLength = 0
    96  		)
    97  		for _, arg := range arguments {
    98  			if !arg.IsArg {
    99  				continue
   100  			}
   101  			if len(arg.Name) > maxSpaceLength {
   102  				maxSpaceLength = len(arg.Name)
   103  			}
   104  		}
   105  		for _, arg := range arguments {
   106  			if !arg.IsArg {
   107  				continue
   108  			}
   109  			var (
   110  				spaceLength    = maxSpaceLength - len(arg.Name)
   111  				wordwrapPrefix = gstr.Repeat(" ", len(prefix+arg.Name)+spaceLength+4)
   112  			)
   113  			c.printLineBrief(printLineBriefInput{
   114  				Buffer:         buffer,
   115  				Name:           arg.Name,
   116  				Prefix:         prefix,
   117  				Brief:          gstr.Trim(arg.Brief),
   118  				WordwrapPrefix: wordwrapPrefix,
   119  				SpaceLength:    spaceLength,
   120  			})
   121  		}
   122  		buffer.WriteString("\n")
   123  	}
   124  
   125  	// Option.
   126  	if c.hasArgumentFromOption() {
   127  		buffer.WriteString("OPTION\n")
   128  		var (
   129  			nameStr        string
   130  			maxSpaceLength = 0
   131  		)
   132  		for _, arg := range arguments {
   133  			if arg.IsArg {
   134  				continue
   135  			}
   136  			if arg.Short != "" {
   137  				nameStr = fmt.Sprintf("-%s,--%s", arg.Short, arg.Name)
   138  			} else {
   139  				nameStr = fmt.Sprintf("-/--%s", arg.Name)
   140  			}
   141  			if len(nameStr) > maxSpaceLength {
   142  				maxSpaceLength = len(nameStr)
   143  			}
   144  		}
   145  		for _, arg := range arguments {
   146  			if arg.IsArg {
   147  				continue
   148  			}
   149  			if arg.Short != "" {
   150  				nameStr = fmt.Sprintf("-%s, --%s", arg.Short, arg.Name)
   151  			} else {
   152  				nameStr = fmt.Sprintf("-/--%s", arg.Name)
   153  			}
   154  			var (
   155  				brief          = gstr.Trim(arg.Brief)
   156  				spaceLength    = maxSpaceLength - len(nameStr)
   157  				wordwrapPrefix = gstr.Repeat(" ", len(prefix+nameStr)+spaceLength+4)
   158  			)
   159  			c.printLineBrief(printLineBriefInput{
   160  				Buffer:         buffer,
   161  				Name:           nameStr,
   162  				Prefix:         prefix,
   163  				Brief:          brief,
   164  				WordwrapPrefix: wordwrapPrefix,
   165  				SpaceLength:    spaceLength,
   166  			})
   167  		}
   168  		buffer.WriteString("\n")
   169  	}
   170  
   171  	// Example.
   172  	if c.Examples != "" {
   173  		buffer.WriteString("EXAMPLE\n")
   174  		for _, line := range gstr.SplitAndTrim(gstr.Trim(c.Examples), "\n") {
   175  			buffer.WriteString(prefix)
   176  			buffer.WriteString(gstr.WordWrap(gstr.Trim(line), maxLineChars, "\n"+prefix))
   177  			buffer.WriteString("\n")
   178  		}
   179  		buffer.WriteString("\n")
   180  	}
   181  
   182  	// Description.
   183  	if c.Description != "" {
   184  		buffer.WriteString("DESCRIPTION\n")
   185  		for _, line := range gstr.SplitAndTrim(gstr.Trim(c.Description), "\n") {
   186  			buffer.WriteString(prefix)
   187  			buffer.WriteString(gstr.WordWrap(gstr.Trim(line), maxLineChars, "\n"+prefix))
   188  			buffer.WriteString("\n")
   189  		}
   190  		buffer.WriteString("\n")
   191  	}
   192  
   193  	// Additional.
   194  	if c.Additional != "" {
   195  		lineStr := gstr.WordWrap(gstr.Trim(c.Additional), maxLineChars, "\n")
   196  		buffer.WriteString(lineStr)
   197  		buffer.WriteString("\n")
   198  	}
   199  	content := buffer.String()
   200  	content = gstr.Replace(content, "\t", "    ")
   201  	_, _ = writer.Write([]byte(content))
   202  }
   203  
   204  type printLineBriefInput struct {
   205  	Buffer         *bytes.Buffer
   206  	Name           string
   207  	Prefix         string
   208  	Brief          string
   209  	WordwrapPrefix string
   210  	SpaceLength    int
   211  }
   212  
   213  func (c *Command) printLineBrief(in printLineBriefInput) {
   214  	briefArray := gstr.SplitAndTrim(in.Brief, "\n")
   215  	if len(briefArray) == 0 {
   216  		// If command brief is empty, it just prints its command name.
   217  		briefArray = []string{""}
   218  	}
   219  	for i, line := range briefArray {
   220  		var lineStr string
   221  		if i == 0 {
   222  			lineStr = fmt.Sprintf(
   223  				"%s%s%s%s\n",
   224  				in.Prefix, in.Name, gstr.Repeat(" ", in.SpaceLength+4), line,
   225  			)
   226  		} else {
   227  			lineStr = fmt.Sprintf(
   228  				"%s%s%s%s\n",
   229  				in.Prefix, gstr.Repeat(" ", len(in.Name)), gstr.Repeat(" ", in.SpaceLength+4), line,
   230  			)
   231  		}
   232  		lineStr = gstr.WordWrap(lineStr, maxLineChars, "\n"+in.WordwrapPrefix)
   233  		in.Buffer.WriteString(lineStr)
   234  	}
   235  }
   236  
   237  func (c *Command) defaultHelpFunc(ctx context.Context, parser *Parser) error {
   238  	// Print command help info to stdout.
   239  	c.Print()
   240  	return nil
   241  }