You've already forked postgres_exporter
mirror of
https://github.com/prometheus-community/postgres_exporter.git
synced 2025-08-08 04:42:07 +03:00
Add self-contained gometalinter build tooling.
This commit is contained in:
471
tools/vendor/github.com/Bowery/prompt/term.go
generated
vendored
Normal file
471
tools/vendor/github.com/Bowery/prompt/term.go
generated
vendored
Normal file
@@ -0,0 +1,471 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrCTRLC is returned when CTRL+C is pressed stopping the prompt.
|
||||
ErrCTRLC = errors.New("Interrupted (CTRL+C)")
|
||||
// ErrEOF is returned when CTRL+D is pressed stopping the prompt.
|
||||
ErrEOF = errors.New("EOF (CTRL+D)")
|
||||
)
|
||||
|
||||
// Possible events that may occur when reading from input.
|
||||
const (
|
||||
evChar = iota
|
||||
evSkip
|
||||
evReturn
|
||||
evEOF
|
||||
evCtrlC
|
||||
evBack
|
||||
evClear
|
||||
evHome
|
||||
evEnd
|
||||
evUp
|
||||
evDown
|
||||
evRight
|
||||
evLeft
|
||||
evDel
|
||||
)
|
||||
|
||||
// IsNotTerminal checks if an error is related to the input not being a terminal.
|
||||
func IsNotTerminal(err error) bool {
|
||||
return isNotTerminal(err)
|
||||
}
|
||||
|
||||
// TerminalSize retrieves the columns/rows for the terminal connected to out.
|
||||
func TerminalSize(out *os.File) (int, int, error) {
|
||||
return terminalSize(out)
|
||||
}
|
||||
|
||||
// Terminal contains the state for raw terminal input.
|
||||
type Terminal struct {
|
||||
In *os.File
|
||||
Out *os.File
|
||||
History []string
|
||||
histIdx int
|
||||
simpleReader *bufio.Reader
|
||||
t *terminal
|
||||
}
|
||||
|
||||
// NewTerminal creates a terminal and sets it to raw input mode.
|
||||
func NewTerminal() (*Terminal, error) {
|
||||
in := os.Stdin
|
||||
|
||||
term, err := newTerminal(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Terminal{
|
||||
In: in,
|
||||
Out: os.Stdout,
|
||||
History: make([]string, 0, 10),
|
||||
histIdx: -1,
|
||||
t: term,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Basic gets input and if required tests to ensure input was given.
|
||||
func (term *Terminal) Basic(prefix string, required bool) (string, error) {
|
||||
return term.Custom(prefix, func(input string) (string, bool) {
|
||||
if required && input == "" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return input, true
|
||||
})
|
||||
}
|
||||
|
||||
// BasicDefault gets input and if empty uses the given default.
|
||||
func (term *Terminal) BasicDefault(prefix, def string) (string, error) {
|
||||
return term.Custom(prefix+"(Default: "+def+")", func(input string) (string, bool) {
|
||||
if input == "" {
|
||||
input = def
|
||||
}
|
||||
|
||||
return input, true
|
||||
})
|
||||
}
|
||||
|
||||
// Ask gets input and checks if it's truthy or not, and returns that
|
||||
// in a boolean fashion.
|
||||
func (term *Terminal) Ask(question string) (bool, error) {
|
||||
input, err := term.Custom(question+"?(y/n)", func(input string) (string, bool) {
|
||||
if input == "" {
|
||||
return "", false
|
||||
}
|
||||
input = strings.ToLower(input)
|
||||
|
||||
if input == "y" || input == "yes" {
|
||||
return "yes", true
|
||||
}
|
||||
|
||||
return "", true
|
||||
})
|
||||
|
||||
var ok bool
|
||||
if input != "" {
|
||||
ok = true
|
||||
}
|
||||
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// Custom gets input and calls the given test function with the input to
|
||||
// check if the input is valid, a true return will return the string.
|
||||
func (term *Terminal) Custom(prefix string, test func(string) (string, bool)) (string, error) {
|
||||
var err error
|
||||
var input string
|
||||
var ok bool
|
||||
|
||||
for !ok {
|
||||
input, err = term.GetPrompt(prefix)
|
||||
if err != nil && err != io.EOF {
|
||||
return "", err
|
||||
}
|
||||
|
||||
input, ok = test(input)
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// Password retrieves a password from stdin without echoing it.
|
||||
func (term *Terminal) Password(prefix string) (string, error) {
|
||||
var err error
|
||||
var input string
|
||||
|
||||
for input == "" {
|
||||
input, err = term.GetPassword(prefix)
|
||||
if err != nil && err != io.EOF {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// GetPrompt gets a line with the prefix and echos input.
|
||||
func (term *Terminal) GetPrompt(prefix string) (string, error) {
|
||||
if !term.t.supportsEditing {
|
||||
return term.simplePrompt(prefix)
|
||||
}
|
||||
|
||||
buf := NewBuffer(prefix, term.Out, true)
|
||||
return term.prompt(buf, NewAnsiReader(term.In))
|
||||
}
|
||||
|
||||
// GetPassword gets a line with the prefix and doesn't echo input.
|
||||
func (term *Terminal) GetPassword(prefix string) (string, error) {
|
||||
if !term.t.supportsEditing {
|
||||
return term.simplePrompt(prefix)
|
||||
}
|
||||
|
||||
buf := NewBuffer(prefix, term.Out, false)
|
||||
return term.password(buf, NewAnsiReader(term.In))
|
||||
}
|
||||
|
||||
func (term *Terminal) Close() error {
|
||||
return term.t.Close()
|
||||
}
|
||||
|
||||
// simplePrompt is a fallback prompt without line editing support.
|
||||
func (term *Terminal) simplePrompt(prefix string) (string, error) {
|
||||
if term.simpleReader == nil {
|
||||
term.simpleReader = bufio.NewReader(term.In)
|
||||
}
|
||||
|
||||
_, err := term.Out.Write([]byte(prefix))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
line, err := term.simpleReader.ReadString('\n')
|
||||
line = strings.TrimRight(line, "\r\n ")
|
||||
line = strings.TrimLeft(line, " ")
|
||||
|
||||
return line, err
|
||||
}
|
||||
|
||||
// setup initializes a prompt.
|
||||
func (term *Terminal) setup(buf *Buffer, in io.Reader) (*bufio.Reader, error) {
|
||||
cols, _, err := TerminalSize(buf.Out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf.Cols = cols
|
||||
input := bufio.NewReader(in)
|
||||
|
||||
err = buf.Refresh()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// read reads a rune and parses ANSI escape sequences found
|
||||
func (term *Terminal) read(in *bufio.Reader) (int, rune, error) {
|
||||
char, _, err := in.ReadRune()
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
switch char {
|
||||
default:
|
||||
// Standard chars.
|
||||
return evChar, char, nil
|
||||
case tabKey, ctrlA, ctrlB, ctrlE, ctrlF, ctrlG, ctrlH, ctrlJ, ctrlK, ctrlN,
|
||||
ctrlO, ctrlP, ctrlQ, ctrlR, ctrlS, ctrlT, ctrlU, ctrlV, ctrlW, ctrlX,
|
||||
ctrlY, ctrlZ:
|
||||
// Skip.
|
||||
return evSkip, char, nil
|
||||
case returnKey:
|
||||
// End of line.
|
||||
return evReturn, char, nil
|
||||
case ctrlD:
|
||||
// End of file.
|
||||
return evEOF, char, nil
|
||||
case ctrlC:
|
||||
// End of line, interrupted.
|
||||
return evCtrlC, char, nil
|
||||
case backKey:
|
||||
// Backspace.
|
||||
return evBack, char, nil
|
||||
case ctrlL:
|
||||
// Clear screen.
|
||||
return evClear, char, nil
|
||||
case escKey:
|
||||
// Functions like arrows, home, etc.
|
||||
esc := make([]byte, 2)
|
||||
_, err = in.Read(esc)
|
||||
if err != nil {
|
||||
return -1, char, err
|
||||
}
|
||||
|
||||
// Home, end.
|
||||
if esc[0] == 'O' {
|
||||
switch esc[1] {
|
||||
case 'H':
|
||||
// Home.
|
||||
return evHome, char, nil
|
||||
case 'F':
|
||||
// End.
|
||||
return evEnd, char, nil
|
||||
}
|
||||
|
||||
return evSkip, char, nil
|
||||
}
|
||||
|
||||
// Arrows, delete, pgup, pgdown, insert.
|
||||
if esc[0] == '[' {
|
||||
switch esc[1] {
|
||||
case 'A':
|
||||
// Up.
|
||||
return evUp, char, nil
|
||||
case 'B':
|
||||
// Down.
|
||||
return evDown, char, nil
|
||||
case 'C':
|
||||
// Right.
|
||||
return evRight, char, nil
|
||||
case 'D':
|
||||
// Left.
|
||||
return evLeft, char, nil
|
||||
}
|
||||
|
||||
// Delete, pgup, pgdown, insert.
|
||||
if esc[1] > '0' && esc[1] < '7' {
|
||||
extEsc := make([]byte, 3)
|
||||
_, err = in.Read(extEsc)
|
||||
if err != nil {
|
||||
return -1, char, err
|
||||
}
|
||||
|
||||
if extEsc[0] == '~' {
|
||||
switch esc[1] {
|
||||
case '2', '5', '6':
|
||||
// Insert, pgup, pgdown.
|
||||
return evSkip, char, err
|
||||
case '3':
|
||||
// Delete.
|
||||
return evDel, char, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return evSkip, char, nil
|
||||
}
|
||||
|
||||
// prompt reads from in and parses ANSI escapes writing to buf.
|
||||
func (term *Terminal) prompt(buf *Buffer, in io.Reader) (string, error) {
|
||||
input, err := term.setup(buf, in)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
term.History = append(term.History, "")
|
||||
term.histIdx = len(term.History) - 1
|
||||
curHistIdx := term.histIdx
|
||||
|
||||
for {
|
||||
typ, char, err := term.read(input)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
switch typ {
|
||||
case evChar:
|
||||
err = buf.Insert(char)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
term.History[curHistIdx] = buf.String()
|
||||
case evSkip:
|
||||
continue
|
||||
case evReturn:
|
||||
err = buf.EndLine()
|
||||
return buf.String(), err
|
||||
case evEOF:
|
||||
err = buf.EndLine()
|
||||
if err == nil {
|
||||
err = ErrEOF
|
||||
}
|
||||
|
||||
return buf.String(), err
|
||||
case evCtrlC:
|
||||
err = buf.EndLine()
|
||||
if err == nil {
|
||||
err = ErrCTRLC
|
||||
}
|
||||
|
||||
return buf.String(), err
|
||||
case evBack:
|
||||
err = buf.DelLeft()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
term.History[curHistIdx] = buf.String()
|
||||
case evClear:
|
||||
err = buf.ClsScreen()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evHome:
|
||||
err = buf.Start()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evEnd:
|
||||
err = buf.End()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evUp:
|
||||
idx := term.histIdx
|
||||
if term.histIdx > 0 {
|
||||
idx--
|
||||
}
|
||||
|
||||
err = buf.Set([]rune(term.History[idx])...)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
term.histIdx = idx
|
||||
case evDown:
|
||||
idx := term.histIdx
|
||||
if term.histIdx < len(term.History)-1 {
|
||||
idx++
|
||||
}
|
||||
|
||||
err = buf.Set([]rune(term.History[idx])...)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
term.histIdx = idx
|
||||
case evRight:
|
||||
err = buf.Right()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evLeft:
|
||||
err = buf.Left()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evDel:
|
||||
err = buf.Del()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
term.History[curHistIdx] = buf.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// password reads from in and parses restricted ANSI escapes writing to buf.
|
||||
func (term *Terminal) password(buf *Buffer, in io.Reader) (string, error) {
|
||||
input, err := term.setup(buf, in)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for {
|
||||
typ, char, err := term.read(input)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
switch typ {
|
||||
case evChar:
|
||||
err = buf.Insert(char)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evSkip, evHome, evEnd, evUp, evDown, evRight, evLeft, evDel:
|
||||
continue
|
||||
case evReturn:
|
||||
err = buf.EndLine()
|
||||
return buf.String(), err
|
||||
case evEOF:
|
||||
err = buf.EndLine()
|
||||
if err == nil {
|
||||
err = ErrEOF
|
||||
}
|
||||
|
||||
return buf.String(), err
|
||||
case evCtrlC:
|
||||
err = buf.EndLine()
|
||||
if err == nil {
|
||||
err = ErrCTRLC
|
||||
}
|
||||
|
||||
return buf.String(), err
|
||||
case evBack:
|
||||
err = buf.DelLeft()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evClear:
|
||||
err = buf.ClsScreen()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user