返回 DeepSeek-Reasonix
theme_osc_unix.go
根目录 / internal / cli / theme_osc_unix.go
1 //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
2
3 package cli
4
5 import (
6 "errors"
7 "os"
8 "time"
9
10 "golang.org/x/sys/unix"
11 "golang.org/x/term"
12 )
13
14 const (
15 terminalBGQueryTimeout = 80 * time.Millisecond
16 terminalBGQueryMaxBytes = 256
17 )
18
19 func queryTerminalBackground() (terminalRGB, bool) {
20 if !colorOn() {
21 return terminalRGB{}, false
22 }
23 inFd := int(os.Stdin.Fd())
24 outFd := int(os.Stdout.Fd())
25 if !term.IsTerminal(inFd) || !term.IsTerminal(outFd) {
26 return terminalRGB{}, false
27 }
28
29 oldState, err := term.MakeRaw(inFd)
30 if err != nil {
31 return terminalRGB{}, false
32 }
33 defer term.Restore(inFd, oldState)
34
35 flags, err := unix.FcntlInt(uintptr(inFd), unix.F_GETFL, 0)
36 if err != nil {
37 return terminalRGB{}, false
38 }
39 if err := unix.SetNonblock(inFd, true); err != nil {
40 return terminalRGB{}, false
41 }
42 defer func() { _, _ = unix.FcntlInt(uintptr(inFd), unix.F_SETFL, flags) }()
43
44 if _, err := os.Stdout.Write([]byte("\x1b]11;?\x07")); err != nil {
45 return terminalRGB{}, false
46 }
47
48 deadline := time.Now().Add(terminalBGQueryTimeout)
49 buf := make([]byte, 64)
50 var response []byte
51 for time.Now().Before(deadline) && len(response) < terminalBGQueryMaxBytes {
52 n, err := unix.Read(inFd, buf)
53 if n > 0 {
54 response = append(response, buf[:n]...)
55 if rgb, ok := parseOSC11Response(string(response)); ok {
56 return rgb, true
57 }
58 continue
59 }
60 if err == nil || errors.Is(err, unix.EINTR) {
61 continue
62 }
63 if errors.Is(err, unix.EAGAIN) || errors.Is(err, unix.EWOULDBLOCK) {
64 time.Sleep(5 * time.Millisecond)
65 continue
66 }
67 return terminalRGB{}, false
68 }
69 return parseOSC11Response(string(response))
70 }
71
71 lines GO