github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/actor/sharedaction/help.go (about)

     1  package sharedaction
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/liamawhite/cli-with-i18n/util/sorting"
    10  )
    11  
    12  // ErrorInvalidCommand represents an error that happens when help is called
    13  // with an invalid command.
    14  type ErrorInvalidCommand struct {
    15  	CommandName string
    16  }
    17  
    18  func (err ErrorInvalidCommand) Error() string {
    19  	return fmt.Sprintf("'%s' is not a registered command. See 'cf help -a'", err.CommandName)
    20  }
    21  
    22  // CommandInfo contains the help details of a command
    23  type CommandInfo struct {
    24  	// Name is the command name
    25  	Name string
    26  
    27  	// Description is the command description
    28  	Description string
    29  
    30  	// Alias is the command alias
    31  	Alias string
    32  
    33  	// Usage is the command usage string, may contain examples and flavor text
    34  	Usage string
    35  
    36  	// RelatedCommands is a list of commands related to the command
    37  	RelatedCommands []string
    38  
    39  	// Flags contains the list of flags for this command
    40  	Flags []CommandFlag
    41  
    42  	// Environment is a list of environment variables specific for this command
    43  	Environment []EnvironmentVariable
    44  }
    45  
    46  // CommandFlag contains the help details of a command's flag
    47  type CommandFlag struct {
    48  	// Short is the short form of the flag
    49  	Short string
    50  
    51  	// Long is the long form of the flag
    52  	Long string
    53  
    54  	// Description is the description of the flag
    55  	Description string
    56  
    57  	// Default is the flag's default value
    58  	Default string
    59  }
    60  
    61  // Environment contains env vars specific for this command
    62  type EnvironmentVariable struct {
    63  	Name         string
    64  	Description  string
    65  	DefaultValue string
    66  }
    67  
    68  // CommandInfoByName returns the help information for a particular commandName in
    69  // the commandList.
    70  func (Actor) CommandInfoByName(commandList interface{}, commandName string) (CommandInfo, error) {
    71  	field, found := reflect.TypeOf(commandList).FieldByNameFunc(
    72  		func(fieldName string) bool {
    73  			field, _ := reflect.TypeOf(commandList).FieldByName(fieldName)
    74  			return field.Tag.Get("command") == commandName || field.Tag.Get("alias") == commandName
    75  		},
    76  	)
    77  
    78  	if !found {
    79  		return CommandInfo{}, ErrorInvalidCommand{CommandName: commandName}
    80  	}
    81  
    82  	tag := field.Tag
    83  	cmd := CommandInfo{
    84  		Name:        tag.Get("command"),
    85  		Description: tag.Get("description"),
    86  		Alias:       tag.Get("alias"),
    87  		Flags:       []CommandFlag{},
    88  		Environment: []EnvironmentVariable{},
    89  	}
    90  
    91  	command := field.Type
    92  	for i := 0; i < command.NumField(); i++ {
    93  		fieldTag := command.Field(i).Tag
    94  
    95  		if fieldTag.Get("hidden") != "" {
    96  			continue
    97  		}
    98  
    99  		if fieldTag.Get("usage") != "" {
   100  			cmd.Usage = fieldTag.Get("usage")
   101  			continue
   102  		}
   103  
   104  		if fieldTag.Get("related_commands") != "" {
   105  			relatedCommands := strings.Split(fieldTag.Get("related_commands"), ", ")
   106  			sort.Slice(relatedCommands, sorting.SortAlphabeticFunc(relatedCommands))
   107  			cmd.RelatedCommands = relatedCommands
   108  			continue
   109  		}
   110  
   111  		if fieldTag.Get("description") != "" {
   112  			cmd.Flags = append(cmd.Flags, CommandFlag{
   113  				Short:       fieldTag.Get("short"),
   114  				Long:        fieldTag.Get("long"),
   115  				Description: fieldTag.Get("description"),
   116  				Default:     fieldTag.Get("default"),
   117  			})
   118  		}
   119  
   120  		if fieldTag.Get("environmentName") != "" {
   121  			cmd.Environment = append(cmd.Environment, EnvironmentVariable{
   122  				Name:         fieldTag.Get("environmentName"),
   123  				DefaultValue: fieldTag.Get("environmentDefault"),
   124  				Description:  fieldTag.Get("environmentDescription"),
   125  			})
   126  		}
   127  	}
   128  
   129  	return cmd, nil
   130  }
   131  
   132  // CommandInfos returns a slice of CommandInfo that only fills in
   133  // the Name and Description for all the commands in commandList
   134  func (Actor) CommandInfos(commandList interface{}) map[string]CommandInfo {
   135  	handler := reflect.TypeOf(commandList)
   136  
   137  	infos := make(map[string]CommandInfo, handler.NumField())
   138  	for i := 0; i < handler.NumField(); i++ {
   139  		fieldTag := handler.Field(i).Tag
   140  		commandName := fieldTag.Get("command")
   141  		infos[commandName] = CommandInfo{
   142  			Name:        commandName,
   143  			Description: fieldTag.Get("description"),
   144  			Alias:       fieldTag.Get("alias"),
   145  		}
   146  	}
   147  
   148  	return infos
   149  }