github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/control/controldisplay/table.go (about)

     1  package controldisplay
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/spf13/viper"
     7  	"github.com/turbot/steampipe/pkg/constants"
     8  	"github.com/turbot/steampipe/pkg/control/controlexecute"
     9  )
    10  
    11  type TableRenderer struct {
    12  	resultTree *controlexecute.ExecutionTree
    13  
    14  	// screen width
    15  	width             int
    16  	maxFailedControls int
    17  	maxTotalControls  int
    18  }
    19  
    20  func NewTableRenderer(resultTree *controlexecute.ExecutionTree) *TableRenderer {
    21  	return &TableRenderer{
    22  		resultTree:        resultTree,
    23  		maxFailedControls: resultTree.Root.Summary.Status.FailedCount(),
    24  		maxTotalControls:  resultTree.Root.Summary.Status.TotalCount(),
    25  	}
    26  }
    27  
    28  // MinimumWidth is the width we require
    29  // It is determined by the left indent, title, severity, counter and counter graph
    30  func (r TableRenderer) MinimumWidth() int {
    31  	minimumWidthRequired := r.maxIndent() + minimumGroupTitleWidth + severityMaxLen + minimumCounterWidth + counterGraphSegments
    32  	return minimumWidthRequired
    33  }
    34  
    35  func (r TableRenderer) maxIndent() int {
    36  	depth := r.groupDepth(r.resultTree.Root, 0)
    37  	// each indent level is "| " or "+ " (2 characters)
    38  	return (depth * 2)
    39  }
    40  
    41  func (r TableRenderer) groupDepth(g *controlexecute.ResultGroup, myDepth int) int {
    42  	if len(g.Groups) == 0 {
    43  		return 0
    44  	}
    45  	maxDepth := 0
    46  	for _, subGroup := range g.Groups {
    47  		branchDepth := r.groupDepth(subGroup, myDepth+1)
    48  		if branchDepth > maxDepth {
    49  			maxDepth = branchDepth
    50  		}
    51  	}
    52  	return myDepth + maxDepth
    53  }
    54  
    55  func (r TableRenderer) Render(width int) string {
    56  	r.width = width
    57  
    58  	// the buffer to put the output data in
    59  	builder := strings.Builder{}
    60  
    61  	builder.WriteString(r.renderResult())
    62  	builder.WriteString("\n")
    63  	builder.WriteString(r.renderSummary())
    64  
    65  	return builder.String()
    66  }
    67  
    68  func (r TableRenderer) renderSummary() string {
    69  	// no need to render the summary when the dry-run flag is set
    70  	if viper.GetBool(constants.ArgDryRun) {
    71  		return ""
    72  	}
    73  	return NewSummaryRenderer(r.resultTree, r.width).Render()
    74  }
    75  
    76  func (r TableRenderer) renderResult() string {
    77  	return NewGroupRenderer(r.resultTree.Root, nil, r.maxFailedControls, r.maxTotalControls, r.resultTree, r.width).Render()
    78  }