58 lines
1.4 KiB
Go
58 lines
1.4 KiB
Go
/*
|
|
Package stdinprompt provides an io.Reader that will prompt the user if nothing
|
|
is read within a short period of time. It is useful for programs which default
|
|
to reading from stdin if no commandline arguments are provided, as it can
|
|
indicate to the user that a program is not actually performing any action until
|
|
data arrives. The prompt is not displayed if data becomes available before the
|
|
timeout.
|
|
*/
|
|
package stdinprompt
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
// DefaultPromptTime is the timeout period after which, if no data has
|
|
// been read, we will display a prompt.
|
|
DefaultPromptTime = 250 * time.Millisecond
|
|
|
|
// StdinPromptMsg is the default message displayed.
|
|
StdinPromptMsg = "Waiting for data on stdin."
|
|
)
|
|
|
|
// New returns a new prompting reader for stdin. The prompt will be written to
|
|
// stderr.
|
|
func New() io.Reader {
|
|
return NewEx(os.Stdin, DefaultPromptTime, os.Stderr, StdinPromptMsg)
|
|
}
|
|
|
|
// NewEx returns a new prompting reader. The source may be specified along with
|
|
// the prompt message, timeout and destination.
|
|
func NewEx(raw io.Reader, when time.Duration, term io.Writer, msg string,
|
|
) io.Reader {
|
|
pr := &prompter{
|
|
raw: raw,
|
|
tmr: time.AfterFunc(when, func() {
|
|
fmt.Fprintln(term, msg)
|
|
}),
|
|
}
|
|
return pr
|
|
}
|
|
|
|
type prompter struct {
|
|
raw io.Reader
|
|
tmr *time.Timer
|
|
}
|
|
|
|
func (pr *prompter) Read(buf []byte) (int, error) {
|
|
n, err := pr.raw.Read(buf)
|
|
if n > 0 {
|
|
pr.tmr.Stop()
|
|
}
|
|
return n, err
|
|
}
|