From fbb0b604547d5c4703f7e76fb41e65a090811557 Mon Sep 17 00:00:00 2001 From: Yuki Ito Date: Mon, 8 Jan 2018 17:51:45 +0900 Subject: [PATCH] Add support for fish --- cmd/install/fish.go | 50 ++++++++++++++++++++++++++++++++++++++++++ cmd/install/install.go | 27 +++++++++++++++++++++++ cmd/install/utils.go | 10 +++++++++ 3 files changed, 87 insertions(+) create mode 100644 cmd/install/fish.go diff --git a/cmd/install/fish.go b/cmd/install/fish.go new file mode 100644 index 0000000..f04e7c3 --- /dev/null +++ b/cmd/install/fish.go @@ -0,0 +1,50 @@ +package install + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "text/template" +) + +// (un)install in fish + +type fish struct { + configDir string +} + +func (f fish) Install(cmd, bin string) error { + completionFile := filepath.Join(f.configDir, "completions", fmt.Sprintf("%s.fish", cmd)) + completeCmd := f.cmd(cmd, bin) + if _, err := os.Stat(completionFile); err == nil { + return fmt.Errorf("already installed at %s", completionFile) + } + + return createFile(completionFile, completeCmd) +} + +func (f fish) Uninstall(cmd, bin string) error { + completionFile := filepath.Join(f.configDir, "completions", fmt.Sprintf("%s.fish", cmd)) + if _, err := os.Stat(completionFile); err != nil { + return fmt.Errorf("does not installed in %s", f.configDir) + } + + return os.Remove(completionFile) +} + +func (f fish) cmd(cmd, bin string) string { + var buf bytes.Buffer + params := struct{ Cmd, Bin string }{cmd, bin} + template.Must(template.New("cmd").Parse(` +function __complete_{{.Cmd}} + set -lx COMP_LINE (string join ' ' (commandline -o)) + test (commandline -ct) = "" + and set COMP_LINE "$COMP_LINE " + {{.Bin}} +end +complete -c {{.Cmd}} -a "(__complete_{{.Cmd}})" +`)).Execute(&buf, params) + + return string(buf.Bytes()) +} diff --git a/cmd/install/install.go b/cmd/install/install.go index 082a226..4a70624 100644 --- a/cmd/install/install.go +++ b/cmd/install/install.go @@ -68,9 +68,36 @@ func installers() (i []installer) { if f := rcFile(".zshrc"); f != "" { i = append(i, zsh{f}) } + if d := fishConfigDir(); d != "" { + i = append(i, fish{d}) + } return } +func fishConfigDir() string { + configDir := filepath.Join(getConfigHomePath(), "fish") + if configDir == "" { + return "" + } + if info, err := os.Stat(configDir); err != nil || !info.IsDir() { + return "" + } + return configDir +} + +func getConfigHomePath() string { + u, err := user.Current() + if err != nil { + return "" + } + + configHome := os.Getenv("XDG_CONFIG_HOME") + if configHome == "" { + return filepath.Join(u.HomeDir, ".config") + } + return configHome +} + func getBinaryPath() (string, error) { bin, err := os.Executable() if err != nil { diff --git a/cmd/install/utils.go b/cmd/install/utils.go index 2c8b44c..8bcf4e1 100644 --- a/cmd/install/utils.go +++ b/cmd/install/utils.go @@ -36,6 +36,16 @@ func lineInFile(name string, lookFor string) bool { } } +func createFile(name string, content string) error { + f, err := os.Create(name) + if err != nil { + return err + } + defer f.Close() + _, err = f.WriteString(fmt.Sprintf("%s\n", content)) + return err +} + func appendToFile(name string, content string) error { f, err := os.OpenFile(name, os.O_RDWR|os.O_APPEND, 0) if err != nil {