mirror of
https://github.com/filecoin-project/lotus.git
synced 2025-08-24 01:08:42 +08:00
157 lines
4.0 KiB
Go
157 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
// DocGenerator handles CLI documentation generation
|
|
type DocGenerator struct {
|
|
app *cli.App
|
|
outputDir string
|
|
writer io.Writer
|
|
}
|
|
|
|
// NewDocGenerator creates a new documentation generator
|
|
func NewDocGenerator(outputDir string, app *cli.App) *DocGenerator {
|
|
return &DocGenerator{
|
|
outputDir: outputDir,
|
|
app: app,
|
|
}
|
|
}
|
|
|
|
// Generate generates documentation for the CLI app
|
|
func (g *DocGenerator) Generate(name string) error {
|
|
file, err := g.createMarkdownFile(name)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create markdown file: %w", err)
|
|
}
|
|
defer func() {
|
|
if err := file.Close(); err != nil {
|
|
fmt.Printf("failed to close markdown file: %v\n", err)
|
|
}
|
|
}()
|
|
|
|
return g.generateContent(file, name)
|
|
}
|
|
|
|
// createMarkdownFile creates a new markdown file for output.
|
|
func (g *DocGenerator) createMarkdownFile(name string) (*os.File, error) {
|
|
filePath := filepath.Join(g.outputDir, fmt.Sprintf("cli-%s.md", name))
|
|
return os.Create(filePath)
|
|
}
|
|
|
|
func (g *DocGenerator) generateContent(file *os.File, name string) error {
|
|
bufferedWriter := bufio.NewWriter(file)
|
|
g.writer = bufferedWriter
|
|
g.app.Writer = bufferedWriter
|
|
|
|
if err := g.generateDocs(name); err != nil {
|
|
return fmt.Errorf("failed to generate documentation: %w", err)
|
|
}
|
|
|
|
return bufferedWriter.Flush()
|
|
}
|
|
|
|
// generateDocs orchestrates the documentation generation process
|
|
func (g *DocGenerator) generateDocs(name string) error {
|
|
if err := g.writeAppHeader(); err != nil {
|
|
return fmt.Errorf("failed to write app header: %w", err)
|
|
}
|
|
|
|
return g.writeCommandDocs(g.app.Commands, name, 0)
|
|
}
|
|
|
|
// writeAppHeader writes the application header documentation
|
|
func (g *DocGenerator) writeAppHeader() error {
|
|
if _, err := g.writer.Write([]byte(fmt.Sprintf("# %s\n\n```\n", g.app.Name))); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := g.app.Run(getHelpArgs("", "")); err != nil {
|
|
return fmt.Errorf("failed to write command docs: %w", err)
|
|
}
|
|
|
|
if _, err := g.writer.Write([]byte("```\n")); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (g *DocGenerator) writeCommandDocs(commands cli.Commands, rootName string, depth int) error {
|
|
uncategorizedCmds, categorizedCmds := separateCommands(commands)
|
|
|
|
// Write uncategorized commands first
|
|
if err := g.writeCommands(uncategorizedCmds, rootName, depth); err != nil {
|
|
return fmt.Errorf("failed to write uncategorized commands: %w", err)
|
|
}
|
|
|
|
// Write categorized commands next
|
|
if err := g.writeCommands(categorizedCmds, rootName, depth); err != nil {
|
|
return fmt.Errorf("failed to write categorized commands: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// separateCommands separates commands into uncategorized and categorized
|
|
func separateCommands(commands []*cli.Command) (uncategorized cli.Commands, categorized cli.Commands) {
|
|
for _, cmd := range commands {
|
|
if cmd.Category == "" {
|
|
uncategorized = append(uncategorized, cmd)
|
|
} else {
|
|
categorized = append(categorized, cmd)
|
|
}
|
|
}
|
|
|
|
return uncategorized, categorized
|
|
}
|
|
|
|
// writeCommands writes documentation for all commands recursively
|
|
func (g *DocGenerator) writeCommands(commands cli.Commands, rootName string, depth int) error {
|
|
for _, cmd := range commands {
|
|
if cmd.Name == "help" || cmd.Hidden {
|
|
continue
|
|
}
|
|
|
|
cmdName := fmt.Sprintf("%s %s", rootName, cmd.Name)
|
|
|
|
if _, err := g.writer.Write([]byte(fmt.Sprintf("\n%s %s\n\n```\n", strings.Repeat("#", depth+2), cmdName))); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := g.app.Run(getHelpArgs(rootName, cmd.Name)); err != nil {
|
|
return fmt.Errorf("failed to write command docs: %w", err)
|
|
}
|
|
|
|
if _, err := g.writer.Write([]byte("```\n")); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(cmd.Subcommands) > 0 {
|
|
if err := g.writeCommands(cmd.Subcommands, rootName+" "+cmd.Name, depth+1); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getHelpArgs(rootName string, cmdName string) []string {
|
|
if rootName == "" && cmdName == "" {
|
|
return []string{"-h"}
|
|
}
|
|
|
|
args := strings.Split(rootName, " ")
|
|
args = append(args, cmdName)
|
|
args = append(args, "-h")
|
|
return args
|
|
}
|