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 }