dynamo-browse/internal/dynamo-browse/services/itemrenderer/service.go
2025-11-01 09:50:55 +11:00

102 lines
2.5 KiB
Go

package itemrenderer
import (
"fmt"
"io"
"text/tabwriter"
"lmika.dev/cmd/dynamo-browse/internal/dynamo-browse/models"
"lmika.dev/cmd/dynamo-browse/internal/dynamo-browse/models/itemrender"
)
type Service struct {
annotations Annotation
styles styleRenderer
}
func NewService(
annotations Annotation,
fileTypeStyle StyleRenderer,
metaInfoStyle StyleRenderer,
) *Service {
return &Service{
annotations: testAnnotation{},
styles: styleRenderer{
fileTypeRenderer: fileTypeStyle,
metaInfoRenderer: metaInfoStyle,
},
}
}
func (s *Service) RenderItem(w io.Writer, item models.Item, resultSet *models.ResultSet, plainText bool) {
styles := s.styles
if plainText {
styles = styleRenderer{plainTextStyleRenderer{}, plainTextStyleRenderer{}}
}
tabWriter := tabwriter.NewWriter(w, 0, 1, 1, ' ', 0)
seenColumns := make(map[string]struct{})
for _, colName := range resultSet.Columns() {
seenColumns[colName] = struct{}{}
if r := itemrender.ToRenderer(item[colName]); r != nil {
p := models.AttrPathNode{Key: colName}
s.renderItem(tabWriter, resultSet, item, p, "", r, styles)
}
}
for k, _ := range item {
if _, seen := seenColumns[k]; !seen {
if r := itemrender.ToRenderer(item[k]); r != nil {
p := models.AttrPathNode{Key: k}
s.renderItem(tabWriter, resultSet, item, p, "", r, styles)
}
}
}
tabWriter.Flush()
}
func (m *Service) renderItem(
w io.Writer,
resultSet *models.ResultSet,
item models.Item,
path models.AttrPathNode,
prefix string,
r itemrender.Renderer,
sr styleRenderer,
) {
fmt.Fprint(w, prefix)
fmt.Fprint(w, path.Key)
fmt.Fprint(w, "\t")
fmt.Fprint(w, sr.fileTypeRenderer.Render(r.TypeName()))
fmt.Fprint(w, "\t")
fmt.Fprint(w, r.StringValue())
fmt.Fprint(w, sr.metaInfoRenderer.Render(r.MetaInfo()))
if m.annotations != nil {
fmt.Fprint(w, " ")
fmt.Fprint(w, sr.metaInfoRenderer.Render(m.annotations.AnnotateAttribute(resultSet, item, path)))
}
fmt.Fprint(w, "\n")
if subitems := r.SubItems(); len(subitems) > 0 {
for _, si := range subitems {
p := models.AttrPathNode{Key: si.Key, Parent: &path}
m.renderItem(w, resultSet, item, p, prefix+" ", si.Value, sr)
}
}
}
type styleRenderer struct {
fileTypeRenderer StyleRenderer
metaInfoRenderer StyleRenderer
}
type Annotation interface {
AnnotateAttribute(rs *models.ResultSet, item models.Item, path models.AttrPathNode) string
}
type testAnnotation struct{}
func (t testAnnotation) AnnotateAttribute(rs *models.ResultSet, item models.Item, path models.AttrPathNode) string {
return "( annotation of " + path.Key + " )"
}