github.com/gechr/complete@v0.0.0-20191016221035-401475e3ce1e/cmd/install/install.go (about)

     1  package install
     2  
     3  import (
     4  	"errors"
     5  	"os"
     6  	"os/user"
     7  	"path/filepath"
     8  	"runtime"
     9  
    10  	"github.com/hashicorp/go-multierror"
    11  )
    12  
    13  type installer interface {
    14  	IsInstalled(cmd, bin string) bool
    15  	Install(cmd, bin string) error
    16  	Uninstall(cmd, bin string) error
    17  }
    18  
    19  // Install complete command given:
    20  // cmd: is the command name
    21  func Install(cmd string) error {
    22  	is := installers()
    23  	if len(is) == 0 {
    24  		return errors.New("Did not find any shells to install")
    25  	}
    26  	bin, err := getBinaryPath()
    27  	if err != nil {
    28  		return err
    29  	}
    30  
    31  	for _, i := range is {
    32  		errI := i.Install(cmd, bin)
    33  		if errI != nil {
    34  			err = multierror.Append(err, errI)
    35  		}
    36  	}
    37  
    38  	return err
    39  }
    40  
    41  // IsInstalled returns true if the completion
    42  // for the given cmd is installed.
    43  func IsInstalled(cmd string) bool {
    44  	bin, err := getBinaryPath()
    45  	if err != nil {
    46  		return false
    47  	}
    48  
    49  	for _, i := range installers() {
    50  		installed := i.IsInstalled(cmd, bin)
    51  		if installed {
    52  			return true
    53  		}
    54  	}
    55  
    56  	return false
    57  }
    58  
    59  // Uninstall complete command given:
    60  // cmd: is the command name
    61  func Uninstall(cmd string) error {
    62  	is := installers()
    63  	if len(is) == 0 {
    64  		return errors.New("Did not find any shells to uninstall")
    65  	}
    66  	bin, err := getBinaryPath()
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	for _, i := range is {
    72  		errI := i.Uninstall(cmd, bin)
    73  		if errI != nil {
    74  			err = multierror.Append(err, errI)
    75  		}
    76  	}
    77  
    78  	return err
    79  }
    80  
    81  func installers() (i []installer) {
    82  	// The list of bash config files candidates where it is
    83  	// possible to install the completion command.
    84  	var bashConfFiles []string
    85  	switch runtime.GOOS {
    86  	case "darwin":
    87  		bashConfFiles = []string{".bash_profile"}
    88  	default:
    89  		bashConfFiles = []string{".bashrc", ".bash_profile", ".bash_login", ".profile"}
    90  	}
    91  	for _, rc := range bashConfFiles {
    92  		if f := rcFile(rc); f != "" {
    93  			i = append(i, bash{f})
    94  			break
    95  		}
    96  	}
    97  	if f := rcFile(".zshrc"); f != "" {
    98  		i = append(i, zsh{f})
    99  	}
   100  	if d := fishConfigDir(); d != "" {
   101  		i = append(i, fish{d})
   102  	}
   103  	return
   104  }
   105  
   106  func fishConfigDir() string {
   107  	configDir := filepath.Join(getConfigHomePath(), "fish")
   108  	if configDir == "" {
   109  		return ""
   110  	}
   111  	if info, err := os.Stat(configDir); err != nil || !info.IsDir() {
   112  		return ""
   113  	}
   114  	return configDir
   115  }
   116  
   117  func getConfigHomePath() string {
   118  	u, err := user.Current()
   119  	if err != nil {
   120  		return ""
   121  	}
   122  
   123  	configHome := os.Getenv("XDG_CONFIG_HOME")
   124  	if configHome == "" {
   125  		return filepath.Join(u.HomeDir, ".config")
   126  	}
   127  	return configHome
   128  }
   129  
   130  func getBinaryPath() (string, error) {
   131  	bin, err := os.Executable()
   132  	if err != nil {
   133  		return "", err
   134  	}
   135  	return filepath.Abs(bin)
   136  }
   137  
   138  func rcFile(name string) string {
   139  	u, err := user.Current()
   140  	if err != nil {
   141  		return ""
   142  	}
   143  	path := filepath.Join(u.HomeDir, name)
   144  	if _, err := os.Stat(path); err != nil {
   145  		return ""
   146  	}
   147  	return path
   148  }