✨ 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