github.com/tomwright/dasel@v1.27.3/output_formatter.go (about)

     1  package dasel
     2  
     3  import (
     4  	"bytes"
     5  	"github.com/Masterminds/sprig/v3"
     6  	"text/template"
     7  )
     8  
     9  // FormatNode formats a node with the format template and returns the result.
    10  func FormatNode(node *Node, format string) (*bytes.Buffer, error) {
    11  	tpl, err := formatNodeTemplate(
    12  		&templateNode{
    13  			Node:    node,
    14  			isFirst: true,
    15  			isLast:  true,
    16  		},
    17  	).Parse(format)
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  
    22  	buf := new(bytes.Buffer)
    23  
    24  	err = tpl.Execute(buf, node.InterfaceValue())
    25  	return buf, err
    26  }
    27  
    28  type templateNode struct {
    29  	*Node
    30  
    31  	isFirst bool
    32  	isLast  bool
    33  }
    34  
    35  // FormatNodes formats a slice of nodes with the format template and returns the result.
    36  func FormatNodes(nodes []*Node, format string) (*bytes.Buffer, error) {
    37  	buf := new(bytes.Buffer)
    38  	nodesLen := len(nodes)
    39  	for k, node := range nodes {
    40  		tpl, err := formatNodeTemplate(
    41  			&templateNode{
    42  				Node:    node,
    43  				isFirst: k == 0,
    44  				isLast:  k == (nodesLen - 1),
    45  			},
    46  		).Parse(format)
    47  		if err != nil {
    48  			return nil, err
    49  		}
    50  
    51  		if err := tpl.Execute(buf, node.InterfaceValue()); err != nil {
    52  			return nil, err
    53  		}
    54  	}
    55  	return buf, nil
    56  }
    57  
    58  type formatTemplateFuncs struct {
    59  	node *templateNode
    60  }
    61  
    62  func (funcs *formatTemplateFuncs) funcMap() template.FuncMap {
    63  	return template.FuncMap{
    64  		"query":          funcs.query,
    65  		"queryMultiple":  funcs.queryMultiple,
    66  		"select":         funcs.query,
    67  		"selectMultiple": funcs.queryMultiple,
    68  		"format":         funcs.format,
    69  		"isFirst":        funcs.isFirst,
    70  		"isLast":         funcs.isLast,
    71  		"newline":        funcs.newline,
    72  	}
    73  }
    74  
    75  func (funcs *formatTemplateFuncs) newline() string {
    76  	return "\n"
    77  }
    78  
    79  func (funcs *formatTemplateFuncs) isFirst() bool {
    80  	return funcs.node.isFirst
    81  }
    82  
    83  func (funcs *formatTemplateFuncs) isLast() bool {
    84  	return funcs.node.isLast
    85  }
    86  
    87  func (funcs *formatTemplateFuncs) query(selector string) *Node {
    88  	res, err := funcs.node.Query(selector)
    89  	if err != nil {
    90  		return nil
    91  	}
    92  	return res
    93  }
    94  
    95  func (funcs *formatTemplateFuncs) queryMultiple(selector string) []*Node {
    96  	res, err := funcs.node.QueryMultiple(selector)
    97  	if err != nil {
    98  		return nil
    99  	}
   100  	return res
   101  }
   102  
   103  func (funcs *formatTemplateFuncs) format(format string, target interface{}) string {
   104  	switch t := target.(type) {
   105  	case []*Node:
   106  		buf, err := FormatNodes(t, format)
   107  		if err != nil {
   108  			return err.Error()
   109  		}
   110  		res := buf.String()
   111  		return res
   112  	case *Node:
   113  		buf, err := FormatNode(t, format)
   114  		if err != nil {
   115  			return err.Error()
   116  		}
   117  		return buf.String()
   118  	}
   119  
   120  	return "<nil>"
   121  }
   122  
   123  func formatNodeTemplate(node *templateNode) *template.Template {
   124  	funcs := &formatTemplateFuncs{
   125  		node: node,
   126  	}
   127  	return template.
   128  		New("nodeFormat").
   129  		Funcs(sprig.TxtFuncMap()).
   130  		Funcs(funcs.funcMap())
   131  }