Skip to content

Commit

Permalink
Add process that generate bash/fish/zsh completion file
Browse files Browse the repository at this point in the history
  • Loading branch information
nao1215 committed Apr 16, 2022
1 parent 063673a commit b09d5af
Show file tree
Hide file tree
Showing 2 changed files with 203 additions and 0 deletions.
175 changes: 175 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package cmd

import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/nao1215/gup/internal/assets"
"github.com/nao1215/gup/internal/completion"
"github.com/nao1215/gup/internal/file"
"github.com/nao1215/gup/internal/print"
"github.com/spf13/cobra"
)
Expand All @@ -15,7 +24,173 @@ If you update all binaries, just run '$ gup update'`,
// Execute run gup process.
func Execute() {
assets.DeployIconIfNeeded()
deployShellCompletionFileIfNeeded(rootCmd)

rootCmd.CompletionOptions.DisableDefaultCmd = true
if err := rootCmd.Execute(); err != nil {
print.Err(err)
}
}

// deleteShellCompletionFileIfNeeded creates the shell completion file.
// If the file with the same contents already exists, it is not created.
func deployShellCompletionFileIfNeeded(cmd *cobra.Command) {
makeBashCompletionFileIfNeeded(cmd)
makeFishCompletionFileIfNeeded(cmd)
makeZshCompletionFileIfNeeded(cmd)
}

func makeBashCompletionFileIfNeeded(cmd *cobra.Command) {
if existSameBashCompletionFile(cmd) {
return
}

path := completion.BashCompletionFilePath()
if err := os.MkdirAll(filepath.Dir(path), 0775); err != nil {
print.Err(fmt.Errorf("can not create bash-completion file: %w", err))
return
}

if err := cmd.GenBashCompletionFile(path); err != nil {
print.Err(fmt.Errorf("can not create bash-completion file: %w", err))
return
}
print.Info("create bash-completion file: " + path)
}

func makeFishCompletionFileIfNeeded(cmd *cobra.Command) {
if isSameFishCompletionFile(cmd) {
return
}

path := completion.FishCompletionFilePath()
if err := os.MkdirAll(filepath.Dir(path), 0775); err != nil {
print.Err(fmt.Errorf("can not create fish-completion file: %w", err))
return
}

if err := cmd.GenFishCompletionFile(path, false); err != nil {
print.Err(fmt.Errorf("can not create fish-completion file: %w", err))
return
}
print.Info("create fish-completion file: " + path)
}

func makeZshCompletionFileIfNeeded(cmd *cobra.Command) {
if isSameZshCompletionFile(cmd) {
return
}

path := completion.ZshCompletionFilePath()
if err := os.MkdirAll(filepath.Dir(path), 0775); err != nil {
print.Err(fmt.Errorf("can not create zsh-completion file: %w", err))
return
}

if err := cmd.GenZshCompletionFile(path); err != nil {
print.Err(fmt.Errorf("can not create zsh-completion file: %w", err))
return
}
print.Info("create zsh-completion file: " + path)

const zshFpath = "fpath=(~/.zsh/completion $fpath)"
zshrcPath := completion.ZshrcPath()
if !file.IsFile(zshrcPath) {
fp, err := os.OpenFile(zshrcPath, os.O_RDWR|os.O_CREATE, 0664)
if err != nil {
print.Err(fmt.Errorf("can not add zsh $fpath in .zshrc: %w", err))
return
}
defer fp.Close()
if _, err := fp.WriteString(zshFpath); err != nil {
print.Err(fmt.Errorf("can not add zsh $fpath in .zshrc: %w", err))
return
}
}

zshrc, err := ioutil.ReadFile(zshrcPath)
if err != nil {
print.Err(fmt.Errorf("can not read .zshrc: %w", err))
return
}

if strings.Contains(string(zshrc), zshFpath) {
return
}

fp, err := os.OpenFile(zshrcPath, os.O_RDWR|os.O_APPEND, 0664)
if err != nil {
print.Err(fmt.Errorf("can not add zsh $fpath in .zshrc: %w", err))
return
}
defer fp.Close()

if _, err := fp.WriteString(zshFpath); err != nil {
print.Err(fmt.Errorf("can not add zsh $fpath in .zshrc: %w", err))
return
}
}

func existSameBashCompletionFile(cmd *cobra.Command) bool {
path := completion.BashCompletionFilePath()
if !file.IsFile(path) {
return false
}

currentBashCompletion := new(bytes.Buffer)
cmd.GenBashCompletion(currentBashCompletion)

bashCompletionInLocal, err := ioutil.ReadFile(path)
if err != nil {
return false
}

if bytes.Compare(currentBashCompletion.Bytes(), bashCompletionInLocal) != 0 {
return false
}
return true
}

func isSameFishCompletionFile(cmd *cobra.Command) bool {
path := completion.FishCompletionFilePath()
if !file.IsFile(path) {
return false
}

currentFishCompletion := new(bytes.Buffer)
if err := cmd.GenFishCompletion(currentFishCompletion, false); err != nil {
return false
}

fishCompletionInLocal, err := ioutil.ReadFile(path)
if err != nil {
return false
}

if bytes.Compare(currentFishCompletion.Bytes(), fishCompletionInLocal) != 0 {
return false
}
return true
}

func isSameZshCompletionFile(cmd *cobra.Command) bool {
path := completion.ZshCompletionFilePath()
if !file.IsFile(path) {
return false
}

currentZshCompletion := new(bytes.Buffer)
if err := cmd.GenFishCompletion(currentZshCompletion, false); err != nil {
return false
}

zshCompletionInLocal, err := ioutil.ReadFile(path)
if err != nil {
return false
}

if bytes.Compare(currentZshCompletion.Bytes(), zshCompletionInLocal) != 0 {
return false
}
return true
}
28 changes: 28 additions & 0 deletions internal/completion/completion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package completion

import (
"os"
"path/filepath"

"github.com/nao1215/gup/internal/cmdinfo"
)

// BashCompletionFilePath return bash-completion file path.
func BashCompletionFilePath() string {
return filepath.Join(os.Getenv("HOME"), ".config", "bash_completion.d", cmdinfo.Name())
}

// FishCompletionFilePath return fish-completion file path.
func FishCompletionFilePath() string {
return filepath.Join(os.Getenv("HOME"), ".config", "fish", "completions", cmdinfo.Name()+".fish")
}

// ZshCompletionFilePath return zsh-completion file path.
func ZshCompletionFilePath() string {
return filepath.Join(os.Getenv("HOME"), ".zsh", "completion", "_"+cmdinfo.Name())
}

// ZshrcPath return .zshrc path.
func ZshrcPath() string {
return filepath.Join(os.Getenv("HOME"), ".zshrc")
}

0 comments on commit b09d5af

Please sign in to comment.