github.com/henvic/wedeploycli@v1.7.6-0.20200319005353-3630f582f284/shell/internal/termsession/termsession.go (about) 1 package termsession 2 3 import ( 4 "context" 5 "os" 6 7 "github.com/henvic/wedeploycli/verbose" 8 "github.com/wedeploy/gosocketio" 9 "golang.org/x/crypto/ssh/terminal" 10 ) 11 12 // TermSession to use on the shell. 13 type TermSession struct { 14 ctx context.Context 15 cancel context.CancelFunc 16 17 fd int 18 isTerm bool 19 width int 20 height int 21 state *terminal.State 22 23 watcher chan os.Signal 24 25 socket *gosocketio.Namespace 26 } 27 28 // New terminal session. 29 func New(shell *gosocketio.Namespace) *TermSession { 30 return &TermSession{ 31 fd: int(os.Stdin.Fd()), 32 socket: shell, 33 } 34 } 35 36 // Start terminal session. 37 func (t *TermSession) Start(ctx context.Context, tty bool) (err error) { 38 t.isTerm = tty 39 40 if !t.isTerm { 41 return nil 42 } 43 44 t.ctx, t.cancel = context.WithCancel(ctx) 45 t.start() 46 47 t.state, err = terminal.MakeRaw(t.fd) 48 49 if err != nil { 50 return err 51 } 52 53 if t.isTerm { 54 go t.watchResize() 55 } 56 57 return nil 58 } 59 60 // Resize the terminal session if proportions changed. 61 func (t *TermSession) Resize() { 62 if !t.isTerm { 63 return 64 } 65 66 width, height, err := terminal.GetSize(t.fd) 67 68 if err != nil { 69 verbose.Debug("can't get resize dimensions:", err) 70 return 71 } 72 73 if width == 0 || height == 0 || (width == t.width && height == t.height) { 74 return 75 } 76 77 t.width = width 78 t.height = height 79 80 if t.socket == nil { 81 verbose.Debug("Can't send resize terminal signal (socket not set)") 82 } 83 84 r := map[string]int{ 85 "width": width, 86 "height": height, 87 } 88 89 if err := t.socket.Emit("resize", &r); err != nil { 90 verbose.Debug("error emitting resize message:", err) 91 } 92 } 93 94 // Restore the terminal connected (close). 95 func (t *TermSession) Restore() error { 96 if !t.isTerm { 97 return nil 98 } 99 100 t.restore() 101 102 if t.state == nil { 103 return nil 104 } 105 106 return terminal.Restore(t.fd, t.state) 107 }