package terminal import ( "errors" "fmt" "io" gotty "github.com/ijc/Gotty" ) type Info interface { Parse(attr string, params ...interface{}) (string, error) ClearEnd(out io.Writer) ClearLine(out io.Writer) CursorUp(out io.Writer, count int) CursorDown(out io.Writer, count int) HideCursor(out io.Writer) ShowCursor(out io.Writer) } /* Satisfied by gotty.TermInfo as well as noTermInfo from below */ type termInfo interface { Parse(attr string, params ...interface{}) (string, error) } type noTermInfo int // canary used when no terminfo. func (ti noTermInfo) Parse(attr string, params ...interface{}) (string, error) { return "", errors.New("noTermInfo") } type info struct { termInfo } var _ = Info(info{}) func OpenInfo(terminal string) Info { if i, err := gotty.OpenTermInfo(terminal); err == nil { return info{i} } return info{noTermInfo(0)} } func (i info) ClearLine(out io.Writer) { // el2 (clear whole line) is not exposed by terminfo. // First clear line from beginning to cursor if attr, err := i.Parse("el1"); err == nil { fmt.Fprintf(out, "%s", attr) } else { fmt.Fprintf(out, "\x1b[1K") } // Then clear line from cursor to end if attr, err := i.Parse("el"); err == nil { fmt.Fprintf(out, "%s", attr) } else { fmt.Fprintf(out, "\x1b[K") } } func (i info) ClearEnd(out io.Writer) { // clear line from cursor to end if attr, err := i.Parse("el"); err == nil { fmt.Fprintf(out, "%s", attr) } else { fmt.Fprintf(out, "\x1b[K") } } func (i info) CursorUp(out io.Writer, count int) { if count == 0 { // Should never be the case, but be tolerant return } if attr, err := i.Parse("cuu", count); err == nil { fmt.Fprintf(out, "%s", attr) } else { fmt.Fprintf(out, "\x1b[%dA", count) } } func (i info) CursorDown(out io.Writer, count int) { if count == 0 { // Should never be the case, but be tolerant return } if attr, err := i.Parse("cud", count); err == nil { fmt.Fprintf(out, "%s", attr) } else { fmt.Fprintf(out, "\x1b[%dB", count) } } func (i info) HideCursor(out io.Writer) { if attr, err := i.Parse("civis"); err == nil { fmt.Fprintf(out, "%s", attr) } } func (i info) ShowCursor(out io.Writer) { if attr, err := i.Parse("cnorm"); err == nil { fmt.Fprintf(out, "%s", attr) } }