diff options
| author | Přemysl Eric Janouch <p@janouch.name> | 2021-06-22 01:57:15 +0200 | 
|---|---|---|
| committer | Přemysl Eric Janouch <p@janouch.name> | 2021-06-22 23:25:02 +0200 | 
| commit | 8276f6bcb97be2a2ab0c76de1135517a3b97dc4b (patch) | |
| tree | 27efbce56f802cf1f797852e71b34419485ff1c2 /hswg | |
| parent | dd5c583e8b48b2f12e7d0875fff1f8580e0a956a (diff) | |
| download | haven-8276f6bcb97be2a2ab0c76de1135517a3b97dc4b.tar.gz haven-8276f6bcb97be2a2ab0c76de1135517a3b97dc4b.tar.xz haven-8276f6bcb97be2a2ab0c76de1135517a3b97dc4b.zip | |
hswg: an initial attempt at refactoring main()
Diffstat (limited to 'hswg')
| -rw-r--r-- | hswg/main.go | 195 | 
1 files changed, 112 insertions, 83 deletions
| diff --git a/hswg/main.go b/hswg/main.go index 5076bd1..a23e343 100644 --- a/hswg/main.go +++ b/hswg/main.go @@ -187,49 +187,61 @@ func expand(m *map[string]*Entry, name string, chunk []byte) []byte {  	})  } -func singleFile() { -	html, meta, err := Render(os.Stdin, configuration.NewConfiguration()) +var tagRE = regexp.MustCompile(`<[^<>]+>`) + +func renderEntry(name string, entries *map[string]*Entry) error { +	e := (*entries)[name] + +	f, err := os.Open(e.PathSource)  	if err != nil { -		log.Println(err) -	} else if meta.Title != "" { -		_, _ = os.Stdout.WriteString("<h1>") -		_ = xml.EscapeText(os.Stdout, []byte(meta.Title)) -		_, _ = os.Stdout.WriteString("</h1>\n") +		return err  	} -	_, _ = io.Copy(os.Stdout, html) -} -func main() { -	if len(os.Args) < 2 { -		singleFile() -		return +	if i, err := f.Stat(); err != nil { +		return err +	} else { +		e.mtime = i.ModTime()  	} -	if len(os.Args) < 3 { -		log.Fatalf("usage: %s TEMPLATE GLOB...\n", os.Args[0]) + +	var html *bytes.Buffer +	if html, e.Metadata, err = Render(f, configuration.NewConfiguration( +		configuration.WithFilename(e.PathSource), +		configuration.WithLastUpdated(e.mtime), +	)); err != nil { +		return err  	} -	// Read the common page header. -	header, err := ioutil.ReadFile(os.Args[1]) -	if err != nil { -		log.Fatalln(err) +	// Every page needs to have a title. +	if e.Title == "" { +		e.Title = name  	} -	t, err := template.New("page").Parse(string(header)) -	if err != nil { -		log.Fatalln(err) +	// Expand LinkWords anywhere between <tags>. +	// We want something like the inverse of Regexp.ReplaceAllStringFunc. +	raw, last, expanded := html.Bytes(), 0, bytes.NewBuffer(nil) +	for _, where := range tagRE.FindAllIndex(raw, -1) { +		_, _ = expanded.Write(expand(entries, name, raw[last:where[0]])) +		_, _ = expanded.Write(raw[where[0]:where[1]]) +		last = where[1]  	} +	_, _ = expanded.Write(expand(entries, name, raw[last:])) +	e.Content = template.HTML(expanded.String()) +	return nil +} +func loadEntries(globs []string) (map[string]*Entry, error) {  	// Create a map from document names to their page entries.  	entries := map[string]*Entry{} -	for _, glob := range os.Args[2:] { +	for _, glob := range globs {  		matches, err := filepath.Glob(glob)  		if err != nil { -			log.Fatalf("%s: %s\n", glob, err) +			return nil, fmt.Errorf("%s: %s\n", glob, err)  		}  		for _, path := range matches {  			name := stripExtension(filepath.Base(path))  			if conflict, ok := entries[name]; ok { -				log.Fatalf("%s: conflicts with %s\n", name, conflict.PathSource) +				return nil, fmt.Errorf("%s: conflicts with %s\n", +					name, conflict.PathSource)  			}  			entries[name] = &Entry{  				PathSource:      path, @@ -239,68 +251,38 @@ func main() {  		}  	} -	tagRE := regexp.MustCompile(`<[^<>]+>`) -	for name, e := range entries { -		f, err := os.Open(e.PathSource) -		if err != nil { -			log.Fatalln(err) -		} - -		if i, err := f.Stat(); err != nil { -			log.Fatalln(err) -		} else { -			e.mtime = i.ModTime() -		} - -		var html *bytes.Buffer -		if html, e.Metadata, err = Render(f, configuration.NewConfiguration( -			configuration.WithFilename(e.PathSource), -			configuration.WithLastUpdated(e.mtime), -		)); err != nil { -			log.Fatalln(err) -		} - -		// Every page needs to have a title. -		if e.Title == "" { -			e.Title = name -		} - -		// Expand LinkWords anywhere between <tags>. -		// We want something like the inverse of Regexp.ReplaceAllStringFunc. -		raw, last, expanded := html.Bytes(), 0, bytes.NewBuffer(nil) -		for _, where := range tagRE.FindAllIndex(raw, -1) { -			_, _ = expanded.Write(expand(&entries, name, raw[last:where[0]])) -			_, _ = expanded.Write(raw[where[0]:where[1]]) -			last = where[1] +	for name := range entries { +		if err := renderEntry(name, &entries); err != nil { +			return nil, err  		} -		_, _ = expanded.Write(expand(&entries, name, raw[last:])) -		e.Content = template.HTML(expanded.String())  	} +	return entries, nil +} -	for _, e := range entries { -		f, err := os.Create(e.PathDestination) -		if err != nil { -			log.Fatalln(err) -		} - -		backlinks := []string{} -		for name := range e.backlinks { -			backlinks = append(backlinks, name) -		} -		sort.Strings(backlinks) -		for _, name := range backlinks { -			e.Backlinks = -				append(e.Backlinks, template.HTML(makeLink(&entries, name))) -		} +func writeEntry(e *Entry, t *template.Template, +	entries *map[string]*Entry) error { +	f, err := os.Create(e.PathDestination) +	if err != nil { +		return err +	} -		if err = t.Execute(f, e); err != nil { -			log.Fatalln(err) -		} +	backlinks := []string{} +	for name := range e.backlinks { +		backlinks = append(backlinks, name)  	} +	sort.Strings(backlinks) +	for _, name := range backlinks { +		e.Backlinks = +			append(e.Backlinks, template.HTML(makeLink(entries, name))) +	} + +	return t.Execute(f, e) +} +func writeIndex(t *template.Template, entries *map[string]*Entry) error {  	// Reorder entries reversely, primarily by date, secondarily by filename.  	ordered := []*Entry{} -	for _, e := range entries { +	for _, e := range *entries {  		ordered = append(ordered, e)  	} @@ -322,15 +304,62 @@ func main() {  		return p2.Before(*p1)  	}) -	// Execute a template from the standard input. +	// TODO(p): Splitting content to categories would be nice. +	return t.Execute(os.Stdout, ordered) +} + +func singleFile() { +	html, meta, err := Render(os.Stdin, configuration.NewConfiguration()) +	if err != nil { +		log.Println(err) +	} else if meta.Title != "" { +		_, _ = os.Stdout.WriteString("<h1>") +		_ = xml.EscapeText(os.Stdout, []byte(meta.Title)) +		_, _ = os.Stdout.WriteString("</h1>\n") +	} +	_, _ = io.Copy(os.Stdout, html) +} + +func main() { +	if len(os.Args) < 2 { +		singleFile() +		return +	} +	if len(os.Args) < 3 { +		log.Fatalf("usage: %s TEMPLATE GLOB...\n", os.Args[0]) +	} + +	// Read the common page header. +	header, err := ioutil.ReadFile(os.Args[1]) +	if err != nil { +		log.Fatalln(err) +	} +	t, err := template.New("page").Parse(string(header)) +	if err != nil { +		log.Fatalln(err) +	} + +	// Process all entries. +	entries, err := loadEntries(os.Args[2:]) +	if err != nil { +		log.Fatalln(err) +	} +	for _, e := range entries { +		if err := writeEntry(e, t, &entries); err != nil { +			log.Fatalln(err) +		} +	} + +	// Read a template from the standard input, write an index.  	var input []byte  	if input, err = ioutil.ReadAll(os.Stdin); err != nil {  		log.Fatalln(err)  	} - -	// TODO(p): Splitting content to categories would be nice.  	t, err = template.New("-").Parse(string(input)) -	if err = t.Execute(os.Stdout, ordered); err != nil { +	if err != nil { +		log.Fatalln(err) +	} +	if err := writeIndex(t, &entries); err != nil {  		log.Fatalln(err)  	}  } | 
