diff options
-rw-r--r-- | .exrc | 2 | ||||
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | GNUmakefile | 11 | ||||
-rw-r--r-- | cmd/extwiki/main.go | 151 | ||||
-rw-r--r-- | src/wikipedia/links.gen.go | 10 |
5 files changed, 168 insertions, 7 deletions
@@ -6,6 +6,8 @@ endfunction autocmd BufNewFile,BufRead */cmd/extpo/* \ setlocal makeprg=go\ build\ ./cmd/extpo +autocmd BufNewFile,BufRead */cmd/extwiki/* + \ setlocal makeprg=go\ build\ ./cmd/extwiki autocmd FileType go autocmd BufWritePre <buffer> \ call s:SaveExcursion('gofmt -s') @@ -1,6 +1,7 @@ # Binaries euro-cash.eu extpo +extwiki !cmd/* *.mo diff --git a/GNUmakefile b/GNUmakefile index 0eadd9d..d117a1a 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -7,6 +7,7 @@ sqlfiles := $(shell find src/dbx/sql -name '*.sql') templates := $(shell find src/templates -name '*.tmpl') extpo := $(wildcard cmd/extpo/*.go) +extwiki := $(wildcard cmd/extwiki/*.go) ENABLED_LANGUAGES := $(shell ./aux/enabled-languages) @@ -15,9 +16,11 @@ all: euro-cash.eu extpo euro-cash.eu: $(cssfiles) $(templates) $(gofiles) $(sqlfiles) $(GO) build -extract: extpo +extract: extpo extwiki find . -name '*.go' -exec xgotext --foreign-user -o po/backend.pot {} + - find . -name '*.html.tmpl' -exec ./extpo {} + \ + find . -name '*.html.tmpl' -exec ./extwiki {} + \ + | gofmt >src/wikipedia/links.gen.go + find . -name '*.html.tmpl' -exec ./extpo {} + \ | msgcat po/backend.pot - -o po/messages.pot for bcp in $(ENABLED_LANGUAGES); \ do \ @@ -41,6 +44,9 @@ po: extpo: $(extpo) $(GO) build ./cmd/extpo +extwiki: $(extwiki) + $(GO) build ./cmd/extwiki + %.min.css: %.css if command -v lightningcss >/dev/null; \ then \ @@ -53,6 +59,7 @@ clean: find . -type f \( \ -name euro-cash.eu \ -or -name extpo \ + -or -name extwiki \ -or -name '*.min.css' \ -or -name '*.tar.gz' \ \) -delete diff --git a/cmd/extwiki/main.go b/cmd/extwiki/main.go new file mode 100644 index 0000000..76e0f3a --- /dev/null +++ b/cmd/extwiki/main.go @@ -0,0 +1,151 @@ +package main + +import ( + "flag" + "fmt" + "maps" + "os" + "path/filepath" + "slices" + "sort" + "text/template/parse" +) + +var ( + titles = make(map[string]struct{}) + configs = map[string]int{"Wikipedia": 1} +) + +func usage() { + fmt.Fprintf(os.Stderr, "Usage: %s [flags] template...\n", + filepath.Base(os.Args[0])) + flag.PrintDefaults() +} + +func main() { + try(os.Chdir(filepath.Dir(os.Args[0]))) + + outpath := flag.String("out", "-", "output file") + flag.Usage = usage + flag.Parse() + + if flag.NArg() < 1 { + flag.Usage() + os.Exit(1) + } + + var outfile *os.File + if *outpath == "-" { + outfile = os.Stdout + } else { + outfile = try2(os.Create(*outpath)) + } + + for _, f := range flag.Args() { + process(f) + } + + fmt.Fprint(outfile, `// Code generated by extwiki. DO NOT EDIT. + +package wikipedia + +var extractedTitles = [...]string{ +`) + xs := slices.Collect(maps.Keys(titles)) + sort.Strings(xs) + for _, t := range xs { + fmt.Fprintf(outfile, "%q,\n", t) + } + fmt.Fprint(outfile, "}\n") +} + +func process(path string) { + currentFile := try2(os.ReadFile(path)) + trees := make(map[string]*parse.Tree) + t := parse.New(path) + t.Mode |= parse.ParseComments | parse.SkipFuncCheck + try2(t.Parse(string(currentFile), "", "", trees)) + for _, t := range trees { + processNode(t.Root) + } +} + +func processNode(node parse.Node) { + switch n := node.(type) { + case *parse.ListNode: + for _, m := range n.Nodes { + processNode(m) + } + case *parse.PipeNode: + for _, m := range n.Cmds { + processNode(m) + } + case *parse.TemplateNode: + processNode(n.Pipe) + case *parse.IfNode: + processBranch(n.BranchNode) + case *parse.RangeNode: + processBranch(n.BranchNode) + case *parse.WithNode: + processBranch(n.BranchNode) + case *parse.BranchNode: + processBranch(*n) + case *parse.ActionNode: + processNode(n.Pipe) + case *parse.CommandNode: + if len(n.Args) == 0 { + break + } + + var funcname string + f, ok := n.Args[0].(*parse.FieldNode) + if !ok || len(f.Ident) == 0 { + ff, ok := n.Args[0].(*parse.VariableNode) + if !ok || len(ff.Ident) == 0 { + fff, ok := n.Args[0].(*parse.IdentifierNode) + if !ok { + for _, pipe := range n.Args { + processNode(pipe) + } + break + } + funcname = fff.Ident + } else { + funcname = ff.Ident[len(ff.Ident)-1] + } + } else { + funcname = f.Ident[len(f.Ident)-1] + } + + i, ok := configs[funcname] + if !ok { + for _, pipe := range n.Args { + processNode(pipe) + } + break + } + + if sn, ok := n.Args[i].(*parse.StringNode); ok { + titles[sn.Text] = struct{}{} + } + } +} + +func processBranch(n parse.BranchNode) { + processNode(n.List) + if n.ElseList != nil { + processNode(n.ElseList) + } +} + +func try(err error) { + if err != nil { + fmt.Fprintf(os.Stderr, "%s: %s\n", filepath.Base(os.Args[0]), err) + os.Exit(1) + } +} + +func try2[T any](val T, err error) T { + try(err) + return val +} diff --git a/src/wikipedia/links.gen.go b/src/wikipedia/links.gen.go index 9e491fd..42900cc 100644 --- a/src/wikipedia/links.gen.go +++ b/src/wikipedia/links.gen.go @@ -1,13 +1,13 @@ -package wikipedia +// Code generated by extwiki. DO NOT EDIT. -/* TODO: Extract these programmatically */ +package wikipedia var extractedTitles = [...]string{ "Coat of arms of Andorra", - "Royal cypher", "Coat of arms of Germany", + "Dubravka (drama)", "Eurovision Song Contest", - "Nikola Tesla", "Glagolitic script", - "Dubravka (drama)", + "Nikola Tesla", + "Royal cypher", } |