github.com/myhau/pulumi/pkg/v3@v3.70.2-0.20221116134521-f2775972e587/backend/display/internal/terminal/info.go (about) 1 package terminal 2 3 import ( 4 "fmt" 5 "io" 6 7 gotty "github.com/ijc/Gotty" 8 ) 9 10 type Info interface { 11 Parse(attr string, params ...interface{}) (string, error) 12 13 ClearLine(out io.Writer) 14 CursorUp(out io.Writer, count int) 15 CursorDown(out io.Writer, count int) 16 } 17 18 /* Satisfied by gotty.TermInfo as well as noTermInfo from below */ 19 type termInfo interface { 20 Parse(attr string, params ...interface{}) (string, error) 21 } 22 23 type noTermInfo int // canary used when no terminfo. 24 25 func (ti noTermInfo) Parse(attr string, params ...interface{}) (string, error) { 26 return "", fmt.Errorf("noTermInfo") 27 } 28 29 type info struct { 30 termInfo 31 } 32 33 var _ = Info(info{}) 34 35 func OpenInfo(terminal string) Info { 36 if i, err := gotty.OpenTermInfo(terminal); err == nil { 37 return info{i} 38 } 39 return info{noTermInfo(0)} 40 } 41 42 func (i info) ClearLine(out io.Writer) { 43 // el2 (clear whole line) is not exposed by terminfo. 44 45 // First clear line from beginning to cursor 46 if attr, err := i.Parse("el1"); err == nil { 47 fmt.Fprintf(out, "%s", attr) 48 } else { 49 fmt.Fprintf(out, "\x1b[1K") 50 } 51 // Then clear line from cursor to end 52 if attr, err := i.Parse("el"); err == nil { 53 fmt.Fprintf(out, "%s", attr) 54 } else { 55 fmt.Fprintf(out, "\x1b[K") 56 } 57 } 58 59 func (i info) CursorUp(out io.Writer, count int) { 60 if count == 0 { // Should never be the case, but be tolerant 61 return 62 } 63 if attr, err := i.Parse("cuu", count); err == nil { 64 fmt.Fprintf(out, "%s", attr) 65 } else { 66 fmt.Fprintf(out, "\x1b[%dA", count) 67 } 68 } 69 70 func (i info) CursorDown(out io.Writer, count int) { 71 if count == 0 { // Should never be the case, but be tolerant 72 return 73 } 74 if attr, err := i.Parse("cud", count); err == nil { 75 fmt.Fprintf(out, "%s", attr) 76 } else { 77 fmt.Fprintf(out, "\x1b[%dB", count) 78 } 79 }