Skip to content

Commit eb81799

Browse files
tobymuesli
authored andcommitted
Darwin specific implementation for term status
On Darwin, the ioctl syscall requires the `TIOCGETA` and `TIOCSETA` constants. The Google termios library has the Linux constants hard-coded, so this fix reimplements some functions for Darwin. This fixes the dark background check in OS X Terminal.
1 parent 6515b86 commit eb81799

File tree

4 files changed

+97
-26
lines changed

4 files changed

+97
-26
lines changed

examples/hello-world/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,6 @@ func main() {
3636
termenv.String("cyan").Foreground(p.Color("0")).Background(p.Color("#66C2CD")),
3737
termenv.String("gray").Foreground(p.Color("0")).Background(p.Color("#B9BFCA")),
3838
)
39+
40+
fmt.Printf("\n\t%s %t\n", termenv.String("Has dark background?").Bold(), termenv.HasDarkBackground())
3941
}

termenv_darwin.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// +build darwin
2+
3+
package termenv
4+
5+
import (
6+
"fmt"
7+
"os"
8+
"syscall"
9+
"unsafe"
10+
11+
"github.com/google/goterm/term"
12+
)
13+
14+
type Termios struct {
15+
Iflag uintptr
16+
Oflag uintptr
17+
Cflag uintptr
18+
Lflag uintptr
19+
Cc [20]byte
20+
Ispeed uintptr
21+
Ospeed uintptr
22+
}
23+
24+
func Attr(file *os.File) (Termios, error) {
25+
var t Termios
26+
fd := file.Fd()
27+
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGETA), uintptr(unsafe.Pointer(&t)))
28+
if errno != 0 {
29+
return t, errno
30+
}
31+
return t, nil
32+
}
33+
34+
func Set(t Termios, file *os.File) error {
35+
fd := file.Fd()
36+
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCSETA), uintptr(unsafe.Pointer(&t)))
37+
if errno != 0 {
38+
return errno
39+
}
40+
return nil
41+
}
42+
43+
func termStatusReport(sequence int) (string, error) {
44+
t, err := Attr(os.Stdout)
45+
if err != nil {
46+
return "", ErrStatusReport
47+
}
48+
defer Set(t, os.Stdout)
49+
50+
noecho := t
51+
noecho.Lflag &= term.ECHO &^ term.ICANON
52+
if err := Set(noecho, os.Stdout); err != nil {
53+
return "", ErrStatusReport
54+
}
55+
fmt.Printf("\033]%d;?\007", sequence)
56+
s, ok := readWithTimeout(os.Stdout)
57+
if !ok {
58+
return "", ErrStatusReport
59+
}
60+
// fmt.Println("Rcvd", s[1:])
61+
return s, nil
62+
}

termenv_linux.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// +build dragonfly freebsd linux netbsd openbsd solaris
2+
3+
package termenv
4+
5+
import (
6+
"fmt"
7+
"os"
8+
9+
"github.com/google/goterm/term"
10+
)
11+
12+
func termStatusReport(sequence int) (string, error) {
13+
t, err := term.Attr(os.Stdout)
14+
if err != nil {
15+
return "", ErrStatusReport
16+
}
17+
defer t.Set(os.Stdout)
18+
19+
noecho := t
20+
noecho.Lflag = noecho.Lflag &^ term.ECHO
21+
noecho.Lflag = noecho.Lflag &^ term.ICANON
22+
if err := noecho.Set(os.Stdout); err != nil {
23+
return "", ErrStatusReport
24+
}
25+
26+
fmt.Printf("\033]%d;?\007", sequence)
27+
s, ok := readWithTimeout(os.Stdout)
28+
if !ok {
29+
return "", ErrStatusReport
30+
}
31+
// fmt.Println("Rcvd", s[1:])
32+
return s, nil
33+
}

termenv_unix.go

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@
33
package termenv
44

55
import (
6-
"fmt"
76
"os"
87
"strconv"
98
"strings"
109
"syscall"
11-
12-
"github.com/google/goterm/term"
1310
)
1411

1512
func colorProfile() Profile {
@@ -73,29 +70,6 @@ func backgroundColor() Color {
7370
return ANSIColor(0)
7471
}
7572

76-
func termStatusReport(sequence int) (string, error) {
77-
t, err := term.Attr(os.Stdout)
78-
if err != nil {
79-
return "", ErrStatusReport
80-
}
81-
defer t.Set(os.Stdout)
82-
83-
noecho := t
84-
noecho.Lflag = noecho.Lflag &^ term.ECHO
85-
noecho.Lflag = noecho.Lflag &^ term.ICANON
86-
if err := noecho.Set(os.Stdout); err != nil {
87-
return "", ErrStatusReport
88-
}
89-
90-
fmt.Printf("\033]%d;?\007", sequence)
91-
s, ok := readWithTimeout(os.Stdout)
92-
if !ok {
93-
return "", ErrStatusReport
94-
}
95-
// fmt.Println("Rcvd", s[1:])
96-
return s, nil
97-
}
98-
9973
func readWithTimeout(f *os.File) (string, bool) {
10074
var readfds syscall.FdSet
10175
fd := f.Fd()

0 commit comments

Comments
 (0)