Created
June 13, 2019 22:34
-
-
Save ajstarks/18d87e01207ee919754d6dbc025973c8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Go Gestalt | |
// make a series of pages visualizing the layout of Go code | |
package main | |
import ( | |
"bufio" | |
"flag" | |
"fmt" | |
"os" | |
"regexp" | |
"strings" | |
"github.com/ajstarks/deck/generate" | |
) | |
const ( | |
commentcolor = "lightgray" | |
structcolor = "rgb(0,0,127)" | |
packagecolor = "black" | |
defcolor = "gray" | |
funcolor = "rgb(127,0,0)" | |
importcolor = "rgb(0,127,0)" | |
tabsize = 4 | |
) | |
// vmap maps one range into another | |
func vmap(value float64, low1 float64, high1 float64, low2 float64, high2 float64) float64 { | |
return low2 + (high2-low2)*(value-low1)/(high1-low1) | |
} | |
// rematch indicates a match of a regular expression | |
// errors are considered no match | |
func rematch(pattern, s string) bool { | |
m, err := regexp.MatchString(pattern, s) | |
if err != nil { | |
return false | |
} | |
return m | |
} | |
// process reads an input file, and generates a series of pages | |
// showing the structure of the code. | |
func process(filename string, deck *generate.Deck, maxline int) error { | |
r, err := os.Open(filename) | |
if err != nil { | |
return err | |
} | |
color := defcolor | |
top := 90.0 | |
bottom := 5.0 | |
left := 5.0 | |
right := 20.0 | |
y := top | |
page := 1 | |
colsize := 25.0 | |
deck.StartDeck() | |
deck.StartSlide() | |
deck.Text(left, 95, filename, "sans", 1.5, "") | |
deck.TextEnd(95, 95, fmt.Sprintf("Page %d", page), "sans", 1, "") | |
scanner := bufio.NewScanner(r) | |
var incomment bool | |
for scanner.Scan() { | |
t := scanner.Text() | |
if strings.HasPrefix(t, "/*") { | |
incomment = true | |
} | |
if strings.HasPrefix(t, "*/") { | |
incomment = false | |
} | |
if rematch(".*//", t) || incomment { | |
color = commentcolor | |
} else if rematch("^package", t) { | |
color = packagecolor | |
} else if rematch("^func.*{", t) { | |
color = funcolor | |
} else if rematch("^type.*struct.*{", t) || rematch("^type.*interface.*{", t) { | |
color = structcolor | |
} else if rematch("^import", t) { | |
color = importcolor | |
} else { | |
color = defcolor | |
} | |
linelen := len(t) | |
ntabs := strings.Count(t, "\t") | |
ntlen := linelen - ntabs | |
codelen := ntlen + (ntabs * tabsize) | |
fmaxline := float64(maxline) | |
x := vmap(float64(codelen), 0, fmaxline, left, right) | |
tabshift := float64(ntabs) | |
deck.Line(left+tabshift, y, x, y, 0.5, color) | |
y -= 1.0 | |
// new column | |
if y < bottom { | |
y = top | |
left += colsize | |
right += colsize | |
} | |
// new page | |
if left > 100 { | |
top = 90.0 | |
bottom = 5.0 | |
left = 5.0 | |
right = 20.0 | |
y = top | |
page++ | |
deck.EndSlide() | |
deck.StartSlide() | |
deck.Text(left, 95, filename, "sans", 1.5, "") | |
deck.TextEnd(95, 95, fmt.Sprintf("Page %d", page), "sans", 1, "") | |
} | |
} | |
deck.EndSlide() | |
deck.EndDeck() | |
r.Close() | |
return nil | |
} | |
// for every input file, make a deck | |
func main() { | |
linelength := flag.Int("l", 100, "max line length") | |
flag.Parse() | |
deck := generate.NewSlides(os.Stdout, 0, 0) | |
for _, f := range flag.Args() { | |
if err := process(f, deck, *linelength); err != nil { | |
fmt.Fprintf(os.Stderr, "%v\n", err) | |
continue | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment