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 }