Dan Anglin
c53978cd91
- feat: add a field for the type of work location (e.g. hybrid) - refactor: move the Tex and PDF generating code to a new internal package which also moves the templates there as well. - fix: add a default value for the --output field for the generate command. - fix: add an error for when the user does not specify an input file when generating the PDF. - fix: the package name for each of the files in the templateFuncs package.
98 lines
2.5 KiB
Go
98 lines
2.5 KiB
Go
package cmd
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"codeflow.dananglin.me.uk/apollo/spruce/internal/pdf"
|
|
)
|
|
|
|
type GenerateCommand struct {
|
|
*flag.FlagSet
|
|
summary string
|
|
input string
|
|
output string
|
|
employmentHistory int
|
|
verbose bool
|
|
}
|
|
|
|
type noInputSpecifiedError struct{}
|
|
|
|
func (e noInputSpecifiedError) Error() string {
|
|
return "no input file specified, please set the --input field"
|
|
}
|
|
|
|
func NewGenerateCommand() *GenerateCommand {
|
|
gc := GenerateCommand{
|
|
FlagSet: flag.NewFlagSet("generate", flag.ExitOnError),
|
|
summary: "Generate a PDF file from an existing CV JSON file.",
|
|
}
|
|
|
|
gc.StringVar(&gc.input, "input", "", "specify the CV JSON file that you want to input to the builder.")
|
|
gc.StringVar(&gc.output, "output", "cv.pdf", "specify the name of the output CV file.")
|
|
gc.IntVar(&gc.employmentHistory, "employment-history", 10, "show employment history within these number of years.")
|
|
gc.BoolVar(&gc.verbose, "verbose", false, "set to true to enable verbose logging.")
|
|
|
|
gc.Usage = usageFunc(gc.Name(), gc.summary, gc.FlagSet)
|
|
|
|
return &gc
|
|
}
|
|
|
|
func (g *GenerateCommand) Run() error {
|
|
if g.input == "" {
|
|
return noInputSpecifiedError{}
|
|
}
|
|
|
|
historyLimit := time.Now().AddDate(-1*g.employmentHistory, 0, 0)
|
|
|
|
tempDir, err := os.MkdirTemp("/tmp", "cv-builder-")
|
|
if err != nil {
|
|
return fmt.Errorf("unable to create a temporary directory; %w", err)
|
|
}
|
|
|
|
defer func() {
|
|
err := os.RemoveAll(tempDir)
|
|
if err != nil {
|
|
slog.Warn(fmt.Sprintf("WARN: An error occurred when removing the temporary directory; %v", err))
|
|
}
|
|
}()
|
|
|
|
pdfFileName, err := pdf.Generate(tempDir, g.input, historyLimit, g.verbose)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to create the PDF file; %w", err)
|
|
}
|
|
|
|
if err := copyfile(filepath.Join(tempDir, "cv.pdf"), g.output); err != nil {
|
|
return fmt.Errorf("unable to copy %s to %s; %w", pdfFileName, g.output, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func copyfile(source, destination string) error {
|
|
inputFile, err := os.Open(source)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to open %s; %w", source, err)
|
|
}
|
|
defer inputFile.Close()
|
|
|
|
outputFile, err := os.Create(destination)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to create %s; %w", destination, err)
|
|
}
|
|
defer outputFile.Close()
|
|
|
|
_, err = io.Copy(outputFile, inputFile)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to copy %s to %s; %w", source, destination, err)
|
|
}
|
|
|
|
slog.Info("File successfully copied.", "source", source, "destination", destination)
|
|
|
|
return nil
|
|
}
|