5d6b8141ec
As of Go 1.16, the same functionality is now provided by package io or package os, and those implementations should be preferred in new code.
155 lines
3.9 KiB
Go
155 lines
3.9 KiB
Go
// Package gendocs provides the gendocs command.
|
|
package gendocs
|
|
|
|
import (
|
|
"bytes"
|
|
"log"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
"text/template"
|
|
"time"
|
|
|
|
"github.com/rclone/rclone/cmd"
|
|
"github.com/rclone/rclone/lib/file"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/cobra/doc"
|
|
"github.com/spf13/pflag"
|
|
)
|
|
|
|
func init() {
|
|
cmd.Root.AddCommand(commandDefinition)
|
|
}
|
|
|
|
// define things which go into the frontmatter
|
|
type frontmatter struct {
|
|
Date string
|
|
Title string
|
|
Description string
|
|
Slug string
|
|
URL string
|
|
Source string
|
|
}
|
|
|
|
var frontmatterTemplate = template.Must(template.New("frontmatter").Parse(`---
|
|
title: "{{ .Title }}"
|
|
description: "{{ .Description }}"
|
|
slug: {{ .Slug }}
|
|
url: {{ .URL }}
|
|
# autogenerated - DO NOT EDIT, instead edit the source code in {{ .Source }} and as part of making a release run "make commanddocs"
|
|
---
|
|
`))
|
|
|
|
var commandDefinition = &cobra.Command{
|
|
Use: "gendocs output_directory",
|
|
Short: `Output markdown docs for rclone to the directory supplied.`,
|
|
Long: `
|
|
This produces markdown docs for the rclone commands to the directory
|
|
supplied. These are in a format suitable for hugo to render into the
|
|
rclone.org website.`,
|
|
RunE: func(command *cobra.Command, args []string) error {
|
|
cmd.CheckArgs(1, 1, command, args)
|
|
now := time.Now().Format(time.RFC3339)
|
|
|
|
// Create the directory structure
|
|
root := args[0]
|
|
out := filepath.Join(root, "commands")
|
|
err := file.MkdirAll(out, 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Write the flags page
|
|
var buf bytes.Buffer
|
|
cmd.Root.SetOutput(&buf)
|
|
cmd.Root.SetArgs([]string{"help", "flags"})
|
|
cmd.GeneratingDocs = true
|
|
err = cmd.Root.Execute()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = os.WriteFile(filepath.Join(root, "flags.md"), buf.Bytes(), 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Look up name => description for prepender
|
|
var description = map[string]string{}
|
|
var addDescription func(root *cobra.Command)
|
|
addDescription = func(root *cobra.Command) {
|
|
name := strings.ReplaceAll(root.CommandPath(), " ", "_") + ".md"
|
|
description[name] = root.Short
|
|
for _, c := range root.Commands() {
|
|
addDescription(c)
|
|
}
|
|
}
|
|
addDescription(cmd.Root)
|
|
|
|
// markup for the docs files
|
|
prepender := func(filename string) string {
|
|
name := filepath.Base(filename)
|
|
base := strings.TrimSuffix(name, path.Ext(name))
|
|
data := frontmatter{
|
|
Date: now,
|
|
Title: strings.ReplaceAll(base, "_", " "),
|
|
Description: description[name],
|
|
Slug: base,
|
|
URL: "/commands/" + strings.ToLower(base) + "/",
|
|
Source: strings.ReplaceAll(strings.ReplaceAll(base, "rclone", "cmd"), "_", "/") + "/",
|
|
}
|
|
var buf bytes.Buffer
|
|
err := frontmatterTemplate.Execute(&buf, data)
|
|
if err != nil {
|
|
log.Fatalf("Failed to render frontmatter template: %v", err)
|
|
}
|
|
return buf.String()
|
|
}
|
|
linkHandler := func(name string) string {
|
|
base := strings.TrimSuffix(name, path.Ext(name))
|
|
return "/commands/" + strings.ToLower(base) + "/"
|
|
}
|
|
|
|
// Hide all of the root entries flags
|
|
cmd.Root.Flags().VisitAll(func(flag *pflag.Flag) {
|
|
flag.Hidden = true
|
|
})
|
|
err = doc.GenMarkdownTreeCustom(cmd.Root, out, prepender, linkHandler)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var outdentTitle = regexp.MustCompile(`(?m)^#(#+)`)
|
|
|
|
// Munge the files to add a link to the global flags page
|
|
err = filepath.Walk(out, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !info.IsDir() {
|
|
b, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
doc := string(b)
|
|
doc = strings.Replace(doc, "\n### SEE ALSO", `
|
|
See the [global flags page](/flags/) for global options not listed here.
|
|
|
|
### SEE ALSO`, 1)
|
|
// outdent all the titles by one
|
|
doc = outdentTitle.ReplaceAllString(doc, `$1`)
|
|
err = os.WriteFile(path, []byte(doc), 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|