cmd/doc: added support for text format

Signed-off-by: Sam Alba <sam.alba@gmail.com>
This commit is contained in:
Sam Alba 2021-06-03 12:15:36 +02:00
parent 8c3c934f3c
commit 92d993f434

View File

@ -4,8 +4,10 @@ import (
"context" "context"
"fmt" "fmt"
"io/fs" "io/fs"
"os"
"regexp" "regexp"
"strings" "strings"
"text/tabwriter"
"unicode/utf8" "unicode/utf8"
"cuelang.org/go/cue" "cuelang.org/go/cue"
@ -13,22 +15,24 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"go.dagger.io/dagger/cmd/dagger/cmd/common"
"go.dagger.io/dagger/cmd/dagger/logger" "go.dagger.io/dagger/cmd/dagger/logger"
"go.dagger.io/dagger/compiler" "go.dagger.io/dagger/compiler"
"go.dagger.io/dagger/environment" "go.dagger.io/dagger/environment"
"go.dagger.io/dagger/stdlib" "go.dagger.io/dagger/stdlib"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/term"
) )
const ( const (
textFormat = "txt" textFormat = "txt"
markdownFormat = "md" markdownFormat = "md"
textPadding = " "
) )
var docCmd = &cobra.Command{ var docCmd = &cobra.Command{
Use: "doc [PACKAGE | PATH]", Use: "doc [PACKAGE | PATH]",
Short: "document a package", Short: "document a package",
Args: cobra.MaximumNArgs(1), Args: cobra.ExactArgs(1),
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
// Fix Viper bug for duplicate flags: // Fix Viper bug for duplicate flags:
// https://github.com/spf13/viper/issues/233 // https://github.com/spf13/viper/issues/233
@ -63,28 +67,6 @@ func init() {
} }
} }
func extractComment(v cue.Value) string {
docs := []string{}
for _, c := range v.Doc() {
docs = append(docs, strings.TrimSpace(c.Text()))
}
doc := strings.Join(docs, " ")
lines := strings.Split(doc, "\n")
// Strip out FIXME, TODO, and INTERNAL comments
docs = []string{}
for _, line := range lines {
if strings.HasPrefix(line, "FIXME: ") ||
strings.HasPrefix(line, "TODO: ") ||
strings.HasPrefix(line, "INTERNAL: ") {
continue
}
docs = append(docs, line)
}
return strings.Join(docs, " ")
}
func extractSpec(v cue.Value) string { func extractSpec(v cue.Value) string {
node := v.Source() node := v.Source()
if node == nil { if node == nil {
@ -110,7 +92,7 @@ func mdEscape(s string) string {
func terminalTrim(msg string) string { func terminalTrim(msg string) string {
// If we're not running on a terminal, return the whole string // If we're not running on a terminal, return the whole string
size, _, err := terminal.GetSize(1) size, _, err := term.GetSize(1)
if err != nil { if err != nil {
return msg return msg
} }
@ -123,6 +105,11 @@ func terminalTrim(msg string) string {
return msg return msg
} }
func formatLabel(name string, val *compiler.Value) string {
label := val.Path().String()
return strings.TrimPrefix(label, name+".")
}
func loadCode(packageName string) (*compiler.Value, error) { func loadCode(packageName string) (*compiler.Value, error) {
sources := map[string]fs.FS{ sources := map[string]fs.FS{
stdlib.Path: stdlib.FS, stdlib.Path: stdlib.FS,
@ -144,10 +131,15 @@ func PrintDoc(ctx context.Context, packageName string, val *compiler.Value, form
lg.Fatal().Err(err).Msg("cannot get fields") lg.Fatal().Err(err).Msg("cannot get fields")
} }
comment := common.ValueDocString(val)
// Print title // Print title
switch format { switch format {
case textFormat: case textFormat:
fmt.Printf("Package:\t%s\n", packageName) fmt.Printf("Package %s\n", packageName)
if comment != "" {
fmt.Printf("\n%s\n", comment)
}
case markdownFormat: case markdownFormat:
importPath := strings.Split(packageName, "/") importPath := strings.Split(packageName, "/")
switch { switch {
@ -158,6 +150,9 @@ func PrintDoc(ctx context.Context, packageName string, val *compiler.Value, form
default: default:
fmt.Printf("## %s\n", packageName) fmt.Printf("## %s\n", packageName)
} }
if comment != "" {
fmt.Printf("\n%s\n", comment)
}
} }
for _, field := range fields { for _, field := range fields {
@ -171,22 +166,58 @@ func PrintDoc(ctx context.Context, packageName string, val *compiler.Value, form
continue continue
} }
// Package name + comment
comment := common.ValueDocString(v)
switch format { switch format {
case textFormat: case textFormat:
comment := extractComment(v.Cue()) fmt.Printf("\n%s\n\n%s%s\n", name, textPadding, comment)
if comment != "" {
comment = fmt.Sprintf(": %s", comment)
}
fmt.Printf("\n=> %s%s\n", name, comment)
case markdownFormat: case markdownFormat:
comment := extractComment(v.Cue())
if comment != "" { if comment != "" {
comment = fmt.Sprintf("\n\n%s", comment) comment = fmt.Sprintf("\n\n%s", comment)
} }
fmt.Printf("\n#### %s%s\n\n", name, mdEscape(comment)) fmt.Printf("\n#### %s%s\n\n", name, mdEscape(comment))
fmt.Printf("##### Fields\n\n") fmt.Printf("##### Fields\n\n")
} }
// Package inputs
inp := environment.ScanInputs(ctx, v)
switch format {
case textFormat:
if len(inp) == 0 {
fmt.Printf("\n%sInputs: none\n", textPadding)
break
}
w := tabwriter.NewWriter(os.Stdout, 0, 4, len(textPadding), ' ', 0)
fmt.Printf("\n%sInputs:\n", textPadding)
for _, i := range inp {
docStr := terminalTrim(common.ValueDocString(i))
fmt.Fprintf(w, "\t\t%s\t%s\t%s\n",
formatLabel(name, i), common.FormatValue(i), docStr)
}
w.Flush()
case markdownFormat:
// todo
}
// Package outputs
out := environment.ScanOutputs(ctx, v)
switch format {
case textFormat:
if len(out) == 0 {
fmt.Printf("\n%sOutputs: none\n", textPadding)
break
}
w := tabwriter.NewWriter(os.Stdout, 0, 4, len(textPadding), ' ', 0)
fmt.Printf("\n%sOutputs:\n", textPadding)
for _, o := range out {
docStr := terminalTrim(common.ValueDocString(o))
fmt.Fprintf(w, "\t\t%s\t%s\t%s\n",
formatLabel(name, o), common.FormatValue(o), docStr)
}
w.Flush()
case markdownFormat:
// todo
}
} }
environment.ScanOutputs(ctx, val)
} }