mirror of
https://github.com/regclient/regclient.git
synced 2025-04-18 22:44:00 +03:00
Feat: Add cobra command for documentation
This will be used for generating website content. Signed-off-by: Brandon Mitchell <git@bmitch.net>
This commit is contained in:
parent
16973da2a2
commit
bbb902ba69
@ -14,6 +14,7 @@ import (
|
||||
"github.com/regclient/regclient"
|
||||
"github.com/regclient/regclient/cmd/regbot/sandbox"
|
||||
"github.com/regclient/regclient/config"
|
||||
"github.com/regclient/regclient/internal/cobradoc"
|
||||
"github.com/regclient/regclient/internal/pqueue"
|
||||
"github.com/regclient/regclient/internal/version"
|
||||
"github.com/regclient/regclient/pkg/template"
|
||||
@ -23,7 +24,7 @@ import (
|
||||
|
||||
const (
|
||||
usageDesc = `Utility for automating repository actions
|
||||
More details at https://github.com/regclient/regclient`
|
||||
More details at <https://github.com/regclient/regclient>`
|
||||
// UserAgent sets the header on http requests
|
||||
UserAgent = "regclient/regbot"
|
||||
)
|
||||
@ -88,6 +89,7 @@ returns after the last script completes.`,
|
||||
rootTopCmd.AddCommand(serverCmd)
|
||||
rootTopCmd.AddCommand(onceCmd)
|
||||
rootTopCmd.AddCommand(versionCmd)
|
||||
rootTopCmd.AddCommand(cobradoc.NewCmd(rootTopCmd.Name(), "cli-doc"))
|
||||
|
||||
rootTopCmd.PersistentPreRunE = rootOpts.rootPreRun
|
||||
return rootTopCmd, &rootOpts
|
||||
|
@ -2,8 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@ -12,69 +10,6 @@ import (
|
||||
"github.com/regclient/regclient/types/ref"
|
||||
)
|
||||
|
||||
func NewCompletionCmd(rootOpts *rootCmd) *cobra.Command {
|
||||
var completionTopCmd = &cobra.Command{
|
||||
Use: "completion [bash|zsh|fish|powershell]",
|
||||
Short: "Generate completion script",
|
||||
Long: fmt.Sprintf(`To load completions:
|
||||
|
||||
Bash:
|
||||
|
||||
$ source <(%[1]s completion bash)
|
||||
|
||||
# To load completions for each session, execute once:
|
||||
# Linux:
|
||||
$ %[1]s completion bash > /etc/bash_completion.d/%[1]s
|
||||
# macOS:
|
||||
$ %[1]s completion bash > $(brew --prefix)/etc/bash_completion.d/%[1]s
|
||||
|
||||
Zsh:
|
||||
|
||||
# If shell completion is not already enabled in your environment,
|
||||
# you will need to enable it. You can execute the following once:
|
||||
|
||||
$ echo "autoload -U compinit; compinit" >> ~/.zshrc
|
||||
|
||||
# To load completions for each session, execute once:
|
||||
$ %[1]s completion zsh > "${fpath[1]}/_%[1]s"
|
||||
|
||||
# You will need to start a new shell for this setup to take effect.
|
||||
|
||||
fish:
|
||||
|
||||
$ %[1]s completion fish | source
|
||||
|
||||
# To load completions for each session, execute once:
|
||||
$ %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish
|
||||
|
||||
PowerShell:
|
||||
|
||||
PS> %[1]s completion powershell | Out-String | Invoke-Expression
|
||||
|
||||
# To load completions for every new session, run:
|
||||
PS> %[1]s completion powershell > %[1]s.ps1
|
||||
# and source this file from your PowerShell profile.
|
||||
`, rootOpts.name),
|
||||
DisableFlagsInUseLine: true,
|
||||
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
|
||||
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
switch args[0] {
|
||||
case "bash":
|
||||
_ = cmd.Root().GenBashCompletionV2(os.Stdout, true)
|
||||
case "zsh":
|
||||
_ = cmd.Root().GenZshCompletion(os.Stdout)
|
||||
case "fish":
|
||||
_ = cmd.Root().GenFishCompletion(os.Stdout, true)
|
||||
case "powershell":
|
||||
_ = cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return completionTopCmd
|
||||
}
|
||||
|
||||
type completeFunc func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)
|
||||
|
||||
// completeArgList takes a list of completion functions and completes each arg separately
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/regclient/regclient"
|
||||
"github.com/regclient/regclient/config"
|
||||
"github.com/regclient/regclient/internal/cobradoc"
|
||||
"github.com/regclient/regclient/internal/strparse"
|
||||
"github.com/regclient/regclient/internal/version"
|
||||
"github.com/regclient/regclient/pkg/template"
|
||||
@ -39,7 +40,7 @@ func NewRootCmd() (*cobra.Command, *rootCmd) {
|
||||
Use: "regctl <cmd>",
|
||||
Short: "Utility for accessing docker registries",
|
||||
Long: `Utility for accessing docker registries
|
||||
More details at https://github.com/regclient/regclient`,
|
||||
More details at <https://github.com/regclient/regclient>`,
|
||||
Example: `
|
||||
# login to ghcr.io
|
||||
regctl registry login ghcr.io
|
||||
@ -94,10 +95,10 @@ regctl version --format '{{.VCSTag}}'`,
|
||||
|
||||
rootTopCmd.PersistentPreRunE = rootOpts.rootPreRun
|
||||
rootTopCmd.AddCommand(versionCmd)
|
||||
rootTopCmd.AddCommand(cobradoc.NewCmd(rootOpts.name, "cli-doc"))
|
||||
rootTopCmd.AddCommand(
|
||||
NewArtifactCmd(&rootOpts),
|
||||
NewBlobCmd(&rootOpts),
|
||||
NewCompletionCmd(&rootOpts),
|
||||
NewConfigCmd(&rootOpts),
|
||||
NewDigestCmd(&rootOpts),
|
||||
NewImageCmd(&rootOpts),
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
|
||||
"github.com/regclient/regclient"
|
||||
"github.com/regclient/regclient/config"
|
||||
"github.com/regclient/regclient/internal/cobradoc"
|
||||
"github.com/regclient/regclient/internal/pqueue"
|
||||
"github.com/regclient/regclient/internal/version"
|
||||
"github.com/regclient/regclient/pkg/template"
|
||||
@ -68,7 +69,7 @@ func NewRootCmd() (*cobra.Command, *rootCmd) {
|
||||
Use: "regsync <cmd>",
|
||||
Short: "Utility for mirroring docker repositories",
|
||||
Long: `Utility for mirroring docker repositories
|
||||
More details at https://github.com/regclient/regclient`,
|
||||
More details at <https://github.com/regclient/regclient>`,
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: true,
|
||||
}
|
||||
@ -135,6 +136,7 @@ sync step is finished.`,
|
||||
rootTopCmd.AddCommand(onceCmd)
|
||||
rootTopCmd.AddCommand(configCmd)
|
||||
rootTopCmd.AddCommand(versionCmd)
|
||||
rootTopCmd.AddCommand(cobradoc.NewCmd(rootTopCmd.Name(), "cli-doc"))
|
||||
|
||||
rootTopCmd.PersistentPreRunE = rootOpts.rootPreRun
|
||||
return rootTopCmd, &rootOpts
|
||||
|
@ -59,6 +59,8 @@ The following functions have been added in addition to the defaults available in
|
||||
Returns current time object, e.g. `{{ $t := time.Now }}{{printf "%d%d%d" $t.Year $t.Month $t.Day}}`.
|
||||
- `time.Parse`:
|
||||
Parses string using layout into time object, e.g. `{{ $t := time.Parse "2006-01-02" "2020-06-07"}}`.
|
||||
- `trimSpace`:
|
||||
Trim whitespace from the start and end of a string.
|
||||
- `upper`:
|
||||
Converts a string to uppercase.
|
||||
|
||||
|
120
internal/cobradoc/cobradoc.go
Normal file
120
internal/cobradoc/cobradoc.go
Normal file
@ -0,0 +1,120 @@
|
||||
// Package cobradoc is used to generate documentation from cobra commands.
|
||||
package cobradoc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/regclient/regclient/pkg/template"
|
||||
)
|
||||
|
||||
// List outputs a list of cobra commands.
|
||||
func List(cmd *cobra.Command, hidden bool, out io.Writer) {
|
||||
var recurse func(cmd *cobra.Command, out io.Writer)
|
||||
recurse = func(cmd *cobra.Command, out io.Writer) {
|
||||
fmt.Fprintf(out, "%s\n", cmd.CommandPath())
|
||||
for _, child := range cmd.Commands() {
|
||||
if !hidden && child.Hidden {
|
||||
continue
|
||||
}
|
||||
recurse(child, out)
|
||||
}
|
||||
}
|
||||
recurse(cmd, out)
|
||||
}
|
||||
|
||||
// Markdown outputs docs on a cobra command in Markdown format.
|
||||
func Markdown(cmd *cobra.Command, out io.Writer) error {
|
||||
cmd.InitDefaultHelpCmd()
|
||||
cmd.InitDefaultHelpFlag()
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
name := cmd.CommandPath()
|
||||
|
||||
buf.WriteString("## " + name + "\n\n")
|
||||
buf.WriteString(cmd.Short + "\n\n")
|
||||
if len(cmd.Long) > 0 {
|
||||
buf.WriteString("### Synopsis\n\n")
|
||||
buf.WriteString(strings.TrimSpace(cmd.Long) + "\n\n")
|
||||
}
|
||||
if cmd.Runnable() {
|
||||
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine()))
|
||||
}
|
||||
if len(cmd.Example) > 0 {
|
||||
buf.WriteString("### Examples\n\n")
|
||||
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", strings.TrimSpace(cmd.Example)))
|
||||
}
|
||||
if err := printOptions(buf, cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := buf.WriteTo(out)
|
||||
return err
|
||||
}
|
||||
|
||||
func printOptions(buf *bytes.Buffer, cmd *cobra.Command) error {
|
||||
flags := cmd.NonInheritedFlags()
|
||||
flags.SetOutput(buf)
|
||||
if flags.HasAvailableFlags() {
|
||||
buf.WriteString("### Options\n\n```\n")
|
||||
flags.PrintDefaults()
|
||||
buf.WriteString("```\n\n")
|
||||
}
|
||||
|
||||
parentFlags := cmd.InheritedFlags()
|
||||
parentFlags.SetOutput(buf)
|
||||
if parentFlags.HasAvailableFlags() {
|
||||
buf.WriteString("### Options inherited from parent commands\n\n```\n")
|
||||
parentFlags.PrintDefaults()
|
||||
buf.WriteString("```\n\n")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type docOpts struct {
|
||||
format string
|
||||
hidden bool
|
||||
list bool
|
||||
}
|
||||
|
||||
// NewCmd generates a new cobra command for generating docs.
|
||||
func NewCmd(rootName, newName string) *cobra.Command {
|
||||
opts := docOpts{}
|
||||
var docCmd = &cobra.Command{
|
||||
Hidden: true,
|
||||
Use: newName,
|
||||
Short: "Document CLI",
|
||||
Long: `Document Cobra CLI`,
|
||||
Example: fmt.Sprintf(`
|
||||
# list all commands
|
||||
%[1]s %[2]s --list
|
||||
|
||||
# output documentation for the "version" command
|
||||
%[1]s %[2]s version`, rootName, newName),
|
||||
Args: cobra.ArbitraryArgs,
|
||||
RunE: opts.runCLIDoc,
|
||||
}
|
||||
docCmd.Flags().BoolVar(&opts.hidden, "hidden", false, "Include hidden commands in the list")
|
||||
docCmd.Flags().BoolVar(&opts.list, "list", false, "List all commands")
|
||||
docCmd.Flags().StringVar(&opts.format, "format", "", "Format output with go template syntax")
|
||||
|
||||
return docCmd
|
||||
}
|
||||
|
||||
func (opts *docOpts) runCLIDoc(cmd *cobra.Command, args []string) error {
|
||||
if opts.list {
|
||||
List(cmd.Parent(), opts.hidden, cmd.OutOrStdout())
|
||||
return nil
|
||||
}
|
||||
docCmd, _, err := cmd.Parent().Find(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if opts.format != "" {
|
||||
return template.Writer(cmd.OutOrStdout(), opts.format, docCmd)
|
||||
}
|
||||
return Markdown(docCmd, cmd.OutOrStdout())
|
||||
}
|
@ -49,6 +49,7 @@ var tmplFuncs = gotemplate.FuncMap{
|
||||
"lower": strings.ToLower,
|
||||
"split": strings.Split,
|
||||
"time": func() *TimeFuncs { return &TimeFuncs{} },
|
||||
"trimSpace": strings.TrimSpace,
|
||||
"upper": strings.ToUpper,
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user