github.com/nektos/act@v0.2.63/pkg/common/draw.go (about) 1 package common 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "strings" 8 ) 9 10 // Style is a specific style 11 type Style int 12 13 // Styles 14 const ( 15 StyleDoubleLine = iota 16 StyleSingleLine 17 StyleDashedLine 18 StyleNoLine 19 ) 20 21 // NewPen creates a new pen 22 func NewPen(style Style, color int) *Pen { 23 bgcolor := 49 24 if os.Getenv("CLICOLOR") == "0" { 25 color = 0 26 bgcolor = 0 27 } 28 return &Pen{ 29 style: style, 30 color: color, 31 bgcolor: bgcolor, 32 } 33 } 34 35 type styleDef struct { 36 cornerTL string 37 cornerTR string 38 cornerBL string 39 cornerBR string 40 lineH string 41 lineV string 42 } 43 44 var styleDefs = []styleDef{ 45 {"\u2554", "\u2557", "\u255a", "\u255d", "\u2550", "\u2551"}, 46 {"\u256d", "\u256e", "\u2570", "\u256f", "\u2500", "\u2502"}, 47 {"\u250c", "\u2510", "\u2514", "\u2518", "\u254c", "\u254e"}, 48 {" ", " ", " ", " ", " ", " "}, 49 } 50 51 // Pen struct 52 type Pen struct { 53 style Style 54 color int 55 bgcolor int 56 } 57 58 // Drawing struct 59 type Drawing struct { 60 buf *strings.Builder 61 width int 62 } 63 64 func (p *Pen) drawTopBars(buf io.Writer, labels ...string) { 65 style := styleDefs[p.style] 66 for _, label := range labels { 67 bar := strings.Repeat(style.lineH, len(label)+2) 68 fmt.Fprintf(buf, " ") 69 fmt.Fprintf(buf, "\x1b[%d;%dm", p.color, p.bgcolor) 70 fmt.Fprintf(buf, "%s%s%s", style.cornerTL, bar, style.cornerTR) 71 fmt.Fprintf(buf, "\x1b[%dm", 0) 72 } 73 fmt.Fprintf(buf, "\n") 74 } 75 func (p *Pen) drawBottomBars(buf io.Writer, labels ...string) { 76 style := styleDefs[p.style] 77 for _, label := range labels { 78 bar := strings.Repeat(style.lineH, len(label)+2) 79 fmt.Fprintf(buf, " ") 80 fmt.Fprintf(buf, "\x1b[%d;%dm", p.color, p.bgcolor) 81 fmt.Fprintf(buf, "%s%s%s", style.cornerBL, bar, style.cornerBR) 82 fmt.Fprintf(buf, "\x1b[%dm", 0) 83 } 84 fmt.Fprintf(buf, "\n") 85 } 86 func (p *Pen) drawLabels(buf io.Writer, labels ...string) { 87 style := styleDefs[p.style] 88 for _, label := range labels { 89 fmt.Fprintf(buf, " ") 90 fmt.Fprintf(buf, "\x1b[%d;%dm", p.color, p.bgcolor) 91 fmt.Fprintf(buf, "%s %s %s", style.lineV, label, style.lineV) 92 fmt.Fprintf(buf, "\x1b[%dm", 0) 93 } 94 fmt.Fprintf(buf, "\n") 95 } 96 97 // DrawArrow between boxes 98 func (p *Pen) DrawArrow() *Drawing { 99 drawing := &Drawing{ 100 buf: new(strings.Builder), 101 width: 1, 102 } 103 fmt.Fprintf(drawing.buf, "\x1b[%dm", p.color) 104 fmt.Fprintf(drawing.buf, "\u2b07") 105 fmt.Fprintf(drawing.buf, "\x1b[%dm", 0) 106 return drawing 107 } 108 109 // DrawBoxes to draw boxes 110 func (p *Pen) DrawBoxes(labels ...string) *Drawing { 111 width := 0 112 for _, l := range labels { 113 width += len(l) + 2 + 2 + 1 114 } 115 drawing := &Drawing{ 116 buf: new(strings.Builder), 117 width: width, 118 } 119 p.drawTopBars(drawing.buf, labels...) 120 p.drawLabels(drawing.buf, labels...) 121 p.drawBottomBars(drawing.buf, labels...) 122 123 return drawing 124 } 125 126 // Draw to writer 127 func (d *Drawing) Draw(writer io.Writer, centerOnWidth int) { 128 padSize := (centerOnWidth - d.GetWidth()) / 2 129 if padSize < 0 { 130 padSize = 0 131 } 132 for _, l := range strings.Split(d.buf.String(), "\n") { 133 if len(l) > 0 { 134 padding := strings.Repeat(" ", padSize) 135 fmt.Fprintf(writer, "%s%s\n", padding, l) 136 } 137 } 138 } 139 140 // GetWidth of drawing 141 func (d *Drawing) GetWidth() int { 142 return d.width 143 }