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