package door import ( "fmt" "strings" ) type BarStyle int8 const ( SOLID BarStyle = iota HALF_STEP GRADIENT ) type Percent_Style int8 const ( PERCENT_NONE Percent_Style = iota PERCENT PERCENT_SPACE ) type BarRange struct { Percent int64 Color string } type BarLine struct { Width int Style BarStyle Percent int64 // percentage * 100 PercentStyle Percent_Style ColorRange []BarRange UpdateP func() int64 Line } func (bl *BarLine) CheckRange() { if len(bl.ColorRange) != 0 { // Ok, there is a color range. Get checking for _, br := range bl.ColorRange { if bl.Percent <= br.Percent { bl.DefaultColor = br.Color break } } } } func (bl *BarLine) Output() string { var output string var step_width int64 if bl.UpdateP != nil { bl.Percent = bl.UpdateP() } bl.CheckRange() switch bl.Style { case SOLID: step_width = int64(100 * 100 / bl.Width) var steps int = int(bl.Percent / step_width) if Unicode { output += strings.Repeat("\u2588", steps) } else { output += strings.Repeat("\xdb", steps) } // This will work, because we aren't trying to len(output) with unicode. output += strings.Repeat(" ", int(bl.Width-steps)) case HALF_STEP: step_width = int64(100 * 100 / bl.Width) var steps int = int(bl.Percent * 2 / step_width) if Unicode { output += strings.Repeat("\u2588", steps/2) } else { output += strings.Repeat("\xdb", steps/2) } if steps%2 == 1 { if Unicode { output += "\u258c" } else { output += "\xdd" } steps++ } output += strings.Repeat(" ", bl.Width-(steps/2)) case GRADIENT: step_width = int64(100 * 100 / bl.Width) var steps int = int(bl.Percent * 4 / step_width) if Unicode { output += strings.Repeat("\u2588", steps/4) } else { output += strings.Repeat("\xdb", steps/4) } if steps%4 != 0 { switch steps % 4 { case 1: if Unicode { output += "\u2591" } else { output += "\xb0" } case 2: if Unicode { output += "\u2592" } else { output += "\xb1" } case 3: if Unicode { output += "\u2593" } else { output += "\xb2" } } for steps%4 != 0 { steps++ } } output += strings.Repeat(" ", bl.Width-(steps/4)) } if bl.PercentStyle != PERCENT_NONE { percent := fmt.Sprintf("%d", bl.Percent/100) var pos int = bl.Width/2 - 1 if percent != "100" { percent += "%" if len(percent) < 3 { percent = " " + percent } } if bl.PercentStyle == PERCENT_SPACE { percent = " " + percent + " " pos-- } // to process/slice the string (with unicode) do this: // convert to []rune, slice that, convert back to string // // sliceable := []rune(output) // newString := string(sliceable[:5]) + " new content " + (sliceable[10:]) // fmt.Printf("%d %d [%s] %d [%s]\n", bl.Width, pos, percent, len(output), output) if Unicode { runes := []rune(output) output = string(runes[:pos]) + percent + string(runes[pos+len(percent):]) } else { output = output[:pos] + percent + output[pos+len(percent):] } } return bl.DefaultColor + output }