Skip to content
This repository has been archived by the owner on Jul 29, 2021. It is now read-only.

Commit

Permalink
Add support for examples.
Browse files Browse the repository at this point in the history
Fixes #2
  • Loading branch information
abursavich committed Apr 16, 2018
1 parent deb306d commit 742d932
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 15 deletions.
107 changes: 107 additions & 0 deletions example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package main

import (
"bytes"
"go/doc"
"go/printer"
"regexp"
"sort"
"strings"
"unicode"
"unicode/utf8"

"golang.org/x/tools/godoc"
)

type example struct {
Name string
Doc string
Code string
Output string
}

func examplesFunc(info *godoc.PageInfo, name string) []*example {
var egs []*example
for _, eg := range info.Examples {
if name != "*" && stripExampleSuffix(eg.Name) != name {
continue
}
doc := eg.Doc
out := eg.Output
code, wholeFile := exampleCode(info, eg)
if wholeFile {
doc = ""
out = ""
}
egs = append(egs, &example{
Name: eg.Name,
Doc: doc,
Code: code,
Output: out,
})
}
sort.Slice(egs, func(i int, j int) bool {
ni, si := splitExampleName(egs[i].Name)
nj, sj := splitExampleName(egs[j].Name)
if ni == nj {
return si < sj
}
return ni < nj
})
return egs
}

var exampleOutputRx = regexp.MustCompile(`(?i)//[[:space:]]*(unordered )?output:`)

func exampleCode(info *godoc.PageInfo, eg *doc.Example) (code string, wholeFile bool) {
// Print code
var buf bytes.Buffer
cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
config := &printer.Config{Mode: printer.UseSpaces, Tabwidth: *tabWidth}
config.Fprint(&buf, info.FSet, cnode)
code = strings.Trim(buf.String(), "\n")
wholeFile = true

if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
wholeFile = false
// Remove surrounding braces.
code = strings.Trim(code[1:n-1], "\n")
// Remove output from code.
if loc := exampleOutputRx.FindStringIndex(code); loc != nil {
code = strings.TrimRightFunc(code[:loc[0]], unicode.IsSpace)
}
// Unindent code.
lines := strings.Split(code, "\n")
unindent(lines)
code = strings.Join(lines, "\n")
}

return code, wholeFile
}

func splitExampleName(s string) (name, suffix string) {
i := strings.LastIndex(s, "_")
if 0 <= i && i < len(s)-1 && !startsWithUppercase(s[i+1:]) {
name = s[:i]
suffix = " (" + strings.Title(s[i+1:]) + ")"
return
}
name = s
return
}

// stripExampleSuffix strips lowercase braz in Foo_braz or Foo_Bar_braz from name
// while keeping uppercase Braz in Foo_Braz.
func stripExampleSuffix(name string) string {
if i := strings.LastIndex(name, "_"); i != -1 {
if i < len(name)-1 && !startsWithUppercase(name[i+1:]) {
name = name[:i]
}
}
return name
}

func startsWithUppercase(s string) bool {
r, _ := utf8.DecodeRuneInString(s)
return unicode.IsUpper(r)
}
23 changes: 17 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,15 @@ var (
fs = vfs.NameSpace{}

funcs = map[string]interface{}{
"comment_md": commentMdFunc,
"base": path.Base,
"md": mdFunc,
"pre": preFunc,
"kebab": kebabFunc,
"bitscape": bitscapeFunc, //Escape [] for bitbucket confusion
"comment_md": commentMdFunc,
"base": path.Base,
"md": mdFunc,
"pre": preFunc,
"kebab": kebabFunc,
"bitscape": bitscapeFunc, //Escape [] for bitbucket confusion
"show_examples": func() bool { return *showExamples },
"examples": examplesFunc,
"output": outputFunc,
}
)

Expand All @@ -86,6 +89,14 @@ func preFunc(text string) string {
return "``` go\n" + text + "\n```"
}

func outputFunc(output string) string {
lines := strings.Split(output, "\n")
for i, line := range lines {
lines[i] = " " + line
}
return "\n" + strings.Join(lines, "\n")
}

