spruce/main.go
Dan Anglin 11b9d4df15
feat: new cv builder tool
New CV builder tool migrated from the private repository.
2023-02-18 21:01:28 +00:00

116 lines
2.5 KiB
Go

package main
import (
"embed"
"encoding/json"
"flag"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"text/template"
)
//go:embed templates/tex/*
var templates embed.FS
func main() {
var input, output string
flag.StringVar(&input, "input", "", "specify the CV JSON file that you want to input to the builder.")
flag.StringVar(&output, "output", "", "specify the name of the output CV file.")
flag.Parse()
tempDir, err := os.MkdirTemp("/tmp", "cv-builder-")
if err != nil {
log.Fatalf("ERROR: Unable to create a temporary directory; %v", err)
}
defer func() {
err := os.RemoveAll(tempDir)
if err != nil {
log.Printf("WARN: An error occurred when removing the temporary directory; %v", err)
}
}()
texFile, err := tex(input, tempDir)
if err != nil {
log.Fatalf("ERROR: %v", err)
}
if err := pdf(tempDir, texFile, output); err != nil {
log.Fatalf("ERROR: %v", err)
}
}
// tex generates the CV document as a Tex file.
func tex(input, tempDir string) (string, error) {
data, err := os.ReadFile(input)
if err != nil {
return "", fmt.Errorf("unable to read data from file; %w", err)
}
var cv Cv
if err = json.Unmarshal(data, &cv); err != nil {
return "", fmt.Errorf("unable to decode JSON data; %w", err)
}
// if CV_CONTACT_PHONE is set then add it to the CV
phone := os.Getenv("CV_CONTACT_PHONE")
if len(phone) > 0 {
cv.Contact.Phone = phone
}
output := filepath.Join(tempDir, "cv.tex")
file, err := os.Create(output)
if err != nil {
return "", fmt.Errorf("unable to create output file %s; %w", output, err)
}
defer file.Close()
fmap := template.FuncMap{
"notLastElement": notLastElement,
"join": join,
"durationToString": durationToString,
}
t := template.Must(template.New("cv.tmpl.tex").
Funcs(fmap).
Delims("<<", ">>").
ParseFS(templates, "templates/tex/*.tmpl.tex"),
)
if err = t.Execute(file, cv); err != nil {
return "", fmt.Errorf("unable to execute the CV template. %w", err)
}
log.Printf("INFO: Tex file %s was successfully created.", output)
return output, nil
}
// pdf generates the CV document as a PDF file from the tex file.
func pdf(tempDir, texFile, output string) error {
pathArg := "--path=" + tempDir
command := exec.Command("mtxrun", pathArg, "--script", "context", texFile)
command.Stderr = os.Stderr
command.Stdout = os.Stdout
if err := command.Run(); err != nil {
return err
}
if output == "" {
output = "./cv.pdf"
}
if err := os.Rename(filepath.Join(tempDir, "cv.pdf"), output); err != nil {
return err
}
return nil
}