diff --git a/cmd/completion.go b/cmd/completion.go new file mode 100644 index 00000000..86b8d5ec --- /dev/null +++ b/cmd/completion.go @@ -0,0 +1,46 @@ +package cmd + +import ( + "os" + + "github.com/spf13/cobra" +) + +// completionCmd represents the completion command +var completionCmd = &cobra.Command{ + Use: "completion", + Short: "generate shell completion files", + Long: ``, +} + +var bashCompletionCmd = &cobra.Command{ + Use: "bash", + Short: "generate bash completion file", + Long: `To load completion run + +. <(lab completion bash) + +To configure your bash shell to load completions for each session add to your bashrc + +# ~/.bashrc or ~/.profile +. <(lab completion bash) +`, + Run: func(cmd *cobra.Command, args []string) { + RootCmd.GenBashCompletion(os.Stdout) + }, +} + +var zshCompletionCmd = &cobra.Command{ + Use: "zsh", + Short: "generate zsh completion file", + Long: `The author of lab has no idea how to load the generated zsh completion files, if you know how to load this output please open an issue at https://github.com/zaquestion/lab/issues and explain`, + Run: func(cmd *cobra.Command, args []string) { + RootCmd.GenZshCompletion(os.Stdout) + }, +} + +func init() { + completionCmd.AddCommand(bashCompletionCmd) + completionCmd.AddCommand(zshCompletionCmd) + RootCmd.AddCommand(completionCmd) +} diff --git a/cmd/root.go b/cmd/root.go index ba1453b8..1a8c666a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -21,7 +21,7 @@ import ( // RootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ Use: "lab", - Short: "A Git Wrapper for GitLab", + Short: "Lab makes it simple to clone, fork, and interact with repositories on GitLab, including seamless workflows for creating merge requests, issues and snippets", Long: ``, Run: func(cmd *cobra.Command, args []string) { if ok, err := cmd.Flags().GetBool("version"); err == nil && ok { @@ -58,6 +58,14 @@ func labUsageFormat(c *cobra.Command) string { } func helpFunc(cmd *cobra.Command, args []string) { + if !git.IsAliased { + cmd.Root().SetHelpFunc(nil) + err := cmd.Help() + if err != nil { + log.Fatal(err) + } + return + } // When help func is called from the help command args will be // populated. When help is called with cmd.Help(), the args are not // passed through, so we pick them up ourselves here diff --git a/internal/git/git.go b/internal/git/git.go index 5607e20b..6cadb7ac 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" "time" @@ -15,14 +16,33 @@ import ( gitconfig "github.com/tcnksm/go-gitconfig" ) -// IsHub is true when using "hub" as the git binary -var IsHub bool +var ( + // IsHub is true when using "hub" as the git binary + IsHub bool + // IsAliased is true when git is aliased to lab + IsAliased bool +) func init() { _, err := exec.LookPath("hub") if err == nil { IsHub = true } + + out, err := exec.Command("ps", "-p", strconv.Itoa(os.Getppid()), "-o", "cmd=").CombinedOutput() + sh := strings.TrimSpace(string(out)) + switch sh { + case "bash", "-bash": + out, err = exec.Command("bash", "-i", "-c", "type git").CombinedOutput() + if strings.HasSuffix(string(out), "git is aliased to `lab'\n") { + IsAliased = true + } + case "zsh", "-zsh": + out, err = exec.Command("zsh", "-i", "-c", "whence git").CombinedOutput() + if strings.HasSuffix(string(out), "lab\n") { + IsAliased = true + } + } } // New looks up the hub or git binary and returns a cmd which outputs to stdout