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  }