Files
coder/scripts/clidocgen/gen.go
T
Spike Curtis bddb808b25 chore: arrange imports in a standard way (#21452)
Fixes all our Go file imports to match the preferred spec that we've _mostly_ been using. For example:

```
import (
	"context"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"golang.org/x/xerrors"
	"gopkg.in/natefinch/lumberjack.v2"

	"cdr.dev/slog/v3"
	"github.com/coder/coder/v2/codersdk/agentsdk"
	"github.com/coder/serpent"
)
```

3 groups: standard library, 3rd partly libs, Coder libs.

This PR makes the change across the codebase. The PR in the stack above modifies our formatting to maintain this state of affairs, and is a separate PR so it's possible to review that one in detail.
2026-01-08 15:24:11 +04:00

156 lines
3.3 KiB
Go

package main
import (
_ "embed"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/acarl005/stripansi"
"github.com/coder/coder/v2/buildinfo"
"github.com/coder/flog"
"github.com/coder/serpent"
)
//go:embed command.tpl
var commandTemplateRaw string
var commandTemplate *template.Template
func init() {
commandTemplate = template.Must(
template.New("command.tpl").Funcs(template.FuncMap{
"visibleSubcommands": func(cmd *serpent.Command) []*serpent.Command {
var visible []*serpent.Command
for _, sub := range cmd.Children {
if sub.Hidden {
continue
}
visible = append(visible, sub)
}
return visible
},
"visibleOptions": func(cmd *serpent.Command) []serpent.Option {
var visible []serpent.Option
for _, opt := range cmd.Options {
if opt.Hidden {
continue
}
visible = append(visible, opt)
}
return visible
},
"atRoot": func(cmd *serpent.Command) bool {
return cmd.FullName() == "coder"
},
"newLinesToBr": func(s string) string {
return strings.ReplaceAll(s, "\n", "<br/>")
},
"wrapCode": func(s string) string {
return fmt.Sprintf("<code>%s</code>", s)
},
"commandURI": fmtDocFilename,
"fullName": fullName,
"tableHeader": func() string {
return `| | |
| --- | --- |`
},
"typeHelper": func(opt *serpent.Option) string {
switch v := opt.Value.(type) {
case *serpent.Enum:
return strings.Join(v.Choices, "\\|")
case *serpent.EnumArray:
return fmt.Sprintf("[%s]", strings.Join(v.Choices, "\\|"))
default:
return v.Type()
}
},
},
).Parse(strings.TrimSpace(commandTemplateRaw)),
)
}
func fullName(cmd *serpent.Command) string {
if cmd.FullName() == "coder" {
return "coder"
}
return strings.TrimPrefix(cmd.FullName(), "coder ")
}
func fmtDocFilename(cmd *serpent.Command) string {
if cmd.FullName() == "coder" {
// Special case for index.
return "./index.md"
}
name := strings.ReplaceAll(fullName(cmd), " ", "_")
return fmt.Sprintf("%s.md", name)
}
func writeCommand(w io.Writer, cmd *serpent.Command) error {
var b strings.Builder
err := commandTemplate.Execute(&b, cmd)
if err != nil {
return err
}
content := stripansi.Strip(b.String())
// Remove the version and its right space, since during this script running
// there is no build info available
content = strings.ReplaceAll(content, buildinfo.Version()+" ", "")
// Remove references to the current working directory
cwd, err := os.Getwd()
if err != nil {
return err
}
content = strings.ReplaceAll(content, cwd, ".")
homedir, err := os.UserHomeDir()
if err != nil {
return err
}
content = strings.ReplaceAll(content, homedir, "~")
_, err = w.Write([]byte(content))
return err
}
func genTree(dir string, cmd *serpent.Command, wroteLog map[string]*serpent.Command) error {
if cmd.Hidden {
return nil
}
path := filepath.Join(dir, fmtDocFilename(cmd))
// Write out root.
fi, err := os.OpenFile(
path,
os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o644,
)
if err != nil {
return err
}
defer fi.Close()
err = writeCommand(fi, cmd)
if err != nil {
return err
}
flog.Successf(
"wrote\t%s",
fi.Name(),
)
wroteLog[path] = cmd
for _, sub := range cmd.Children {
err = genTree(dir, sub, wroteLog)
if err != nil {
return err
}
}
return nil
}