dynamo-browse/internal/dynamo-browse/services/itemrenderer/service.go
Leon Mika 4fb9dd0b5b
All checks were successful
ci / Build (push) Successful in 3m7s
Item annotations and async methods (#4)
- New UCL method for setting up item annotations
- New UCL package for running commands asynchronously

Reviewed-on: #4
Co-authored-by: Leon Mika <lmika@lmika.org>
Co-committed-by: Leon Mika <lmika@lmika.org>
2025-11-04 03:30:43 +00:00

111 lines
2.8 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 {
annotation Annotation
styles styleRenderer
}
func NewService(
fileTypeStyle StyleRenderer,
metaInfoStyle StyleRenderer,
) *Service {
if fileTypeStyle == nil {
fileTypeStyle = plainTextStyleRenderer{}
}
if metaInfoStyle == nil {
metaInfoStyle = plainTextStyleRenderer{}
}
return &Service{
annotation: nil,
styles: styleRenderer{
fileTypeRenderer: fileTypeStyle,
metaInfoRenderer: metaInfoStyle,
},
}
}
func (s *Service) SetAnnotation(a Annotation) {
s.annotation = a
}
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.annotation != nil {
fmt.Fprint(w, " ")
fmt.Fprint(w, sr.metaInfoRenderer.Render(m.annotation.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 AnnotationFunc func(rs *models.ResultSet, item models.Item, path models.AttrPathNode) string
func (af AnnotationFunc) AnnotateAttribute(rs *models.ResultSet, item models.Item, path models.AttrPathNode) string {
return af(rs, item, path)
}