Allows tools to use Go-standard formatting
This commit is contained in:
parent
a36217073a
commit
0a96c21881
@ -2,7 +2,7 @@
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
paths=$(ls tools/*.go examples/*/*.go)
|
||||
paths=$(ls examples/*/*.go)
|
||||
|
||||
gbe_to_4spaces() {
|
||||
local os=$(tr [A-Z] [a-z] <<< "`uname`")
|
||||
|
@ -1,17 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"github.com/russross/blackfriday"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"github.com/russross/blackfriday"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var cacheDir = "/tmp/gobyexample-cache"
|
||||
@ -19,99 +19,99 @@ var siteDir = "./public"
|
||||
var pygmentizeBin = "./vendor/pygments/pygmentize"
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func ensureDir(dir string) {
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
check(err)
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
check(err)
|
||||
}
|
||||
|
||||
func copyFile(src, dst string) {
|
||||
dat, err := ioutil.ReadFile(src)
|
||||
check(err)
|
||||
err = ioutil.WriteFile(dst, dat, 0644)
|
||||
check(err)
|
||||
dat, err := ioutil.ReadFile(src)
|
||||
check(err)
|
||||
err = ioutil.WriteFile(dst, dat, 0644)
|
||||
check(err)
|
||||
}
|
||||
|
||||
func pipe(bin string, arg []string, src string) []byte {
|
||||
cmd := exec.Command(bin, arg...)
|
||||
in, err := cmd.StdinPipe()
|
||||
check(err)
|
||||
out, err := cmd.StdoutPipe()
|
||||
check(err)
|
||||
err = cmd.Start()
|
||||
check(err)
|
||||
_, err = in.Write([]byte(src))
|
||||
check(err)
|
||||
err = in.Close()
|
||||
check(err)
|
||||
bytes, err := ioutil.ReadAll(out)
|
||||
check(err)
|
||||
err = cmd.Wait()
|
||||
check(err)
|
||||
return bytes
|
||||
cmd := exec.Command(bin, arg...)
|
||||
in, err := cmd.StdinPipe()
|
||||
check(err)
|
||||
out, err := cmd.StdoutPipe()
|
||||
check(err)
|
||||
err = cmd.Start()
|
||||
check(err)
|
||||
_, err = in.Write([]byte(src))
|
||||
check(err)
|
||||
err = in.Close()
|
||||
check(err)
|
||||
bytes, err := ioutil.ReadAll(out)
|
||||
check(err)
|
||||
err = cmd.Wait()
|
||||
check(err)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func sha1Sum(s string) string {
|
||||
h := sha1.New()
|
||||
h.Write([]byte(s))
|
||||
b := h.Sum(nil)
|
||||
return fmt.Sprintf("%x", b)
|
||||
h := sha1.New()
|
||||
h.Write([]byte(s))
|
||||
b := h.Sum(nil)
|
||||
return fmt.Sprintf("%x", b)
|
||||
}
|
||||
|
||||
func mustReadFile(path string) string {
|
||||
bytes, err := ioutil.ReadFile(path)
|
||||
check(err)
|
||||
return string(bytes)
|
||||
bytes, err := ioutil.ReadFile(path)
|
||||
check(err)
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
func cachedPygmentize(lex string, src string) string {
|
||||
ensureDir(cacheDir)
|
||||
arg := []string{"-l", lex, "-f", "html"}
|
||||
cachePath := cacheDir + "/pygmentize-" + strings.Join(arg, "-") + "-" + sha1Sum(src)
|
||||
cacheBytes, cacheErr := ioutil.ReadFile(cachePath)
|
||||
if cacheErr == nil {
|
||||
return string(cacheBytes)
|
||||
}
|
||||
renderBytes := pipe(pygmentizeBin, arg, src)
|
||||
// Newer versions of Pygments add silly empty spans.
|
||||
renderCleanString := strings.Replace(string(renderBytes), "<span></span>", "", -1)
|
||||
writeErr := ioutil.WriteFile(cachePath, []byte(renderCleanString), 0600)
|
||||
check(writeErr)
|
||||
return renderCleanString
|
||||
ensureDir(cacheDir)
|
||||
arg := []string{"-l", lex, "-f", "html"}
|
||||
cachePath := cacheDir + "/pygmentize-" + strings.Join(arg, "-") + "-" + sha1Sum(src)
|
||||
cacheBytes, cacheErr := ioutil.ReadFile(cachePath)
|
||||
if cacheErr == nil {
|
||||
return string(cacheBytes)
|
||||
}
|
||||
renderBytes := pipe(pygmentizeBin, arg, src)
|
||||
// Newer versions of Pygments add silly empty spans.
|
||||
renderCleanString := strings.Replace(string(renderBytes), "<span></span>", "", -1)
|
||||
writeErr := ioutil.WriteFile(cachePath, []byte(renderCleanString), 0600)
|
||||
check(writeErr)
|
||||
return renderCleanString
|
||||
}
|
||||
|
||||
func markdown(src string) string {
|
||||
return string(blackfriday.MarkdownCommon([]byte(src)))
|
||||
return string(blackfriday.MarkdownCommon([]byte(src)))
|
||||
}
|
||||
|
||||
func readLines(path string) []string {
|
||||
src := mustReadFile(path)
|
||||
return strings.Split(src, "\n")
|
||||
src := mustReadFile(path)
|
||||
return strings.Split(src, "\n")
|
||||
}
|
||||
|
||||
func mustGlob(glob string) []string {
|
||||
paths, err := filepath.Glob(glob)
|
||||
check(err)
|
||||
return paths
|
||||
paths, err := filepath.Glob(glob)
|
||||
check(err)
|
||||
return paths
|
||||
}
|
||||
|
||||
func whichLexer(path string) string {
|
||||
if strings.HasSuffix(path, ".go") {
|
||||
return "go"
|
||||
} else if strings.HasSuffix(path, ".sh") {
|
||||
return "console"
|
||||
}
|
||||
panic("No lexer for " + path)
|
||||
if strings.HasSuffix(path, ".go") {
|
||||
return "go"
|
||||
} else if strings.HasSuffix(path, ".sh") {
|
||||
return "console"
|
||||
}
|
||||
panic("No lexer for " + path)
|
||||
}
|
||||
|
||||
func debug(msg string) {
|
||||
if os.Getenv("DEBUG") == "1" {
|
||||
fmt.Fprintln(os.Stderr, msg)
|
||||
}
|
||||
if os.Getenv("DEBUG") == "1" {
|
||||
fmt.Fprintln(os.Stderr, msg)
|
||||
}
|
||||
}
|
||||
|
||||
var docsPat = regexp.MustCompile("^\\s*(\\/\\/|#)\\s")
|
||||
@ -119,169 +119,169 @@ var dashPat = regexp.MustCompile("\\-+")
|
||||
|
||||
// Seg is a segment of an example
|
||||
type Seg struct {
|
||||
Docs, DocsRendered string
|
||||
Code, CodeRendered string
|
||||
CodeEmpty, CodeLeading, CodeRun bool
|
||||
Docs, DocsRendered string
|
||||
Code, CodeRendered string
|
||||
CodeEmpty, CodeLeading, CodeRun bool
|
||||
}
|
||||
|
||||
// Example is info extracted from an example file
|
||||
type Example struct {
|
||||
ID, Name string
|
||||
GoCode, GoCodeHash, URLHash string
|
||||
Segs [][]*Seg
|
||||
NextExample *Example
|
||||
ID, Name string
|
||||
GoCode, GoCodeHash, URLHash string
|
||||
Segs [][]*Seg
|
||||
NextExample *Example
|
||||
}
|
||||
|
||||
func parseHashFile(sourcePath string) (string, string) {
|
||||
lines := readLines(sourcePath)
|
||||
return lines[0], lines[1]
|
||||
lines := readLines(sourcePath)
|
||||
return lines[0], lines[1]
|
||||
}
|
||||
|
||||
func resetURLHashFile(codehash, code, sourcePath string) string {
|
||||
payload := strings.NewReader(code)
|
||||
resp, err := http.Post("https://play.golang.org/share", "text/plain", payload)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
urlkey := string(body)
|
||||
data := fmt.Sprintf("%s\n%s\n", codehash, urlkey)
|
||||
ioutil.WriteFile(sourcePath, []byte(data), 0644)
|
||||
return urlkey
|
||||
payload := strings.NewReader(code)
|
||||
resp, err := http.Post("https://play.golang.org/share", "text/plain", payload)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
urlkey := string(body)
|
||||
data := fmt.Sprintf("%s\n%s\n", codehash, urlkey)
|
||||
ioutil.WriteFile(sourcePath, []byte(data), 0644)
|
||||
return urlkey
|
||||
}
|
||||
|
||||
func parseSegs(sourcePath string) ([]*Seg, string) {
|
||||
lines := readLines(sourcePath)
|
||||
filecontent := strings.Join(lines, "\n")
|
||||
segs := []*Seg{}
|
||||
lastSeen := ""
|
||||
for _, line := range lines {
|
||||
if line == "" {
|
||||
lastSeen = ""
|
||||
continue
|
||||
}
|
||||
matchDocs := docsPat.MatchString(line)
|
||||
matchCode := !matchDocs
|
||||
newDocs := (lastSeen == "") || ((lastSeen != "docs") && (segs[len(segs)-1].Docs != ""))
|
||||
newCode := (lastSeen == "") || ((lastSeen != "code") && (segs[len(segs)-1].Code != ""))
|
||||
if newDocs || newCode {
|
||||
debug("NEWSEG")
|
||||
}
|
||||
if matchDocs {
|
||||
trimmed := docsPat.ReplaceAllString(line, "")
|
||||
if newDocs {
|
||||
newSeg := Seg{Docs: trimmed, Code: ""}
|
||||
segs = append(segs, &newSeg)
|
||||
} else {
|
||||
segs[len(segs)-1].Docs = segs[len(segs)-1].Docs + "\n" + trimmed
|
||||
}
|
||||
debug("DOCS: " + line)
|
||||
lastSeen = "docs"
|
||||
} else if matchCode {
|
||||
if newCode {
|
||||
newSeg := Seg{Docs: "", Code: line}
|
||||
segs = append(segs, &newSeg)
|
||||
} else {
|
||||
segs[len(segs)-1].Code = segs[len(segs)-1].Code + "\n" + line
|
||||
}
|
||||
debug("CODE: " + line)
|
||||
lastSeen = "code"
|
||||
}
|
||||
}
|
||||
for i, seg := range segs {
|
||||
seg.CodeEmpty = (seg.Code == "")
|
||||
seg.CodeLeading = (i < (len(segs) - 1))
|
||||
seg.CodeRun = strings.Contains(seg.Code, "package main")
|
||||
}
|
||||
return segs, filecontent
|
||||
lines := readLines(sourcePath)
|
||||
filecontent := strings.Join(lines, "\n")
|
||||
segs := []*Seg{}
|
||||
lastSeen := ""
|
||||
for _, line := range lines {
|
||||
if line == "" {
|
||||
lastSeen = ""
|
||||
continue
|
||||
}
|
||||
matchDocs := docsPat.MatchString(line)
|
||||
matchCode := !matchDocs
|
||||
newDocs := (lastSeen == "") || ((lastSeen != "docs") && (segs[len(segs)-1].Docs != ""))
|
||||
newCode := (lastSeen == "") || ((lastSeen != "code") && (segs[len(segs)-1].Code != ""))
|
||||
if newDocs || newCode {
|
||||
debug("NEWSEG")
|
||||
}
|
||||
if matchDocs {
|
||||
trimmed := docsPat.ReplaceAllString(line, "")
|
||||
if newDocs {
|
||||
newSeg := Seg{Docs: trimmed, Code: ""}
|
||||
segs = append(segs, &newSeg)
|
||||
} else {
|
||||
segs[len(segs)-1].Docs = segs[len(segs)-1].Docs + "\n" + trimmed
|
||||
}
|
||||
debug("DOCS: " + line)
|
||||
lastSeen = "docs"
|
||||
} else if matchCode {
|
||||
if newCode {
|
||||
newSeg := Seg{Docs: "", Code: line}
|
||||
segs = append(segs, &newSeg)
|
||||
} else {
|
||||
segs[len(segs)-1].Code = segs[len(segs)-1].Code + "\n" + line
|
||||
}
|
||||
debug("CODE: " + line)
|
||||
lastSeen = "code"
|
||||
}
|
||||
}
|
||||
for i, seg := range segs {
|
||||
seg.CodeEmpty = (seg.Code == "")
|
||||
seg.CodeLeading = (i < (len(segs) - 1))
|
||||
seg.CodeRun = strings.Contains(seg.Code, "package main")
|
||||
}
|
||||
return segs, filecontent
|
||||
}
|
||||
|
||||
func parseAndRenderSegs(sourcePath string) ([]*Seg, string) {
|
||||
segs, filecontent := parseSegs(sourcePath)
|
||||
lexer := whichLexer(sourcePath)
|
||||
for _, seg := range segs {
|
||||
if seg.Docs != "" {
|
||||
seg.DocsRendered = markdown(seg.Docs)
|
||||
}
|
||||
if seg.Code != "" {
|
||||
seg.CodeRendered = cachedPygmentize(lexer, seg.Code)
|
||||
}
|
||||
}
|
||||
// we are only interested in the 'go' code to pass to play.golang.org
|
||||
if lexer != "go" {
|
||||
filecontent = ""
|
||||
}
|
||||
return segs, filecontent
|
||||
segs, filecontent := parseSegs(sourcePath)
|
||||
lexer := whichLexer(sourcePath)
|
||||
for _, seg := range segs {
|
||||
if seg.Docs != "" {
|
||||
seg.DocsRendered = markdown(seg.Docs)
|
||||
}
|
||||
if seg.Code != "" {
|
||||
seg.CodeRendered = cachedPygmentize(lexer, seg.Code)
|
||||
}
|
||||
}
|
||||
// we are only interested in the 'go' code to pass to play.golang.org
|
||||
if lexer != "go" {
|
||||
filecontent = ""
|
||||
}
|
||||
return segs, filecontent
|
||||
}
|
||||
|
||||
func parseExamples() []*Example {
|
||||
exampleNames := readLines("examples.txt")
|
||||
examples := make([]*Example, 0)
|
||||
for _, exampleName := range exampleNames {
|
||||
if (exampleName != "") && !strings.HasPrefix(exampleName, "#") {
|
||||
example := Example{Name: exampleName}
|
||||
exampleID := strings.ToLower(exampleName)
|
||||
exampleID = strings.Replace(exampleID, " ", "-", -1)
|
||||
exampleID = strings.Replace(exampleID, "/", "-", -1)
|
||||
exampleID = strings.Replace(exampleID, "'", "", -1)
|
||||
exampleID = dashPat.ReplaceAllString(exampleID, "-")
|
||||
example.ID = exampleID
|
||||
example.Segs = make([][]*Seg, 0)
|
||||
sourcePaths := mustGlob("examples/" + exampleID + "/*")
|
||||
for _, sourcePath := range sourcePaths {
|
||||
if strings.HasSuffix(sourcePath, ".hash") {
|
||||
example.GoCodeHash, example.URLHash = parseHashFile(sourcePath)
|
||||
} else {
|
||||
sourceSegs, filecontents := parseAndRenderSegs(sourcePath)
|
||||
if filecontents != "" {
|
||||
example.GoCode = filecontents
|
||||
}
|
||||
example.Segs = append(example.Segs, sourceSegs)
|
||||
}
|
||||
}
|
||||
newCodeHash := sha1Sum(example.GoCode)
|
||||
if example.GoCodeHash != newCodeHash {
|
||||
example.URLHash = resetURLHashFile(newCodeHash, example.GoCode, "examples/"+example.ID+"/"+example.ID+".hash")
|
||||
}
|
||||
examples = append(examples, &example)
|
||||
}
|
||||
}
|
||||
for i, example := range examples {
|
||||
if i < (len(examples) - 1) {
|
||||
example.NextExample = examples[i+1]
|
||||
}
|
||||
}
|
||||
return examples
|
||||
exampleNames := readLines("examples.txt")
|
||||
examples := make([]*Example, 0)
|
||||
for _, exampleName := range exampleNames {
|
||||
if (exampleName != "") && !strings.HasPrefix(exampleName, "#") {
|
||||
example := Example{Name: exampleName}
|
||||
exampleID := strings.ToLower(exampleName)
|
||||
exampleID = strings.Replace(exampleID, " ", "-", -1)
|
||||
exampleID = strings.Replace(exampleID, "/", "-", -1)
|
||||
exampleID = strings.Replace(exampleID, "'", "", -1)
|
||||
exampleID = dashPat.ReplaceAllString(exampleID, "-")
|
||||
example.ID = exampleID
|
||||
example.Segs = make([][]*Seg, 0)
|
||||
sourcePaths := mustGlob("examples/" + exampleID + "/*")
|
||||
for _, sourcePath := range sourcePaths {
|
||||
if strings.HasSuffix(sourcePath, ".hash") {
|
||||
example.GoCodeHash, example.URLHash = parseHashFile(sourcePath)
|
||||
} else {
|
||||
sourceSegs, filecontents := parseAndRenderSegs(sourcePath)
|
||||
if filecontents != "" {
|
||||
example.GoCode = filecontents
|
||||
}
|
||||
example.Segs = append(example.Segs, sourceSegs)
|
||||
}
|
||||
}
|
||||
newCodeHash := sha1Sum(example.GoCode)
|
||||
if example.GoCodeHash != newCodeHash {
|
||||
example.URLHash = resetURLHashFile(newCodeHash, example.GoCode, "examples/"+example.ID+"/"+example.ID+".hash")
|
||||
}
|
||||
examples = append(examples, &example)
|
||||
}
|
||||
}
|
||||
for i, example := range examples {
|
||||
if i < (len(examples) - 1) {
|
||||
example.NextExample = examples[i+1]
|
||||
}
|
||||
}
|
||||
return examples
|
||||
}
|
||||
|
||||
func renderIndex(examples []*Example) {
|
||||
indexTmpl := template.New("index")
|
||||
_, err := indexTmpl.Parse(mustReadFile("templates/index.tmpl"))
|
||||
check(err)
|
||||
indexF, err := os.Create(siteDir + "/index.html")
|
||||
check(err)
|
||||
err = indexTmpl.Execute(indexF, examples)
|
||||
check(err)
|
||||
indexTmpl := template.New("index")
|
||||
_, err := indexTmpl.Parse(mustReadFile("templates/index.tmpl"))
|
||||
check(err)
|
||||
indexF, err := os.Create(siteDir + "/index.html")
|
||||
check(err)
|
||||
err = indexTmpl.Execute(indexF, examples)
|
||||
check(err)
|
||||
}
|
||||
|
||||
func renderExamples(examples []*Example) {
|
||||
exampleTmpl := template.New("example")
|
||||
_, err := exampleTmpl.Parse(mustReadFile("templates/example.tmpl"))
|
||||
check(err)
|
||||
for _, example := range examples {
|
||||
exampleF, err := os.Create(siteDir + "/" + example.ID)
|
||||
check(err)
|
||||
exampleTmpl.Execute(exampleF, example)
|
||||
}
|
||||
exampleTmpl := template.New("example")
|
||||
_, err := exampleTmpl.Parse(mustReadFile("templates/example.tmpl"))
|
||||
check(err)
|
||||
for _, example := range examples {
|
||||
exampleF, err := os.Create(siteDir + "/" + example.ID)
|
||||
check(err)
|
||||
exampleTmpl.Execute(exampleF, example)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
copyFile("templates/site.css", siteDir+"/site.css")
|
||||
copyFile("templates/favicon.ico", siteDir+"/favicon.ico")
|
||||
copyFile("templates/404.html", siteDir+"/404.html")
|
||||
copyFile("templates/play.png", siteDir+"/play.png")
|
||||
examples := parseExamples()
|
||||
renderIndex(examples)
|
||||
renderExamples(examples)
|
||||
copyFile("templates/site.css", siteDir+"/site.css")
|
||||
copyFile("templates/favicon.ico", siteDir+"/favicon.ico")
|
||||
copyFile("templates/404.html", siteDir+"/404.html")
|
||||
copyFile("templates/play.png", siteDir+"/play.png")
|
||||
examples := parseExamples()
|
||||
renderIndex(examples)
|
||||
renderExamples(examples)
|
||||
}
|
||||
|
@ -1,45 +1,45 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func readLines(path string) []string {
|
||||
srcBytes, err := ioutil.ReadFile(path)
|
||||
check(err)
|
||||
return strings.Split(string(srcBytes), "\n")
|
||||
srcBytes, err := ioutil.ReadFile(path)
|
||||
check(err)
|
||||
return strings.Split(string(srcBytes), "\n")
|
||||
}
|
||||
|
||||
var commentPat = regexp.MustCompile("\\s*\\/\\/")
|
||||
|
||||
func main() {
|
||||
sourcePaths, err := filepath.Glob("./examples/*/*")
|
||||
check(err)
|
||||
foundLongFile := false
|
||||
for _, sourcePath := range sourcePaths {
|
||||
foundLongLine := false
|
||||
lines := readLines(sourcePath)
|
||||
for i, line := range lines {
|
||||
if !foundLongLine && !commentPat.MatchString(line) && (utf8.RuneCountInString(line) > 58) {
|
||||
fmt.Printf("measure: %s:%d\n", sourcePath, i+1)
|
||||
foundLongLine = true
|
||||
foundLongFile = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if foundLongFile {
|
||||
os.Exit(1)
|
||||
}
|
||||
sourcePaths, err := filepath.Glob("./examples/*/*")
|
||||
check(err)
|
||||
foundLongFile := false
|
||||
for _, sourcePath := range sourcePaths {
|
||||
foundLongLine := false
|
||||
lines := readLines(sourcePath)
|
||||
for i, line := range lines {
|
||||
if !foundLongLine && !commentPat.MatchString(line) && (utf8.RuneCountInString(line) > 58) {
|
||||
fmt.Printf("measure: %s:%d\n", sourcePath, i+1)
|
||||
foundLongLine = true
|
||||
foundLongFile = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if foundLongFile {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user