cli

package
v0.15.0 Latest Latest
Warning

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

Go to latest
Published: Jan 24, 2021 License: BSD-2-Clause Imports: 17 Imported by: 0

Documentation

Overview

Package cli implements a generic interactive line editor.

Example (Loop)

This will be run by `go test` and compare the output to that in the comment at the end of the function. See https://golang.org/pkg/testing/#pkg-examples.

buffer := ""
firstDrawerCall := true
drawer := func(flag redrawFlag) {
	// Because the consumption of events is batched, calls to the drawer is
	// nondeterministic except for the first and final calls.
	switch {
	case firstDrawerCall:
		fmt.Printf("initial buffer is %q\n", buffer)
		firstDrawerCall = false
	case flag&finalRedraw != 0:
		fmt.Printf("final buffer is %q\n", buffer)
	}
}

lp := newLoop()
lp.HandleCb(func(e event) {
	if e == '\n' {
		lp.Return(buffer, nil)
		return
	}
	buffer += string(e.(rune))
})
go func() {
	for _, event := range "echo\n" {
		lp.Input(event)
	}
}()
lp.RedrawCb(drawer)
buf, err := lp.Run()
fmt.Printf("returned buffer is %q\n", buf)
fmt.Printf("returned error is %v\n", err)
Output:

initial buffer is ""
final buffer is "echo"
returned buffer is "echo"
returned error is <nil>

Index

Examples

Constants

View Source
const Selected = "<- selected"

Selected is a special value in the argument to WriteListing, signalling that the argument before it is the selected line.

Variables

View Source
var StdTTY = NewTTY(os.Stdin, os.Stderr)

StdTTY is the terminal connected to inputs from stdin and output to stderr.

Functions

func CategorizeSmallWord added in v0.14.0

func CategorizeSmallWord(r rune) int

CategorizeSmallWord determines if the rune is whitespace, alphanum, or something else.

func IsAlnum added in v0.14.0

func IsAlnum(r rune) bool

IsAlnum determines if the rune is an alphanumeric character.

func Left

func Left(s ListBoxState) int

Left moves the selection to the item to the left. It is only meaningful in horizontal layout and suitable as an argument to Widget.Select.

func ModeLine

func ModeLine(content string, space bool) ui.Text

ModeLine returns a text styled as a modeline.

func ModePrompt

func ModePrompt(content string, space bool) func() ui.Text

ModePrompt returns a callback suitable as the prompt in the codearea of a

func Next

func Next(s ListBoxState) int

Next moves the selection to the previous item, or does nothing if the last item is currently selected. It is a suitable as an argument to Widget.Select.

func NextPage

func NextPage(s ListBoxState) int

NextPage moves the selection to the item one page after. It is only meaningful in vertical layout and suitable as an argument to Widget.Select.

TODO(xiaq): This does not correctly with multi-line items.

func NextWrap

func NextWrap(s ListBoxState) int

NextWrap moves the selection to the previous item, or to the first item if the last item is currently selected. It is a suitable as an argument to Widget.Select.

func Prev

func Prev(s ListBoxState) int

Prev moves the selection to the previous item, or does nothing if the first item is currently selected. It is a suitable as an argument to Widget.Select.

func PrevPage

func PrevPage(s ListBoxState) int

PrevPage moves the selection to the item one page before. It is only meaningful in vertical layout and suitable as an argument to Widget.Select.

TODO(xiaq): This does not correctly with multi-line items.

func PrevWrap

func PrevWrap(s ListBoxState) int

PrevWrap moves the selection to the previous item, or to the last item if the first item is currently selected. It is a suitable as an argument to Widget.Select.

func Right(s ListBoxState) int

Right moves the selection to the item to the right. It is only meaningful in horizontal layout and suitable as an argument to Widget.Select.

func SetAddon

func SetAddon(a App, addon Widget)

SetAddon sets the addon widget of the app.

func SetCodeBuffer

func SetCodeBuffer(a App, buf CodeBuffer)

SetCodeBuffer sets the code buffer of the main code area widget of the app.

func TestHandle

func TestHandle(t *testing.T, tests []HandleTest)

TestHandle runs the given Handler tests.

func TestRender

func TestRender(t *testing.T, tests []RenderTest)

TestRender runs the given Renderer tests.

func WriteListing

func WriteListing(b *term.BufferBuilder, name, filter string, lines ...string)

WriteListing is a unit test helper that emulates the rendering of a "listing" type addon. Among the lines arguments, the value "<- selected" is special and signals that the argument before it is the selected line.

Types

type App

