diff --git a/compiler/compile.go b/compiler/compile.go index dff2404..cf161cf 100644 --- a/compiler/compile.go +++ b/compiler/compile.go @@ -17,7 +17,6 @@ package compiler import ( "os" "path/filepath" - "strings" log "github.com/Sirupsen/logrus" "github.com/jjdekker/ponder/helpers" @@ -69,31 +68,36 @@ func CompileDir(path string, opts *settings.Settings) { func generateScores() func(string, os.FileInfo) error { return func(path string, file os.FileInfo) error { + var ( + score *settings.Score + err error + ) switch filepath.Ext(path) { case ".ly": log.WithFields(log.Fields{"path": path}).Info("adding lilypond file") - scores = append(scores, settings.Score{ - Name: filepath.Base(path)[:strings.LastIndex(filepath.Base(path), ".")], - Path: path, - LastModified: file.ModTime(), - }) + score, err = settings.FromLy(path) + if score != nil { + score.LastModified = file.ModTime() + } case ".json": if filepath.Base(path) != "ponder.json" { log.WithFields(log.Fields{"path": path}).Info("adding json file") - if score, err := settings.FromJSON(path); err != nil { - log.WithFields(log.Fields{ - "error": err, - "path": path, - }).Warning("unable to parse score settings, skipping...") - } else { - scores = append(scores, *score) - } + score, err = settings.FromJSON(path) } default: log.WithFields(log.Fields{"path": path}).Debug("ignoring file") } + + if err != nil { + log.WithFields(log.Fields{ + "error": err, + "path": path, + }).Warning("unable to parse score settings, skipping...") + } else if score != nil { + scores = append(scores, *score) + } return nil } } diff --git a/settings/score.go b/settings/score.go index ebd5e90..1281a5e 100644 --- a/settings/score.go +++ b/settings/score.go @@ -15,8 +15,10 @@ package settings import ( + "bufio" "encoding/json" "io/ioutil" + "os" "path/filepath" "strings" "time" @@ -25,6 +27,8 @@ import ( "github.com/jjdekker/ponder/helpers" ) +const lyToken = "% PONDER" + // Score represents the settings for a specific score file type Score struct { Name string // The name of the score in the songbook @@ -51,6 +55,41 @@ func FromJSON(path string) (*Score, error) { return &s, nil } +// FromLy reads the score metadata from a lilypond file. +// The metadata should be on one line preceded by the lyToken. +// The data itself should be in json format. +func FromLy(path string) (*Score, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + scan := bufio.NewScanner(file) + var line string + for scan.Scan() { + if strings.Contains(scan.Text(), lyToken) { + line = strings.TrimLeftFunc(scan.Text(), func(r rune) bool { + return r != '{' + }) + break + } + } + file.Close() + + var s Score + if line != "" { + err = json.Unmarshal([]byte(line), &s) + if err != nil { + return nil, err + } + } + if s.Name == "" { + s.Name = filepath.Base(path)[:strings.LastIndex(filepath.Base(path), ".")] + } + s.Path = path + + return &s, nil +} + // CreateScore creates a json file for a score given its path func CreateScore(path, workDir string) { if filepath.Ext(path) != ".pdf" {