-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41 from thaJeztah/split_implementations
split exported functions from implementation
- Loading branch information
Showing
8 changed files
with
206 additions
and
180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// Package term provides structures and helper functions to work with | ||
// terminal (state, sizes). | ||
package term |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,102 +1,85 @@ | ||
//go:build !windows | ||
// +build !windows | ||
|
||
// Package term provides structures and helper functions to work with | ||
// terminal (state, sizes). | ||
package term | ||
|
||
import ( | ||
"errors" | ||
"io" | ||
"os" | ||
|
||
"golang.org/x/sys/unix" | ||
) | ||
import "io" | ||
|
||
// ErrInvalidState is returned if the state of the terminal is invalid. | ||
// | ||
// Deprecated: ErrInvalidState is no longer used. | ||
var ErrInvalidState = errors.New("Invalid terminal state") | ||
|
||
// State represents the state of the terminal. | ||
type State struct { | ||
termios unix.Termios | ||
} | ||
// State holds the platform-specific state / console mode for the terminal. | ||
type State terminalState | ||
|
||
// Winsize represents the size of the terminal window. | ||
type Winsize struct { | ||
Height uint16 | ||
Width uint16 | ||
x uint16 | ||
y uint16 | ||
|
||
// Only used on Unix | ||
x uint16 | ||
y uint16 | ||
} | ||
|
||
// StdStreams returns the standard streams (stdin, stdout, stderr). | ||
// | ||
// On Windows, it attempts to turn on VT handling on all std handles if | ||
// supported, or falls back to terminal emulation. On Unix, this returns | ||
// the standard [os.Stdin], [os.Stdout] and [os.Stderr]. | ||
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { | ||
return os.Stdin, os.Stdout, os.Stderr | ||
return stdStreams() | ||
} | ||
|
||
// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. | ||
func GetFdInfo(in interface{}) (uintptr, bool) { | ||
var inFd uintptr | ||
var isTerminalIn bool | ||
if file, ok := in.(*os.File); ok { | ||
inFd = file.Fd() | ||
isTerminalIn = IsTerminal(inFd) | ||
} | ||
return inFd, isTerminalIn | ||
func GetFdInfo(in interface{}) (fd uintptr, isTerminal bool) { | ||
return getFdInfo(in) | ||
} | ||
|
||
// GetWinsize returns the window size based on the specified file descriptor. | ||
func GetWinsize(fd uintptr) (*Winsize, error) { | ||
return getWinsize(fd) | ||
} | ||
|
||
// SetWinsize tries to set the specified window size for the specified file | ||
// descriptor. It is only implemented on Unix, and returns an error on Windows. | ||
func SetWinsize(fd uintptr, ws *Winsize) error { | ||
return setWinsize(fd, ws) | ||
} | ||
|
||
// IsTerminal returns true if the given file descriptor is a terminal. | ||
func IsTerminal(fd uintptr) bool { | ||
_, err := tcget(fd) | ||
return err == nil | ||
return isTerminal(fd) | ||
} | ||
|
||
// RestoreTerminal restores the terminal connected to the given file descriptor | ||
// to a previous state. | ||
func RestoreTerminal(fd uintptr, state *State) error { | ||
if state == nil { | ||
return errors.New("invalid terminal state") | ||
} | ||
return tcset(fd, &state.termios) | ||
return restoreTerminal(fd, state) | ||
} | ||
|
||
// SaveState saves the state of the terminal connected to the given file descriptor. | ||
func SaveState(fd uintptr) (*State, error) { | ||
termios, err := tcget(fd) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &State{termios: *termios}, nil | ||
return saveState(fd) | ||
} | ||
|
||
// DisableEcho applies the specified state to the terminal connected to the file | ||
// descriptor, with echo disabled. | ||
func DisableEcho(fd uintptr, state *State) error { | ||
newState := state.termios | ||
newState.Lflag &^= unix.ECHO | ||
|
||
if err := tcset(fd, &newState); err != nil { | ||
return err | ||
} | ||
return nil | ||
return disableEcho(fd, state) | ||
} | ||
|
||
// SetRawTerminal puts the terminal connected to the given file descriptor into | ||
// raw mode and returns the previous state. On UNIX, this puts both the input | ||
// and output into raw mode. On Windows, it only puts the input into raw mode. | ||
func SetRawTerminal(fd uintptr) (*State, error) { | ||
oldState, err := MakeRaw(fd) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return oldState, err | ||
// raw mode and returns the previous state. On UNIX, this is the equivalent of | ||
// [MakeRaw], and puts both the input and output into raw mode. On Windows, it | ||
// only puts the input into raw mode. | ||
func SetRawTerminal(fd uintptr) (previousState *State, err error) { | ||
return setRawTerminal(fd) | ||
} | ||
|
||
// SetRawTerminalOutput puts the output of terminal connected to the given file | ||
// descriptor into raw mode. On UNIX, this does nothing and returns nil for the | ||
// state. On Windows, it disables LF -> CRLF translation. | ||
func SetRawTerminalOutput(fd uintptr) (*State, error) { | ||
return nil, nil | ||
func SetRawTerminalOutput(fd uintptr) (previousState *State, err error) { | ||
return setRawTerminalOutput(fd) | ||
} | ||
|
||
// MakeRaw puts the terminal (Windows Console) connected to the | ||
// given file descriptor into raw mode and returns the previous state of | ||
// the terminal so that it can be restored. | ||
func MakeRaw(fd uintptr) (previousState *State, err error) { | ||
return makeRaw(fd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
//go:build !windows | ||
// +build !windows | ||
|
||
package term | ||
|
||
import ( | ||
"errors" | ||
"io" | ||
"os" | ||
|
||
"golang.org/x/sys/unix" | ||
) | ||
|
||
// ErrInvalidState is returned if the state of the terminal is invalid. | ||
// | ||
// Deprecated: ErrInvalidState is no longer used. | ||
var ErrInvalidState = errors.New("Invalid terminal state") | ||
|
||
// terminalState holds the platform-specific state / console mode for the terminal. | ||
type terminalState struct { | ||
termios unix.Termios | ||
} | ||
|
||
func stdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { | ||
return os.Stdin, os.Stdout, os.Stderr | ||
} | ||
|
||
func getFdInfo(in interface{}) (uintptr, bool) { | ||
var inFd uintptr | ||
var isTerminalIn bool | ||
if file, ok := in.(*os.File); ok { | ||
inFd = file.Fd() | ||
isTerminalIn = isTerminal(inFd) | ||
} | ||
return inFd, isTerminalIn | ||
} | ||
|
||
func getWinsize(fd uintptr) (*Winsize, error) { | ||
uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) | ||
ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel} | ||
return ws, err | ||
} | ||
|
||
func setWinsize(fd uintptr, ws *Winsize) error { | ||
return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, &unix.Winsize{ | ||
Row: ws.Height, | ||
Col: ws.Width, | ||
Xpixel: ws.x, | ||
Ypixel: ws.y, | ||
}) | ||
} | ||
|
||
func isTerminal(fd uintptr) bool { | ||
_, err := tcget(fd) | ||
return err == nil | ||
} | ||
|
||
func restoreTerminal(fd uintptr, state *State) error { | ||
if state == nil { | ||
return errors.New("invalid terminal state") | ||
} | ||
return tcset(fd, &state.termios) | ||
} | ||
|
||
func saveState(fd uintptr) (*State, error) { | ||
termios, err := tcget(fd) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &State{termios: *termios}, nil | ||
} | ||
|
||
func disableEcho(fd uintptr, state *State) error { | ||
newState := state.termios | ||
newState.Lflag &^= unix.ECHO | ||
|
||
return tcset(fd, &newState) | ||
} | ||
|
||
func setRawTerminal(fd uintptr) (*State, error) { | ||
return makeRaw(fd) | ||
} | ||
|
||
func setRawTerminalOutput(fd uintptr) (*State, error) { | ||
return nil, nil | ||
} | ||
|
||
func tcget(fd uintptr) (*unix.Termios, error) { | ||
p, err := unix.IoctlGetTermios(int(fd), getTermios) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return p, nil | ||
} | ||
|
||
func tcset(fd uintptr, p *unix.Termios) error { | ||
return unix.IoctlSetTermios(int(fd), setTermios, p) | ||
} |
Oops, something went wrong.