type App interface {
	// MutateState mutates the state of the app.
	MutateState(f func(*State))
	// CopyState returns a copy of the a state.
	CopyState() State
	// CodeArea returns the codearea widget of the app.
	CodeArea() CodeArea
	// ReadCode requests the App to read code from the terminal by running an
	// event loop. This function is not re-entrant.
	ReadCode() (string, error)
	// Redraw requests a redraw. It never blocks and can be called regardless of
	// whether the App is active or not.
	Redraw()
	// RedrawFull requests a full redraw. It never blocks and can be called
	// regardless of whether the App is active or not.
	RedrawFull()
	// CommitEOF causes the main loop to exit with EOF. If this method is called
	// when an event is being handled, the main loop will exit after the handler
	// returns.
	CommitEOF()
	// CommitCode causes the main loop to exit with the current code content. If
	// this method is called when an event is being handled, the main loop will
	// exit after the handler returns.
	CommitCode()
	// Notify adds a note and requests a redraw.
	Notify(note string)
}

App represents a CLI app.

func NewApp

func NewApp(spec AppSpec) App

NewApp creates a new App from the given specification.

type AppSpec

type AppSpec struct {
	TTY               TTY
	MaxHeight         func() int
	RPromptPersistent func() bool
	BeforeReadline    []func()
	AfterReadline     []func(string)

	Highlighter Highlighter
	Prompt      Prompt
	RPrompt     Prompt

	OverlayHandler Handler
	Abbreviations  func(f func(abbr, full string))
	QuotePaste     func() bool

	SmallWordAbbreviations func(f func(abbr, full string))

	CodeAreaState CodeAreaState
	State         State
}

AppSpec specifies the configuration and initial state for an App.

type CodeArea

type CodeArea interface {
	Widget
	// CopyState returns a copy of the state.
	CopyState() CodeAreaState
	// MutateState calls the given the function while locking StateMutex.
	MutateState(f func(*CodeAreaState))
	// Submit triggers the OnSubmit callback.
	Submit()
}

CodeArea is a Widget for displaying and editing code.

func NewCodeArea

func NewCodeArea(spec CodeAreaSpec) CodeArea

NewCodeArea creates a new CodeArea from the given spec.

type CodeAreaSpec

type CodeAreaSpec struct {
	// A Handler that takes precedence over the default handling of events.
	OverlayHandler Handler
	// A function that highlights the given code and returns any errors it has
	// found when highlighting. If this function is not given, the Widget does
	// not highlight the code nor show any errors.
	Highlighter func(code string) (ui.Text, []error)
	// Prompt callback.
	Prompt func() ui.Text
	// Right-prompt callback.
	RPrompt func() ui.Text
	// A function that calls the callback with string pairs for abbreviations
	// and their expansions. If this function is not given, the Widget does not
	// expand any abbreviations.
	Abbreviations          func(f func(abbr, full string))
	SmallWordAbbreviations func(f func(abbr, full string))
	// A function that returns whether pasted texts (from bracketed pastes)
	// should be quoted. If this function is not given, the Widget defaults to
	// not quoting pasted texts.
	QuotePaste func() bool
	// A function that is called on the submit event.
	OnSubmit func()

	// State. When used in New, this field specifies the initial state.
	State CodeAreaState
}

CodeAreaSpec specifies the configuration and initial state for CodeArea.

type CodeAreaState

type CodeAreaState struct {
	Buffer      CodeBuffer
	Pending     PendingCode
	HideRPrompt bool
}

CodeAreaState keeps the mutable state of the CodeArea widget.

func (*CodeAreaState) ApplyPending

func (s *CodeAreaState) ApplyPending()

ApplyPending applies pending code to the code buffer, and resets pending code.

type CodeBuffer

type CodeBuffer struct {
	// Content of the buffer.
	Content string
	// Position of the dot (more commonly known as the cursor), as a byte index
	// into Content.
	Dot int
}

CodeBuffer represents the buffer of the CodeArea widget.

func GetCodeBuffer

func GetCodeBuffer(a App) CodeBuffer

GetCodeBuffer returns the code buffer of the main code area widget of the app.

func (*CodeBuffer) InsertAtDot

func (c *CodeBuffer) InsertAtDot(text string)

type ColView

type ColView interface {
	Widget
	// MutateState mutates the state.
	MutateState(f func(*ColViewState))
	// CopyState returns a copy of the state.
	CopyState() ColViewState
	// Left triggers the OnLeft callback.
	Left()
	// Right triggers the OnRight callback.
	Right()
}

ColView is a Widget that arranges several widgets in a column.

func NewColView

func NewColView(spec ColViewSpec) ColView

NewColView creates a new ColView from the given spec.

type ColViewSpec

type ColViewSpec struct {
	// An overlay handler.
	OverlayHandler Handler
	// A function that takes the number of columns and return weights for the
	// widths of the columns. The returned slice must have a size of n. If this
	// function is nil, all the columns will have the same weight.
	Weights func(n int) []int
	// A function called when the Left method of Widget is called, or when Left
	// is pressed and unhandled.
	OnLeft func(w ColView)
	// A function called when the Right method of Widget is called, or when
	// Right is pressed and unhandled.
	OnRight func(w ColView)

	// State. Specifies the initial state when used in New.
	State ColViewState
}

ColViewSpec specifies the configuration and initial state for ColView.

type ColViewState

type ColViewState struct {
	Columns     []Widget
	FocusColumn int
}

ColViewState keeps the mutable state of the ColView widget.

type ComboBox

type ComboBox interface {
	Widget
	// Returns the embedded codearea widget.
	CodeArea() CodeArea
	// Returns the embedded listbox widget.
	ListBox() ListBox
	// Forces the filtering to rerun.
	Refilter()
}

ComboBox is a Widget that combines a ListBox and a CodeArea.

func NewComboBox

func NewComboBox(spec ComboBoxSpec) ComboBox

NewComboBox creates a new ComboBox from the given spec.

type ComboBoxSpec

type ComboBoxSpec struct {
	CodeArea CodeAreaSpec
	ListBox  ListBoxSpec
	OnFilter func(ComboBox, string)
}

ComboBoxSpec specifies the configuration and initial state for ComboBox.

type DummyHandler

type DummyHandler struct{}

DummyHandler is a trivial implementation of Handler.

func (DummyHandler) Handle

func (DummyHandler) Handle(term.Event) bool

Handle always returns false.

type Empty

type Empty struct{}

Empty is an empty widget.

func (Empty) Handle

func (Empty) Handle(event term.Event) bool

Handle always returns false.

func (Empty) Render

func (Empty) Render(width, height int) *term.Buffer

Render shows nothing, although the resulting Buffer still occupies one line.

type Focuser

type Focuser interface {
	Focus() bool
}

Focuser is an interface that addon widgets may implement.

type FuncHandler

type FuncHandler func(term.Event) bool

FuncHandler is a function-based implementation of Handler.

func (FuncHandler) Handle

func (f FuncHandler) Handle(event term.Event) bool

Handle handles the event by calling the function.

type HScrollbar

type HScrollbar struct {
	Total int
	Low   int
	High  int
}

HScrollbar is a Renderer for a horizontal scrollbar.

func (HScrollbar) Render

func (h HScrollbar) Render(width, height int) *term.Buffer

type HandleTest

type HandleTest struct {
	Name   string
	Given  Handler
	Event  term.Event
	Events []term.Event

	WantNewState  interface{}
	WantUnhandled bool
}

HandleTest is a test case to be used in TestHandle.

type Handler

type Handler interface {
	// Try to handle a terminal event and returns whether the event has been
	// handled.
	Handle(event term.Event) bool
}

Handler wraps the Handle method.

type Highlighter

type Highlighter interface {
	// Get returns the highlighted code and any static errors.
	Get(code string) (ui.Text, []error)
	// LateUpdates returns a channel for delivering late updates.
	LateUpdates() <-chan struct{}
}

Highlighter represents a code highlighter whose result can be delivered asynchronously.

type Items

type Items interface {
	// Show renders the item at the given zero-based index.
	Show(i int) ui.Text
	// Len returns the number of items.
	Len() int
}

Items is an interface for accessing multiple items.

type Label

type Label struct {
	Content ui.Text
}

Label is a Renderer that writes out a text.

func (Label) Handle

func (l Label) Handle(event term.Event) bool

Handle always returns false.

func (Label) Render

func (l Label) Render(width, height int) *term.Buffer

Render shows the content. If the given box is too small, the text is cropped.

type ListBox

type ListBox interface {
	Widget
	// CopyState returns a copy of the state.
	CopyState() ListBoxState
	// Reset resets the state of the widget with the given items and index of
	// the selected item. It triggers the OnSelect callback if the index is
	// valid.
	Reset(it Items, selected int)
	// Select changes the selection by calling f with the current state, and
	// using the return value as the new selection index. It triggers the
	// OnSelect callback if the selected index has changed and is valid.
	Select(f func(ListBoxState) int)
	// Accept accepts the currently selected item.
	Accept()
}

ListBox is a list for displaying and selecting from a list of items.

func NewListBox

func NewListBox(spec ListBoxSpec) ListBox

NewListBox creates a new ListBox from the given spec.

type ListBoxSpec

type ListBoxSpec struct {
	// A Handler that takes precedence over the default handling of events.
	OverlayHandler Handler
	// A placeholder to show when there are no items.
	Placeholder ui.Text
	// A function to call when the selected item has changed.
	OnSelect func(it Items, i int)
	// A function called on the accept event.
	OnAccept func(it Items, i int)
	// Whether the listbox should be rendered in a horizontal  Note that
	// in the horizontal layout, items must have only one line.
	Horizontal bool
	// The minimal amount of space to reserve for left and right sides of each
	// entry.
	Padding int
	// If true, the left padding of each item will be styled the same as the
	// first segment of the item, and the right spacing and padding will be
	// styled the same as the last segment of the item.
	ExtendStyle bool

	// State. When used in New, this field specifies the initial state.
	State ListBoxState
}

ListBoxSpec specifies the configuration and initial state for ListBox.

type ListBoxState

type ListBoxState struct {
	Items    Items
	Selected int
	First    int
	Height   int
}

ListBoxState keeps the mutable state ListBox.

type MapHandler

type MapHandler map[term.Event]func()

MapHandler is a map-backed implementation of Handler.

func (MapHandler) Handle

func (m MapHandler) Handle(event term.Event) bool

Handle handles the event by calling the function corresponding to the event in the map. If there is no corresponding function, it returns false.

type PendingCode

type PendingCode struct {
	// Beginning index of the text area that the pending code replaces, as a
	// byte index into RawState.Code.
	From int
	// End index of the text area that the pending code replaces, as a byte
	// index into RawState.Code.
	To int
	// The content of the pending code.
	Content string
}

PendingCode represents pending code, such as during completion.

type Prompt

type Prompt interface {
	// Trigger requests a re-computation of the prompt. The force flag is set
	// when triggered for the first time during a ReadCode session or after a
	// SIGINT that resets the editor.
	Trigger(force bool)
	// Get returns the current prompt.
	Get() ui.Text
	// LastUpdates returns a channel for notifying late updates.
	LateUpdates() <-chan struct{}
}

Prompt represents a prompt whose result can be delivered asynchronously.

func NewConstPrompt

func NewConstPrompt(t ui.Text) Prompt

NewConstPrompt returns a Prompt that always shows the given text.

type RenderTest

type RenderTest struct {
	Name   string
	Given  Renderer
	Width  int
	Height int
	Want   interface{ Buffer() *term.Buffer }
}

RenderTest is a test case to be used in TestRenderer.

type Renderer

type Renderer interface {
	// Render onto a region of bound width and height.
	Render(width, height int) *term.Buffer
}

Renderer wraps the Render method.

type State

type State struct {
	// Notes that have been added since the last redraw.
	Notes []string
	// An addon widget. When non-nil, it is shown under the codearea widget and
	// terminal events are handled by it.
	//
	// The addon widget may implement the Focuser interface, in which case the
	// Focus method is used to determine whether the cursor should be placed on
	// the addon widget during each render. If the widget does not implement the
	// Focuser interface, the cursor is always placed on the addon widget.
	Addon Widget
}

State represents mutable state of an App.

type TTY

type TTY interface {
	// Setup sets up the terminal for the CLI app.
	//
	// This method returns a restore function that undoes the setup, and any
	// error during setup. It only returns fatal errors that make the terminal
	// unsuitable for later operations; non-fatal errors may be reported by
	// showing a warning message, but not returned.
	//
	// This method should be called before any other method is called.
	Setup() (restore func(), err error)

	// ReadEvent reads a terminal event.
	ReadEvent() (term.Event, error)
	// SetRawInput requests the next n ReadEvent calls to read raw events. It
	// is applicable to environments where events are represented as a special
	// sequences, such as VT100. It is a no-op if events are delivered as whole
	// units by the terminal, such as Windows consoles.
	SetRawInput(n int)

	// StopInput causes input delivery to be stopped. When this function
	// returns, the channel previously returned by StartInput will no longer
	// deliver input events.
	StopInput()

	// NotifySignals start relaying signals and returns a channel on which
	// signals are delivered.
	NotifySignals() <-chan os.Signal
	// StopSignals stops the relaying of signals. After this function returns,
	// the channel returned by NotifySignals will no longer deliver signals.
	StopSignals()

	// Size returns the height and width of the terminal.
	Size() (h, w int)

	// Buffer returns the current buffer. The initial value of the current
	// buffer is nil.
	Buffer() *term.Buffer
	// ResetBuffer resets the current buffer to nil without actuating any redraw.
	ResetBuffer()
	// UpdateBuffer updates the current buffer and draw it to the terminal.
	UpdateBuffer(bufNotes, bufMain *term.Buffer, full bool) error
}

