All checks were successful
ci / Build (push) Successful in 3m7s
- 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>
111 lines
2.8 KiB
Go
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)
|
|
}
|