// Original Source https://github.com/golang/tools/blob/master/godoc/godoc.go#L562
func srcLinkFunc(s string) string {
s = path.Clean("/" + s)
Expand Down
26 changes: 17 additions & 9 deletions template.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package main

var pkgTemplate = `{{with .PDoc}}
var pkgTemplate = `{{define "examples_md"}}{{- range .}}
#### <a name="example_{{.Name}}">Example{{example_suffix .Name}}</a>
{{comment_md .Doc}}
Code:
{{pre .Code}}{{if .Output}}
Output:
{{output .Output}}
{{end}}
{{end}}{{end}}{{with .PDoc}}
{{if $.IsMain}}
> {{ base .ImportPath }}
{{comment_md .Doc}}
Expand All @@ -9,13 +17,13 @@ var pkgTemplate = `{{with .PDoc}}
` + "`" + `import "{{.ImportPath}}"` + "`" + `
* [Overview](#pkg-overview)
* [Index](#pkg-index){{if $.Examples}}
* [Index](#pkg-index){{if and $.Examples show_examples}}
* [Examples](#pkg-examples){{- end}}{{if $.Dirs}}
* [Subdirectories](#pkg-subdirectories){{- end}}
## <a name="pkg-overview">Overview</a>
{{comment_md .Doc}}
{{example_html $ ""}}
{{template "examples_md" (examples $ "")}}
## <a name="pkg-index">Index</a>{{if .Consts}}
* [Constants](#pkg-constants){{end}}{{if .Vars}}
Expand All @@ -25,8 +33,8 @@ var pkgTemplate = `{{with .PDoc}}
* [{{node_html $ .Decl false | sanitize}}](#{{$name_html}}){{- end}}{{- range .Methods}}{{$name_html := html .Name}}
* [{{node_html $ .Decl false | sanitize}}](#{{$tname_html}}.{{$name_html}}){{- end}}{{- end}}{{- if $.Notes}}{{- range $marker, $item := $.Notes}}
* [{{noteTitle $marker | html}}s](#pkg-note-{{$marker}}){{end}}{{end}}
{{if $.Examples}}
#### <a name="pkg-examples">Examples</a>{{- range $.Examples}}
{{if and $.Examples show_examples}}
#### <a name="pkg-examples">Examples</a>{{- range examples $ "*" }}
* [{{example_name .Name}}](#example_{{.Name}}){{- end}}{{- end}}
{{with .Filenames}}
#### <a name="pkg-files">Package files</a>
Expand All @@ -43,7 +51,7 @@ var pkgTemplate = `{{with .PDoc}}
{{range .Funcs}}{{$name_html := html .Name}}## <a name="{{$name_html}}">func</a> [{{$name_html}}]({{posLink_url $ .Decl}})
{{node $ .Decl | pre}}
{{comment_md .Doc}}
{{example_html $ .Name}}
{{template "examples_md" (examples $ .Name)}}
{{callgraph_html $ "" .Name}}{{end}}
{{range .Types}}{{$tname := .Name}}{{$tname_html := html .Name}}## <a name="{{$tname_html}}">type</a> [{{$tname_html}}]({{posLink_url $ .Decl}})
{{node $ .Decl | pre}}
Expand All @@ -53,20 +61,20 @@ var pkgTemplate = `{{with .PDoc}}
{{node $ .Decl | pre }}
{{comment_md .Doc}}{{end}}
{{example_html $ $tname}}
{{template "examples_md" (examples $ $tname)}}
{{implements_html $ $tname}}
{{methodset_html $ $tname}}
{{range .Funcs}}{{$name_html := html .Name}}### <a name="{{$name_html}}">func</a> [{{$name_html}}]({{posLink_url $ .Decl}})
{{node $ .Decl | pre}}
{{comment_md .Doc}}
{{example_html $ .Name}}{{end}}
{{template "examples_md" (examples $ .Name)}}{{end}}
{{callgraph_html $ "" .Name}}
{{range .Methods}}{{$name_html := html .Name}}### <a name="{{$tname_html}}.{{$name_html}}">func</a> ({{md .Recv}}) [{{$name_html}}]({{posLink_url $ .Decl}})
{{node $ .Decl | pre}}
{{comment_md .Doc}}
{{$name := printf "%s_%s" $tname .Name}}{{example_html $ $name}}
{{$name := printf "%s_%s" $tname .Name}}{{template "examples_md" (examples $ $name)}}
{{callgraph_html $ .Recv .Name}}
{{end}}{{end}}{{end}}
Expand Down

0 comments on commit 742d932

Please sign in to comment.