okami.mom/ultraviolet
git clone https://git.nkp.pet/okami.mom/ultraviolet
6ea2266
upstream
1package uv 2 3import ( 4"io" 5"os" 6"runtime" 7 8"github.com/charmbracelet/x/term" 9) 10 11var isWindows = runtime .GOOS == "windows" 12 13// File is an interface that represents a file with a file descriptor. 14// 15// This is typically an [os.File] like [os.Stdin] and [os.Stdout]. 16type File interface { 17 io.ReadWriteCloser 18 term.File 19 20// Name returns the name of the file. 21Name ()string 22} 23 24// Winsize represents the size of a terminal in cells and pixels. 25// 26// This is the same as [unix.Winsize], but defined here for cross-platform compatibility. 27type Winsize struct { 28Row uint16 29Col uint16 30Xpixel uint16 31Ypixel uint16 32} 33 34// Console represents a cross-platform console I/O interface. 35type Console interface { 36 io.ReadWriteCloser 37 38// Environ returns the console's environment variables. 39Environ () []string 40 41// Getenv retrieves the value of the environment variable named by the key. 42Getenv (key string )string 43 44// LookupEnv retrieves the value of the environment variable named by the key 45// and a boolean indicating whether the variable is present. 46LookupEnv (key string ) (string ,bool ) 47 48// Reader returns the input reader of the console. 49Reader () io.Reader 50 51// Writer returns the output writer of the console. 52Writer () io.Writer 53 54// MakeRaw puts the console input side into raw mode. 55MakeRaw () (state * term.State ,err error ) 56 57// Restore restores the console to its previous state. 58Restore ()error 59 60// GetSize returns the current size of the console. 61GetSize () (width ,height int ,err error ) 62 63// GetWinsize returns the current size of the console in cells and pixels. 64GetWinsize () (* Winsize ,error ) 65} 66 67// TTY represents a Unix TTY device. It implements the [Console] interface. 68type TTY struct { 69* console 70} 71 72var _ Console = (* TTY )(nil ) 73 74// WinCon represents a Windows Console. It implements the [Console] interface. 75type WinCon struct { 76* console 77} 78 79var _ Console = (* WinCon )(nil ) 80 81// Console is a cross-platform console I/O. 82type console struct { 83input File 84inputState * term.State 85output File 86outputState * term.State 87environ Environ 88} 89 90// DefaultConsole returns a new default console instance that uses standard I/O 91// [os.Stdin], [os.Stdout], and [os.Environ]. 92// 93// To use [os.Stderr] as the output, you can create a new console with 94// [NewConsole] and pass [os.Stderr] as the output parameter. 95func DefaultConsole ()Console { 96return NewConsole (os .Stdin ,os .Stdout ,os .Environ ()) 97} 98 99// ControllingConsole returns a new console instance that uses the current 100// controlling terminal's input and output file descriptors. 101func ControllingConsole () (Console ,error ) { 102inTty ,outTty ,err := OpenTTY () 103if err != nil { 104return nil ,err 105 } 106return NewConsole (inTty ,outTty ,os .Environ ()),nil 107} 108 109// NewConsole creates a new [Console] with the given input, output, and 110// environment variables. 111// 112// You can use [OpenTTY] to open the current controlling console files and pass 113// them to this function. Use [ControllingConsole] for a convenience function 114// that does this for you. 115// 116// Use this to create a new terminal for PTY processes by passing the PTY slave 117// file as the input and output and any environment variables the process 118// needs. 119func NewConsole (input ,output File ,environ []string )Console { 120if input == nil { 121input = os .Stdin 122 } 123if output == nil { 124output = os .Stdout 125 } 126if environ == nil { 127environ = os .Environ () 128 } 129return newConsole (input ,output ,environ ) 130} 131 132// Environ returns the console's environment variables. 133func (t * console )Environ () []string { 134return t .environ 135} 136 137// Writer returns the output writer of the console. 138func (t * console )Writer () io.Writer { 139return t .output 140} 141 142// Reader returns the input reader of the console. 143func (t * console )Reader () io.Reader { 144return t .input 145} 146 147// Write writes data to the console's output. 148func (t * console )Write (p []byte ) (n int ,err error ) { 149return t .output .Write (p ) 150} 151 152// Read reads data from the console's input. 153func (t * console )Read (p []byte ) (n int ,err error ) { 154return t .input .Read (p ) 155} 156 157// Getenv retrieves the value of the environment variable named by the key. 158func (t * console )Getenv (key string )string { 159return t .environ .Getenv (key ) 160} 161 162// LookupEnv retrieves the value of the environment variable named by the key 163// and a boolean indicating whether the variable is present. 164func (t * console )LookupEnv (key string ) (string ,bool ) { 165return t .environ .LookupEnv (key ) 166} 167 168// MakeRaw puts the console input side into raw mode. 169func (t * console )MakeRaw () (state * term.State ,err error ) { 170inState ,outState ,err := makeRaw (t .input ,t .output ) 171if err != nil { 172return nil ,err 173 } 174t .inputState = inState 175t .outputState = outState 176if inState != nil { 177return inState ,nil 178 } 179return outState ,nil 180} 181 182// Restore restores the console to its previous state. 183func (t * console )Restore ()error { 184if t .inputState != nil { 185if err := term .Restore (t .input .Fd (),t .inputState );err != nil { 186return err 187 } 188t .inputState = nil 189 } 190if t .outputState != nil { 191if err := term .Restore (t .output .Fd (),t .outputState );err != nil { 192return err 193 } 194t .outputState = nil 195 } 196return nil 197} 198 199// Close restores the console to its previous state and releases resources. 200func (t * console )Close ()error { 201if err := t .Restore ();err != nil { 202return err 203 } 204return nil 205} 206 207// GetSize returns the current size of the console. 208func (t * console )GetSize () (width ,height int ,err error ) { 209return getSize (t .input ,t .output ) 210} 211 212// GetWinsize returns the current size of the console in cells and pixels. 213func (t * console )GetWinsize () (* Winsize ,error ) { 214ws ,err := getWinsize (t .input ,t .output ) 215if err != nil { 216return nil ,err 217 } 218return & ws ,nil 219}