Documentation ¶
Overview ¶
Package status provides Status, LineBuffer and Group
Index ¶
- func DefaultErrorString[Item any](err error, item Item, index int) string
- func DefaultPrefixString[Item any](item Item, index int) string
- func DefaultResultString[Item, Result any](result Result, item Item, index int) string
- func DefaultWaitString[Item any](item Item, index int) string
- func RunErrorGroup[Item any](writer io.Writer, group Group[Item, error], items []Item) error
- func StreamGroup[T any](str stream.IOStream, count int, ...) error
- func UseErrorGroup[Item any](status *Status, group Group[Item, error], items []Item) error
- func WriterGroup[T any](writer io.Writer, count int, handler func(value T, output io.Writer) error, ...) error
- type Group
- type LineBuffer
- func (lb *LineBuffer) Close() error
- func (lb *LineBuffer) ReadFrom(r io.Reader) (n int64, err error)
- func (lb *LineBuffer) Write(b []byte) (int, error)
- func (lb *LineBuffer) WriteByte(b byte) error
- func (lb *LineBuffer) WriteRune(r rune) (int, error)
- func (lb *LineBuffer) WriteString(s string) (int, error)
- type Status
- func (st *Status) Bypass() io.Writer
- func (st *Status) Close(id int)
- func (st *Status) Line(prefix string, id int) io.WriteCloser
- func (st *Status) Open(message string) (id int)
- func (st *Status) OpenLine(prefix, data string) io.WriteCloser
- func (st *Status) Set(id int, message string)
- func (st *Status) Start()
- func (st *Status) Stop()
- type StreamGroupOption
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefaultErrorString ¶
DefaultErrorString implements the default result handler for UseErrorGroup and RunErrorGroup. When error is nil, returns the string "done", else returns the string "failed" with an error description.
func DefaultPrefixString ¶
DefaultPrefixString is the default implementation of [Group.PrefixString]. It uses the default 'v' verb of the 'fmt' package to format the item.
func DefaultResultString ¶
DefaultResultString is the default implementation of [Group.ResultString]. It uses fmt.Sprint on the result type.
func DefaultWaitString ¶
DefaultWaitString returns the string "waiting" for any item.
func RunErrorGroup ¶
RunErrorGroup calls group.Run(status, items) and returns the first non-nil error, or nil otherwise. When group.ResultString is nil, uses DefaultErrorString instead.
func StreamGroup ¶ added in v0.1.0
func StreamGroup[T any](str stream.IOStream, count int, handler func(value T, str stream.IOStream) error, items []T, opts ...StreamGroupOption[T]) error
StreamGroup is like WriterGroup, but operates on an IOStream.
When underlying operations are non-interactive, use WriterGroup instead.
func UseErrorGroup ¶
UseErrorGroup calls group.Use(status, items) and returns the first non-nil error, or nil otherwise. When group.ResultString is nil, uses DefaultErrorString instead.
func WriterGroup ¶ added in v0.2.1
func WriterGroup[T any](writer io.Writer, count int, handler func(value T, output io.Writer) error, items []T, opts ...StreamGroupOption[T]) error
WriterGroup intelligently runs handler over items concurrently.
Count determines the number of concurrent invocations to run. count <= 0 indicates no limit. count = 1 indicates running handler in order.
handler is additionally passed a writer. When there is only one concurrent invocation, the original writer as a parameter. When there is more than one concurrent invocation, each invocation is passed a single line of a new Status. The Status will send output to the standard output of str.
WriterGroup returns the first non-nil error returned by each call to handler; or nil otherwise.
Types ¶
type Group ¶
type Group[Item any, Result any] struct { // PrefixString is called once on each line of the [Status] to add a prefix. // When nil, [DefaultPrefixString] is used. PrefixString func(item Item, index int) string // When PrefixAlign is set, automatically ensure that all prefixes are of the same length, // by adding appropriate spaces. PrefixAlign bool // ResultString is called to generate a message for when the given item has finished processing. // It is called with the returned error. // When nil, [DefaultErrString] is used. ResultString func(res Result, item Item, index int) string // Handler is a handler called for each item to run. // It is passed an io.Writer that writes directly to the specified line of the status. // Handler must not be nil. Handler func(item Item, index int, writer io.Writer) Result // HandlerLimit is the maximum number of handlers to run concurrently. // A HandlerLimit of <= 0 indicates no limit. // // Handlers are in principle called in order, however for HandlerLimit > 1 // this cannot be strictly enforced. // // The Limit is only enforced within a single call to [Use] or []. HandlerLimit int // WaitString is called when the status line for a specific handler is initialized, but the Handler has not yet been called. // // When WaitString is nil, lines are only initialized once they are needed. // Setting WaitString != nil causes output to appear in order. WaitString func(item Item, index int) string }
Group represents a concurrent set of operations. Each operation takes an Item as a parameter, as well as an io.Writer. Each operation returns a Result. Each writer writes to a dedicated line of a Status.
func (Group[Item, Result]) Run ¶
Run creates a new Status, and then directs output to it using [Use].
See also New, [Use].
func (Group[Item, Result]) Use ¶
Use calls Handler for all passed items.
It sends output to the provided status, while respecting HandlerLimit. Each output is displayed on a separate line.
If group.WaitString is nil, lines are closed as soon as they are no longer needed. Otherwise they are closed right before returning.
Use returns once all Handlers have returned.
type LineBuffer ¶
type LineBuffer struct { // Line is called once a complete newline-terminated line has been written to this LineBuffer. // It is called for each line, in the correct order. // The parameter has a trailing '\r\n' or '\n' trimmed. // // Write methods block until the Line function has returned. // Therefore Line must not trigger another Write into the LineBuffer. Line func(line string) // FlushPartialLineAfter forces flushing output after a specific amount of time. // Set to 0 to disable. // // If the line has not been completed, the current partial line will be flushed. // A completed line will always be written. FlushPartialLineAfter time.Duration // FlushLineOnClose indicates if Line should be called a final time when calling close. // Line will only be called when the last write did not end in a newline character. FlushLineOnClose bool // CloseLine is called when the Close function of this LineBuffer is called for the first time. // // CloseLine may be nil, in which case it is not called. CloseLine func() // contains filtered or unexported fields }
LineBuffer is an io.Writer that calls a function Line for every newline-delimited line written to it. Do not copy a non-zero LineBuffer.
Example ¶
// create a new line buffer buffer := LineBuffer{ Line: func(line string) { fmt.Printf("Line(%q)\n", line) }, CloseLine: func() { fmt.Println("CloseLine()") }, } // write some text into it, calling Line() with each completed line buffer.WriteString("line 1\npartial") buffer.WriteString(" line 2\n\n line not terminated") // close the buffer, calling CloseLine() buffer.Close() // futures writes are no longer calling Line buffer.WriteString("another\nline\n")
Output: Line("line 1") Line("partial line 2") Line("") CloseLine()
func (*LineBuffer) Close ¶
func (lb *LineBuffer) Close() error
Close closes this LineBuffer, ensuring any future calls to [Write] or [Close] and friends return an error. When there was an unfinished line, close may cause a final flush of the buffer Close may block and wait for any concurrent calls to [Write] and friends active at the time of the Close call to finish.
Writing to this LineBuffer after Close has returned a nil error no longer call the [Line] function. Calling Close multiple times returns nil error, and performs no further actions.
func (*LineBuffer) ReadFrom ¶
func (lb *LineBuffer) ReadFrom(r io.Reader) (n int64, err error)
ReadFrom reads all available bytes from r into this LineBuffer, until an error is encountered. io.EOF is not considered an error.
func (*LineBuffer) Write ¶
func (lb *LineBuffer) Write(b []byte) (int, error)
Write writes b into the internal buffer. When this completes one or more lines, calls Line appropriatly.
func (*LineBuffer) WriteByte ¶
func (lb *LineBuffer) WriteByte(b byte) error
WriteByte is like [Write], but takes a single byte.
func (*LineBuffer) WriteRune ¶
func (lb *LineBuffer) WriteRune(r rune) (int, error)
WriteRune is like [Write], but takes a single rune
func (*LineBuffer) WriteString ¶
func (lb *LineBuffer) WriteString(s string) (int, error)
WriteString is like [Write], but takes a string
type Status ¶
type Status struct {
// contains filtered or unexported fields
}
Status represents an interactive status display that can write to multiple lines at once.
A Status must be initialized using New, then started (and stopped again) to write messages. Status may not be reused.
A typical usage is as follows:
st := New(os.Stdout, 10) st.Start() defer st.Stop() // ... whatever usage here ... st.Set("line 0", 0)
Using the status to Write messages outside of the Start / Stop process results in no-ops.
Status should only be used on interactive terminals. On other [io.Writer]s, a so-called compatibility mode can be used, that writes updates to the terminal line by line. See NewWithCompat.
func New ¶
New creates a new writer with the provided number of status lines.
The ids of the status lines are guaranteed to be 0...(count-1). When count is less than 0, it is set to 0.
func NewWithCompat ¶ added in v0.0.17
NewWithCompat is like New, but places the Status into a compatibility mode if and only if writer does not represent a terminal.
In compatibility mode, Status automatically prints each line to the output, instead of putting them onto separate lines.
func (*Status) Bypass ¶
Bypass returns a writer that completely bypasses this Status, and writes directly to the underlying writer. [Start] must have been called.
func (*Status) Close ¶
Close removes the status line with the provided id from this status. The last value of the status line is written to the top of the output. Close may block until the removal has been processed.
Calling Close on a line which is not active results is a no-op.
Close may safely be called concurrently with other methods.
Close may only be called after [Start] has been called, but before [Stop]. Other calls are silently ignored.
func (*Status) Line ¶
func (st *Status) Line(prefix string, id int) io.WriteCloser
Line returns an io.WriteCloser linked to the status line with the provided id. Writing a complete newline-delimited line to it behaves just like [Set] with that line prefixed with prefix would. Calling io.WriteCloser.Close behaves just like [Close] would.
Line may be called at any time. Line should not be called multiple times with the same id.
func (*Status) Open ¶
Open adds a new status line and returns its' id. The new status line is initially set to message. It may be further updated with calls to [Set], or removed with [Done]. Open may block until the addition has been processed.
Open may safely be called concurrently with other methods.
Open may only be called after [Start] has been called, but before [Stop]. Other calls are silently ignored, and return an invalid line id.
func (*Status) OpenLine ¶
func (st *Status) OpenLine(prefix, data string) io.WriteCloser
OpenLine behaves like a call to [Open] followed by a call to [Line].
OpenLine may only be called after [Start] has been called, but before [Stop]. Other calls are silently ignored, and return a no-op io.Writer.
func (*Status) Set ¶
Set sets the status line with the given id to contain message. message should not contain newline characters. Set may block until the addition has been processed.
Calling Set on a line which is not active results is a no-op.
Set may safely be called concurrently with other methods.
Set may only be called after [Start] has been called, but before [Stop]. Other calls are silently ignored, and return an invalid line id.
func (*Status) Start ¶
func (st *Status) Start()
Start instructs this Status to start writing output to the underlying writer.
No other process should write to the underlying writer, while this process is running. Instead [Bypass] should be used. See also [Stop].
Start may not be called more than once, extra calls may result in a panic.
type StreamGroupOption ¶ added in v0.1.0
StreamGroupOption represents an option for WriterGroup. The boolean indicates if the option is being applied to a status line or not.
NOTE(twiesing): This name is here for backwards compatibility reasons.
func SmartMessage ¶ added in v0.1.0
func SmartMessage[T any](handler func(value T) string) StreamGroupOption[T]
SmartMessage sets the message to display as a prefix before invoking a handler.