package completion import ( _ "embed" "errors" "fmt" "github.com/ewy1/pik/paths" "github.com/ewy1/pik/spool" "os" "path/filepath" "strings" ) //go:embed completion.sh var completionCode string var completionFormat = ` # %s %s ` var completionComment = "pik completion (installed by `pik --install-completion`)" var completionCodeByShell = map[string]string{ "bash": ". <(pik --completion)", "zsh": `autoload -Uz compinit && compinit && source <(pik --completion)`, } var completionFileByShell = map[string]string{ "bash": ".bashrc", "zsh": ".zshrc", } // AlreadyInstalledError is returned when we already found completion code in your shell rc file var AlreadyInstalledError = errors.New("completion already installed") // Add finds the right file to append the completion code to and does that func Add(shell string) *spool.ExitCode { f := filepath.Join(paths.HomeDir.String(), completionFileByShell[shell]) content, err := os.ReadFile(f) if err != nil { return &spool.FatalReadFailure } if strings.Contains(string(content), strings.TrimSpace(completionCodeByShell[shell])) { return &spool.CompletionAlreadyInstalledFailure } fd, err := os.OpenFile(f, os.O_APPEND|os.O_WRONLY, 0600) defer fd.Close() if err != nil { return &spool.FatalReadFailure } _, err = fd.Write([]byte(fmt.Sprintf(completionFormat, completionComment, completionCodeByShell[shell]))) if err != nil { return &spool.CompletionFailure } successMessage(shell, f) return &spool.Success } func successMessage(shell string, file string) { _, _ = spool.Print("Installed completion for %s in %s\n", shell, file) } // Echo prints the actual completion script // because it is baked in with the program it should always be version-appropriate func Echo() *spool.ExitCode { _, _ = spool.Print("%s", completionCode) return &spool.Success }