github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/ansititle/ansititle_unix.go (about) 1 //go:build !windows && !plan9 && !js 2 // +build !windows,!plan9,!js 3 4 package ansititle 5 6 import ( 7 "bytes" 8 "errors" 9 "os" 10 11 "github.com/lmorg/murex/utils/readline" 12 ) 13 14 var ErrNotTTY = errors.New("not a TTY") 15 16 func Write(title []byte) error { 17 fd := os.Stdout.Fd() 18 if !readline.IsTerminal(int(fd)) { 19 return ErrNotTTY 20 } 21 22 return write(formatTitle(title)) 23 } 24 25 func formatTitle(title []byte) []byte { 26 if len(title) == 0 { 27 return nil 28 } 29 title = sanatise(title) 30 ansi := make([]byte, len(title)+6) 31 32 copy(ansi[0:4], []byte{27, ']', '2', ';'}) 33 copy(ansi[4:len(title)+4], title) 34 //ansi[len(ansi)-1] = 7 35 ansi[len(ansi)-2] = 27 36 ansi[len(ansi)-1] = '\\' 37 38 return ansi 39 } 40 41 func Icon(title []byte) error { 42 fd := os.Stdout.Fd() 43 if !readline.IsTerminal(int(fd)) { 44 return ErrNotTTY 45 } 46 47 return write(formatIcon(title)) 48 } 49 50 func formatIcon(title []byte) []byte { 51 if len(title) == 0 { 52 return nil 53 } 54 title = sanatise(title) 55 ansi := make([]byte, len(title)+6) 56 57 copy(ansi[0:4], []byte{27, ']', '1', ';'}) 58 copy(ansi[4:len(title)+4], title) 59 //ansi[len(ansi)-1] = 7 60 ansi[len(ansi)-2] = 27 61 ansi[len(ansi)-1] = '\\' 62 63 return ansi 64 } 65 66 func Tmux(title []byte) error { 67 fd := os.Stdout.Fd() 68 if !readline.IsTerminal(int(fd)) { 69 return ErrNotTTY 70 } 71 if value, exists := os.LookupEnv("TMUX"); !exists || value == "" { 72 return errors.New("tmux doesn't appear to be running") 73 } 74 75 return write(formatTmux(title)) 76 } 77 78 func formatTmux(title []byte) []byte { 79 if len(title) == 0 { 80 return nil 81 } 82 title = sanatise(title) 83 ansi := make([]byte, len(title)+4) 84 85 copy(ansi[0:2], []byte{27, 'k'}) 86 copy(ansi[2:len(title)+2], title) 87 copy(ansi[len(ansi)-2:], []byte{27, '\\'}) 88 89 return ansi 90 } 91 92 func sanatise(b []byte) []byte { 93 b = bytes.ReplaceAll(b, []byte{'\r'}, nil) 94 // replace all control characters with space 95 for i := range b { 96 if b[i] < 32 || b[i] == 127 { 97 b[i] = 32 98 } 99 } 100 101 return b 102 }