xpty

package module
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2020 License: BSD-3-Clause Imports: 13 Imported by: 1

README

termtest/xpty

Xpty provides an abstraction to run a terminal application in a pseudo-terminal environment for Linux, Mac and Windows. On Windows it uses the ActiveState/termtest/conpty to run the application inside of a ConPTY terminal. The pseudo-terminal is automatically attached to a virtual terminal that is compatible with an xterm-terminal.

The problem

Attaching the pseudo-terminal to an xterm-compatible virtual terminal is for the following reason:

If the terminal application sends a cursor position request (CPR) signal, the application usually blocks on read until it receives the response (the column and row number of the cursor) from terminal. xpty helps unblocking such programmes, as it actually generates the awaited response.

Rune-by-rune streaming

Reading from the underlying terminal is done with the ReadRune() function that returns the next interpretable rune. Such fine-grained and slow output processing allows us to keep the state of the virtual terminal deterministic.

Example

xp, _ := xpty.New(20, 10)
defer xp.Close()

cmd := exec.Command("/bin/bash")
xp.StartProcessInTerminal(cmd)

xp.TerminalInPipe().WriteString("echo hello world\n")
xp.TerminalInPipe().WriteString("exit\n")

buf := new(bytes.Buffer)
n, _ := xp.WriteTo(buf)

fmt.Printf("Raw output:\n%s\n", buf.String())
fmt.Printf("Terminal output:\n%s\n", xp.State.String())

Documentation

Overview

Package xpty is an abstraction of a pseudoterminal that is attached to a virtual xterm-compatible terminal.

This can be used to automate the execution of terminal applications that rely on running inside of a real terminal: Especially if the terminal application sends a cursor position request (CPR) signal, it usually blocks on read until it receives the response (the column and row number of the cursor) from terminal.

The state of the virtual terminal can also be accessed at any point. So, the output displayed to a user running the application in a "real" terminal can be inspected and analyzed.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type PassthroughPipe

type PassthroughPipe struct {
	// contains filtered or unexported fields
}

PassthroughPipe pipes data from a io.Reader and allows setting a read deadline. If a timeout is reached the error is returned, otherwise the error from the provided io.Reader returned is passed through instead.

func NewPassthroughPipe

func NewPassthroughPipe(r *bufio.Reader) *PassthroughPipe

NewPassthroughPipe returns a new pipe for a io.Reader that passes through non-timeout errors.

func (*PassthroughPipe) Close

func (p *PassthroughPipe) Close() error

Close releases all resources allocated by the pipe

func (*PassthroughPipe) IsBlocked

func (p *PassthroughPipe) IsBlocked() bool

IsBlocked returns true when the PassthroughPipe is (most likely) blocked reading ie., waiting for input

func (*PassthroughPipe) ReadRune

func (p *PassthroughPipe) ReadRune() (rune, int, error)

ReadRune reads from the PassthroughPipe and errors out if no data has been written to the pipe before the read deadline expired If read is called after the PassthroughPipe has been closed `0, io.EOF` is returned

func (*PassthroughPipe) SetReadDeadline

func (p *PassthroughPipe) SetReadDeadline(d time.Time)

SetReadDeadline sets a deadline for a successful read

type Xpty

type Xpty struct {
	Term  *vt10x.VT
	State *vt10x.State
	// contains filtered or unexported fields
}

Xpty reprents an abstract peudo-terminal for the Windows or *nix architecture

func New

func New(cols uint16, rows uint16, recordHistory bool) (*Xpty, error)

New opens a pseudo-terminal of the given size

func (*Xpty) Close

func (p *Xpty) Close() error

Close closes the abstracted pseudo-terminal

func (*Xpty) CloseReaders

func (p *Xpty) CloseReaders() error

CloseReaders closes the passthrough pipe

func (*Xpty) CloseTTY

func (p *Xpty) CloseTTY() error

CloseTTY closes just the terminal, giving you some time to finish reading from the pass-through pipe later. Call CloseReaders() when you are done reading all the data that is still buffered Consider this little dance to avoid losing any data:

go func() {
     ...
		// command finishes
     cmd.Wait()
     // wait until the pass-through pipe has consumed all data
     xp.WaitTillDrained()
     xp.CloseTTY()
}()
xp.WriteTo(...)
// now close the passthrough pipe
xp.CloseReaders()

func (*Xpty) ReadRune

func (p *Xpty) ReadRune() (rune, int, error)

ReadRune reads a single rune from the terminal output pipe, and updates the terminal

func (*Xpty) Resize

func (p *Xpty) Resize(cols, rows uint16) error

Resize resizes the underlying pseudo-terminal

func (*Xpty) SetReadDeadline

func (p *Xpty) SetReadDeadline(d time.Time)

SetReadDeadline sets a deadline for a successful read the next rune

func (*Xpty) StartProcessInTerminal

func (p *Xpty) StartProcessInTerminal(cmd *exec.Cmd) error

StartProcessInTerminal executes the given command connected to the abstracted pseudo-terminal

func (*Xpty) TerminalInPipe

func (p *Xpty) TerminalInPipe() io.Writer

TerminalInPipe returns a writer that can be used to write user input to the pseudo terminal. On unix this is the /dev/ptm file

func (*Xpty) TerminalOutFd

func (p *Xpty) TerminalOutFd() uintptr

TerminalOutFd returns the file descriptor of the terminal

func (*Xpty) Tty

func (p *Xpty) Tty() *os.File

Tty returns the pseudo terminal files that an application can read from or write to This is only available on linux, and would return the "slave" /dev/pts file

func (*Xpty) WaitTillDrained

func (p *Xpty) WaitTillDrained()

WaitTillDrained waits until the PassthroughPipe is blocked in the reading state. When this function returns, the PassthroughPipe should be blocked in the reading state waiting for more input.

func (*Xpty) WriteTo

func (p *Xpty) WriteTo(w io.Writer) (int64, error)

WriteTo writes the terminal output stream to a writer w

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL