github.com/alecthomas/kong@v0.9.1-0.20240410131203-2ab5733f1179/context.go (about)

     1  package kong
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"reflect"
     8  	"sort"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  // Path records the nodes and parsed values from the current command-line.
    14  type Path struct {
    15  	Parent *Node
    16  
    17  	// One of these will be non-nil.
    18  	App        *Application
    19  	Positional *Positional
    20  	Flag       *Flag
    21  	Argument   *Argument
    22  	Command    *Command
    23  
    24  	// Flags added by this node.
    25  	Flags []*Flag
    26  
    27  	// True if this Path element was created as the result of a resolver.
    28  	Resolved bool
    29  }
    30  
    31  // Node returns the Node associated with this Path, or nil if Path is a non-Node.
    32  func (p *Path) Node() *Node {
    33  	switch {
    34  	case p.App != nil:
    35  		return p.App.Node
    36  
    37  	case p.Argument != nil:
    38  		return p.Argument
    39  
    40  	case p.Command != nil:
    41  		return p.Command
    42  	}
    43  	return nil
    44  }
    45  
    46  // Visitable returns the Visitable for this path element.
    47  func (p *Path) Visitable() Visitable {
    48  	switch {
    49  	case p.App != nil:
    50  		return p.App
    51  
    52  	case p.Argument != nil:
    53  		return p.Argument
    54  
    55  	case p.Command != nil:
    56  		return p.Command
    57  
    58  	case p.Flag != nil:
    59  		return p.Flag
    60  
    61  	case p.Positional != nil:
    62  		return p.Positional
    63  	}
    64  	return nil
    65  }
    66  
    67  // Context contains the current parse context.
    68  type Context struct {
    69  	*Kong
    70  	// A trace through parsed nodes.
    71  	Path []*Path
    72  	// Original command-line arguments.
    73  	Args []string
    74  	// Error that occurred during trace, if any.
    75  	Error error
    76  
    77  	values    map[*Value]reflect.Value // Temporary values during tracing.
    78  	bindings  bindings
    79  	resolvers []Resolver // Extra context-specific resolvers.
    80  	scan      *Scanner
    81  }
    82  
    83  // Trace path of "args" through the grammar tree.
    84  //
    85  // The returned Context will include a Path of all commands, arguments, positionals and flags.
    86  //
    87  // This just constructs a new trace. To fully apply the trace you must call Reset(), Resolve(),
    88  // Validate() and Apply().
    89  func Trace(k *Kong, args []string) (*Context, error) {
    90  	c := &Context{
    91  		Kong: k,
    92  		Args: args,
    93  		Path: []*Path{
    94  			{App: k.Model, Flags: k.Model.Flags},
    95  		},
    96  		values:   map[*Value]reflect.Value{},
    97  		scan:     Scan(args...),
    98  		bindings: bindings{},
    99  	}
   100  	c.Error = c.trace(c.Model.Node)
   101  	return c, nil
   102  }
   103  
   104  // Bind adds bindings to the Context.
   105  func (c *Context) Bind(args ...interface{}) {
   106  	c.bindings.add(args...)
   107  }
   108  
   109  // BindTo adds a binding to the Context.
   110  //
   111  // This will typically have to be called like so:
   112  //
   113  //	BindTo(impl, (*MyInterface)(nil))
   114  func (c *Context) BindTo(impl, iface interface{}) {
   115  	c.bindings.addTo(impl, iface)
   116  }
   117  
   118  // BindToProvider allows binding of provider functions.
   119  //
   120  // This is useful when the Run() function of different commands require different values that may
   121  // not all be initialisable from the main() function.
   122  func (c *Context) BindToProvider(provider interface{}) error {
   123  	return c.bindings.addProvider(provider)
   124  }
   125  
   126  // Value returns the value for a particular path element.
   127  func (c *Context) Value(path *Path) reflect.Value {
   128  	switch {
   129  	case path.Positional != nil:
   130  		return c.values[path.Positional]
   131  	case path.Flag != nil:
   132  		return c.values[path.Flag.Value]
   133  	case path.Argument != nil:
   134  		return c.values[path.Argument.Argument]
   135  	}
   136  	panic("can only retrieve value for flag, argument or positional")
   137  }
   138  
   139  // Selected command or argument.
   140  func (c *Context) Selected() *Node {
   141  	var selected *Node
   142  	for _, path := range c.Path {
   143  		switch {
   144  		case path.Command != nil:
   145  			selected = path.Command
   146  		case path.Argument != nil:
   147  			selected = path.Argument
   148  		}
   149  	}
   150  	return selected
   151  }
   152  
   153  // Empty returns true if there were no arguments provided.
   154  func (c *Context) Empty() bool {
   155  	for _, path := range c.Path {
   156  		if !path.Resolved && path.App == nil {
   157  			return false
   158  		}
   159  	}
   160  	return true
   161  }
   162  
   163  // Validate the current context.
   164  func (c *Context) Validate() error { //nolint: gocyclo
   165  	err := Visit(c.Model, func(node Visitable, next Next) error {
   166  		switch node := node.(type) {
   167  		case *Value:
   168  			ok := atLeastOneEnvSet(node.Tag.Envs)
   169  			if node.Enum != "" && (!node.Required || node.HasDefault || (len(node.Tag.Envs) != 0 && ok)) {
   170  				if err := checkEnum(node, node.Target); err != nil {
   171  					return err
   172  				}
   173  			}
   174  
   175  		case *Flag:
   176  			ok := atLeastOneEnvSet(node.Tag.Envs)
   177  			if node.Enum != "" && (!node.Required || node.HasDefault || (len(node.Tag.Envs) != 0 && ok)) {
   178  				if err := checkEnum(node.Value, node.Target); err != nil {
   179  					return err
   180  				}
   181  			}
   182  		}
   183  		return next(nil)
   184  	})
   185  	if err != nil {
   186  		return err
   187  	}
   188  	for _, el := range c.Path {
   189  		var (
   190  			value reflect.Value
   191  			desc  string
   192  		)
   193  		switch node := el.Visitable().(type) {
   194  		case *Value:
   195  			value = node.Target
   196  			desc = node.ShortSummary()
   197  
   198  		case *Flag:
   199  			value = node.Target
   200  			desc = node.ShortSummary()
   201  
   202  		case *Application:
   203  			value = node.Target
   204  			desc = ""
   205  
   206  		case *Node:
   207  			value = node.Target
   208  			desc = node.Path()
   209  		}
   210  		if validate := isValidatable(value); validate != nil {
   211  			if err := validate.Validate(); err != nil {
   212  				if desc != "" {
   213  					return fmt.Errorf("%s: %w", desc, err)
   214  				}
   215  				return err
   216  			}
   217  		}
   218  	}
   219  	for _, resolver := range c.combineResolvers() {
   220  		if err := resolver.Validate(c.Model); err != nil {
   221  			return err
   222  		}
   223  	}
   224  	for _, path := range c.Path {
   225  		var value *Value
   226  		switch {
   227  		case path.Flag != nil:
   228  			value = path.Flag.Value
   229  
   230  		case path.Positional != nil:
   231  			value = path.Positional
   232  		}
   233  		if value != nil && value.Tag.Enum != "" {
   234  			if err := checkEnum(value, value.Target); err != nil {
   235  				return err
   236  			}
   237  		}
   238  		if err := checkMissingFlags(path.Flags); err != nil {
   239  			return err
   240  		}
   241  	}
   242  	// Check the terminal node.
   243  	node := c.Selected()
   244  	if node == nil {
   245  		node = c.Model.Node
   246  	}
   247  
   248  	// Find deepest positional argument so we can check if all required positionals have been provided.
   249  	positionals := 0
   250  	for _, path := range c.Path {
   251  		if path.Positional != nil {
   252  			positionals = path.Positional.Position + 1
   253  		}
   254  	}
   255  
   256  	if err := checkMissingChildren(node); err != nil {
   257  		return err
   258  	}
   259  	if err := checkMissingPositionals(positionals, node.Positional); err != nil {
   260  		return err
   261  	}
   262  	if err := checkXorDuplicates(c.Path); err != nil {
   263  		return err
   264  	}
   265  
   266  	if node.Type == ArgumentNode {
   267  		value := node.Argument
   268  		if value.Required && !value.Set {
   269  			return fmt.Errorf("%s is required", node.Summary())
   270  		}
   271  	}
   272  	return nil
   273  }
   274  
   275  // Flags returns the accumulated available flags.
   276  func (c *Context) Flags() (flags []*Flag) {
   277  	for _, trace := range c.Path {
   278  		flags = append(flags, trace.Flags...)
   279  	}
   280  	return
   281  }
   282  
   283  // Command returns the full command path.
   284  func (c *Context) Command() string {
   285  	command := []string{}
   286  	for _, trace := range c.Path {
   287  		switch {
   288  		case trace.Positional != nil:
   289  			command = append(command, "<"+trace.Positional.Name+">")
   290  
   291  		case trace.Argument != nil:
   292  			command = append(command, "<"+trace.Argument.Name+">")
   293  
   294  		case trace.Command != nil:
   295  			command = append(command, trace.Command.Name)
   296  		}
   297  	}
   298  	return strings.Join(command, " ")
   299  }
   300  
   301  // AddResolver adds a context-specific resolver.
   302  //
   303  // This is most useful in the BeforeResolve() hook.
   304  func (c *Context) AddResolver(resolver Resolver) {
   305  	c.resolvers = append(c.resolvers, resolver)
   306  }
   307  
   308  // FlagValue returns the set value of a flag if it was encountered and exists, or its default value.
   309  func (c *Context) FlagValue(flag *Flag) interface{} {
   310  	for _, trace := range c.Path {
   311  		if trace.Flag == flag {
   312  			v, ok := c.values[trace.Flag.Value]
   313  			if !ok {
   314  				break
   315  			}
   316  			return v.Interface()
   317  		}
   318  	}
   319  	if flag.Target.IsValid() {
   320  		return flag.Target.Interface()
   321  	}
   322  	return flag.DefaultValue.Interface()
   323  }
   324  
   325  // Reset recursively resets values to defaults (as specified in the grammar) or the zero value.
   326  func (c *Context) Reset() error {
   327  	return Visit(c.Model.Node, func(node Visitable, next Next) error {
   328  		if value, ok := node.(*Value); ok {
   329  			return next(value.Reset())
   330  		}
   331  		return next(nil)
   332  	})
   333  }
   334  
   335  func (c *Context) endParsing() {
   336  	args := []string{}
   337  	for {
   338  		token := c.scan.Pop()
   339  		if token.Type == EOLToken {
   340  			break
   341  		}
   342  		args = append(args, token.String())
   343  	}
   344  	// Note: tokens must be pushed in reverse order.
   345  	for i := range args {
   346  		c.scan.PushTyped(args[len(args)-1-i], PositionalArgumentToken)
   347  	}
   348  }
   349  
   350  func (c *Context) trace(node *Node) (err error) { //nolint: gocyclo
   351  	positional := 0
   352  	node.Active = true
   353  
   354  	flags := []*Flag{}
   355  	flagNode := node
   356  	if node.DefaultCmd != nil && node.DefaultCmd.Tag.Default == "withargs" {
   357  		// Add flags of the default command if the current node has one
   358  		// and that default command allows args / flags without explicitly
   359  		// naming the command on the CLI.
   360  		flagNode = node.DefaultCmd
   361  	}
   362  	for _, group := range flagNode.AllFlags(false) {
   363  		flags = append(flags, group...)
   364  	}
   365  
   366  	if node.Passthrough {
   367  		c.endParsing()
   368  	}
   369  
   370  	for !c.scan.Peek().IsEOL() {
   371  		token := c.scan.Peek()
   372  		switch token.Type {
   373  		case UntypedToken:
   374  			switch v := token.Value.(type) {
   375  			case string:
   376  
   377  				switch {
   378  				case v == "-":
   379  					fallthrough
   380  				default: //nolint
   381  					c.scan.Pop()
   382  					c.scan.PushTyped(token.Value, PositionalArgumentToken)
   383  
   384  				// Indicates end of parsing. All remaining arguments are treated as positional arguments only.
   385  				case v == "--":
   386  					c.scan.Pop()
   387  					c.endParsing()
   388  
   389  				// Long flag.
   390  				case strings.HasPrefix(v, "--"):
   391  					c.scan.Pop()
   392  					// Parse it and push the tokens.
   393  					parts := strings.SplitN(v[2:], "=", 2)
   394  					if len(parts) > 1 {
   395  						c.scan.PushTyped(parts[1], FlagValueToken)
   396  					}
   397  					c.scan.PushTyped(parts[0], FlagToken)
   398  
   399  				// Short flag.
   400  				case strings.HasPrefix(v, "-"):
   401  					c.scan.Pop()
   402  					// Note: tokens must be pushed in reverse order.
   403  					if tail := v[2:]; tail != "" {
   404  						c.scan.PushTyped(tail, ShortFlagTailToken)
   405  					}
   406  					c.scan.PushTyped(v[1:2], ShortFlagToken)
   407  				}
   408  			default:
   409  				c.scan.Pop()
   410  				c.scan.PushTyped(token.Value, PositionalArgumentToken)
   411  			}
   412  
   413  		case ShortFlagTailToken:
   414  			c.scan.Pop()
   415  			// Note: tokens must be pushed in reverse order.
   416  			if tail := token.String()[1:]; tail != "" {
   417  				c.scan.PushTyped(tail, ShortFlagTailToken)
   418  			}
   419  			c.scan.PushTyped(token.String()[0:1], ShortFlagToken)
   420  
   421  		case FlagToken:
   422  			if err := c.parseFlag(flags, token.String()); err != nil {
   423  				return err
   424  			}
   425  
   426  		case ShortFlagToken:
   427  			if err := c.parseFlag(flags, token.String()); err != nil {
   428  				return err
   429  			}
   430  
   431  		case FlagValueToken:
   432  			return fmt.Errorf("unexpected flag argument %q", token.Value)
   433  
   434  		case PositionalArgumentToken:
   435  			candidates := []string{}
   436  
   437  			// Ensure we've consumed all positional arguments.
   438  			if positional < len(node.Positional) {
   439  				arg := node.Positional[positional]
   440  
   441  				if arg.Passthrough {
   442  					c.endParsing()
   443  				}
   444  
   445  				arg.Active = true
   446  				err := arg.Parse(c.scan, c.getValue(arg))
   447  				if err != nil {
   448  					return err
   449  				}
   450  				c.Path = append(c.Path, &Path{
   451  					Parent:     node,
   452  					Positional: arg,
   453  				})
   454  				positional++
   455  				break
   456  			}
   457  
   458  			// Assign token value to a branch name if tagged as an alias
   459  			// An alias will be ignored in the case of an existing command
   460  			cmds := make(map[string]bool)
   461  			for _, branch := range node.Children {
   462  				if branch.Type == CommandNode {
   463  					cmds[branch.Name] = true
   464  				}
   465  			}
   466  			for _, branch := range node.Children {
   467  				for _, a := range branch.Aliases {
   468  					_, ok := cmds[a]
   469  					if token.Value == a && !ok {
   470  						token.Value = branch.Name
   471  						break
   472  					}
   473  				}
   474  			}
   475  
   476  			// After positional arguments have been consumed, check commands next...
   477  			for _, branch := range node.Children {
   478  				if branch.Type == CommandNode && !branch.Hidden {
   479  					candidates = append(candidates, branch.Name)
   480  				}
   481  				if branch.Type == CommandNode && branch.Name == token.Value {
   482  					c.scan.Pop()
   483  					c.Path = append(c.Path, &Path{
   484  						Parent:  node,
   485  						Command: branch,
   486  						Flags:   branch.Flags,
   487  					})
   488  					return c.trace(branch)
   489  				}
   490  			}
   491  
   492  			// Finally, check arguments.
   493  			for _, branch := range node.Children {
   494  				if branch.Type == ArgumentNode {
   495  					arg := branch.Argument
   496  					if err := arg.Parse(c.scan, c.getValue(arg)); err == nil {
   497  						c.Path = append(c.Path, &Path{
   498  							Parent:   node,
   499  							Argument: branch,
   500  							Flags:    branch.Flags,
   501  						})
   502  						return c.trace(branch)
   503  					}
   504  				}
   505  			}
   506  
   507  			// If there is a default command that allows args and nothing else
   508  			// matches, take the branch of the default command
   509  			if node.DefaultCmd != nil && node.DefaultCmd.Tag.Default == "withargs" {
   510  				c.Path = append(c.Path, &Path{
   511  					Parent:  node,
   512  					Command: node.DefaultCmd,
   513  					Flags:   node.DefaultCmd.Flags,
   514  				})
   515  				return c.trace(node.DefaultCmd)
   516  			}
   517  
   518  			return findPotentialCandidates(token.String(), candidates, "unexpected argument %s", token)
   519  		default:
   520  			return fmt.Errorf("unexpected token %s", token)
   521  		}
   522  	}
   523  	return c.maybeSelectDefault(flags, node)
   524  }
   525  
   526  // End of the line, check for a default command, but only if we're not displaying help,
   527  // otherwise we'd only ever display the help for the default command.
   528  func (c *Context) maybeSelectDefault(flags []*Flag, node *Node) error {
   529  	for _, flag := range flags {
   530  		if flag.Name == "help" && flag.Set {
   531  			return nil
   532  		}
   533  	}
   534  	if node.DefaultCmd != nil {
   535  		c.Path = append(c.Path, &Path{
   536  			Parent:  node.DefaultCmd,
   537  			Command: node.DefaultCmd,
   538  			Flags:   node.DefaultCmd.Flags,
   539  		})
   540  	}
   541  	return nil
   542  }
   543  
   544  // Resolve walks through the traced path, applying resolvers to any unset flags.
   545  func (c *Context) Resolve() error {
   546  	resolvers := c.combineResolvers()
   547  	if len(resolvers) == 0 {
   548  		return nil
   549  	}
   550  
   551  	inserted := []*Path{}
   552  	for _, path := range c.Path {
   553  		for _, flag := range path.Flags {
   554  			// Flag has already been set on the command-line.
   555  			if _, ok := c.values[flag.Value]; ok {
   556  				continue
   557  			}
   558  
   559  			// Pick the last resolved value.
   560  			var selected interface{}
   561  			for _, resolver := range resolvers {
   562  				s, err := resolver.Resolve(c, path, flag)
   563  				if err != nil {
   564  					return fmt.Errorf("%s: %w", flag.ShortSummary(), err)
   565  				}
   566  				if s == nil {
   567  					continue
   568  				}
   569  				selected = s
   570  			}
   571  
   572  			if selected == nil {
   573  				continue
   574  			}
   575  
   576  			scan := Scan().PushTyped(selected, FlagValueToken)
   577  			delete(c.values, flag.Value)
   578  			err := flag.Parse(scan, c.getValue(flag.Value))
   579  			if err != nil {
   580  				return err
   581  			}
   582  			inserted = append(inserted, &Path{
   583  				Flag:     flag,
   584  				Resolved: true,
   585  			})
   586  		}
   587  	}
   588  	c.Path = append(c.Path, inserted...)
   589  	return nil
   590  }
   591  
   592  // Combine application-level resolvers and context resolvers.
   593  func (c *Context) combineResolvers() []Resolver {
   594  	resolvers := []Resolver{}
   595  	resolvers = append(resolvers, c.Kong.resolvers...)
   596  	resolvers = append(resolvers, c.resolvers...)
   597  	return resolvers
   598  }
   599  
   600  func (c *Context) getValue(value *Value) reflect.Value {
   601  	v, ok := c.values[value]
   602  	if !ok {
   603  		v = reflect.New(value.Target.Type()).Elem()
   604  		switch v.Kind() {
   605  		case reflect.Ptr:
   606  			v.Set(reflect.New(v.Type().Elem()))
   607  		case reflect.Slice:
   608  			v.Set(reflect.MakeSlice(v.Type(), 0, 0))
   609  		case reflect.Map:
   610  			v.Set(reflect.MakeMap(v.Type()))
   611  		default:
   612  		}
   613  		c.values[value] = v
   614  	}
   615  	return v
   616  }
   617  
   618  // ApplyDefaults if they are not already set.
   619  func (c *Context) ApplyDefaults() error {
   620  	return Visit(c.Model.Node, func(node Visitable, next Next) error {
   621  		var value *Value
   622  		switch node := node.(type) {
   623  		case *Flag:
   624  			value = node.Value
   625  		case *Node:
   626  			value = node.Argument
   627  		case *Value:
   628  			value = node
   629  		default:
   630  		}
   631  		if value != nil {
   632  			if err := value.ApplyDefault(); err != nil {
   633  				return err
   634  			}
   635  		}
   636  		return next(nil)
   637  	})
   638  }
   639  
   640  // Apply traced context to the target grammar.
   641  func (c *Context) Apply() (string, error) {
   642  	path := []string{}
   643  
   644  	for _, trace := range c.Path {
   645  		var value *Value
   646  		switch {
   647  		case trace.App != nil:
   648  		case trace.Argument != nil:
   649  			path = append(path, "<"+trace.Argument.Name+">")
   650  			value = trace.Argument.Argument
   651  		case trace.Command != nil:
   652  			path = append(path, trace.Command.Name)
   653  		case trace.Flag != nil:
   654  			value = trace.Flag.Value
   655  		case trace.Positional != nil:
   656  			path = append(path, "<"+trace.Positional.Name+">")
   657  			value = trace.Positional
   658  		default:
   659  			panic("unsupported path ?!")
   660  		}
   661  		if value != nil {
   662  			value.Apply(c.getValue(value))
   663  		}
   664  	}
   665  
   666  	return strings.Join(path, " "), nil
   667  }
   668  
   669  func flipBoolValue(value reflect.Value) error {
   670  	if value.Kind() == reflect.Bool {
   671  		value.SetBool(!value.Bool())
   672  		return nil
   673  	}
   674  
   675  	if value.Kind() == reflect.Ptr {
   676  		if !value.IsNil() {
   677  			return flipBoolValue(value.Elem())
   678  		}
   679  		return nil
   680  	}
   681  
   682  	return fmt.Errorf("cannot negate a value of %s", value.Type().String())
   683  }
   684  
   685  func (c *Context) parseFlag(flags []*Flag, match string) (err error) {
   686  	candidates := []string{}
   687  
   688  	for _, flag := range flags {
   689  		long := "--" + flag.Name
   690  		matched := long == match
   691  		candidates = append(candidates, long)
   692  		if flag.Short != 0 {
   693  			short := "-" + string(flag.Short)
   694  			matched = matched || (short == match)
   695  			candidates = append(candidates, short)
   696  		}
   697  		for _, alias := range flag.Aliases {
   698  			alias = "--" + alias
   699  			matched = matched || (alias == match)
   700  			candidates = append(candidates, alias)
   701  		}
   702  
   703  		neg := "--no-" + flag.Name
   704  		if !matched && !(match == neg && flag.Tag.Negatable) {
   705  			continue
   706  		}
   707  		// Found a matching flag.
   708  		c.scan.Pop()
   709  		if match == neg && flag.Tag.Negatable {
   710  			flag.Negated = true
   711  		}
   712  		err := flag.Parse(c.scan, c.getValue(flag.Value))
   713  		if err != nil {
   714  			var expected *expectedError
   715  			if errors.As(err, &expected) && expected.token.InferredType().IsAny(FlagToken, ShortFlagToken) {
   716  				return fmt.Errorf("%s; perhaps try %s=%q?", err.Error(), flag.ShortSummary(), expected.token)
   717  			}
   718  			return err
   719  		}
   720  		if flag.Negated {
   721  			value := c.getValue(flag.Value)
   722  			err := flipBoolValue(value)
   723  			if err != nil {
   724  				return err
   725  			}
   726  			flag.Value.Apply(value)
   727  		}
   728  		c.Path = append(c.Path, &Path{Flag: flag})
   729  		return nil
   730  	}
   731  	return findPotentialCandidates(match, candidates, "unknown flag %s", match)
   732  }
   733  
   734  // Call an arbitrary function filling arguments with bound values.
   735  func (c *Context) Call(fn any, binds ...interface{}) (out []interface{}, err error) {
   736  	fv := reflect.ValueOf(fn)
   737  	bindings := c.Kong.bindings.clone().add(binds...).add(c).merge(c.bindings) //nolint:govet
   738  	return callAnyFunction(fv, bindings)
   739  }
   740  
   741  // RunNode calls the Run() method on an arbitrary node.
   742  //
   743  // This is useful in conjunction with Visit(), for dynamically running commands.
   744  //
   745  // Any passed values will be bindable to arguments of the target Run() method. Additionally,
   746  // all parent nodes in the command structure will be bound.
   747  func (c *Context) RunNode(node *Node, binds ...interface{}) (err error) {
   748  	type targetMethod struct {
   749  		node   *Node
   750  		method reflect.Value
   751  		binds  bindings
   752  	}
   753  	methodBinds := c.Kong.bindings.clone().add(binds...).add(c).merge(c.bindings)
   754  	methods := []targetMethod{}
   755  	for i := 0; node != nil; i, node = i+1, node.Parent {
   756  		method := getMethod(node.Target, "Run")
   757  		methodBinds = methodBinds.clone()
   758  		for p := node; p != nil; p = p.Parent {
   759  			methodBinds = methodBinds.add(p.Target.Addr().Interface())
   760  		}
   761  		if method.IsValid() {
   762  			methods = append(methods, targetMethod{node, method, methodBinds})
   763  		}
   764  	}
   765  	if len(methods) == 0 {
   766  		return fmt.Errorf("no Run() method found in hierarchy of %s", c.Selected().Summary())
   767  	}
   768  	_, err = c.Apply()
   769  	if err != nil {
   770  		return err
   771  	}
   772  
   773  	for _, method := range methods {
   774  		if err = callFunction(method.method, method.binds); err != nil {
   775  			return err
   776  		}
   777  	}
   778  	return nil
   779  }
   780  
   781  // Run executes the Run() method on the selected command, which must exist.
   782  //
   783  // Any passed values will be bindable to arguments of the target Run() method. Additionally,
   784  // all parent nodes in the command structure will be bound.
   785  func (c *Context) Run(binds ...interface{}) (err error) {
   786  	node := c.Selected()
   787  	if node == nil {
   788  		if len(c.Path) > 0 {
   789  			selected := c.Path[0].Node()
   790  			if selected.Type == ApplicationNode {
   791  				method := getMethod(selected.Target, "Run")
   792  				if method.IsValid() {
   793  					return c.RunNode(selected, binds...)
   794  				}
   795  			}
   796  		}
   797  		return fmt.Errorf("no command selected")
   798  	}
   799  	return c.RunNode(node, binds...)
   800  }
   801  
   802  // PrintUsage to Kong's stdout.
   803  //
   804  // If summary is true, a summarised version of the help will be output.
   805  func (c *Context) PrintUsage(summary bool) error {
   806  	options := c.helpOptions
   807  	options.Summary = summary
   808  	return c.help(options, c)
   809  }
   810  
   811  func checkMissingFlags(flags []*Flag) error {
   812  	xorGroupSet := map[string]bool{}
   813  	xorGroup := map[string][]string{}
   814  	missing := []string{}
   815  	for _, flag := range flags {
   816  		if flag.Set {
   817  			for _, xor := range flag.Xor {
   818  				xorGroupSet[xor] = true
   819  			}
   820  		}
   821  		if !flag.Required || flag.Set {
   822  			continue
   823  		}
   824  		if len(flag.Xor) > 0 {
   825  			for _, xor := range flag.Xor {
   826  				if xorGroupSet[xor] {
   827  					continue
   828  				}
   829  				xorGroup[xor] = append(xorGroup[xor], flag.Summary())
   830  			}
   831  		} else {
   832  			missing = append(missing, flag.Summary())
   833  		}
   834  	}
   835  	for xor, flags := range xorGroup {
   836  		if !xorGroupSet[xor] && len(flags) > 1 {
   837  			missing = append(missing, strings.Join(flags, " or "))
   838  		}
   839  	}
   840  
   841  	if len(missing) == 0 {
   842  		return nil
   843  	}
   844  
   845  	sort.Strings(missing)
   846  
   847  	return fmt.Errorf("missing flags: %s", strings.Join(missing, ", "))
   848  }
   849  
   850  func checkMissingChildren(node *Node) error {
   851  	missing := []string{}
   852  
   853  	missingArgs := []string{}
   854  	for _, arg := range node.Positional {
   855  		if arg.Required && !arg.Set {
   856  			missingArgs = append(missingArgs, arg.Summary())
   857  		}
   858  	}
   859  	if len(missingArgs) > 0 {
   860  		missing = append(missing, strconv.Quote(strings.Join(missingArgs, " ")))
   861  	}
   862  
   863  	for _, child := range node.Children {
   864  		if child.Hidden {
   865  			continue
   866  		}
   867  		if child.Argument != nil {
   868  			if !child.Argument.Required {
   869  				continue
   870  			}
   871  			missing = append(missing, strconv.Quote(child.Summary()))
   872  		} else {
   873  			missing = append(missing, strconv.Quote(child.Name))
   874  		}
   875  	}
   876  	if len(missing) == 0 {
   877  		return nil
   878  	}
   879  
   880  	if len(missing) > 5 {
   881  		missing = append(missing[:5], "...")
   882  	}
   883  	if len(missing) == 1 {
   884  		return fmt.Errorf("expected %s", missing[0])
   885  	}
   886  	return fmt.Errorf("expected one of %s", strings.Join(missing, ",  "))
   887  }
   888  
   889  // If we're missing any positionals and they're required, return an error.
   890  func checkMissingPositionals(positional int, values []*Value) error {
   891  	// All the positionals are in.
   892  	if positional >= len(values) {
   893  		return nil
   894  	}
   895  
   896  	// We're low on supplied positionals, but the missing one is optional.
   897  	if !values[positional].Required {
   898  		return nil
   899  	}
   900  
   901  	missing := []string{}
   902  	for ; positional < len(values); positional++ {
   903  		arg := values[positional]
   904  		// TODO(aat): Fix hardcoding of these env checks all over the place :\
   905  		if len(arg.Tag.Envs) != 0 {
   906  			if atLeastOneEnvSet(arg.Tag.Envs) {
   907  				continue
   908  			}
   909  		}
   910  		missing = append(missing, "<"+arg.Name+">")
   911  	}
   912  	if len(missing) == 0 {
   913  		return nil
   914  	}
   915  	return fmt.Errorf("missing positional arguments %s", strings.Join(missing, " "))
   916  }
   917  
   918  func checkEnum(value *Value, target reflect.Value) error {
   919  	switch target.Kind() {
   920  	case reflect.Slice, reflect.Array:
   921  		for i := 0; i < target.Len(); i++ {
   922  			if err := checkEnum(value, target.Index(i)); err != nil {
   923  				return err
   924  			}
   925  		}
   926  		return nil
   927  
   928  	case reflect.Map, reflect.Struct:
   929  		return errors.New("enum can only be applied to a slice or value")
   930  
   931  	case reflect.Ptr:
   932  		if target.IsNil() {
   933  			return nil
   934  		}
   935  		return checkEnum(value, target.Elem())
   936  	default:
   937  		enumSlice := value.EnumSlice()
   938  		v := fmt.Sprintf("%v", target)
   939  		enums := []string{}
   940  		for _, enum := range enumSlice {
   941  			if enum == v {
   942  				return nil
   943  			}
   944  			enums = append(enums, fmt.Sprintf("%q", enum))
   945  		}
   946  		return fmt.Errorf("%s must be one of %s but got %q", value.ShortSummary(), strings.Join(enums, ","), target.Interface())
   947  	}
   948  }
   949  
   950  func checkPassthroughArg(target reflect.Value) bool {
   951  	typ := target.Type()
   952  	switch typ.Kind() {
   953  	case reflect.Slice:
   954  		return typ.Elem().Kind() == reflect.String
   955  	default:
   956  		return false
   957  	}
   958  }
   959  
   960  func checkXorDuplicates(paths []*Path) error {
   961  	for _, path := range paths {
   962  		seen := map[string]*Flag{}
   963  		for _, flag := range path.Flags {
   964  			if !flag.Set {
   965  				continue
   966  			}
   967  			for _, xor := range flag.Xor {
   968  				if seen[xor] != nil {
   969  					return fmt.Errorf("--%s and --%s can't be used together", seen[xor].Name, flag.Name)
   970  				}
   971  				seen[xor] = flag
   972  			}
   973  		}
   974  	}
   975  	return nil
   976  }
   977  
   978  func findPotentialCandidates(needle string, haystack []string, format string, args ...interface{}) error {
   979  	if len(haystack) == 0 {
   980  		return fmt.Errorf(format, args...)
   981  	}
   982  	closestCandidates := []string{}
   983  	for _, candidate := range haystack {
   984  		if strings.HasPrefix(candidate, needle) || levenshtein(candidate, needle) <= 2 {
   985  			closestCandidates = append(closestCandidates, fmt.Sprintf("%q", candidate))
   986  		}
   987  	}
   988  	prefix := fmt.Sprintf(format, args...)
   989  	if len(closestCandidates) == 1 {
   990  		return fmt.Errorf("%s, did you mean %s?", prefix, closestCandidates[0])
   991  	} else if len(closestCandidates) > 1 {
   992  		return fmt.Errorf("%s, did you mean one of %s?", prefix, strings.Join(closestCandidates, ", "))
   993  	}
   994  	return fmt.Errorf("%s", prefix)
   995  }
   996  
   997  type validatable interface{ Validate() error }
   998  
   999  func isValidatable(v reflect.Value) validatable {
  1000  	if !v.IsValid() || (v.Kind() == reflect.Ptr || v.Kind() == reflect.Slice || v.Kind() == reflect.Map) && v.IsNil() {
  1001  		return nil
  1002  	}
  1003  	if validate, ok := v.Interface().(validatable); ok {
  1004  		return validate
  1005  	}
  1006  	if v.CanAddr() {
  1007  		return isValidatable(v.Addr())
  1008  	}
  1009  	return nil
  1010  }
  1011  
  1012  func atLeastOneEnvSet(envs []string) bool {
  1013  	for _, env := range envs {
  1014  		if _, ok := os.LookupEnv(env); ok {
  1015  			return true
  1016  		}
  1017  	}
  1018  	return false
  1019  }