github.com/mithrandie/csvq@v1.18.1/lib/terminal/terminal_general.go (about)

     1  //go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows
     2  
     3  package terminal
     4  
     5  import (
     6  	"context"
     7  	"io"
     8  
     9  	"github.com/mithrandie/csvq/lib/option"
    10  	"github.com/mithrandie/csvq/lib/query"
    11  
    12  	"golang.org/x/crypto/ssh/terminal"
    13  )
    14  
    15  type SSHTerminal struct {
    16  	terminal  *terminal.Terminal
    17  	stdin     int
    18  	origState *terminal.State
    19  	rawState  *terminal.State
    20  	prompt    *Prompt
    21  	tx        *query.Transaction
    22  }
    23  
    24  func NewTerminal(ctx context.Context, scope *query.ReferenceScope) (query.VirtualTerminal, error) {
    25  	stdin := int(scope.Tx.Session.ScreenFd())
    26  	origState, err := terminal.MakeRaw(stdin)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	rawState, err := terminal.GetState(stdin)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	prompt := NewPrompt(scope)
    37  	if err = prompt.LoadConfig(); err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	t := SSHTerminal{
    42  		terminal:  terminal.NewTerminal(NewStdIO(scope.Tx.Session), scope.Tx.Palette.Render(option.PromptEffect, DefaultPrompt)),
    43  		stdin:     stdin,
    44  		origState: origState,
    45  		rawState:  rawState,
    46  		prompt:    prompt,
    47  		tx:        scope.Tx,
    48  	}
    49  
    50  	_ = t.RestoreOriginalMode()
    51  	t.SetPrompt(ctx)
    52  	_ = t.RestoreRawMode()
    53  	return t, nil
    54  }
    55  
    56  func (t SSHTerminal) Teardown() error {
    57  	return t.RestoreOriginalMode()
    58  }
    59  
    60  func (t SSHTerminal) RestoreRawMode() error {
    61  	return terminal.Restore(t.stdin, t.rawState)
    62  }
    63  
    64  func (t SSHTerminal) RestoreOriginalMode() error {
    65  	return terminal.Restore(t.stdin, t.origState)
    66  }
    67  
    68  func (t SSHTerminal) ReadLine() (string, error) {
    69  	if w, h, err := terminal.GetSize(t.stdin); err == nil {
    70  		if err = t.terminal.SetSize(w, h); err != nil {
    71  			return "", err
    72  		}
    73  	}
    74  
    75  	_ = t.RestoreRawMode()
    76  	s, err := t.terminal.ReadLine()
    77  	_ = t.RestoreOriginalMode()
    78  	return s, err
    79  }
    80  
    81  func (t SSHTerminal) Write(s string) error {
    82  	_, err := t.terminal.Write([]byte(s))
    83  	return err
    84  }
    85  
    86  func (t SSHTerminal) WriteError(s string) error {
    87  	_, err := t.tx.Session.Stderr().Write([]byte(s))
    88  	return err
    89  }
    90  
    91  func (t SSHTerminal) SetPrompt(ctx context.Context) {
    92  	str, err := t.prompt.RenderPrompt(ctx)
    93  	if err != nil {
    94  		t.tx.LogError(err.Error())
    95  	}
    96  	t.terminal.SetPrompt(str)
    97  }
    98  
    99  func (t SSHTerminal) SetContinuousPrompt(ctx context.Context) {
   100  	str, err := t.prompt.RenderContinuousPrompt(ctx)
   101  	if err != nil {
   102  		t.tx.LogError(err.Error())
   103  	}
   104  	t.terminal.SetPrompt(str)
   105  }
   106  
   107  func (t SSHTerminal) SaveHistory(s string) error {
   108  	return nil
   109  }
   110  
   111  func (t SSHTerminal) GetSize() (int, int, error) {
   112  	return terminal.GetSize(t.stdin)
   113  }
   114  
   115  func (t SSHTerminal) ReloadConfig() error {
   116  	return t.prompt.LoadConfig()
   117  }
   118  
   119  type StdIO struct {
   120  	reader io.Reader
   121  	writer io.Writer
   122  }
   123  
   124  func (t SSHTerminal) UpdateCompleter() {
   125  	//Do Nothing
   126  }
   127  
   128  func (sh *StdIO) Read(p []byte) (n int, err error) {
   129  	return sh.reader.Read(p)
   130  }
   131  
   132  func (sh *StdIO) Write(p []byte) (n int, err error) {
   133  	return sh.writer.Write(p)
   134  }
   135  
   136  func NewStdIO(sess *query.Session) *StdIO {
   137  	return &StdIO{
   138  		reader: sess.Stdin(),
   139  		writer: sess.Stdout(),
   140  	}
   141  }