From 1b74499f1f81d2fe1a54e48cfaba060a1a6043f4 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Mon, 24 Sep 2012 08:50:54 -0700 Subject: [PATCH] generate proof --- tool/generate.go | 65 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/tool/generate.go b/tool/generate.go index 44de80e..4628a35 100644 --- a/tool/generate.go +++ b/tool/generate.go @@ -1,4 +1,7 @@ -// Generate HTTML document form a Go source file. +// ## golit + +// Generate literate-programming style HTTML +// documentation form Go source files. package main @@ -11,17 +14,19 @@ import ( "strings" ) +// Recognize doc lines, extract their comment prefixes. var docsPat = regexp.MustCompile("^\\s*\\/\\/\\s") -// Just be sure to blow up on non-nil errors. +// Abort on non-nil errors. func check(err error) { if err != nil { panic(err) } } -// Pipe source data through binary at path with -// given argv, return the output. +// For docs and code rendering: pipe source data +// through binary at path with given argv, return +// the output. func pipedCmd(path string, argv []string, source string) string { cmd := exec.Command(path, argv...) in, err := cmd.StdinPipe() @@ -41,8 +46,11 @@ func pipedCmd(path string, argv []string, source string) string { return string(bytes) } +// We'll break the code into {docs, code} pairs, +// and then render those text segments before +// including them in the HTML doc. type segment struct { - docs, code string + docs, code, docsRendered, codeRendered string } func main() { @@ -58,13 +66,10 @@ func main() { check(err) pygmentizePath, err := exec.LookPath("pygmentize") check(err) - fmt.Println(markdownPath, pygmentizePath) - // Read the source file in. + // Read the source file in, split into lines. sourceBytes, err := ioutil.ReadFile(os.Args[1]) check(err) - - // Split into lines. lines := strings.Split(string(sourceBytes), "\n") // Group lines into docs/code segments. @@ -73,7 +78,7 @@ func main() { lastLine := "" for _, line := range lines { head := segments[len(segments)-1] - // Doc line. Trim off the comment markers. + // Doc line - trim off the comment markers. if (line == "" && lastLine == "docs") || docsPat.MatchString(line) { trimLine := docsPat.ReplaceAllString(line, "") if !(lastLine == "code" && head.docs != "") { @@ -82,7 +87,7 @@ func main() { segments = append(segments, &segment{docs: trimLine, code: ""}) } lastLine = "docs" - // Code line. Preserve all whitespace. + // Code line - preserve all whitespace. } else { if !(lastLine == "docs" && head.code != "") { head.code = head.code + "\n" + line @@ -92,7 +97,43 @@ func main() { lastLine = "code" } } + + // Render docs via `markdown` and code via + // `pygmentize`in each segment. for _, seg := range segments { - fmt.Printf("%#v\n", *seg) + seg.docsRendered = pipedCmd(markdownPath, []string{}, seg.docs) + seg.codeRendered = pipedCmd(pygmentizePath, []string{"-l", "go", "-f", "html"}, seg.code) } + + // Print HTML header. + fmt.Print(` + + + + + Page Title + + + +
+
+ + + + + `) + + // Print HTML docs/code segments. + for _, seg := range segments { + fmt.Printf("\n", seg.docsRendered, seg.codeRendered) + } + + // Print HTML footer. + fmt.Print(` + +
%s%s
+
+ + +`) }