// This file is intended for use with "go run"; it isn't really part of the package. //go:build manpages package main import ( "fmt" "log" "os" "path/filepath" clidocstool "github.com/docker/cli-docs-tool" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/commands" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" "github.com/spf13/pflag" ) const defaultSourcePath = "man/src/" type options struct { source string target string } func gen(opts *options) error { log.SetFlags(0) dockerCLI, err := command.NewDockerCli() if err != nil { return err } cmd := &cobra.Command{ Use: "docker [OPTIONS] COMMAND [ARG...]", Short: "The base command for the Docker CLI.", } clientOpts, _ := cli.SetupRootCommand(cmd) if err := dockerCLI.Initialize(clientOpts); err != nil { return err } commands.AddCommands(cmd, dockerCLI) // TODO(thaJeztah): cli-docs-tool should already be able to do this, but assumes source-files are not in subdirectories (it looks for `src/docker_command_subcommand.md`) if err := loadLongDescription(cmd, opts.source); err != nil { return err } c, err := clidocstool.New(clidocstool.Options{ Root: cmd, SourceDir: opts.source, TargetDir: opts.target, ManHeader: &doc.GenManHeader{ Title: "DOCKER", Section: "1", Source: "Docker Community", Manual: "Docker User Manuals", }, Plugin: false, }) if err != nil { return err } fmt.Println("Manpage source folder:", opts.source) fmt.Println("Generating man pages into", opts.target) return c.GenManTree(cmd) } func loadLongDescription(parentCommand *cobra.Command, path string) error { for _, cmd := range parentCommand.Commands() { cmd.DisableFlagsInUseLine = true if cmd.Name() == "" { continue } fullpath := filepath.Join(path, cmd.Name()+".md") if cmd.HasSubCommands() { if err := loadLongDescription(cmd, filepath.Join(path, cmd.Name())); err != nil { return err } } if _, err := os.Stat(fullpath); err != nil { log.Printf("WARN: %s does not exist, skipping\n", fullpath) continue } log.Printf("INFO: %s found\n", fullpath) content, err := os.ReadFile(fullpath) if err != nil { return err } cmd.Long = string(content) fullpath = filepath.Join(path, cmd.Name()+"-example.md") if _, err := os.Stat(fullpath); err != nil { continue } content, err = os.ReadFile(fullpath) if err != nil { return err } cmd.Example = string(content) } return nil } func run() error { opts := &options{} flags := pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError) flags.StringVar(&opts.source, "source", defaultSourcePath, "Manpage source folder") flags.StringVar(&opts.target, "target", "/tmp", "Target path for generated man pages") if err := flags.Parse(os.Args[1:]); err != nil { return err } return gen(opts) } func main() { if err := run(); err != nil { log.Printf("ERROR: %+v", err) os.Exit(1) } }