github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/gnovm/cmd/gno/doc.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"flag"
     7  	"fmt"
     8  	"io/fs"
     9  	"os"
    10  	"path/filepath"
    11  
    12  	"github.com/gnolang/gno/gnovm/pkg/doc"
    13  	"github.com/gnolang/gno/gnovm/pkg/gnoenv"
    14  	"github.com/gnolang/gno/gnovm/pkg/gnomod"
    15  	"github.com/gnolang/gno/tm2/pkg/commands"
    16  )
    17  
    18  type docCfg struct {
    19  	all        bool
    20  	src        bool
    21  	unexported bool
    22  	short      bool
    23  	rootDir    string
    24  }
    25  
    26  func newDocCmd(io commands.IO) *commands.Command {
    27  	c := &docCfg{}
    28  	return commands.NewCommand(
    29  		commands.Metadata{
    30  			Name:       "doc",
    31  			ShortUsage: "doc [flags] <pkgsym>",
    32  			ShortHelp:  "get documentation for the specified package or symbol (type, function, method, or variable/constant)",
    33  		},
    34  		c,
    35  		func(_ context.Context, args []string) error {
    36  			return execDoc(c, args, io)
    37  		},
    38  	)
    39  }
    40  
    41  func (c *docCfg) RegisterFlags(fs *flag.FlagSet) {
    42  	fs.BoolVar(
    43  		&c.all,
    44  		"all",
    45  		false,
    46  		"show documentation for all symbols in package",
    47  	)
    48  
    49  	fs.BoolVar(
    50  		&c.src,
    51  		"src",
    52  		false,
    53  		"show source code for symbols",
    54  	)
    55  
    56  	fs.BoolVar(
    57  		&c.unexported,
    58  		"u",
    59  		false,
    60  		"show unexported symbols as well as exported",
    61  	)
    62  
    63  	fs.BoolVar(
    64  		&c.short,
    65  		"short",
    66  		false,
    67  		"show a one line representation for each symbol",
    68  	)
    69  
    70  	fs.StringVar(
    71  		&c.rootDir,
    72  		"root-dir",
    73  		"",
    74  		"clone location of github.com/gnolang/gno (gno binary tries to guess it)",
    75  	)
    76  }
    77  
    78  func execDoc(cfg *docCfg, args []string, io commands.IO) error {
    79  	// guess opts.RootDir
    80  	if cfg.rootDir == "" {
    81  		cfg.rootDir = gnoenv.RootDir()
    82  	}
    83  
    84  	wd, err := os.Getwd()
    85  	if err != nil {
    86  		return fmt.Errorf("could not determine working directory: %w", err)
    87  	}
    88  
    89  	var modDirs []string
    90  
    91  	rd, err := gnomod.FindRootDir(wd)
    92  	if err != nil && !errors.Is(err, gnomod.ErrGnoModNotFound) {
    93  		return fmt.Errorf("error determining root gno.mod file: %w", err)
    94  	}
    95  	if !errors.Is(err, gnomod.ErrGnoModNotFound) {
    96  		modDirs = append(modDirs, rd)
    97  	}
    98  
    99  	examplesModules, err := findGnomodExamples(filepath.Join(cfg.rootDir, "examples"))
   100  	if err != nil {
   101  		io.Printfln("warning: error scanning examples directory for modules: %v", err)
   102  	} else {
   103  		modDirs = append(modDirs, examplesModules...)
   104  	}
   105  
   106  	// select dirs from which to gather directories
   107  	dirs := []string{filepath.Join(cfg.rootDir, "gnovm/stdlibs")}
   108  	res, err := doc.ResolveDocumentable(dirs, modDirs, args, cfg.unexported)
   109  	if res == nil {
   110  		return err
   111  	}
   112  	if err != nil {
   113  		io.Printfln("warning: error parsing some candidate packages:\n%v", err)
   114  	}
   115  	return res.WriteDocumentation(
   116  		io.Out(),
   117  		&doc.WriteDocumentationOptions{
   118  			ShowAll:    cfg.all,
   119  			Source:     cfg.src,
   120  			Unexported: cfg.unexported,
   121  			Short:      false,
   122  		},
   123  	)
   124  }
   125  
   126  func findGnomodExamples(dir string) ([]string, error) {
   127  	dirs := make([]string, 0, 64) // "hint" about the size
   128  	err := filepath.WalkDir(dir, func(path string, e fs.DirEntry, err error) error {
   129  		if err != nil {
   130  			return err
   131  		}
   132  		if !e.IsDir() && e.Name() == "gno.mod" {
   133  			dirs = append(dirs, filepath.Dir(path))
   134  		}
   135  		return nil
   136  	})
   137  	return dirs, err
   138  }