| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- package console
- import (
- "fmt"
- "io"
- "os"
- "strconv"
- "strings"
- "github.com/sirupsen/logrus"
- )
- type resource struct {
- name string
- status string
- details string
- }
- type progress struct {
- console console
- resources []*resource
- }
- type ProgressWriter interface {
- ResourceEvent(name string, status string, details string)
- }
- func NewProgressWriter() ProgressWriter {
- return &progress{
- console: ansiConsole{os.Stdout},
- }
- }
- const (
- blue = "36;2"
- red = "31;1"
- green = "32;1"
- )
- func (p *progress) ResourceEvent(name string, status string, details string) {
- if logrus.IsLevelEnabled(logrus.DebugLevel) {
- logrus.Debugf("> %s : %s %s\n", name, status, details)
- return
- }
- p.console.MoveUp(len(p.resources))
- newResource := true
- for _, r := range p.resources {
- if r.name == name {
- newResource = false
- r.status = status
- r.details = details
- break
- }
- }
- if newResource {
- p.resources = append(p.resources, &resource{name, status, details})
- }
- var width int
- for _, r := range p.resources {
- l := len(r.name)
- if width < l {
- width = l
- }
- }
- for _, r := range p.resources {
- s := r.status
- if strings.HasSuffix(s, "_IN_PROGRESS") {
- s = p.console.WiP(s)
- } else if strings.HasSuffix(s, "_COMPLETE") {
- s = p.console.OK(s)
- } else if strings.HasSuffix(s, "_FAILED") {
- s = p.console.KO(s)
- }
- p.console.ClearLine()
- p.console.Printf("%-"+strconv.Itoa(width)+"s ... %s %s", r.name, s, r.details) // nolint:errcheck
- p.console.MoveDown(1)
- }
- }
- type console interface {
- Printf(format string, a ...interface{})
- MoveUp(int)
- MoveDown(int)
- ClearLine()
- OK(string) string
- KO(string) string
- WiP(string) string
- }
- type ansiConsole struct {
- out io.Writer
- }
- func (c ansiConsole) Printf(format string, a ...interface{}) {
- fmt.Fprintf(c.out, format, a...) // nolint:errcheck
- fmt.Fprintf(c.out, "\r")
- }
- func (c ansiConsole) MoveUp(i int) {
- if i == 0 {
- return
- }
- fmt.Fprintf(c.out, "\033[%dA", i) // nolint:errcheck
- }
- func (c ansiConsole) MoveDown(i int) {
- if i == 0 {
- return
- }
- fmt.Fprintf(c.out, "\033[%dB", i) // nolint:errcheck
- }
- func (c ansiConsole) ClearLine() {
- fmt.Fprint(c.out, "\033[2K\r") // nolint:errcheck
- }
- func (c ansiConsole) OK(s string) string {
- return ansiColor(green, s)
- }
- func (c ansiConsole) KO(s string) string {
- return ansiColor(red, s)
- }
- func (c ansiConsole) WiP(s string) string {
- return ansiColor(blue, s)
- }
- func ansiColor(code, s string) string {
- return fmt.Sprintf("%s%s%s", ansi(code), s, ansi("0"))
- }
- func ansi(code string) string {
- return fmt.Sprintf("\033[%sm", code)
- }
|