github.com/posener/flag@v0.0.0-20170525115107-e8c69325eea7/complete.go (about)

     1  package flag
     2  
     3  import (
     4  	gflag "flag"
     5  	"fmt"
     6  	"strings"
     7  )
     8  
     9  // Complete tries to complete the command line that was already
    10  // entered. It returns true on success, on which the main program
    11  // should exit
    12  func Complete() bool {
    13  	return CommandLine.Complete()
    14  }
    15  
    16  // Complete tries to complete the command line according to a FlagSet.
    17  // It returns true on success, on which the main program should exit.
    18  func (f *FlagSet) Complete() bool {
    19  	l := readLine()
    20  	if l == nil {
    21  		return cli.Run()
    22  	}
    23  
    24  	options := f.complete(l)
    25  
    26  	for _, option := range options {
    27  		fmt.Println(option)
    28  	}
    29  	return true
    30  }
    31  
    32  func (f *FlagSet) complete(line *line) []string {
    33  	var options []string
    34  
    35  	// flag completion according to last completed argument in command line
    36  	if flg := f.lastFlag(line.lastCompleted); flg != nil {
    37  		if cmp, ok := flg.Value.(Completer); ok {
    38  			// last flag implements the Completer interface, complete according
    39  			// to its decision
    40  			var only bool
    41  			options, only = cmp.Complete(line.last)
    42  			if only {
    43  				return options
    44  			}
    45  		} else {
    46  			// standard library flag, we want to return an empty
    47  			// choice of completion, since anything can come after this
    48  			// kind of flag, and we should not complete any other
    49  			// flags after it.
    50  			return []string{}
    51  		}
    52  	}
    53  
    54  	// add all flag names to the complete options
    55  	f.VisitAll(func(flg *gflag.Flag) {
    56  		name := "-" + flg.Name
    57  		if strings.HasPrefix(name, line.last) {
    58  			options = append(options, name)
    59  		}
    60  	})
    61  	return options
    62  }
    63  
    64  func (f *FlagSet) lastFlag(lastCompleted string) *gflag.Flag {
    65  	if !strings.HasPrefix(lastCompleted, "-") {
    66  		return nil
    67  	}
    68  	return f.Lookup(lastCompleted[1:])
    69  }
    70  
    71  // Completer interface is for the Complete function
    72  type Completer interface {
    73  	// Complete according to the given last string in the command line.
    74  	// returns list of options to complete the last word in the command
    75  	// line, and a boolean indicating if those options should be the
    76  	// only shown options.
    77  	Complete(last string) (options []string, only bool)
    78  }
    79  
    80  // CompleteFn is function implementing the Completer interface
    81  type CompleteFn func(string) ([]string, bool)
    82  
    83  // Complete implements the Complete interface
    84  func (c CompleteFn) Complete(last string) ([]string, bool) {
    85  	if c == nil {
    86  		return nil, false
    87  	}
    88  	return c(last)
    89  }