github.com/chriswalz/complete@v1.1.2/cmd/cmd.go (about)

     1  // Package cmd used for command line options for the complete tool
     2  package cmd
     3  
     4  import (
     5  	"errors"
     6  	"flag"
     7  	"fmt"
     8  	"os"
     9  	"strings"
    10  
    11  	"github.com/posener/complete/cmd/install"
    12  )
    13  
    14  // CLI for command line
    15  type CLI struct {
    16  	Name          string
    17  	InstallName   string
    18  	UninstallName string
    19  
    20  	install   bool
    21  	uninstall bool
    22  	yes       bool
    23  }
    24  
    25  const (
    26  	defaultInstallName   = "install"
    27  	defaultUninstallName = "uninstall"
    28  )
    29  
    30  // Run is used when running complete in command line mode.
    31  // this is used when the complete is not completing words, but to
    32  // install it or uninstall it.
    33  func (f *CLI) Run() bool {
    34  	err := f.validate()
    35  	if err != nil {
    36  		os.Stderr.WriteString(err.Error() + "\n")
    37  		os.Exit(1)
    38  	}
    39  
    40  	switch {
    41  	case f.install:
    42  		f.prompt()
    43  		err = install.Install(f.Name)
    44  	case f.uninstall:
    45  		f.prompt()
    46  		err = install.Uninstall(f.Name)
    47  	default:
    48  		// non of the action flags matched,
    49  		// returning false should make the real program execute
    50  		return false
    51  	}
    52  
    53  	if err != nil {
    54  		fmt.Printf("%s failed! %s\n", f.action(), err)
    55  		os.Exit(3)
    56  	}
    57  	fmt.Println("Done!")
    58  	return true
    59  }
    60  
    61  // prompt use for approval
    62  // exit if approval was not given
    63  func (f *CLI) prompt() {
    64  	defer fmt.Println(f.action() + "ing...")
    65  	if f.yes {
    66  		return
    67  	}
    68  	fmt.Printf("%s completion for %s? ", f.action(), f.Name)
    69  	var answer string
    70  	fmt.Scanln(&answer)
    71  
    72  	switch strings.ToLower(answer) {
    73  	case "y", "yes":
    74  		return
    75  	default:
    76  		fmt.Println("Cancelling...")
    77  		os.Exit(1)
    78  	}
    79  }
    80  
    81  // AddFlags adds the CLI flags to the flag set.
    82  // If flags is nil, the default command line flags will be taken.
    83  // Pass non-empty strings as installName and uninstallName to override the default
    84  // flag names.
    85  func (f *CLI) AddFlags(flags *flag.FlagSet) {
    86  	if flags == nil {
    87  		flags = flag.CommandLine
    88  	}
    89  
    90  	if f.InstallName == "" {
    91  		f.InstallName = defaultInstallName
    92  	}
    93  	if f.UninstallName == "" {
    94  		f.UninstallName = defaultUninstallName
    95  	}
    96  
    97  	if flags.Lookup(f.InstallName) == nil {
    98  		flags.BoolVar(&f.install, f.InstallName, false,
    99  			fmt.Sprintf("Install completion for %s command", f.Name))
   100  	}
   101  	if flags.Lookup(f.UninstallName) == nil {
   102  		flags.BoolVar(&f.uninstall, f.UninstallName, false,
   103  			fmt.Sprintf("Uninstall completion for %s command", f.Name))
   104  	}
   105  	if flags.Lookup("y") == nil {
   106  		flags.BoolVar(&f.yes, "y", false, "Don't prompt user for typing 'yes' when installing completion")
   107  	}
   108  }
   109  
   110  // validate the CLI
   111  func (f *CLI) validate() error {
   112  	if f.install && f.uninstall {
   113  		return errors.New("Install and uninstall are mutually exclusive")
   114  	}
   115  	return nil
   116  }
   117  
   118  // action name according to the CLI values.
   119  func (f *CLI) action() string {
   120  	switch {
   121  	case f.install:
   122  		return "Install"
   123  	case f.uninstall:
   124  		return "Uninstall"
   125  	default:
   126  		return "unknown"
   127  	}
   128  }