Update Dependencies (#390)

Co-authored-by: Norwin Roosen <git@nroo.de>
Co-authored-by: Norwin <git@nroo.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/390
Reviewed-by: 6543 <6543@obermui.de>
Reviewed-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: Norwin <noerw@noreply.gitea.io>
Co-committed-by: Norwin <noerw@noreply.gitea.io>
This commit is contained in:
Norwin
2021-08-30 23:18:50 +08:00
committed by Andrew Thornton
parent 4b9907fb54
commit d6df0a53b5
665 changed files with 29466 additions and 24547 deletions

View File

@@ -5,7 +5,6 @@ package termenv
import (
"fmt"
"os"
"runtime"
"strconv"
"strings"
@@ -84,53 +83,100 @@ func backgroundColor() Color {
return ANSIColor(0)
}
func readWithTimeout(f *os.File) (string, bool) {
var readfds unix.FdSet
fd := int(f.Fd())
readfds.Set(fd)
for {
// Use select to attempt to read from os.Stdout for 100 ms
_, err := unix.Select(fd+1, &readfds, nil, nil, &unix.Timeval{Usec: 100000})
if err == nil {
break
}
// On MacOS we can see EINTR here if the user
// pressed ^Z. Similar to issue https://github.com/golang/go/issues/22838
if runtime.GOOS == "darwin" && err == unix.EINTR {
continue
}
// log.Printf("select(read error): %v", err)
return "", false
func readNextByte(f *os.File) (byte, error) {
var b [1]byte
n, err := f.Read(b[:])
if err != nil {
return 0, err
}
if !readfds.IsSet(fd) {
// log.Print("select(read timeout)")
return "", false
if n == 0 {
panic("read returned no data")
}
// n > 0 => is readable
var data []byte
b := make([]byte, 1)
for {
_, err := f.Read(b)
return b[0], nil
}
// readNextResponse reads either an OSC response or a cursor position response:
// * OSC response: "\x1b]11;rgb:1111/1111/1111\x1b\\"
// * cursor position response: "\x1b[42;1R"
func readNextResponse(fd *os.File) (response string, isOSC bool, err error) {
start, err := readNextByte(fd)
if err != nil {
return "", false, err
}
// if we encounter a backslash, this is a left-over from the previous OSC
// response, which can be terminated by an optional backslash
if start == '\\' {
start, err = readNextByte(fd)
if err != nil {
// log.Printf("read(%d): %v %d", fd, err, n)
return "", false
return "", false, err
}
// log.Printf("read %d bytes from stdout: %s %d\n", n, data, data[len(data)-1])
}
data = append(data, b[0])
if b[0] == '\a' || (b[0] == '\\' && len(data) > 2) {
// first byte must be ESC
if start != '\033' {
return "", false, ErrStatusReport
}
response += string(start)
// next byte is either '[' (cursor position response) or ']' (OSC response)
tpe, err := readNextByte(fd)
if err != nil {
return "", false, err
}
response += string(tpe)
var oscResponse bool
switch tpe {
case '[':
oscResponse = false
case ']':
oscResponse = true
default:
return "", false, ErrStatusReport
}
for {
b, err := readNextByte(os.Stdout)
if err != nil {
return "", false, err
}
response += string(b)
if oscResponse {
// OSC can be terminated by BEL (\a) or ST (ESC)
if b == '\a' || strings.HasSuffix(response, "\033") {
return response, true, nil
}
} else {
// cursor position response is terminated by 'R'
if b == 'R' {
return response, false, nil
}
}
// both responses have less than 25 bytes, so if we read more, that's an error
if len(response) > 25 {
break
}
}
// fmt.Printf("read %d bytes from stdout: %s\n", n, data)
return string(data), true
return "", false, ErrStatusReport
}
func termStatusReport(sequence int) (string, error) {
// screen/tmux can't support OSC, because they can be connected to multiple
// terminals concurrently.
term := os.Getenv("TERM")
if strings.HasPrefix(term, "screen") {
return "", ErrStatusReport
}
t, err := unix.IoctlGetTermios(unix.Stdout, tcgetattr)
if err != nil {
return "", ErrStatusReport
@@ -144,11 +190,29 @@ func termStatusReport(sequence int) (string, error) {
return "", ErrStatusReport
}
fmt.Printf("\033]%d;?\007", sequence)
s, ok := readWithTimeout(os.Stdout)
if !ok {
// first, send OSC query, which is ignored by terminal which do not support it
fmt.Printf("\033]%d;?\033\\", sequence)
// then, query cursor position, should be supported by all terminals
fmt.Printf("\033[6n")
// read the next response
res, isOSC, err := readNextResponse(os.Stdout)
if err != nil {
return "", err
}
// if this is not OSC response, then the terminal does not support it
if !isOSC {
return "", ErrStatusReport
}
// fmt.Println("Rcvd", s[1:])
return s, nil
// read the cursor query response next and discard the result
_, _, err = readNextResponse(os.Stdout)
if err != nil {
return "", err
}
// fmt.Println("Rcvd", res[1:])
return res, nil
}