diff --git a/cmd/add.go b/cmd/add.go index b86f1dbe..a5367a15 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -5,6 +5,7 @@ import ( "github.com/spf13/cobra" + "github.com/evilmartians/lefthook/internal/config" "github.com/evilmartians/lefthook/internal/lefthook" ) @@ -14,12 +15,22 @@ var addDoc string func newAddCmd(opts *lefthook.Options) *cobra.Command { args := lefthook.AddArgs{} + addHookCompletions := func(cmd *cobra.Command, args []string, toComplete string) (ret []string, compDir cobra.ShellCompDirective) { + compDir = cobra.ShellCompDirectiveNoFileComp + if len(args) != 0 { + return + } + ret = config.AvailableHooks[:] + return + } + addCmd := cobra.Command{ - Use: "add hook-name", - Short: "This command adds a hook directory to a repository", - Long: addDoc, - Example: "lefthook add pre-commit", - Args: cobra.MinimumNArgs(1), + Use: "add hook-name", + Short: "This command adds a hook directory to a repository", + Long: addDoc, + Example: "lefthook add pre-commit", + ValidArgsFunction: addHookCompletions, + Args: cobra.MinimumNArgs(1), RunE: func(_cmd *cobra.Command, hooks []string) error { args.Hook = hooks[0] return lefthook.Add(opts, &args) diff --git a/cmd/dump.go b/cmd/dump.go index 1dfbc02e..a8a49f25 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -9,9 +9,10 @@ import ( func newDumpCmd(opts *lefthook.Options) *cobra.Command { dumpArgs := lefthook.DumpArgs{} dumpCmd := cobra.Command{ - Use: "dump", - Short: "Prints config merged from all extensions (in YAML format by default)", - Example: "lefthook dump", + Use: "dump", + Short: "Prints config merged from all extensions (in YAML format by default)", + Example: "lefthook dump", + ValidArgsFunction: cobra.NoFileCompletions, Run: func(cmd *cobra.Command, args []string) { lefthook.Dump(opts, dumpArgs) }, diff --git a/cmd/install.go b/cmd/install.go index 8fca459b..eb365e22 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -11,8 +11,9 @@ func newInstallCmd(opts *lefthook.Options) *cobra.Command { var a, force bool installCmd := cobra.Command{ - Use: "install", - Short: "Write basic configuration file in your project repository. Or initialize existed config", + Use: "install", + Short: "Write basic configuration file in your project repository. Or initialize existed config", + ValidArgsFunction: cobra.NoFileCompletions, RunE: func(cmd *cobra.Command, _args []string) error { return lefthook.Install(opts, force) }, diff --git a/cmd/run.go b/cmd/run.go index 4f2999b3..a550b5da 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -3,17 +3,29 @@ package cmd import ( "github.com/spf13/cobra" + "github.com/evilmartians/lefthook/internal/config" "github.com/evilmartians/lefthook/internal/lefthook" ) func newRunCmd(opts *lefthook.Options) *cobra.Command { runArgs := lefthook.RunArgs{} + runHookCompletions := func(cmd *cobra.Command, args []string, toComplete string) (ret []string, compDir cobra.ShellCompDirective) { + compDir = cobra.ShellCompDirectiveNoFileComp + if len(args) != 0 { + return + } + ret = lefthook.ConfigHookCompletions(opts) + ret = append(ret, config.AvailableHooks[:]...) + return + } + runCmd := cobra.Command{ - Use: "run hook-name [git args...]", - Short: "Execute group of hooks", - Example: "lefthook run pre-commit", - Args: cobra.MinimumNArgs(1), + Use: "run hook-name [git args...]", + Short: "Execute group of hooks", + Example: "lefthook run pre-commit", + ValidArgsFunction: runHookCompletions, + Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { // args[0] - hook name // args[1:] - git hook arguments, number and value depends on the hook diff --git a/cmd/uninstall.go b/cmd/uninstall.go index d49c5a6c..901ca575 100644 --- a/cmd/uninstall.go +++ b/cmd/uninstall.go @@ -10,8 +10,9 @@ func newUninstallCmd(opts *lefthook.Options) *cobra.Command { args := lefthook.UninstallArgs{} uninstallCmd := cobra.Command{ - Use: "uninstall", - Short: "Revert install command", + Use: "uninstall", + Short: "Revert install command", + ValidArgsFunction: cobra.NoFileCompletions, RunE: func(cmd *cobra.Command, _args []string) error { return lefthook.Uninstall(opts, &args) }, diff --git a/cmd/version.go b/cmd/version.go index dfd8b34a..858498f0 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -12,8 +12,9 @@ func newVersionCmd(_opts *lefthook.Options) *cobra.Command { var verbose bool versionCmd := cobra.Command{ - Use: "version", - Short: "Show lefthook version", + Use: "version", + Short: "Show lefthook version", + ValidArgsFunction: cobra.NoFileCompletions, Run: func(cmd *cobra.Command, args []string) { log.Println(version.Version(verbose)) }, diff --git a/internal/lefthook/lefthook.go b/internal/lefthook/lefthook.go index 29de2f51..b063ae65 100644 --- a/internal/lefthook/lefthook.go +++ b/internal/lefthook/lefthook.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/afero" + "github.com/evilmartians/lefthook/internal/config" "github.com/evilmartians/lefthook/internal/git" "github.com/evilmartians/lefthook/internal/log" "github.com/evilmartians/lefthook/internal/templates" @@ -123,3 +124,22 @@ func (l *Lefthook) addHook(hook, rc string, assertLefthookInstalled bool) error l.Fs, hookPath, templates.Hook(hook, rc, assertLefthookInstalled), hookFileMode, ) } + +func ConfigHookCompletions(opts *Options) []string { + lefthook, err := initialize(opts) + if err != nil { + return nil + } + cfg, err := config.Load(lefthook.Fs, lefthook.repo) + if err != nil { + return nil + } + if err = cfg.Validate(); err != nil { + return nil + } + hooks := make([]string, 0, len(cfg.Hooks)) + for h := range cfg.Hooks { + hooks = append(hooks, h) + } + return hooks +}