github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/control/controldisplay/dimensions.go (about) 1 package controldisplay 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 8 "github.com/logrusorgru/aurora" 9 "github.com/turbot/go-kit/helpers" 10 "github.com/turbot/steampipe/pkg/control/controlexecute" 11 ) 12 13 type DimensionsRenderer struct { 14 dimensions []controlexecute.Dimension 15 colorGenerator *controlexecute.DimensionColorGenerator 16 width int 17 } 18 19 func NewDimensionsRenderer(dimensions []controlexecute.Dimension, colorGenerator *controlexecute.DimensionColorGenerator, width int) *DimensionsRenderer { 20 return &DimensionsRenderer{ 21 dimensions: dimensions, 22 colorGenerator: colorGenerator, 23 width: width, 24 } 25 } 26 27 // Render returns the dimensions, truncated to the max length if necessary 28 func (r DimensionsRenderer) Render() string { 29 if r.width <= 0 { 30 // this should never happen, since the minimum width is set by the formatter 31 log.Printf("[WARN] dimensions renderer has width of %d\n", r.width) 32 return "" 33 } 34 if len(r.dimensions) == 0 { 35 return "" 36 } 37 // make array of dimension values (including trailing spaces 38 var formattedDimensions = make([]string, len(r.dimensions)) 39 for i, d := range r.dimensions { 40 formattedDimensions[i] = d.Value 41 } 42 43 var length int 44 for length = dimensionsLength(formattedDimensions); length > r.width; { 45 // truncate the first dimension 46 if helpers.PrintableLength(formattedDimensions[0]) > 0 { 47 // truncate the original value, not the already truncated value 48 newLength := helpers.PrintableLength(formattedDimensions[0]) - 1 49 formattedDimensions[0] = helpers.TruncateString(formattedDimensions[0], newLength) 50 } else { 51 // so event with all dimensions 1 long, we still do not have enough space 52 // remove a dimension from the array 53 if len(formattedDimensions) > 2 { 54 r.dimensions = r.dimensions[1:] 55 formattedDimensions = formattedDimensions[1:] 56 } else { 57 // there is only 1 dimension - nothing we can do here, give up 58 return "" 59 } 60 } 61 // update length 62 length = dimensionsLength(formattedDimensions) 63 } 64 65 // ok we now have dimensions that fit in the space, color them 66 // check whether color is disabled 67 68 coloredDimensions := make([]string, 0, len(r.dimensions)) 69 for i, v := range formattedDimensions { 70 // get the source dimension object 71 dimension := r.dimensions[i] 72 73 if len(strings.TrimSpace(dimension.Value)) == 0 { 74 // if the value of the dimension is empty, skip it 75 continue 76 } 77 78 // get the color code - there must be an entry 79 dimensionColorFunc := func(val interface{}) aurora.Value { 80 // if current theme supports colors, apply coloring 81 if ControlColors.UseColor { 82 dimensionColor := r.colorGenerator.Map[dimension.Key][dimension.Value] 83 return aurora.Index(dimensionColor, val) 84 } 85 return aurora.Reset(val) 86 } 87 88 coloredDimensions = append(coloredDimensions, fmt.Sprintf("%s", dimensionColorFunc(v))) 89 } 90 91 return strings.Join(coloredDimensions, " ") 92 } 93 94 // count the total length of the dimensions 95 func dimensionsLength(dimensionValues []string) int { 96 var res int 97 for _, v := range dimensionValues { 98 res += len(v) 99 } 100 // allow for spaces between the dimensions 101 res += len(dimensionValues) - 1 102 return res 103 }