1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
common-configs/i3/helpers/barista/nerdfont-process-css.go

157 lines
4.0 KiB

// This file is run by go generate, and generates nerdfont-provider-data.go.
// +build generation
package main
import (
"bufio"
"bytes"
"io"
"log"
"net/http"
"os"
"strconv"
"strings"
"text/template"
"time"
"unicode"
)
var fileTemplate = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// {{ .Timestamp }}
// using data from
// {{ .URL }}
package main
var NerdFontGlyphs = []Glyph{
{{- range $key, $rune := .Glyphs }}
{
Key: {{ printf "%q" $key }},
Rune: 0x{{ printf "%x" $rune }},
},
{{- end }}
}
`))
const TokenStartString = ".nf-"
const ClassStartString = ":before {\n content: \"\\"
const ClassEndString = "\";\n}\n"
// SplitCSS scans the reader looking for data of the form
// .nf-(key):before {
// content: "\(hex)";
// }
// and returns (key):(hex) when it finds this data.
func SplitCSS(data []byte, atEOF bool) (advance int, token []byte, err error) {
if !bytes.HasPrefix(data, []byte(TokenStartString)) {
// This is not our goal. Skip this line.
nextNewline := bytes.IndexRune(data, '\n');
if nextNewline == -1 {
// Can't skip this line yet because we don't know where it ends!
return 0, nil, nil
} else {
offset := nextNewline + 1
// Skip this line in our own head and see if we get a result.
advance, token, err = SplitCSS(data[offset:], atEOF)
if advance > 0 || token != nil || err != nil {
// If we do, return it adjusted by the offset.
return advance + offset, token, err
} else {
// Otherwise, just tell the scanner to skip the line we found and keep going.
return offset, nil, nil
}
}
}
keyEnd := bytes.Index(data, []byte(ClassStartString))
if keyEnd == -1 {
// We don't know where the key ends!
return 0, nil, nil
}
key := data[len(TokenStartString):keyEnd]
contentEnd := bytes.Index(data, []byte(ClassEndString))
if contentEnd == -1 {
// We don't know where the content ends!
return 0, nil, nil
}
content := data[keyEnd + len(ClassStartString):contentEnd]
token = make([]byte, len(key) + len(content) + 1)
copy(token[:len(key)], key)
token[len(key)] = ':'
copy(token[len(key) + 1:], content)
return contentEnd + len(ClassEndString), token, nil
}
func SplitOnce(s string, sep string) (string, string) {
result := strings.SplitN(s, sep, 2)
if len(result) == 2 {
return result[0], result[1]
} else if len(result) == 1 {
return result[0], ""
} else {
panic("How did we get a different number of strings than 1 or 2 out of SplitN(2)?")
}
}
func main() {
const url = "https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/css/nerd-fonts-generated.css"
rsp, err := http.Get(url)
if err != nil {
log.Fatalf("failed to get css file: %s", err)
}
defer func(b io.ReadCloser) {
err := b.Close()
if err != nil {
log.Printf("failed closing the css file: %s", err)
}
}(rsp.Body)
sc := bufio.NewScanner(rsp.Body)
sc.Split(SplitCSS)
glyphs := make(map[string]rune)
for sc.Scan() {
key, hex := SplitOnce(sc.Text(), ":")
val, err := strconv.ParseInt(hex, 16, 64)
if err != nil {
log.Printf("val %s for %s cannot be parsed as hex: %s", hex, key, err)
continue
}
if val > int64(unicode.MaxRune) {
log.Printf("val 0x%x for %s exceeds MaxRune", val, key)
continue
}
if old, ok := glyphs[key]; ok {
log.Printf("already stored %s as 0x%x but got 0x%x, replacing", key, old, val)
}
glyphs[key] = rune(val)
}
if sc.Err() != nil {
log.Fatalf("failed to scan: %s", sc.Err())
}
f, err := os.Create("nerdfont-provider-data.go")
if err != nil {
log.Fatalf("failed to open the data file: %s", err)
}
defer func(f *os.File) {
err := f.Close()
if err != nil {
log.Printf("failed closing the data file: %s", err)
}
}(f)
err = fileTemplate.Execute(f, struct {
Timestamp time.Time
URL string
Glyphs map[string]rune
}{
Timestamp: time.Now(),
URL: url,
Glyphs: glyphs,
})
if err != nil {
log.Fatalf("failed writing template to the data file: %s", err)
}
}