diff --git a/completions.go b/completions.go new file mode 100644 index 0000000..0009e71 --- /dev/null +++ b/completions.go @@ -0,0 +1,124 @@ +package cmd + +import ( + "io" + "os" + + "go.fifitido.net/cmd/opt" +) + +var outputFileOption = opt.String("output", "o", "", "The file to output the completions to") + +func CompletionsSubcommand() *Command { + cmd := New( + "completions", + WithShortDescription("Generate shell completions"), + WithLongDescription("Generate shell completions"), + ) + + registerBashCompletions(cmd) + registerFishCompletions(cmd) + registerPowerShellCompletions(cmd) + registerZsgCompletions(cmd) + + return cmd +} + +func getCompletionsOut() io.Writer { + outputFile := outputFileOption.Value() + + if outputFile != "" { + var err error + out, err := os.OpenFile(outputFile, os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + panic(err) + } + return out + } + + return os.Stdout +} + +func registerBashCompletions(parent *Command) *Command { + return New( + "bash", + WithShortDescription("Generate bash completions"), + WithLongDescription("Generate bash completions"), + WithOptions(outputFileOption), + WithParent(parent), + WithRunFunc(func(args []string) { + out := getCompletionsOut() + + if fc, ok := out.(io.Closer); ok { + defer fc.Close() + } + + if err := WriteBashCompletions(out, parent.Root()); err != nil { + panic(err) + } + }), + ) +} + +func registerFishCompletions(parent *Command) *Command { + return New( + "fish", + WithShortDescription("Generate fish completions"), + WithLongDescription("Generate fish completions"), + WithOptions(outputFileOption), + WithParent(parent), + WithRunFunc(func(args []string) { + out := getCompletionsOut() + + if fc, ok := out.(io.Closer); ok { + defer fc.Close() + } + + if err := WriteFishCompletions(out, parent.Root()); err != nil { + panic(err) + } + }), + ) +} + +func registerPowerShellCompletions(parent *Command) *Command { + return New( + "powershell", + WithShortDescription("Generate powershell completions"), + WithLongDescription("Generate powershell completions"), + WithOptions(outputFileOption), + WithParent(parent), + WithRunFunc(func(args []string) { + out := getCompletionsOut() + + if fc, ok := out.(io.Closer); ok { + defer fc.Close() + } + + if err := WritePowerShellCompletions(out, parent.Root()); err != nil { + panic(err) + } + }), + ) +} + +func registerZsgCompletions(parent *Command) *Command { + return New( + "zsh", + WithShortDescription("Generate zsh completions"), + WithLongDescription("Generate zsh completions"), + WithOptions(outputFileOption), + WithParent(parent), + WithRunFunc(func(args []string) { + out := getCompletionsOut() + + if fc, ok := out.(io.Closer); ok { + defer fc.Close() + } + + if err := WriteZshCompletions(out, parent.Root()); err != nil { + panic(err) + } + }), + ) +} diff --git a/completions_bash.go b/completions_bash.go new file mode 100644 index 0000000..a790090 --- /dev/null +++ b/completions_bash.go @@ -0,0 +1,19 @@ +package cmd + +import ( + "io" + "text/template" + + "go.fifitido.net/cmd/opt" +) + +func WriteBashCompletions(out io.Writer, rootCmd *Command) error { + return bashTpl.Execute(out, map[string]any{ + "rootCmd": rootCmd, + "globalOpts": opt.Globals(), + }) +} + +var bashTpl = template.Must(template.New("bash").Parse(` + +`)) diff --git a/completions_fish.go b/completions_fish.go new file mode 100644 index 0000000..e2cb825 --- /dev/null +++ b/completions_fish.go @@ -0,0 +1,19 @@ +package cmd + +import ( + "io" + "text/template" + + "go.fifitido.net/cmd/opt" +) + +func WriteFishCompletions(out io.Writer, rootCmd *Command) error { + return fishTpl.Execute(out, map[string]any{ + "rootCmd": rootCmd, + "globalOpts": opt.Globals(), + }) +} + +var fishTpl = template.Must(template.New("fish").Parse(` + +`)) diff --git a/completions_powershell.go b/completions_powershell.go new file mode 100644 index 0000000..a0f271a --- /dev/null +++ b/completions_powershell.go @@ -0,0 +1,19 @@ +package cmd + +import ( + "io" + "text/template" + + "go.fifitido.net/cmd/opt" +) + +func WritePowerShellCompletions(out io.Writer, rootCmd *Command) error { + return powerShellTpl.Execute(out, map[string]any{ + "rootCmd": rootCmd, + "globalOpts": opt.Globals(), + }) +} + +var powerShellTpl = template.Must(template.New("PowerShell").Parse(` + +`)) diff --git a/completions_zsh.go b/completions_zsh.go new file mode 100644 index 0000000..885ec41 --- /dev/null +++ b/completions_zsh.go @@ -0,0 +1,19 @@ +package cmd + +import ( + "io" + "text/template" + + "go.fifitido.net/cmd/opt" +) + +func WriteZshCompletions(out io.Writer, rootCmd *Command) error { + return zshTpl.Execute(out, map[string]any{ + "rootCmd": rootCmd, + "globalOpts": opt.Globals(), + }) +} + +var zshTpl = template.Must(template.New("zsh").Parse(` + +`))