✨ Add plain text formatter
This commit is contained in:
parent
286ac4557d
commit
89e6c2b3bd
5 changed files with 276 additions and 0 deletions
10
formatters/interface.go
Normal file
10
formatters/interface.go
Normal 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
34
formatters/new.go
Normal 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
35
formatters/new_test.go
Normal 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
88
formatters/plain.go
Normal 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
109
formatters/plain_test.go
Normal 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))
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue