1
0
mirror of https://github.com/docker/cli.git synced 2025-04-18 19:24:03 +03:00
cli/man/generate.go
Sebastiaan van Stijn 80bca8eb1d
man: rewrite to use cli-docs-tool manpage generator
It's a wrapper around Cobra's generator, but handles some special
cases. While rewriting, also rewrite the generator code to align
with the mddocs/yamldocs counterpart in docs/generate/

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-25 17:07:40 +01:00

128 lines
2.9 KiB
Go

// 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)
}
}