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  }