github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/doc/doc.go (about) 1 package doc 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "sort" 10 "strings" 11 "time" 12 13 "github.com/spf13/cobra" 14 ) 15 16 // GenMarkdownTreeCustom is the the same as GenMarkdownTree, but 17 // with custom filePrepender and linkHandler. 18 func GenMarkdownTreeCustom(c *cobra.Command, dir string, name string, path string, filePrepender func(string) string, 19 linkHandler func(*cobra.Command, string) string) (err error) { 20 for _, child := range c.Commands() { 21 if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { 22 continue 23 } 24 if err = GenMarkdownTreeCustom(child, dir, name, path, filePrepender, linkHandler); err != nil { 25 return err 26 } 27 } 28 29 basename := strings.Replace(c.CommandPath(), " ", "_", -1) + ".md" 30 filename := filepath.Join(dir, basename) 31 if strings.Contains(filename, name+".md") { 32 filename = filepath.Join(path, "README.md") 33 } 34 35 var f *os.File 36 f, err = os.Create(filepath.Clean(filename)) 37 if err != nil { 38 return err 39 } 40 defer func() { 41 err1 := f.Close() 42 if err == nil { 43 err = err1 44 } 45 }() 46 if _, err = io.WriteString(f, filePrepender(filename)); err != nil { 47 return err 48 } 49 if err = GenMarkdownCustom(c, f, linkHandler); err != nil { 50 return err 51 } 52 return err 53 } 54 55 // GenMarkdownCustom creates custom markdown output. 56 func GenMarkdownCustom(c *cobra.Command, w io.Writer, linkHandler func(*cobra.Command, string) string) error { 57 c.InitDefaultHelpCmd() 58 c.InitDefaultHelpFlag() 59 60 buf := new(bytes.Buffer) 61 name := c.CommandPath() 62 63 short := c.Short 64 long := c.Long 65 if long == "" { 66 long = short 67 } 68 69 buf.WriteString("## " + name + "\n\n") 70 buf.WriteString(short + "\n\n") 71 buf.WriteString("### Synopsis\n\n") 72 buf.WriteString(long + "\n\n") 73 74 if c.Runnable() { 75 buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", c.UseLine())) 76 } 77 78 if len(c.Example) > 0 { 79 buf.WriteString("### Examples\n\n") 80 buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", c.Example)) 81 } 82 83 if err := printOptions(buf, c); err != nil { 84 return err 85 } 86 if hasSeeAlso(c) { 87 buf.WriteString("### SEE ALSO\n\n") 88 if c.HasParent() { 89 parent := c.Parent() 90 pName := parent.CommandPath() 91 link := pName + ".md" 92 link = strings.Replace(link, " ", "_", -1) 93 buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", pName, linkHandler(c, link), parent.Short)) 94 } 95 96 children := c.Commands() 97 sort.Sort(byName(children)) 98 99 for _, child := range children { 100 if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { 101 continue 102 } 103 cname := name + " " + child.Name() 104 link := cname + ".md" 105 link = strings.Replace(link, " ", "_", -1) 106 buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", cname, linkHandler(c, link), child.Short)) 107 } 108 buf.WriteString("\n") 109 } 110 if !c.DisableAutoGenTag { 111 buf.WriteString("###### Auto generated by docgen on " + time.Now().Format("2-Jan-2006") + "\n") 112 } 113 _, err := buf.WriteTo(w) 114 return err 115 } 116 117 func printOptions(buf *bytes.Buffer, c *cobra.Command) error { 118 flags := c.NonInheritedFlags() 119 flags.SetOutput(buf) 120 if flags.HasAvailableFlags() { 121 buf.WriteString("### Options\n\n```\n") 122 flags.PrintDefaults() 123 buf.WriteString("```\n\n") 124 } 125 126 parentFlags := c.InheritedFlags() 127 parentFlags.SetOutput(buf) 128 if parentFlags.HasAvailableFlags() { 129 buf.WriteString("### Options inherited from parent commands\n\n```\n") 130 parentFlags.PrintDefaults() 131 buf.WriteString("```\n\n") 132 } 133 return nil 134 } 135 136 // Test to see if we have a reason to print See Also information in docs 137 // Basically this is a test for a parent commend or a subcommand which is 138 // both not deprecated and not the autogenerated help command. 139 func hasSeeAlso(c *cobra.Command) bool { 140 if c.HasParent() { 141 return true 142 } 143 for _, c := range c.Commands() { 144 if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { 145 continue 146 } 147 return true 148 } 149 return false 150 } 151 152 type byName []*cobra.Command 153 154 func (s byName) Len() int { return len(s) } 155 func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 156 func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }