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 }