Add plain text formatter

This commit is contained in:
Dan Jones 2024-03-07 10:10:54 -06:00
commit 89e6c2b3bd
5 changed files with 276 additions and 0 deletions

10
formatters/interface.go Normal file
View file

@ -0,0 +1,10 @@
package formatters
import "codeberg.org/danjones000/my-log/models"
type Formatter interface {
Name() string
Log(models.Log) (out []byte, err error)
Entry(models.Entry) (out []byte, err error)
Meta(models.Meta) (out []byte, err error)
}

34
formatters/new.go Normal file
View file

@ -0,0 +1,34 @@
package formatters
import (
"errors"
"codeberg.org/danjones000/my-log/config"
)
type formatMaker func(oo config.Outputs) (Formatter, error)
var formatterMap = map[string]formatMaker{
"plain": newPlain,
}
func New(kind string) (f Formatter, err error) {
conf, err := config.Load()
if err != nil {
return
}
if make, ok := formatterMap[kind]; ok {
return make(conf.Outputs)
}
return nil, errors.New("unimplemented")
}
func Kinds() []string {
r := []string{}
for kind, _ := range formatterMap {
r = append(r, kind)
}
return r
}

35
formatters/new_test.go Normal file
View file

@ -0,0 +1,35 @@
package formatters
import (
"fmt"
"os"
"testing"
"codeberg.org/danjones000/my-log/config"
"github.com/stretchr/testify/assert"
)
func TestKinds(t *testing.T) {
assert.Equal(t, []string{"plain"}, Kinds())
}
func TestNewUnsupported(t *testing.T) {
f, err := New("nope")
assert.Nil(t, f)
assert.Error(t, err)
}
func TestNewCantGetConfig(t *testing.T) {
f, _ := os.CreateTemp("", "test")
oldConf := config.ConfigPath
config.ConfigPath = f.Name()
defer f.Close()
defer func() {
config.ConfigPath = oldConf
}()
fmt.Fprint(f, `{"not":"toml"}`)
form, err := New("plain")
assert.Nil(t, form)
assert.Error(t, err)
}

88
formatters/plain.go Normal file
View file

@ -0,0 +1,88 @@
package formatters
import (
"bytes"
"codeberg.org/danjones000/my-log/config"
"codeberg.org/danjones000/my-log/models"
"codeberg.org/danjones000/my-log/tools"
)
func newPlain(oo config.Outputs) (Formatter, error) {
return &PlainText{}, nil
}
type PlainText struct {
// config might go here some day
}
func (pt *PlainText) Name() string {
return "plain"
}
func (pt *PlainText) Log(log models.Log) (out []byte, err error) {
if len(log.Entries) == 0 {
return
}
buff := &bytes.Buffer{}
buff.WriteString(log.Name)
buff.WriteString("\n#######")
written := false
for _, e := range log.Entries {
bb := pt.entryBuffer(e)
if bb.Len() > 0 {
buff.WriteByte(10)
buff.WriteByte(10)
buff.ReadFrom(bb)
written = true
}
}
if written {
out = buff.Bytes()
}
return
}
func (pt *PlainText) entryBuffer(entry models.Entry) *bytes.Buffer {
buff := &bytes.Buffer{}
buff.WriteString("Title: ")
buff.WriteString(entry.Title)
buff.WriteByte(10)
buff.WriteString("Date: ")
buff.WriteString(entry.Date.Format(tools.DateFormat))
for _, m := range entry.Fields {
bb, err := pt.metaBuffer(m)
if (bb.Len() > 0) && (err == nil) {
buff.WriteByte(10)
buff.ReadFrom(bb)
}
}
return buff
}
func (pt *PlainText) Entry(entry models.Entry) ([]byte, error) {
buff := pt.entryBuffer(entry)
return buff.Bytes(), nil
}
func (pt *PlainText) metaBuffer(meta models.Meta) (*bytes.Buffer, error) {
buff := &bytes.Buffer{}
buff.WriteString(meta.Key)
buff.WriteString(": ")
n, err := tools.WriteValue(buff, meta.Value)
if n == 0 || err != nil {
return &bytes.Buffer{}, err
}
return buff, nil
}
func (pt *PlainText) Meta(meta models.Meta) (out []byte, err error) {
buff, err := pt.metaBuffer(meta)
if err != nil {
return
}
out = buff.Bytes()
return
}

109
formatters/plain_test.go Normal file
View file

@ -0,0 +1,109 @@
package formatters
import (
"bufio"
"bytes"
"fmt"
"testing"
"time"
"codeberg.org/danjones000/my-log/models"
"codeberg.org/danjones000/my-log/tools"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestPlainLog(t *testing.T) {
m := []models.Meta{
{"foo", "bar"},
{"baz", 42},
}
e := []models.Entry{
{Title: "one", Date: time.Now(), Fields: m},
{Title: "small", Date: time.Now()},
}
l := models.Log{"stuff", e}
f, err := New("plain")
require.NoError(t, err)
out, err := f.Log(l)
require.NoError(t, err)
read := bytes.NewReader(out)
scan := bufio.NewScanner(read)
scan.Scan()
line := scan.Text()
assert.Equal(t, l.Name, line)
scan.Scan()
line = scan.Text()
assert.Equal(t, "#######", line)
scan.Scan()
scan.Scan()
line = scan.Text()
assert.Equal(t, "Title: "+e[0].Title, line)
scan.Scan()
line = scan.Text()
assert.Equal(t, "Date: "+e[0].Date.Format(tools.DateFormat), line)
scan.Scan()
line = scan.Text()
assert.Equal(t, "foo: bar", line)
scan.Scan()
line = scan.Text()
assert.Equal(t, "baz: 42", line)
scan.Scan()
scan.Scan()
line = scan.Text()
assert.Equal(t, "Title: "+e[1].Title, line)
scan.Scan()
line = scan.Text()
assert.Equal(t, "Date: "+e[1].Date.Format(tools.DateFormat), line)
more := scan.Scan()
assert.False(t, more)
}
func TestPlainName(t *testing.T) {
f, _ := New("plain")
assert.Equal(t, "plain", f.Name())
}
func TestPlainLogNoEntries(t *testing.T) {
f, _ := New("plain")
out, err := f.Log(models.Log{Name: "foo"})
assert.NoError(t, err)
assert.Len(t, out, 0)
}
func TestPlainMetaEmpty(t *testing.T) {
f, _ := New("plain")
out, err := f.Meta(models.Meta{"foo", ""})
assert.NoError(t, err)
assert.Len(t, out, 0)
}
func TestPlainMetaError(t *testing.T) {
f, _ := New("plain")
out, err := f.Meta(models.Meta{"foo", make(chan bool)})
assert.Error(t, err)
assert.Len(t, out, 0)
}
func TestPlainEntry(t *testing.T) {
f, _ := New("plain")
now := time.Now()
out, err := f.Entry(models.Entry{
Title: "foo",
Date: now,
})
assert.NoError(t, err)
assert.Equal(t, fmt.Sprintf("Title: foo\nDate: %s", now.Format(tools.DateFormat)), string(out))
}