From 16e2b3d6b654809e62743f4c6022844ca8db1b87 Mon Sep 17 00:00:00 2001 From: Kyoichiro Yamada Date: Sun, 8 Dec 2019 09:34:15 +0900 Subject: [PATCH] support change-directory command fix: #33 --- README.md | 9 ++++++--- command/get.go | 10 ++++++++-- command/setup.go | 25 +++++++++++++------------ command/setup_test.go | 5 ----- go.mod | 2 ++ go.sum | 18 ++++++++++++++++++ main.go | 21 ++++++++++++++++----- sh/assets.go | 30 ++++++++++++++++++++++++++++++ sh/src/init.bash | 31 +++++++++++++++++++++++++++++++ sh/src/init.zsh | 30 ++++++++++++++++++++++++++++++ 10 files changed, 154 insertions(+), 27 deletions(-) create mode 100755 sh/assets.go create mode 100644 sh/src/init.bash create mode 100644 sh/src/init.zsh diff --git a/README.md b/README.md index 187adaf3..c3fde935 100644 --- a/README.md +++ b/README.md @@ -247,20 +247,23 @@ Local repositories are placed under `gogh.root` with named github.com/*user*/*re To be enabled shell extentions (for zsh / bash), set up gogh in your shell-rc file (`.bashrc` / `.zshrc`). -* `gogogh` command +* `gogo cd` command * shorthand for `cd $(gogh find )` +* `gogo get --cd` option * auto-completions ``` eval "$(gogh setup)" ``` -If you want to rename `gogogh` command, specify `--cd-function-name=` like below. +If you have not set `SHELL` envar right, tell your shell explicitly. ``` -eval "$(gogh setup --cd-function-name=foobar)" +eval "$(gogh setup --shell bash)" ``` +NOTE: Now gogh supports `bash` or `zsh` only. + # DEFERENCES TO `ghq` * `ghq` is too complex for me. That's why I forked this project from it. diff --git a/command/get.go b/command/get.go index 4acbdfc4..0a81ee4f 100644 --- a/command/get.go +++ b/command/get.go @@ -29,11 +29,17 @@ func Get(ctx gogh.Context, update, withSSH, shallow bool, repo *gogh.Repo) error } if !project.Exists { log.Println("info: Clone", fmt.Sprintf("%s -> %s", repoURL, project.FullPath)) - return git().Clone(ctx, project, repoURL, shallow) + if err := git().Clone(ctx, project, repoURL, shallow); err != nil { + return err + } + fmt.Println(project.FullPath) } if update { log.Println("info: Update", project.FullPath) - return git().Update(ctx, project) + if err := git().Update(ctx, project); err != nil { + return err + } + fmt.Println(project.FullPath) } log.Println("warn: Exists", project.FullPath) return nil diff --git a/command/setup.go b/command/setup.go index d423debb..6e4c06f9 100644 --- a/command/setup.go +++ b/command/setup.go @@ -2,25 +2,26 @@ package command import ( "fmt" + "io" "path/filepath" "github.com/kyoh86/gogh/gogh" + "github.com/kyoh86/gogh/sh" ) // Setup shells in shell scipt // Usage: eval "$(gogh setup)" -func Setup(ctx gogh.Context, cdFuncName, shell string) error { - _, shName := filepath.Split(shell) - switch shName { - case "zsh": - fmt.Fprintf(ctx.Stdout(), `function %s { cd $(gogh find $@) }%s`, cdFuncName, "\n") - fmt.Fprintf(ctx.Stdout(), `eval "$(gogh --completion-script-zsh)"%s`, "\n") - return nil - case "bash": - fmt.Fprintf(ctx.Stdout(), `function %s { cd $(gogh find $@) }%s`, cdFuncName, "\n") - fmt.Fprintf(ctx.Stdout(), `eval "$(gogh --completion-script-bash)"%s`, "\n") - return nil - default: +func Setup(ctx gogh.Context, _, shell string) error { + _ = sh.Assets + _, shellName := filepath.Split(shell) + assetName := "/src/init." + shellName + if !sh.Assets.Exists(assetName) { return fmt.Errorf("unsupported shell %q", shell) } + file, err := sh.Assets.Open(assetName) + if err != nil { + return err + } + _, err = io.Copy(ctx.Stdout(), file) + return err } diff --git a/command/setup_test.go b/command/setup_test.go index b24d4dfb..ef731529 100644 --- a/command/setup_test.go +++ b/command/setup_test.go @@ -15,11 +15,6 @@ func ExampleSetup() { if err := command.Setup(&config.Config{}, "gogh-cd", "bash"); err != nil { panic(err) } - // Output: - // function gogh-cd { cd $(gogh find $@) } - // eval "$(gogh --completion-script-zsh)" - // function gogh-cd { cd $(gogh find $@) } - // eval "$(gogh --completion-script-bash)" } func TestSetup(t *testing.T) { diff --git a/go.mod b/go.mod index db342a00..8b35790a 100644 --- a/go.mod +++ b/go.mod @@ -9,12 +9,14 @@ require ( github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/comail/colog v0.0.0-20160416085026-fba8e7b1f46c github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deadcheat/goblet v1.3.1 github.com/github/hub v2.10.0+incompatible github.com/google/go-github/v24 v24.0.1 github.com/joeshaw/envdecode v0.0.0-20180312135643-c9e015854467 github.com/karrick/godirwalk v1.8.0 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kr/pretty v0.1.0 // indirect + github.com/kyoh86/richgo v0.3.3 // indirect github.com/kyoh86/xdg v1.0.0 github.com/mattn/go-colorable v0.1.1 // indirect github.com/mattn/go-isatty v0.0.7 // indirect diff --git a/go.sum b/go.sum index 6a216834..e30b68dc 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,13 @@ github.com/comail/colog v0.0.0-20160416085026-fba8e7b1f46c/go.mod h1:1WwgAwMKQLY github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deadcheat/goblet v1.3.1 h1:OPOYQjHlbPmG8fFCt8GNNGECLVhaJ0n7F7cP5Mh7G/A= +github.com/deadcheat/goblet v1.3.1/go.mod h1:IrMNyAwyrVgB30HsND2WgleTUM4wHTS9m40yNY6NJQg= +github.com/deadcheat/gonch v0.0.0-20180528124129-c2ff7a019863 h1:WiIagMEsLYiZCeD76SSLTJPdBdnmXkrFOFbI6Chf0xg= +github.com/deadcheat/gonch v0.0.0-20180528124129-c2ff7a019863/go.mod h1:/5mH3gAuXUxGN3maOBAxBfB8RXvP9tBIX5fx2x1k0V0= github.com/github/hub v2.10.0+incompatible h1:gK3M/y1ZD/Mc0ytSDykzL8C9q8k7pVTTiEa+1SanJZk= github.com/github/hub v2.10.0+incompatible/go.mod h1:zQrzJEdze2hfWJDgktd/L6sROjAdCThFrzjbxw4keTs= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= @@ -36,33 +41,45 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kyoh86/richgo v0.3.3 h1:fW7ygWNMg1INcX3Yoha9v1C5nYlvd/IodJUf0Batz6Q= +github.com/kyoh86/richgo v0.3.3/go.mod h1:S65jllVRxBm59fqIXfCa3cPxQYRT9u9v45EPQVeuoH0= +github.com/kyoh86/xdg v0.0.0-20171007020617-d28e4c5d7b81/go.mod h1:Z5mDqe0fxyxn3W2yTxsBAOQqIrXADQIh02wrTnaRM38= github.com/kyoh86/xdg v1.0.0 h1:TD1layQ0epNApNwGRblnQnT3S/2UH/gCQN1cmXWotvE= github.com/kyoh86/xdg v1.0.0/go.mod h1:Z5mDqe0fxyxn3W2yTxsBAOQqIrXADQIh02wrTnaRM38= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.0-20170925054904-a5cdd64afdee/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= +github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709 h1:Ko2LQMrRU+Oy/+EDBwX7eZ2jp3C47eDBB8EIhKTun+I= github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/thoas/go-funk v0.0.0-20190328084834-b6996520715f h1:hucXnlEXfHvrY7vI9hP1bJX/olUUt5a6u3QvxXrtANw= github.com/thoas/go-funk v0.0.0-20190328084834-b6996520715f/go.mod h1:mlR+dHGb+4YgXkf13rkQTuzrneeHANxOm6+ZnEV9HsA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/wacul/ptr v0.0.0-20170209030335-91632201dfc8 h1:js9Z9dWq50Ttu4D1YRqgS1gkSgRfpKp+rMza4io7qNw= +github.com/wacul/ptr v0.0.0-20170209030335-91632201dfc8/go.mod h1:BD0gjsZrCwtoR+yWDB9v2hQ8STlq9tT84qKfa+3txOc= golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac h1:7d7lG9fHOLdL6jZPtnV4LpI41SbohIJ1Atq7U991dMg= golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20180404174746-b3c676e531a6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170927054621-314a259e304f/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87 h1:GqwDwfvIpC33dK9bA1fD+JiDUNsuAiQiEkpHqUKze4o= golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= @@ -71,5 +88,6 @@ google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRS google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index 015a13b4..0933e189 100644 --- a/main.go +++ b/main.go @@ -21,6 +21,8 @@ var ( ) func main() { + log.SetOutput(os.Stderr) + app := kingpin.New("gogh", "GO GitHub project manager").Version(fmt.Sprintf("%s-%s (%s)", version, commit, date)).Author("kyoh86") app.Command("config", "Get and set options") @@ -105,11 +107,16 @@ func get(app *kingpin.Application) (string, func() error) { withSSH bool shallow bool repoNames gogh.Repos + cd bool + // unused: it is dummy to accept option. + // its function defined in init.*sh in the /sh/src + // if we want to use gogh get --cd, ) cmd := app.Command("get", "Clone/sync with a remote repository") cmd.Flag("update", "Update the local project if cloned already").Short('u').BoolVar(&update) cmd.Flag("ssh", "Clone with SSH").BoolVar(&withSSH) cmd.Flag("shallow", "Do a shallow clone").BoolVar(&shallow) + cmd.Flag("cd", "Jump to the local project").BoolVar(&cd) cmd.Arg("repositories", "Target repositories ( | / | )").Required().SetValue(&repoNames) return mainutil.WrapCommand(cmd, func(ctx gogh.Context) error { @@ -283,15 +290,19 @@ func root(app *kingpin.Application) (string, func() error) { func setup(app *kingpin.Application) (string, func() error) { var ( - cdFuncName string - shell string + shell string ) - cmd := app.Command("setup", "Generate shell script to setup gogh").Hidden() - cmd.Flag("cd-function-name", "Name of the function to define").Default("gogogh").Hidden().StringVar(&cdFuncName) + cmd := app.Command("setup", `Generate shell script to setup gogh + +If you want to use "gogh cd", "gogh get --cd" and autocompletions for gogh, + +set up gogh in your shell-rc file (".bashrc" / ".zshrc") like below. + +eval "$(gogh setup)"`).Hidden() cmd.Flag("shell", "Target shell path").Envar("SHELL").Hidden().StringVar(&shell) return mainutil.WrapCommand(cmd, func(ctx gogh.Context) error { - return command.Setup(ctx, cdFuncName, shell) + return command.Setup(ctx, "", shell) }) } diff --git a/sh/assets.go b/sh/assets.go new file mode 100755 index 00000000..761785ad --- /dev/null +++ b/sh/assets.go @@ -0,0 +1,30 @@ +package sh + +import ( + "time" + + "github.com/deadcheat/goblet" +) + +//go:generate goblet -g --ignore-dotfiles -o assets.go -p sh src + +// Assets a generated file system +var Assets = goblet.NewFS( + map[string][]string{ + "/src": []string{ + "init.bash", "init.zsh", + }, + }, + map[string]*goblet.File{ + "/src/init.bash": goblet.NewFile("/src/init.bash", _Assetsa96e64fd7a6ce6e1579ce8d99622cfdcf8c12b96, 0x1a4, time.Unix(1575764391, 1575764391416360881)), + "/src/init.zsh": goblet.NewFile("/src/init.zsh", _Assetsd275f00e2d9fab456599903fda40166d6da9aa46, 0x1a4, time.Unix(1575764381, 1575764381889652313)), + "/src": goblet.NewFile("/src", nil, 0x800001ed, time.Unix(1575764391, 1575764391416360881)), + }, +) + +// binary data +var ( + _Assetsa96e64fd7a6ce6e1579ce8d99622cfdcf8c12b96 = []byte("#!/bin/bash\n\nfunction gogh() {\n case $1 in\n \"cd\" )\n shift\n cd \"$(command gogh find \"$@\" | tee /dev/tty | tail -n1)\" || return\n ;;\n\n \"get\" )\n local CD=0\n for arg in \"$@\"; do\n if [ \"${arg}\" = '--cd' ]; then\n CD=1\n fi\n done\n\n if [ $CD -eq 1 ]; then\n loc=\"$(command gogh \"$@\" | tee /dev/tty | tail -n1)\"\n cd \"$loc\" || return\n else\n command gogh \"$@\"\n fi\n ;;\n\n * )\n command gogh \"$@\"\n ;;\n esac\n}\neval \"$(command gogh --completion-script-bash)\"\n") + _Assetsd275f00e2d9fab456599903fda40166d6da9aa46 = []byte("function gogh() {\n exec 5>&1\n case $1 in\n \"cd\" )\n shift\n cd \"$(command gogh find \"$@\" | tee /dev/tty | tail -n1)\" || return\n ;;\n\n \"get\" )\n local CD=0\n for arg in \"$@\"; do\n if [ \"${arg}\" = '--cd' ]; then\n CD=1\n fi\n done\n\n if [ $CD -eq 1 ]; then\n loc=\"$(command gogh \"$@\" | tee /dev/tty | tail -n1)\"\n cd \"$loc\" || return\n else\n command gogh \"$@\"\n fi\n ;;\n\n * )\n command gogh \"$@\"\n ;;\n esac\n}\neval \"$(command gogh --completion-script-zsh)\"\n") +) + diff --git a/sh/src/init.bash b/sh/src/init.bash new file mode 100644 index 00000000..8b926df7 --- /dev/null +++ b/sh/src/init.bash @@ -0,0 +1,31 @@ +#!/bin/bash + +function gogh() { + case $1 in + "cd" ) + shift + cd "$(command gogh find "$@" | tee /dev/tty | tail -n1)" || return + ;; + + "get" ) + local CD=0 + for arg in "$@"; do + if [ "${arg}" = '--cd' ]; then + CD=1 + fi + done + + if [ $CD -eq 1 ]; then + loc="$(command gogh "$@" | tee /dev/tty | tail -n1)" + cd "$loc" || return + else + command gogh "$@" + fi + ;; + + * ) + command gogh "$@" + ;; + esac +} +eval "$(command gogh --completion-script-bash)" diff --git a/sh/src/init.zsh b/sh/src/init.zsh new file mode 100644 index 00000000..0ed309d9 --- /dev/null +++ b/sh/src/init.zsh @@ -0,0 +1,30 @@ +function gogh() { + exec 5>&1 + case $1 in + "cd" ) + shift + cd "$(command gogh find "$@" | tee /dev/tty | tail -n1)" || return + ;; + + "get" ) + local CD=0 + for arg in "$@"; do + if [ "${arg}" = '--cd' ]; then + CD=1 + fi + done + + if [ $CD -eq 1 ]; then + loc="$(command gogh "$@" | tee /dev/tty | tail -n1)" + cd "$loc" || return + else + command gogh "$@" + fi + ;; + + * ) + command gogh "$@" + ;; + esac +} +eval "$(command gogh --completion-script-zsh)"