Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(zsh): ignore inserting zsh-completion if system don't have zsh shell #1025

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 66 additions & 19 deletions pkg/autocomplete/zsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package autocomplete
import (
"fmt"
"os"
"os/exec"
"os/user"
"path/filepath"
"strings"
Expand Down Expand Up @@ -52,33 +53,62 @@ _cli_zsh_autocomplete() {

compdef _cli_zsh_autocomplete envd`

var zshConfig = `
# envd zsh-completion
[ -f ~/.config/envd/envd.zsh ] && source ~/.config/envd/envd.zsh
`

// If debugging this, it might be required to run `rm ~/.zcompdump*` to remove the cache
func InsertZSHCompleteEntry() error {
// should be the same on linux and macOS
path := "/usr/local/share/zsh/site-functions/_envd"
dirPath := filepath.Dir(path)

dirPathExists, err := fileutil.DirExists(dirPath)
// check the system has zsh
_, err := exec.LookPath("zsh")
if err != nil {
return errors.Wrapf(err, "failed to check if %s exists", dirPath)
}
if !dirPathExists {
log.L.Warnf("Warning: unable to enable zsh-completion: %s does not exist", dirPath)
return nil // zsh-completion isn't available, silently fail.
log.L.Debugf("can't find zsh in this system, stop setting the zsh-completion.")
return nil
}

pathExists, err := fileutil.FileExists(path)
if err != nil {
return errors.Wrapf(err, "failed to check if %s exists", path)
// should be the same on linux and macOS
filename := "envd.zsh"
homeDir := os.Getenv("HOME")
dirs := []string{
"/usr/share/zsh/site-functions",
"/usr/local/share/zsh/site-functions",
fileutil.DefaultConfigDir,
}
if pathExists {
return nil // file already exists, don't update it.

var f *os.File
var lastErr error
path := ""
for _, dir := range dirs {
dirPathExists, err := fileutil.DirExists(dir)
if err != nil {
return errors.Wrapf(err, "failed to check if %s exists", dir)
}
if dirPathExists {
path = fmt.Sprintf("%s/%s", dir, filename)
log.L.Debugf("use the zsh-completion path for envd: %s", path)

pathExists, err := fileutil.FileExists(path)
if err != nil {
lastErr = errors.Wrapf(err, "failed to check if %s exists", path)
}
if pathExists {
return nil // file already exists, don't update it.
}

// create the completion file
f, err = os.Create(path)
if err != nil {
lastErr = err
continue
}

break
}
}

// create the completion file
f, err := os.Create(path)
if err != nil {
return err
if f == nil {
return lastErr
}
defer f.Close()

Expand All @@ -93,6 +123,23 @@ func InsertZSHCompleteEntry() error {
return errors.Wrapf(err, "failed writing to %s", path)
}

if strings.HasPrefix(path, homeDir) {
zshFile, err := os.OpenFile(fmt.Sprintf("%s/.zshrc", homeDir), os.O_RDWR|os.O_APPEND|os.O_CREATE, 0660)
if err != nil {
log.L.Warnf("unable to open the `~/.zshrc`, please add the following lines into `~/.zshrc` to get the envd zsh completion:\n"+
" %s\n", zshConfig)
return err
}
defer zshFile.Close()

_, err = fmt.Fprintf(zshFile, "%s\n", zshConfig)
if err != nil {
log.L.Warnf("unable to write the `~/.zshrc`, please add the following lines into `~/.zshrc` to get the envd zsh completion:\n"+
" %s\n", zshConfig)
return err
}
}

return deleteZcompdump()
}

Expand Down