TTY is the type the terminal dependency of the editor needs to satisfy.

func NewTTY

func NewTTY(in, out *os.File) TTY

NewTTY returns a new TTY from input and output terminal files.

type TestItems

type TestItems struct {
	Prefix string
	Style  ui.Styling
	NItems int
}

TestItems is an implementation of Items useful for testing.

func (TestItems) Len

func (it TestItems) Len() int

Len returns it.NItems.

func (TestItems) Show

func (it TestItems) Show(i int) ui.Text

Show returns a plain text consisting of the prefix and i. If the prefix is empty, it defaults to "item ".

type TextView

type TextView interface {
	Widget
	// ScrollBy scrolls the widget by the given delta. Positive values scroll
	// down, and negative values scroll up.
	ScrollBy(delta int)
	// MutateState mutates the state.
	MutateState(f func(*TextViewState))
	// CopyState returns a copy of the State.
	CopyState() TextViewState
}

TextView is a Widget for displaying text, with support for vertical scrolling.

NOTE: This widget now always crops long lines. In future it should support wrapping and horizontal scrolling.

func NewTextView

func NewTextView(spec TextViewSpec) TextView

NewTextView builds a TextView from the given spec.

type TextViewSpec

type TextViewSpec struct {
	// A Handler that takes precedence over the default handling of events.
	OverlayHandler Handler
	// If true, a vertical scrollbar will be shown when there are more lines
	// that can be displayed, and the widget responds to Up and Down keys.
	Scrollable bool
	// State. Specifies the initial state if used in New.
	State TextViewState
}

TextViewSpec specifies the configuration and initial state for a Widget.

type TextViewState

type TextViewState struct {
	Lines []string
	First int
}

TextViewState keeps mutable state of TextView.

type VScrollbar

type VScrollbar struct {
	Total int
	Low   int
	High  int
}

VScrollbar is a Renderer for a vertical scrollbar.

func (VScrollbar) Render

func (v VScrollbar) Render(width, height int) *term.Buffer

type VScrollbarContainer

type VScrollbarContainer struct {
	Content   Renderer
	Scrollbar VScrollbar
}

VScrollbarContainer is a Renderer consisting of content and a vertical scrollbar on the right.

func (VScrollbarContainer) Render

func (v VScrollbarContainer) Render(width, height int) *term.Buffer

type Widget

type Widget interface {
	Renderer
	Handler
}

Widget is the basic component of UI; it knows how to handle events and how to render itself.

func Addon

func Addon(a App) Widget

Addon gets the current addon widget of the app.

Directories

Path Synopsis
addons
completion
Package completion implements the UI for showing, filtering and inserting completion candidates.
Package completion implements the UI for showing, filtering and inserting completion candidates.
histlist
Package histlist implements the history listing addon.
Package histlist implements the history listing addon.
histwalk
Package histwalk implements the history walking addon.
Package histwalk implements the history walking addon.
instant
Package instant implements an addon that executes code whenever it changes and shows the result.
Package instant implements an addon that executes code whenever it changes and shows the result.
lastcmd
Package lastcmd implements an addon that supports inserting the last command or words from it.
Package lastcmd implements an addon that supports inserting the last command or words from it.
listing
Package listing provides the custom listing addon.
Package listing provides the custom listing addon.
location
Package location implements an addon that supports viewing location history and changing to a selected directory.
Package location implements an addon that supports viewing location history and changing to a selected directory.
navigation
Package navigation provides the functionality of navigating the filesystem.
Package navigation provides the functionality of navigating the filesystem.
stub
Package stub implements the stub addon, a general-purpose addon that shows a modeline and supports pluggable binding.
Package stub implements the stub addon, a general-purpose addon that shows a modeline and supports pluggable binding.
Package clitest provides utilities for testing cli.App.
Package clitest provides utilities for testing cli.App.
Package histutil provides utilities for working with command history.
Package histutil provides utilities for working with command history.
Package lscolors provides styling of filenames based on file features.
Package lscolors provides styling of filenames based on file features.
Package prompt provides an implementation of the cli.Prompt interface.
Package prompt provides an implementation of the cli.Prompt interface.
Package term provides functionality for working with terminals.
Package term provides functionality for working with terminals.

Jump to

Keyboard shortcuts

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