github.com/Code-Hex/battery@v1.0.0/battery.go (about) 1 package battery 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "math" 8 "strconv" 9 10 "github.com/fatih/color" 11 ) 12 13 // LENGTH: 8 14 var chars = []string{ 15 "▏", 16 "▎", 17 "▍", 18 "▌", 19 "▋", 20 "▊", 21 "▉", 22 "█", 23 } 24 25 // Icons of battery 26 var icons = []string{ 27 " ", 28 " ", 29 " ", 30 " ", 31 " ", 32 " ", 33 } 34 35 type Bar struct { 36 buffer bytes.Buffer 37 gauge string 38 gaugeWidth int 39 width int 40 nowVal int 41 elapsed int 42 totalVal int 43 charLen int 44 format string 45 prefix string 46 postfix string 47 charge string 48 ShowPercent bool 49 ShowCounter bool 50 Showthunder bool 51 ShowElapsed bool 52 ShowIcon bool 53 EnableColor bool 54 EnableTmux bool 55 } 56 57 func digit(num int) string { 58 return strconv.Itoa(int(math.Log10(float64(num))) + 1) 59 } 60 61 func New(total int) *Bar { 62 if total <= 0 { 63 panic(errors.New("Please specify total size that is greater than zero")) 64 } 65 bar := &Bar{ 66 buffer: bytes.Buffer{}, 67 totalVal: total, 68 nowVal: -1, 69 charLen: len(chars), 70 format: "%s", 71 prefix: "|", 72 postfix: "|", 73 charge: "ϟ", 74 ShowPercent: true, 75 ShowCounter: true, 76 Showthunder: false, 77 ShowElapsed: false, 78 ShowIcon: false, 79 EnableColor: false, 80 EnableTmux: true, 81 } 82 return bar.SetWidth(3) 83 } 84 85 func (bar *Bar) SetPrefix(char rune) *Bar { 86 bar.prefix = string(char) 87 return bar 88 } 89 90 func (bar *Bar) SetPostfix(char rune) *Bar { 91 bar.postfix = string(char) 92 return bar 93 } 94 95 func (bar *Bar) SetWidth(width int) *Bar { 96 bar.width = width 97 // +1 for postfix 98 bar.gaugeWidth = width + 1 99 100 return bar 101 } 102 103 func (bar *Bar) Set(percent, elapsed int) *Bar { 104 bar.nowVal = percent 105 bar.elapsed = elapsed 106 return bar 107 } 108 109 func (bar *Bar) Run() { 110 bar.writer() 111 } 112 113 func (bar *Bar) writer() { 114 if bar.ShowPercent { 115 bar.format = "%3d%%" + bar.format 116 } 117 118 if bar.ShowCounter { 119 digit := digit(bar.totalVal) 120 bar.format += " %" + digit + "d/%" + digit + "d" 121 } 122 123 if bar.ShowElapsed { 124 bar.format += "%s" 125 } 126 127 if bar.nowVal <= bar.totalVal { 128 bar.print() 129 } 130 131 } 132 133 func (bar *Bar) print() { 134 frac := float64(bar.nowVal) / float64(bar.totalVal) 135 136 if bar.Showthunder { 137 // append prefix 138 bar.gauge += bar.prefix 139 mid := int(math.Ceil(float64(bar.gaugeWidth / 2))) 140 for i := 1; i < mid; i++ { 141 bar.gauge += " " 142 } 143 // Middle 144 bar.gauge += bar.charge 145 for i := mid + 1; i < bar.gaugeWidth; i++ { 146 bar.gauge += " " 147 } 148 // append postfix 149 bar.gauge += bar.postfix 150 bar.write(frac) 151 152 return 153 } 154 155 if bar.ShowIcon { 156 // append an icon 157 bar.gauge += icons[bar.nowVal / 20] 158 } else { 159 barLen, fracBarLen := bar.divmod(frac) 160 161 // append prefix 162 bar.gauge += bar.prefix 163 164 // append full block 165 for i := 1; i < barLen; i++ { 166 bar.gauge += chars[bar.charLen-1] 167 } 168 169 // append lower block 170 bar.gauge += chars[fracBarLen] 171 172 // padding with whitespace 173 for i := barLen + 1; i < bar.gaugeWidth; i++ { 174 bar.gauge += " " 175 } 176 // append postfix 177 bar.gauge += bar.postfix 178 } 179 180 bar.write(frac) 181 } 182 183 func (bar *Bar) write(frac float64) { 184 var args []interface{} 185 percent := int(frac * 100) 186 187 if bar.ShowPercent { 188 args = append(args, percent) 189 } 190 191 args = append(args, string(bar.gauge)) 192 193 if bar.ShowCounter { 194 args = append(args, bar.nowVal) 195 args = append(args, bar.totalVal) 196 } 197 198 if bar.ShowElapsed { 199 if bar.elapsed > 0 { 200 args = append(args, fmt.Sprintf(" %d:%02d", bar.elapsed/60, bar.elapsed%60)) 201 } else { 202 args = append(args, "") 203 } 204 } 205 206 if bar.EnableColor { 207 if bar.EnableTmux { 208 bar.colorTmuxPrint(percent, args...) 209 } else { 210 bar.colorPrint(percent, args...) 211 } 212 } else { 213 fmt.Fprintf(&bar.buffer, bar.format, args...) 214 } 215 color.Output.Write(bar.buffer.Bytes()) 216 } 217 218 func (bar *Bar) colorTmuxPrint(percent int, args ...interface{}) { 219 if percent >= 60 { 220 bar.format = "#[fg=green]" + bar.format 221 } else if 20 <= percent && percent < 60 { 222 bar.format = "#[fg=yellow]" + bar.format 223 } else { 224 bar.format = "#[fg=red]" + bar.format 225 } 226 fmt.Fprintf(&bar.buffer, bar.format+"#[default]", args...) 227 } 228 229 func (bar *Bar) colorPrint(percent int, args ...interface{}) { 230 if percent >= 60 { 231 bar.buffer.WriteString(color.GreenString(bar.format, args...)) 232 } else if 20 <= percent && percent < 60 { 233 bar.buffer.WriteString(color.YellowString(bar.format, args...)) 234 } else { 235 bar.buffer.WriteString(color.RedString(bar.format, args...)) 236 } 237 } 238 239 func (bar *Bar) divmod(frac float64) (int, int) { 240 // Over 100% 241 if frac >= 1.0 { 242 return bar.width, bar.charLen - 1 243 } 244 pre := int(frac * float64(bar.width) * float64(bar.charLen)) 245 return pre/bar.charLen + 1, pre % bar.charLen 246 }