From 966a1162a56652b4d56ffe003af05161841fb192 Mon Sep 17 00:00:00 2001 From: JP Appel Date: Thu, 1 May 2025 16:32:27 -0400 Subject: Implement json output --- pkg/index/index.go | 27 +++++++++------- pkg/query/outputs.go | 88 +++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 86 insertions(+), 29 deletions(-) (limited to 'pkg') diff --git a/pkg/index/index.go b/pkg/index/index.go index 074b659..4bab21b 100644 --- a/pkg/index/index.go +++ b/pkg/index/index.go @@ -13,12 +13,12 @@ import ( ) type Document struct { - Path string - Title string `yaml:"title"` - Date time.Time `yaml:"date"` - FileTime time.Time - Authors []string `yaml:"authors"` - Tags []string `yaml:"tags"` + Path string `yaml:"-" json:"path"` + Title string `yaml:"title" json:"title"` + Date time.Time `yaml:"date" json:"date"` + FileTime time.Time `yaml:"-" json:"filetime"` + Authors []string `yaml:"authors" json:"authors"` + Tags []string `yaml:"tags" json:"tags"` Links []string OtherMeta string // unsure about how to handle this } @@ -205,7 +205,7 @@ func (idx Index) ParseOne(path string) (*Document, error) { doc := &Document{} doc.Path = path - f, err := os.Open(string(path)) + f, err := os.Open(path) if err != nil { return nil, err } @@ -224,12 +224,16 @@ func (idx Index) ParseOne(path string) (*Document, error) { return nil, errors.New("Short read") } + // FIXME: unmarshalling is **VERY** borked up rn + if err := yaml.Unmarshal(buf, &doc); err != nil { + return nil, err + } // TODO: implement custom unmarshaller, for singular `Author` - dec := yaml.NewDecoder(f) + // dec := yaml.NewDecoder(f) // TODO: handle no yaml header error - if err := dec.Decode(&doc); err != nil { - panic(err) - } + // if err := dec.Decode(&doc); err != nil { + // panic(err) + // } // TODO: body parsing @@ -239,6 +243,7 @@ func (idx Index) ParseOne(path string) (*Document, error) { func (idx Index) Parse(paths []string, numWorkers uint) { jobs := make(chan string, numWorkers) results := make(chan Document, numWorkers) + idx.Documents = make(map[string]*Document, len(paths)) wg := &sync.WaitGroup{} wg.Add(int(numWorkers)) diff --git a/pkg/query/outputs.go b/pkg/query/outputs.go index a18fd16..f258452 100644 --- a/pkg/query/outputs.go +++ b/pkg/query/outputs.go @@ -1,6 +1,7 @@ package query import ( + "encoding/json" "errors" "fmt" "strings" @@ -30,10 +31,11 @@ const ( // TODO: change interface to use byte slices type Outputer interface { - OutputOne(doc index.Document) (string, error) - Output(docs []index.Document) (string, error) + OutputOne(doc *index.Document) (string, error) + Output(docs []*index.Document) (string, error) } +type DefaultOutput struct{} type JsonOutput struct{} type CustomOutput struct { stringTokens []string @@ -41,14 +43,66 @@ type CustomOutput struct { datetimeFormat string } -func (o JsonOutput) OutputOne(doc index.Document) (string, error) { - // TODO: implement - return "", nil +// compile time interface check +var _ Outputer = &DefaultOutput{} +var _ Outputer = &JsonOutput{} +var _ Outputer = &CustomOutput{} + +// Returns " <date> authors:<authors...> tags:<tags>" +// and a nil error +func (o DefaultOutput) OutputOne(doc *index.Document) (string, error) { + b := strings.Builder{} + o.writeDoc(&b, doc) + + return b.String(), nil +} + +func (o DefaultOutput) Output(docs []*index.Document) (string, error) { + b := strings.Builder{} + + for i, doc := range docs { + o.writeDoc(&b, doc) + if i != len(docs)-1 { + b.WriteRune('\n') + } + } + + return b.String(), nil } -func (o JsonOutput) Output(docs []index.Document) (string, error) { - // TODO: implement - return "", nil +func (o DefaultOutput) writeDoc(b *strings.Builder, doc *index.Document) bool { + if b == nil { + return false + } + + b.WriteString(doc.Path) + b.WriteRune(' ') + b.WriteString(doc.Title) + b.WriteRune(' ') + b.WriteString(doc.Date.String()) + b.WriteRune(' ') + b.WriteString("authors:") + b.WriteString(strings.Join(doc.Authors, ",")) + b.WriteString(" tags:") + b.WriteString(strings.Join(doc.Tags, ",")) + + return true +} + +func (o JsonOutput) OutputOne(doc *index.Document) (string, error) { + b, err := json.Marshal(doc) + if err != nil { + return "", err + } + return string(b), nil +} + +func (o JsonOutput) Output(docs []*index.Document) (string, error) { + b, err := json.Marshal(docs) + if err != nil { + return "", err + } + return string(b), nil } func parseOutputFormat(formatStr string) ([]OutputToken, []string, error) { @@ -114,7 +168,7 @@ func NewCustomOutput(formatStr string, datetimeFormat string) (CustomOutput, err return CustomOutput{strToks, outToks, datetimeFormat}, nil } -func (o CustomOutput) OutputOne(doc index.Document) (string, error) { +func (o CustomOutput) OutputOne(doc *index.Document) (string, error) { b := strings.Builder{} // TODO: determine realistic initial capacity @@ -125,25 +179,23 @@ func (o CustomOutput) OutputOne(doc index.Document) (string, error) { return b.String(), nil } -func (o CustomOutput) Output(docs []index.Document) (string, error) { +func (o CustomOutput) Output(docs []*index.Document) (string, error) { b := strings.Builder{} // TODO: determine realistic initial capacity - for i := range len(docs) - 1 { - if err := o.writeDoc(&b, docs[i]); err != nil { + for i, doc := range docs { + if err := o.writeDoc(&b, doc); err != nil { return "", err } - b.WriteRune('\n') - } - if err := o.writeDoc(&b, docs[len(docs)-1]); err != nil { - return "", err + if i != len(docs)-1 { + b.WriteRune('\n') + } } - b.WriteRune('\n') return b.String(), nil } -func (o CustomOutput) writeDoc(b *strings.Builder, doc index.Document) error { +func (o CustomOutput) writeDoc(b *strings.Builder, doc *index.Document) error { curStrTok := 0 for _, token := range o.tokens { if token == OUT_TOK_STR { -- cgit v1.2.3