-
Notifications
You must be signed in to change notification settings - Fork 40
/
tty.go
97 lines (81 loc) · 1.72 KB
/
tty.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package instance
import (
"errors"
"os"
"os/signal"
"syscall"
"github.com/moby/term"
)
var terminationSignals = []os.Signal{syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT}
type Tty struct {
fdout uintptr
fdin uintptr
outPrevState *term.State
inPrevState *term.State
resizeChan chan sizeMsg
interruptChan chan struct{}
}
type sizeMsg struct {
width uint32
height uint32
}
func NewTty() *Tty {
fdout := os.Stdout.Fd()
fdin := os.Stdin.Fd()
resizeChan := make(chan sizeMsg, 1)
interruptChan := make(chan struct{}, 1)
return &Tty{
fdout: fdout,
fdin: fdin,
resizeChan: resizeChan,
interruptChan: interruptChan,
}
}
func (tty *Tty) GetTtySize() (uint32, uint32) {
ws, err := term.GetWinsize(tty.fdout)
if err != nil {
return 0, 0
}
return uint32(ws.Width), uint32(ws.Height)
}
func (tty *Tty) SetTtyTerminal() error {
var err error
tty.outPrevState, err = term.SetRawTerminalOutput(tty.fdout)
if err != nil {
return err
}
tty.inPrevState, err = term.SetRawTerminal(tty.fdin)
if err != nil {
return err
}
return err
}
func (tty *Tty) RestoreTerminal() error {
if tty.outPrevState != nil {
err := term.RestoreTerminal(tty.fdout, tty.outPrevState)
if err != nil {
return err
}
}
if tty.inPrevState != nil {
err := term.RestoreTerminal(tty.fdin, tty.inPrevState)
if err != nil {
return err
}
}
return nil
}
func (tty *Tty) MonitorInterrupt(interruptChan chan error) error {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, terminationSignals...)
defer func() {
signal.Stop(sigChan)
close(sigChan)
}()
go func() {
for range sigChan {
interruptChan <- errors.New("interrupted")
}
}()
return nil
}