Documentation
¶
Overview ¶
Package term offers a (data) type term.Node that allows to define a user interface using callbacks:
package main import ( "fmt" "log" "git.sr.ht/~slukits/term" ) func init() { log.Default().SetFlags(0) } var uiDef = term.Node{ Label: "terminal ui", // the initial prompt Callback: func(_ term.Terminal) (term.Nodes, term.Inputs) { return term.Nodes{{ Label: "hello", Help: "responds with 'world'" Callback: hello, }, { Label: "echo", Help: "repeats a user's input", Callback: echoEndpoint }}, nil }, } func hello(trm *term.Terminal) (term.Nodes, term.Inputs) { fmt.Fprintln(trm, "world\r") return nil, nil } func echoEndpoint(trm term.Terminal) (term.Nodes, term.Inputs) { return nil, echoInput } func echoInput(ii term.Inputs) Nodes { ii.SetPromptSuffix("your input please") ii.OnInput(func(ii term.Inputs) term.Node { ii.SetPromptSuffix("press any key") fmt.Fprintf(ii.Terminal(), "your input was: '%s'\n", ii.String()) ii.OnKeyPress(func(ii term.Inputs) term.Node { return root }) }) } func main() { if err:= trm.StartCallbackLoop(uiDef); err != nil { log.Fatal(err) } }
Above is the `term`-version of a hello world program including basic input processing. The basic idea is that a consumer of this package only needs to implement endpoints where one can choose to provide further nodes or not or an input collector. Is no input collector term.Inputs and no term.Nodes returned the node is called a "command node", it is called a "context node" if nodes are returned but no input collector and it is called an "input node" if an input collector is returned. I.e. `helloEndpoint` is a command node and `echoEndpoint` is an input node while `root` is a context node. Since an endpoint gets a Terminal implementation to write to, one can easily test endpoints against one owns implementations. Of course in this case it is advisable to define ones own interface to not have the test implementations brake if the Terminal interface gets extended.
Note in the term-ui the question mark user input shows the ui-help display while the pressing enter without any other input shows the context-help display. The ui supports auto-completion and cycling through autocompletion along with the feature of golang.org/x/term.
Index ¶
- Constants
- Variables
- func AppName(n string) settings.Setting
- func Exiter(cb func(FnExiter) FnExiter) settings.Setting
- func MakeRaw(cb func(FnMakeRaw) FnMakeRaw) settings.Setting
- func PrintAlwaysContextHelp(b bool) settings.Setting
- func REPL(root Node, ss ...settings.Setting) error
- func ReadWriter(rw io.ReadWriter, restore func()) settings.Setting
- func RegisterAt(scc *settings.Contexts) settings.Setting
- func Sizer(s FnSizer) settings.Setting
- func TerminalWriter(w func(FnWriter) FnWriter) settings.Setting
- type Anim
- type Buffer
- type BusyPrinter
- type Callback
- type Flag
- type FnExiter
- type FnMakeRaw
- type FnSizer
- type FnWriter
- type Focus
- type Input
- type InputProcessor
- type Inputs
- type LayoutDirective
- type LayoutDirectives
- type Node
- type Nodes
- type ProgressPrinter
- type Spinner
Constants ¶
const ( CtrlC = internal.CtrlC Cr = internal.Cr BS = internal.BS TAB = internal.TAB QM = internal.QM CtrlN = internal.CtrlN CtrlP = internal.CtrlP CtrlL = internal.CtrlL )
const DefaultAppName = "term"
const (
InitialBSHelp = internal.InitialBSHelp
)
Variables ¶
var ErrInputProcessor = errors.New("context: report input: no input processor")
var ErrInvalidNode = errors.New("invalid node")
var ErrInvalidRoot = errors.New("invalid root node")
var ErrNoParent = errors.New("root has no parent")
var ErrRW = errors.New("setup default stdin read/writer")
ErrRW may be returned from term.Start when the default read/writer fails set up (os.Stdin), i.e. can not be made raw.
var ErrReadLine = errors.New("terminal: read-line error")
ErrReadLine is returned by Terminal.StartCallbackLoop in case something went wrong during reading the user input.
Functions ¶
func MakeRaw ¶
MakeRaw allows to mock term.MakeRaw for the default read/writer generation which fails under test since we don't have a command line available. With this mock this error can be suppressed but it is only suitable for tests NOT calling Terminal.StartCallbackLoop. For tests calling StartCallbackLoop use the term.ReadWriter setting to mock up the whole read/writer instead of only an aspect of its construction.
func PrintAlwaysContextHelp ¶
PrintAlwaysContextHelp indicates if the context help is printed with every context switch.
func REPL ¶
REPL sets the root context applying all given settings and blocks until the user presses ctrl-c or ctrl-d. REPL calls back to any of root's context nodes n if it is selected by the user and keeps track of the current context. REPL fails if given root node is not valid or the application of a given setting fails.
func ReadWriter ¶
func ReadWriter(rw io.ReadWriter, restore func()) settings.Setting
ReadWriter allows to mock up a terminals read/writer. Since the default read/writer manipulates os.Stdin, creating the default read/writer also sets up the restoring of os.Stdin. Hence a mockup of a terminal's read/writer also must mock the restore feature.
func RegisterAt ¶
RegisterAt registers a term.Start at given settings contexts. NOTE this must be the first setting passed into term.Start!
Types ¶
type Buffer ¶
type Buffer struct {
// contains filtered or unexported fields
}
Buffer is a concurrency save bytes Buffer which can be send over channels to avoid permanent reallocation.
type BusyPrinter ¶
BusyPrinter implementation may be set on a Node.SetBusyPrinter where you also specify the frequency. In each interval during the node's callback execution the busy printer implementation gets the previously printed bytes and is notified if it is called the last time. Then the busy printer will returns the bytes to be printer next to the terminal. To remove pressure from the garbage collector its reasonable for the previous and next bytes buffer to be the same (create a local bytes copy of previous as needed and use Buffer.Reset before adding next content).
type Callback ¶
Callback implementations control a nodes relationship to the term-ui in case it has the focus and are set to a Node's Callback field; both return values may be nil. If both return-values are nil then the Callback's Node is called a command-node and the node looses focus instantly after its callback returns. If the callback's returned Nodes are not nil while returned Inputs are the Callback's Node is called a context-node. Is the returned Inputs not nil while returned Nodes may be nil or not the Callback's Node is called an input Node.
type FnMakeRaw ¶
FnMakeRaw is the function signature for the setting to mock the "make raw" functionality which defaults to term.MakeRaw (of "golang.org/x/term").
type FnSizer ¶
FnSizer is a function that takes a file-handle (representing a terminal) an returns in case of a terminal its width and height (i.e. number of columns and rows). FnSizer fails if width and height can't be determined.
type FnWriter ¶
FnWriter is the function to which a Terminal.Write call is passed on. By default its golang.org/x/term.Terminal.Write.
type Input ¶
type Input struct {
// contains filtered or unexported fields
}
An Input instance provided to a Nodes term.Inputs return value of its term.Callback function lets the node control how the input is collected and finally retrieve the collected input.
func (*Input) OnInput ¶
func (i *Input) OnInput(cb InputProcessor)
OnInput sets an InputProcessor callback for the next user input terminated by an end of line.
func (*Input) OnKeyPress ¶
func (i *Input) OnKeyPress(cb InputProcessor)
OnKeyPress sets an InputProcessor callback for the next key-press of the user.
func (*Input) SetPromptSuffix ¶
type InputProcessor ¶
InputProcessor is informed about an input and either wants to collect further input or switch to a new context replacing the input node's parent node. In the former case an Input.On* callback must be set and returned node must be nil. In the later case returned node must not be nil. If an InputProcessor returns while no Node is returned and no Input.On* callback is set term panics.
type Inputs ¶
type Inputs func(*Input)
Inputs is one of the two return values of a term.Callback and if it is not nil it indicates that the Node whose callback returned an not nil input wants to collect a more arbitrary user input then it can be collected by a node selection.
type LayoutDirective ¶
type LayoutDirective uint32
const ( VUnaligned LayoutDirective = iota + 1 VCenter VBottom ContextBody )
func (LayoutDirective) Byte ¶
func (ld LayoutDirective) Byte() []byte
func (LayoutDirective) String ¶
func (ld LayoutDirective) String() string
type LayoutDirectives ¶
type LayoutDirectives []LayoutDirective
type Node ¶
type Node struct { // Label is a mandatory unique string amongst a Nodes neighbors and // the expected user input selecting this node which is triggering // its callback and in case of children also a context change. Label string // Short is a shortcut of the label which is used in a terminal's // prompt if a Node is a parent context of the terminal's current // context. Short string // Note describes (optionally) the semantics of a selectable node. Note string // Selected describes (optionally) the semantics of a selected node. Selected string // Callback is executed when a Node is selected by the user. A node // is invalid if it has no Callback set or there are two different // nodes in the callbacks return value with the same label. Callback Callback // contains filtered or unexported fields }
A Node defines a context or command of a term user interface.
func (*Node) Flag ¶
Flag given node n with exceptional properties for example to control context changes.
func (*Node) SetBusyPrinter ¶
func (n *Node) SetBusyPrinter(bp BusyPrinter, interval time.Duration)
SetBusyPrinter sets given node n's busy-printer which is activated while n's callback is executed.
func (*Node) SetProgressPrinter ¶
func (n *Node) SetProgressPrinter(pp ProgressPrinter)
SetProgressPrinter sets given node n's progress-printer which is activated while n is the active context.
type ProgressPrinter ¶
ProgressPrinter may be set at node where progress should be shown while the node is the active context. I.e. it is only evaluated for context nodes. A context printer may return false to indicate that there is no more progress to be made.
type Spinner ¶
type Spinner struct { // Anim the sequence of runes which we animate over; defaults to `-\|/` Anim Anim // Last for the last print; defaults to - Last rune // LineFilter indicates the line in which we should find the rune to animate LineFilter []byte // contains filtered or unexported fields }
Spinner animates a '-' to '/' => '|' => '\' => '-'. Typically you will want to set Spinner.LineFilter to indicate in which line to find the animation rune. (The first find in that line is animated).
func (Spinner) BusyPrinter ¶
func (s Spinner) BusyPrinter() BusyPrinter