diff --git a/cmd/cd.go b/cmd/cd.go new file mode 100644 index 0000000..9587a98 --- /dev/null +++ b/cmd/cd.go @@ -0,0 +1,118 @@ +/* +Copyright © 2021 kouki@kmdkuk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package cmd + +import ( + "fmt" + "io" + "os" + "os/exec" + "strings" + + "github.com/spf13/cobra" + "golang.org/x/xerrors" +) + +var finder string + +// cdCmd represents the cd command +var cdCmd = &cobra.Command{ + Use: "cd", + Short: "Use peco to move to the dirty Directory.", + Long: `Use peco to move to the dirty Directory.`, + RunE: func(cmd *cobra.Command, args []string) error { + dir, err := findDirtyGit(filePath) + if err != nil { + return xerrors.Errorf("%w", err) + } + + result, err := runFinder(dir) + if err != nil { + return xerrors.Errorf("%w", err) + } + err = os.Chdir(result) + if err != nil { + return xerrors.Errorf("%w", err) + } + shell, err := getShell(os.Environ()) + if err != nil { + return xerrors.Errorf("%w", err) + } + s := exec.Command(shell) + s.Stdin = os.Stdin + s.Stdout = os.Stdout + s.Stderr = os.Stderr + fmt.Println("--------------------------------------------------------------------------------------------------------------") + fmt.Println("[WARNING][git-push-notifier]Exit with `exit`, since the child process is responsible for the directory change.") + fmt.Println("--------------------------------------------------------------------------------------------------------------") + if err := s.Run(); err != nil { + return xerrors.Errorf("%w", err) + } + return nil + }, +} + +func init() { + rootCmd.AddCommand(cdCmd) + + cdCmd.Flags().StringVarP(&finder, "finder", "f", "peco", "Select the finder you want to use()") +} + +func runFinder(dirs []string) (string, error) { + f := exec.Command(finder) + f.Stderr = os.Stderr + in, err := f.StdinPipe() + if err != nil { + return "", err + } + errCh := make(chan error, 1) + go func() { + SliceRead(dirs, in) + errCh <- in.Close() + }() + + err = <-errCh + if err != nil { + return "", xerrors.Errorf("%w", err) + } + result, err := f.Output() + if err != nil { + return "", xerrors.Errorf("%w", err) + } + + return strings.TrimRight(string(result), "\n"), nil +} +func SliceRead(s []string, out io.WriteCloser) { + for _, item := range s { + fmt.Fprintln(out, item) + } +} + +func getShell(env []string) (string, error) { + for _, s := range env { + kv := strings.Split(s, "=") + if kv[0] == "SHELL" { + return kv[1], nil + } + } + return "", xerrors.New("not found $SHELL") +} diff --git a/cmd/root.go b/cmd/root.go index 430be52..a18fd4b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -50,13 +50,7 @@ to quickly create a Cobra application.`, // Uncomment the following line if your bare application // has an action associated with it: RunE: func(cmd *cobra.Command, args []string) error { - f := file.NewFile(filePath) - gitDir, err := f.FindGitDir() - if err != nil { - return xerrors.Errorf("%w", err) - } - g := git.NewGit(gitDir) - dirtyDir, err := g.FindDirtyGit() + dirtyDir, err := findDirtyGit(filePath) if err != nil { return xerrors.Errorf("%w", err) } @@ -86,7 +80,7 @@ func init() { // when this action is called directly. rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") - rootCmd.Flags().StringVarP(&filePath, "path", "p", "/", "Path of the root to traverse") + rootCmd.PersistentFlags().StringVarP(&filePath, "path", "p", "/", "Path of the root to traverse") } // initConfig reads in config file and ENV variables if set. @@ -113,3 +107,13 @@ func initConfig() { log.Error("Using config file:", viper.ConfigFileUsed()) } } + +func findDirtyGit(filepath string) ([]string, error) { + f := file.NewFile(filePath) + gitDir, err := f.FindGitDir() + if err != nil { + return nil, xerrors.Errorf("%w", err) + } + g := git.NewGit(gitDir) + return g.FindDirtyGit() +} diff --git a/tools.go b/tools.go index 8be7b50..011fdc1 100644 --- a/tools.go +++ b/tools.go @@ -4,4 +4,5 @@ package tools import ( _ "github.com/golangci/golangci-lint/cmd/golangci-lint@v1.40.1" + _ "github.com/spf13/cobra/cobra@v1.1.3" )