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:
7
tools/vendor/github.com/Bowery/prompt/CONTRIBUTORS.md
generated
vendored
Normal file
7
tools/vendor/github.com/Bowery/prompt/CONTRIBUTORS.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
- [Larz Conwell](https://github.com/larzconwell)
|
||||
- [Steve Kaliski](https://github.com/sjkaliski)
|
||||
- [NHOrus](https://github.com/NHOrus)
|
||||
- [Attila Fülöp](https://github.com/AttilaFueloep)
|
||||
- [Gereon Frey](https://github.com/gfrey)
|
||||
- [Aaron Bieber](https://github.com/qbit)
|
||||
- [Ricky Medina](https://github.com/r-medina)
|
21
tools/vendor/github.com/Bowery/prompt/LICENSE
generated
vendored
Normal file
21
tools/vendor/github.com/Bowery/prompt/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 Bowery, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
38
tools/vendor/github.com/Bowery/prompt/README.md
generated
vendored
Normal file
38
tools/vendor/github.com/Bowery/prompt/README.md
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# Prompt
|
||||
|
||||
[](https://circleci.com/gh/Bowery/prompt/tree/master)
|
||||
|
||||
[](https://godoc.org/github.com/Bowery/prompt)
|
||||
|
||||
Prompt is a cross platform line-editing prompting library. Read the GoDoc page
|
||||
for more info and for API details.
|
||||
|
||||
## Features
|
||||
- Keyboard shortcuts in prompts
|
||||
- History support
|
||||
- Secure password prompt
|
||||
- Custom prompt support
|
||||
- Fallback prompt for unsupported terminals
|
||||
- ANSI conversion for Windows
|
||||
|
||||
## Todo
|
||||
- Multi-line prompt as a Terminal option
|
||||
- Make refresh less jittery on Windows([possible reason](https://github.com/Bowery/prompt/blob/master/output_windows.go#L108))
|
||||
- Multi-byte character support on Windows
|
||||
- `AnsiWriter` should execute the equivalent ANSI escape code functionality on Windows
|
||||
- Support for more ANSI escape codes on Windows.
|
||||
- More keyboard shortcuts from Readlines shortcut list
|
||||
|
||||
## Contributing
|
||||
|
||||
Make sure Go is setup and running the latest release version, and make sure your `GOPATH` is setup properly.
|
||||
|
||||
Follow the guidelines [here](https://guides.github.com/activities/contributing-to-open-source/#contributing).
|
||||
|
||||
Please be sure to `gofmt` any code before doing commits. You can simply run `gofmt -w .` to format all the code in the directory.
|
||||
|
||||
Lastly don't forget to add your name to [`CONTRIBUTORS.md`](https://github.com/Bowery/prompt/blob/master/CONTRIBUTORS.md)
|
||||
|
||||
## License
|
||||
|
||||
Prompt is MIT licensed, details can be found [here](https://raw.githubusercontent.com/Bowery/prompt/master/LICENSE).
|
39
tools/vendor/github.com/Bowery/prompt/ansi_unix.go
generated
vendored
Normal file
39
tools/vendor/github.com/Bowery/prompt/ansi_unix.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly solaris
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// AnsiReader is an io.Reader that wraps an *os.File.
|
||||
type AnsiReader struct {
|
||||
file *os.File
|
||||
}
|
||||
|
||||
// NewAnsiReader creates a AnsiReader from the given input file.
|
||||
func NewAnsiReader(in *os.File) *AnsiReader {
|
||||
return &AnsiReader{file: in}
|
||||
}
|
||||
|
||||
// Read reads data from the input file into b.
|
||||
func (ar *AnsiReader) Read(b []byte) (int, error) {
|
||||
return ar.file.Read(b)
|
||||
}
|
||||
|
||||
// AnsiWriter is an io.Writer that wraps an *os.File.
|
||||
type AnsiWriter struct {
|
||||
file *os.File
|
||||
}
|
||||
|
||||
// NewAnsiWriter creates a AnsiWriter from the given output file.
|
||||
func NewAnsiWriter(out *os.File) *AnsiWriter {
|
||||
return &AnsiWriter{file: out}
|
||||
}
|
||||
|
||||
// Write writes data from b into the input file.
|
||||
func (aw *AnsiWriter) Write(b []byte) (int, error) {
|
||||
return aw.file.Write(b)
|
||||
}
|
510
tools/vendor/github.com/Bowery/prompt/ansi_windows.go
generated
vendored
Normal file
510
tools/vendor/github.com/Bowery/prompt/ansi_windows.go
generated
vendored
Normal file
@@ -0,0 +1,510 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// keyEventType is the key event type for an input record.
|
||||
const keyEventType = 0x0001
|
||||
|
||||
var (
|
||||
readConsoleInput = kernel.NewProc("ReadConsoleInputW")
|
||||
)
|
||||
|
||||
// inputRecord describes a input event from a console.
|
||||
type inputRecord struct {
|
||||
eventType uint16
|
||||
// Magic to get around the union C type, cast
|
||||
// event to the type using unsafe.Pointer.
|
||||
_ [2]byte
|
||||
event [16]byte
|
||||
}
|
||||
|
||||
// keyEventRecord describes a keyboard event.
|
||||
type keyEventRecord struct {
|
||||
keyDown int32
|
||||
repeatCount uint16
|
||||
virtualKeyCode uint16
|
||||
virtualScanCode uint16
|
||||
char uint16
|
||||
controlKeyState uint32
|
||||
}
|
||||
|
||||
// AnsiReader is an io.Reader that reads from a given file and converts Windows
|
||||
// key codes to their equivalent ANSI escape codes.
|
||||
type AnsiReader struct {
|
||||
fd uintptr
|
||||
buf []rune
|
||||
}
|
||||
|
||||
// NewAnsiReader creates a AnsiReader from the given input file.
|
||||
func NewAnsiReader(in *os.File) *AnsiReader {
|
||||
return &AnsiReader{fd: in.Fd()}
|
||||
}
|
||||
|
||||
// Read reads data from the input converting to ANSI escape codes that can be
|
||||
// read over multiple Reads.
|
||||
func (ar *AnsiReader) Read(b []byte) (int, error) {
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if len(ar.buf) == 0 {
|
||||
var runes []rune
|
||||
var read uint32
|
||||
rec := new(inputRecord)
|
||||
|
||||
for runes == nil {
|
||||
ret, _, err := readConsoleInput.Call(ar.fd, uintptr(unsafe.Pointer(rec)),
|
||||
1, uintptr(unsafe.Pointer(&read)))
|
||||
if ret == 0 {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if rec.eventType != keyEventType {
|
||||
continue
|
||||
}
|
||||
|
||||
ke := (*keyEventRecord)(unsafe.Pointer(&rec.event))
|
||||
if ke.keyDown == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
shift := false
|
||||
if ke.controlKeyState&shiftKey != 0 {
|
||||
shift = true
|
||||
}
|
||||
|
||||
ctrl := false
|
||||
if ke.controlKeyState&leftCtrlKey != 0 || ke.controlKeyState&rightCtrlKey != 0 {
|
||||
ctrl = true
|
||||
}
|
||||
|
||||
alt := false
|
||||
if ke.controlKeyState&leftAltKey != 0 || ke.controlKeyState&rightAltKey != 0 {
|
||||
alt = true
|
||||
}
|
||||
|
||||
// Backspace, Return, Space.
|
||||
if ke.char == ctrlH || ke.char == returnKey || ke.char == spaceKey {
|
||||
code := string(returnKey)
|
||||
if ke.char == ctrlH {
|
||||
code = string(backKey)
|
||||
} else if ke.char == spaceKey {
|
||||
code = string(spaceKey)
|
||||
}
|
||||
|
||||
if alt {
|
||||
code = string(escKey) + code
|
||||
}
|
||||
|
||||
runes = []rune(code)
|
||||
break
|
||||
}
|
||||
|
||||
// Generate runes for the chars and key codes.
|
||||
if ke.char > 0 {
|
||||
runes = []rune{rune(ke.char)}
|
||||
} else {
|
||||
code := string(escKey)
|
||||
|
||||
switch ke.virtualKeyCode {
|
||||
case f1Key:
|
||||
if ctrl {
|
||||
continue
|
||||
}
|
||||
|
||||
code += ar.shortFunction("P", shift, ctrl, alt)
|
||||
case f2Key:
|
||||
code += ar.shortFunction("Q", shift, ctrl, alt)
|
||||
case f3Key:
|
||||
code += ar.shortFunction("R", shift, ctrl, alt)
|
||||
case f4Key:
|
||||
code += ar.shortFunction("S", shift, ctrl, alt)
|
||||
case f5Key:
|
||||
code += ar.longFunction("15", shift, ctrl, alt)
|
||||
case f6Key:
|
||||
code += ar.longFunction("17", shift, ctrl, alt)
|
||||
case f7Key:
|
||||
code += ar.longFunction("18", shift, ctrl, alt)
|
||||
case f8Key:
|
||||
code += ar.longFunction("19", shift, ctrl, alt)
|
||||
case f9Key:
|
||||
code += ar.longFunction("20", shift, ctrl, alt)
|
||||
case f10Key:
|
||||
code += ar.longFunction("21", shift, ctrl, alt)
|
||||
case f11Key:
|
||||
code += ar.longFunction("23", shift, ctrl, alt)
|
||||
case f12Key:
|
||||
code += ar.longFunction("24", shift, ctrl, alt)
|
||||
case insertKey:
|
||||
if shift || ctrl {
|
||||
continue
|
||||
}
|
||||
|
||||
code += ar.longFunction("2", shift, ctrl, alt)
|
||||
case deleteKey:
|
||||
code += ar.longFunction("3", shift, ctrl, alt)
|
||||
case homeKey:
|
||||
code += "OH"
|
||||
case endKey:
|
||||
code += "OF"
|
||||
case pgupKey:
|
||||
if shift {
|
||||
continue
|
||||
}
|
||||
|
||||
code += ar.longFunction("5", shift, ctrl, alt)
|
||||
case pgdownKey:
|
||||
if shift {
|
||||
continue
|
||||
}
|
||||
|
||||
code += ar.longFunction("6", shift, ctrl, alt)
|
||||
case upKey:
|
||||
code += ar.arrow("A", shift, ctrl, alt)
|
||||
case downKey:
|
||||
code += ar.arrow("B", shift, ctrl, alt)
|
||||
case leftKey:
|
||||
code += ar.arrow("D", shift, ctrl, alt)
|
||||
case rightKey:
|
||||
code += ar.arrow("C", shift, ctrl, alt)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
runes = []rune(code)
|
||||
}
|
||||
}
|
||||
|
||||
ar.buf = runes
|
||||
}
|
||||
|
||||
// Get items from the buffer.
|
||||
var n int
|
||||
for i, r := range ar.buf {
|
||||
if utf8.RuneLen(r) > len(b) {
|
||||
ar.buf = ar.buf[i:]
|
||||
return n, nil
|
||||
}
|
||||
|
||||
nr := utf8.EncodeRune(b, r)
|
||||
b = b[nr:]
|
||||
n += nr
|
||||
}
|
||||
|
||||
ar.buf = nil
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// shortFunction creates a short function code.
|
||||
func (ar *AnsiReader) shortFunction(ident string, shift, ctrl, alt bool) string {
|
||||
code := "O"
|
||||
|
||||
if shift {
|
||||
code += "1;2"
|
||||
} else if ctrl {
|
||||
code += "1;5"
|
||||
} else if alt {
|
||||
code += "1;3"
|
||||
}
|
||||
|
||||
return code + ident
|
||||
}
|
||||
|
||||
// longFunction creates a long function code.
|
||||
func (ar *AnsiReader) longFunction(ident string, shift, ctrl, alt bool) string {
|
||||
code := "["
|
||||
code += ident
|
||||
|
||||
if shift {
|
||||
code += ";2"
|
||||
} else if ctrl {
|
||||
code += ";5"
|
||||
} else if alt {
|
||||
code += ";3"
|
||||
}
|
||||
|
||||
return code + "~"
|
||||
}
|
||||
|
||||
// arrow creates an arrow code.
|
||||
func (ar *AnsiReader) arrow(ident string, shift, ctrl, alt bool) string {
|
||||
code := "["
|
||||
|
||||
if shift {
|
||||
code += "1;2"
|
||||
} else if ctrl {
|
||||
code += "1;5"
|
||||
} else if alt {
|
||||
code += "1;3"
|
||||
}
|
||||
|
||||
return code + ident
|
||||
}
|
||||
|
||||
// AnsiWriter is an io.Writer that writes to a given file and converts ANSI
|
||||
// escape codes to their equivalent Windows functionality.
|
||||
type AnsiWriter struct {
|
||||
file *os.File
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// NewAnsiWriter creates a AnsiWriter from the given output.
|
||||
func NewAnsiWriter(out *os.File) *AnsiWriter {
|
||||
return &AnsiWriter{file: out}
|
||||
}
|
||||
|
||||
// Write writes the buffer filtering out ANSI escape codes and converting to
|
||||
// the Windows functionality needed. ANSI escape codes may be found over multiple
|
||||
// Writes.
|
||||
func (aw *AnsiWriter) Write(b []byte) (int, error) {
|
||||
needsProcessing := bytes.Contains(b, []byte(string(escKey)))
|
||||
if len(aw.buf) > 0 {
|
||||
needsProcessing = true
|
||||
}
|
||||
|
||||
if !needsProcessing {
|
||||
return aw.file.Write(b)
|
||||
}
|
||||
var p []byte
|
||||
|
||||
for _, char := range b {
|
||||
// Found the beginning of an escape.
|
||||
if char == escKey {
|
||||
aw.buf = append(aw.buf, char)
|
||||
continue
|
||||
}
|
||||
|
||||
// Funtion identifiers.
|
||||
if len(aw.buf) == 1 && (char == '_' || char == 'P' || char == '[' ||
|
||||
char == ']' || char == '^' || char == ' ' || char == '#' ||
|
||||
char == '%' || char == '(' || char == ')' || char == '*' ||
|
||||
char == '+') {
|
||||
aw.buf = append(aw.buf, char)
|
||||
continue
|
||||
}
|
||||
|
||||
// Cursor functions.
|
||||
if len(aw.buf) == 1 && (char == '7' || char == '8') {
|
||||
// Add another char before because finish skips 2 items.
|
||||
aw.buf = append(aw.buf, '_', char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Keyboard functions.
|
||||
if len(aw.buf) == 1 && (char == '=' || char == '>') {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Bottom left function.
|
||||
if len(aw.buf) == 1 && char == 'F' {
|
||||
// Add extra char for finish.
|
||||
aw.buf = append(aw.buf, '_', char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Reset function.
|
||||
if len(aw.buf) == 1 && char == 'c' {
|
||||
// Add extra char for finish.
|
||||
aw.buf = append(aw.buf, '_', char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Space functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == ' ' && (char == 'F' || char == 'G' ||
|
||||
char == 'L' || char == 'M' || char == 'N') {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Number functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == '#' && (char >= '3' && char <= '6') ||
|
||||
char == '8' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Percentage functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == '%' && (char == '@' || char == 'G') {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Character set functions.
|
||||
if len(aw.buf) >= 2 && (aw.buf[1] == '(' || aw.buf[1] == ')' ||
|
||||
aw.buf[1] == '*' || aw.buf[1] == '+') && (char == '0' ||
|
||||
(char >= '4' && char <= '7') || char == '=' || (char >= 'A' &&
|
||||
char <= 'C') || char == 'E' || char == 'H' || char == 'K' ||
|
||||
char == 'Q' || char == 'R' || char == 'Y') {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// APC functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == '_' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
// End of APC.
|
||||
if char == '\\' && aw.buf[len(aw.buf)-1] == escKey {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// DC functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == 'P' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
// End of DC.
|
||||
if char == '\\' && aw.buf[len(aw.buf)-1] == escKey {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// CSI functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == '[' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
// End of CSI.
|
||||
if char == '@' || (char >= 'A' && char <= 'M') || char == 'P' ||
|
||||
char == 'S' || char == 'T' || char == 'X' || char == 'Z' ||
|
||||
char == '`' || (char >= 'b' && char <= 'd') || (char >= 'f' &&
|
||||
char <= 'i') || (char >= 'l' && char <= 'n') || (char >= 'p' &&
|
||||
char <= 't') || char == 'w' || char == 'x' || char == 'z' ||
|
||||
char == '{' || char == '|' {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// OSC functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == ']' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
// Capture incomplete code.
|
||||
if len(aw.buf) == 4 && aw.buf[2] == '0' && char == ';' {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// End of OSC.
|
||||
if (char == '\\' && aw.buf[len(aw.buf)-1] == escKey) || char == ctrlG {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// PM functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == '^' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
// End of PM.
|
||||
if char == '\\' && aw.buf[len(aw.buf)-1] == escKey {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Normal character, resets escape buffer.
|
||||
if len(aw.buf) > 0 {
|
||||
aw.buf = nil
|
||||
}
|
||||
p = append(p, char)
|
||||
}
|
||||
|
||||
_, err := aw.file.Write(p)
|
||||
return len(b), err
|
||||
}
|
||||
|
||||
// finish finishes an ANSI escape code and calls the parsing function. Afterwards
|
||||
// the escape buffer is emptied.
|
||||
func (aw *AnsiWriter) finish(parse func([]byte) error) error {
|
||||
var err error
|
||||
|
||||
if parse != nil {
|
||||
err = parse(aw.buf[2:])
|
||||
}
|
||||
|
||||
aw.buf = nil
|
||||
return err
|
||||
}
|
152
tools/vendor/github.com/Bowery/prompt/buffer.go
generated
vendored
Normal file
152
tools/vendor/github.com/Bowery/prompt/buffer.go
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Buffer contains state for line editing and writing.
|
||||
type Buffer struct {
|
||||
Out *os.File
|
||||
Prompt string
|
||||
Echo bool
|
||||
Cols int
|
||||
pos int
|
||||
size int
|
||||
data []rune
|
||||
}
|
||||
|
||||
// NewBuffer creates a buffer writing to out if echo is true.
|
||||
func NewBuffer(prompt string, out *os.File, echo bool) *Buffer {
|
||||
return &Buffer{
|
||||
Out: out,
|
||||
Prompt: prompt,
|
||||
Echo: echo,
|
||||
}
|
||||
}
|
||||
|
||||
// String returns the data as a string.
|
||||
func (buf *Buffer) String() string {
|
||||
return string(buf.data[:buf.size])
|
||||
}
|
||||
|
||||
// Insert inserts characters at the cursors position.
|
||||
func (buf *Buffer) Insert(rs ...rune) error {
|
||||
rsLen := len(rs)
|
||||
total := buf.size + rsLen
|
||||
|
||||
if total > len(buf.data) {
|
||||
buf.data = append(buf.data, make([]rune, rsLen)...)
|
||||
}
|
||||
|
||||
// Shift characters to make room in the correct pos.
|
||||
if buf.size != buf.pos {
|
||||
copy(buf.data[buf.pos+rsLen:buf.size+rsLen], buf.data[buf.pos:buf.size])
|
||||
}
|
||||
|
||||
for _, r := range rs {
|
||||
buf.data[buf.pos] = r
|
||||
buf.pos++
|
||||
buf.size++
|
||||
}
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// Set sets the content in the buffer.
|
||||
func (buf *Buffer) Set(rs ...rune) error {
|
||||
rsLen := len(rs)
|
||||
buf.data = rs
|
||||
buf.pos = rsLen
|
||||
buf.size = rsLen
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// Start moves the cursor to the start.
|
||||
func (buf *Buffer) Start() error {
|
||||
if buf.pos <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
buf.pos = 0
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// End moves the cursor to the end.
|
||||
func (buf *Buffer) End() error {
|
||||
if buf.pos >= buf.size {
|
||||
return nil
|
||||
}
|
||||
|
||||
buf.pos = buf.size
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// Left moves the cursor one character left.
|
||||
func (buf *Buffer) Left() error {
|
||||
if buf.pos <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
buf.pos--
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// Right moves the cursor one character right.
|
||||
func (buf *Buffer) Right() error {
|
||||
if buf.pos >= buf.size {
|
||||
return nil
|
||||
}
|
||||
|
||||
buf.pos++
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// Del removes the character at the cursor position.
|
||||
func (buf *Buffer) Del() error {
|
||||
if buf.pos >= buf.size {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shift characters after position back one.
|
||||
copy(buf.data[buf.pos:], buf.data[buf.pos+1:buf.size])
|
||||
buf.size--
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// DelLeft removes the character to the left.
|
||||
func (buf *Buffer) DelLeft() error {
|
||||
if buf.pos <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shift characters from position back one.
|
||||
copy(buf.data[buf.pos-1:], buf.data[buf.pos:buf.size])
|
||||
buf.pos--
|
||||
buf.size--
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// EndLine ends the line with CRLF.
|
||||
func (buf *Buffer) EndLine() error {
|
||||
_, err := buf.Out.Write(crlf)
|
||||
return err
|
||||
}
|
||||
|
||||
// toBytes converts a slice of runes to its equivalent in bytes.
|
||||
func toBytes(runes []rune) []byte {
|
||||
var bytes []byte
|
||||
char := make([]byte, utf8.UTFMax)
|
||||
|
||||
for _, r := range runes {
|
||||
n := utf8.EncodeRune(char, r)
|
||||
bytes = append(bytes, char[:n]...)
|
||||
}
|
||||
|
||||
return bytes
|
||||
}
|
76
tools/vendor/github.com/Bowery/prompt/buffer_unix.go
generated
vendored
Normal file
76
tools/vendor/github.com/Bowery/prompt/buffer_unix.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly solaris
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Refresh rewrites the prompt and buffer.
|
||||
func (buf *Buffer) Refresh() error {
|
||||
// If we're not echoing just write prompt.
|
||||
if !buf.Echo {
|
||||
_, err := buf.Out.Write(mvLeftEdge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write([]byte(buf.Prompt))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write(delRight)
|
||||
return err
|
||||
}
|
||||
|
||||
prLen := len(buf.Prompt)
|
||||
start := 0
|
||||
size := buf.size
|
||||
pos := buf.pos
|
||||
|
||||
// Get slice range that should be visible.
|
||||
for prLen+pos >= buf.Cols {
|
||||
start++
|
||||
size--
|
||||
pos--
|
||||
}
|
||||
for prLen+size > buf.Cols {
|
||||
size--
|
||||
}
|
||||
|
||||
_, err := buf.Out.Write(mvLeftEdge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write([]byte(buf.Prompt))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write(toBytes(buf.data[start : size+start]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write(delRight)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write([]byte(fmt.Sprintf(mvToCol, pos+prLen)))
|
||||
return err
|
||||
}
|
||||
|
||||
// ClsScreen clears the screen and refreshes.
|
||||
func (buf *Buffer) ClsScreen() error {
|
||||
_, err := buf.Out.Write(clsScreen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
150
tools/vendor/github.com/Bowery/prompt/buffer_windows.go
generated
vendored
Normal file
150
tools/vendor/github.com/Bowery/prompt/buffer_windows.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
fillConsoleOutputCharacter = kernel.NewProc("FillConsoleOutputCharacterW")
|
||||
setConsoleCursorPosition = kernel.NewProc("SetConsoleCursorPosition")
|
||||
)
|
||||
|
||||
// Refresh rewrites the prompt and buffer.
|
||||
func (buf *Buffer) Refresh() error {
|
||||
csbi := new(consoleScreenBufferInfo)
|
||||
ret, _, err := getConsoleScreenBufferInfo.Call(buf.Out.Fd(),
|
||||
uintptr(unsafe.Pointer(csbi)))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
// If we're not echoing just write prompt.
|
||||
if !buf.Echo {
|
||||
err = buf.delLine(csbi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = buf.mvLeftEdge(csbi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write([]byte(buf.Prompt))
|
||||
return err
|
||||
}
|
||||
|
||||
prLen := len(buf.Prompt)
|
||||
start := 0
|
||||
size := buf.size
|
||||
pos := buf.pos
|
||||
|
||||
// Get slice range that should be visible.
|
||||
for prLen+pos >= buf.Cols {
|
||||
start++
|
||||
size--
|
||||
pos--
|
||||
}
|
||||
for prLen+size > buf.Cols {
|
||||
size--
|
||||
}
|
||||
|
||||
err = buf.delLine(csbi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = buf.mvLeftEdge(csbi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write([]byte(buf.Prompt))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write(toBytes(buf.data[start : size+start]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return buf.mvToCol(csbi, pos+prLen)
|
||||
}
|
||||
|
||||
// ClsScreen clears the screen and refreshes.
|
||||
func (buf *Buffer) ClsScreen() error {
|
||||
var written uint32
|
||||
coords := new(coord)
|
||||
|
||||
csbi := new(consoleScreenBufferInfo)
|
||||
ret, _, err := getConsoleScreenBufferInfo.Call(buf.Out.Fd(),
|
||||
uintptr(unsafe.Pointer(csbi)))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
// Clear everything from 0,0.
|
||||
ret, _, err = fillConsoleOutputCharacter.Call(buf.Out.Fd(), uintptr(' '),
|
||||
uintptr(csbi.size.x*csbi.size.y), uintptr(*(*int32)(unsafe.Pointer(coords))),
|
||||
uintptr(unsafe.Pointer(&written)))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set cursor at 0,0.
|
||||
ret, _, err = setConsoleCursorPosition.Call(buf.Out.Fd(),
|
||||
uintptr(*(*int32)(unsafe.Pointer(coords))))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// delLine deletes the line the csbi cursor is positioned on.
|
||||
// TODO: Possible refresh jittering reason, instead we should copy the Unix
|
||||
// code and write over contents and then remove everything to the right.
|
||||
func (buf *Buffer) delLine(csbi *consoleScreenBufferInfo) error {
|
||||
var written uint32
|
||||
coords := &coord{y: csbi.cursorPosition.y}
|
||||
|
||||
ret, _, err := fillConsoleOutputCharacter.Call(buf.Out.Fd(), uintptr(' '),
|
||||
uintptr(csbi.size.x), uintptr(*(*int32)(unsafe.Pointer(coords))),
|
||||
uintptr(unsafe.Pointer(&written)))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// mvLeftEdge moves the cursor to the beginning of the line the csbi cursor
|
||||
// is positioned on.
|
||||
func (buf *Buffer) mvLeftEdge(csbi *consoleScreenBufferInfo) error {
|
||||
coords := &coord{y: csbi.cursorPosition.y}
|
||||
|
||||
ret, _, err := setConsoleCursorPosition.Call(buf.Out.Fd(),
|
||||
uintptr(*(*int32)(unsafe.Pointer(coords))))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// mvTolCol moves the cursor to the col on the line the csbi cursor is
|
||||
// positioned on.
|
||||
func (buf *Buffer) mvToCol(csbi *consoleScreenBufferInfo, x int) error {
|
||||
coords := &coord{x: int16(x), y: csbi.cursorPosition.y}
|
||||
|
||||
ret, _, err := setConsoleCursorPosition.Call(buf.Out.Fd(),
|
||||
uintptr(*(*int32)(unsafe.Pointer(coords))))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
15
tools/vendor/github.com/Bowery/prompt/ioctl_bsd.go
generated
vendored
Normal file
15
tools/vendor/github.com/Bowery/prompt/ioctl_bsd.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// +build darwin freebsd openbsd netbsd dragonfly
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
tcgets = unix.TIOCGETA
|
||||
tcsets = unix.TIOCSETA
|
||||
tcsetsf = unix.TIOCSETAF
|
||||
)
|
13
tools/vendor/github.com/Bowery/prompt/ioctl_linux.go
generated
vendored
Normal file
13
tools/vendor/github.com/Bowery/prompt/ioctl_linux.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
tcgets = unix.TCGETS
|
||||
tcsets = unix.TCSETS
|
||||
tcsetsf = unix.TCSETSF
|
||||
)
|
41
tools/vendor/github.com/Bowery/prompt/ioctl_solaris.go
generated
vendored
Normal file
41
tools/vendor/github.com/Bowery/prompt/ioctl_solaris.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
tcgets = unix.TCGETS
|
||||
tcsetsf = unix.TCSETSF
|
||||
tcsets = unix.TCSETS
|
||||
)
|
||||
|
||||
// terminalSize retrieves the cols/rows for the terminal connected to out.
|
||||
func terminalSize(out *os.File) (int, int, error) {
|
||||
ws, err := unix.IoctlGetWinsize(int(out.Fd()), unix.TIOCGWINSZ)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
return int(ws.Col), int(ws.Row), nil
|
||||
}
|
||||
|
||||
// getTermios retrieves the termios settings for the terminal descriptor.
|
||||
func getTermios(fd uintptr) (*unix.Termios, error) {
|
||||
return unix.IoctlGetTermios(int(fd), tcgets)
|
||||
}
|
||||
|
||||
// setTermios sets the termios settings for the terminal descriptor,
|
||||
// optionally flushing the buffer before setting.
|
||||
func setTermios(fd uintptr, flush bool, mode *unix.Termios) error {
|
||||
req := tcsets
|
||||
if flush {
|
||||
req = tcsetsf
|
||||
}
|
||||
|
||||
return unix.IoctlSetTermios(int(fd), req, mode)
|
||||
}
|
62
tools/vendor/github.com/Bowery/prompt/ioctl_unix.go
generated
vendored
Normal file
62
tools/vendor/github.com/Bowery/prompt/ioctl_unix.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// winsize contains the size for the terminal.
|
||||
type winsize struct {
|
||||
rows uint16
|
||||
cols uint16
|
||||
_ uint32
|
||||
}
|
||||
|
||||
// terminalSize retrieves the cols/rows for the terminal connected to out.
|
||||
func terminalSize(out *os.File) (int, int, error) {
|
||||
ws := new(winsize)
|
||||
|
||||
_, _, err := unix.Syscall(unix.SYS_IOCTL, out.Fd(),
|
||||
uintptr(unix.TIOCGWINSZ), uintptr(unsafe.Pointer(ws)))
|
||||
if err != 0 {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
return int(ws.cols), int(ws.rows), nil
|
||||
}
|
||||
|
||||
// getTermios retrieves the termios settings for the terminal descriptor.
|
||||
func getTermios(fd uintptr) (*unix.Termios, error) {
|
||||
termios := new(unix.Termios)
|
||||
|
||||
_, _, err := unix.Syscall(unix.SYS_IOCTL, fd, tcgets,
|
||||
uintptr(unsafe.Pointer(termios)))
|
||||
if err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return termios, nil
|
||||
}
|
||||
|
||||
// setTermios sets the termios settings for the terminal descriptor,
|
||||
// optionally flushing the buffer before setting.
|
||||
func setTermios(fd uintptr, flush bool, mode *unix.Termios) error {
|
||||
req := tcsets
|
||||
if flush {
|
||||
req = tcsetsf
|
||||
}
|
||||
|
||||
_, _, err := unix.Syscall(unix.SYS_IOCTL, fd, uintptr(req),
|
||||
uintptr(unsafe.Pointer(mode)))
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
41
tools/vendor/github.com/Bowery/prompt/keys.go
generated
vendored
Normal file
41
tools/vendor/github.com/Bowery/prompt/keys.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
// Line ending in raw mode.
|
||||
var crlf = []byte("\r\n")
|
||||
|
||||
const (
|
||||
backKey = '\u007f'
|
||||
escKey = '\u001B'
|
||||
spaceKey = '\u0020'
|
||||
)
|
||||
|
||||
const (
|
||||
ctrlA = iota + 1
|
||||
ctrlB
|
||||
ctrlC
|
||||
ctrlD
|
||||
ctrlE
|
||||
ctrlF
|
||||
ctrlG
|
||||
ctrlH
|
||||
tabKey
|
||||
ctrlJ
|
||||
ctrlK
|
||||
ctrlL
|
||||
returnKey
|
||||
ctrlN
|
||||
ctrlO
|
||||
ctrlP
|
||||
ctrlQ
|
||||
ctrlR
|
||||
ctrlS
|
||||
ctrlT
|
||||
ctrlU
|
||||
ctrlV
|
||||
ctrlW
|
||||
ctrlX
|
||||
ctrlY
|
||||
ctrlZ
|
||||
)
|
13
tools/vendor/github.com/Bowery/prompt/keys_unix.go
generated
vendored
Normal file
13
tools/vendor/github.com/Bowery/prompt/keys_unix.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly solaris
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
const mvToCol = "\u001b[0G\u001b[%dC"
|
||||
|
||||
var (
|
||||
mvLeftEdge = []byte("\u001b[0G")
|
||||
clsScreen = []byte("\u001b[H\u001b[2J")
|
||||
delRight = []byte("\u001b[0K")
|
||||
)
|
34
tools/vendor/github.com/Bowery/prompt/keys_windows.go
generated
vendored
Normal file
34
tools/vendor/github.com/Bowery/prompt/keys_windows.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
const (
|
||||
f1Key = 0x70 + iota
|
||||
f2Key
|
||||
f3Key
|
||||
f4Key
|
||||
f5Key
|
||||
f6Key
|
||||
f7Key
|
||||
f8Key
|
||||
f9Key
|
||||
f10Key
|
||||
f11Key
|
||||
f12Key
|
||||
|
||||
homeKey = 0x24
|
||||
endKey = 0x23
|
||||
upKey = 0x26
|
||||
downKey = 0x28
|
||||
rightKey = 0x27
|
||||
leftKey = 0x25
|
||||
insertKey = 0x2d
|
||||
pgupKey = 0x21
|
||||
pgdownKey = 0x22
|
||||
deleteKey = 0x2e
|
||||
leftAltKey = 0x2
|
||||
rightAltKey = 0x1
|
||||
leftCtrlKey = 0x8
|
||||
rightCtrlKey = 0x4
|
||||
shiftKey = 0x10
|
||||
)
|
85
tools/vendor/github.com/Bowery/prompt/prompt.go
generated
vendored
Normal file
85
tools/vendor/github.com/Bowery/prompt/prompt.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
// Package prompt implements a cross platform line-editing prompt. It also
|
||||
// provides routines to use ANSI escape sequences across platforms for
|
||||
// terminal connected io.Readers/io.Writers.
|
||||
//
|
||||
// If os.Stdin isn't connected to a terminal or (on Unix)if the terminal
|
||||
// doesn't support the ANSI escape sequences needed a fallback prompt is
|
||||
// provided that doesn't do line-editing. Unix terminals that are not supported
|
||||
// will have the TERM environment variable set to either "dumb" or "cons25".
|
||||
//
|
||||
// The keyboard shortcuts are similar to those found in the Readline library:
|
||||
//
|
||||
// - Enter / CTRL+D
|
||||
// - End the line.
|
||||
// - CTRL+C
|
||||
// - End the line, return error `ErrCTRLC`.
|
||||
// - Backspace
|
||||
// - Remove the character to the left.
|
||||
// - CTRL+L
|
||||
// - Clear the screen(keeping the current lines content).
|
||||
// - Home / End
|
||||
// - Jump to the beginning/end of the line.
|
||||
// - Up arrow / Down arrow
|
||||
// - Go back and forward in the history.
|
||||
// - Left arrow / Right arrow
|
||||
// - Move left/right one character.
|
||||
// - Delete
|
||||
// - Remove the character to the right.
|
||||
package prompt
|
||||
|
||||
// Basic is a wrapper around Terminal.Basic.
|
||||
func Basic(prefix string, required bool) (string, error) {
|
||||
term, err := NewTerminal()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer term.Close()
|
||||
|
||||
return term.Basic(prefix, required)
|
||||
}
|
||||
|
||||
// BasicDefault is a wrapper around Terminal.BasicDefault.
|
||||
func BasicDefault(prefix, def string) (string, error) {
|
||||
term, err := NewTerminal()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer term.Close()
|
||||
|
||||
return term.BasicDefault(prefix, def)
|
||||
}
|
||||
|
||||
// Ask is a wrapper around Terminal.Ask.
|
||||
func Ask(question string) (bool, error) {
|
||||
term, err := NewTerminal()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer term.Close()
|
||||
|
||||
return term.Ask(question)
|
||||
}
|
||||
|
||||
// Custom is a wrapper around Terminal.Custom.
|
||||
func Custom(prefix string, test func(string) (string, bool)) (string, error) {
|
||||
term, err := NewTerminal()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer term.Close()
|
||||
|
||||
return term.Custom(prefix, test)
|
||||
}
|
||||
|
||||
// Password is a wrapper around Terminal.Password.
|
||||
func Password(prefix string) (string, error) {
|
||||
term, err := NewTerminal()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer term.Close()
|
||||
|
||||
return term.Password(prefix)
|
||||
}
|
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
96
tools/vendor/github.com/Bowery/prompt/term_unix.go
generated
vendored
Normal file
96
tools/vendor/github.com/Bowery/prompt/term_unix.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly solaris
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// List of unsupported $TERM values.
|
||||
var unsupported = []string{"", "dumb", "cons25"}
|
||||
|
||||
// supportsEditing checks if the terminal supports ansi escapes.
|
||||
func supportsEditing() bool {
|
||||
term := os.Getenv("TERM")
|
||||
|
||||
for _, t := range unsupported {
|
||||
if t == term {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// isNotTerminal checks if an error is related to the input not being a terminal.
|
||||
func isNotTerminal(err error) bool {
|
||||
return err == unix.ENOTTY
|
||||
}
|
||||
|
||||
// terminal contains the private fields for a Unix terminal.
|
||||
type terminal struct {
|
||||
supportsEditing bool
|
||||
fd uintptr
|
||||
origMode unix.Termios
|
||||
}
|
||||
|
||||
// newTerminal creates a terminal and sets it to raw input mode.
|
||||
func newTerminal(in *os.File) (*terminal, error) {
|
||||
term := &terminal{fd: in.Fd()}
|
||||
|
||||
if !supportsEditing() {
|
||||
return term, nil
|
||||
}
|
||||
|
||||
t, err := getTermios(term.fd)
|
||||
if err != nil {
|
||||
if IsNotTerminal(err) {
|
||||
return term, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
term.origMode = *t
|
||||
mode := term.origMode
|
||||
term.supportsEditing = true
|
||||
|
||||
// Set new mode flags, for reference see cfmakeraw(3).
|
||||
mode.Iflag &^= (unix.BRKINT | unix.IGNBRK | unix.ICRNL |
|
||||
unix.INLCR | unix.IGNCR | unix.ISTRIP | unix.IXON |
|
||||
unix.PARMRK)
|
||||
|
||||
mode.Oflag &^= unix.OPOST
|
||||
|
||||
mode.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON |
|
||||
unix.ISIG | unix.IEXTEN)
|
||||
|
||||
mode.Cflag &^= (unix.CSIZE | unix.PARENB)
|
||||
mode.Cflag |= unix.CS8
|
||||
|
||||
// Set controls; min num of bytes, and timeouts.
|
||||
mode.Cc[unix.VMIN] = 1
|
||||
mode.Cc[unix.VTIME] = 0
|
||||
|
||||
err = setTermios(term.fd, true, &mode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return term, nil
|
||||
}
|
||||
|
||||
// Close disables the terminals raw input.
|
||||
func (term *terminal) Close() error {
|
||||
if term.supportsEditing {
|
||||
err := setTermios(term.fd, false, &term.origMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
116
tools/vendor/github.com/Bowery/prompt/term_windows.go
generated
vendored
Normal file
116
tools/vendor/github.com/Bowery/prompt/term_windows.go
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Flags to control the terminals mode.
|
||||
const (
|
||||
echoInputFlag = 0x0004
|
||||
insertModeFlag = 0x0020
|
||||
lineInputFlag = 0x0002
|
||||
mouseInputFlag = 0x0010
|
||||
processedInputFlag = 0x0001
|
||||
windowInputFlag = 0x0008
|
||||
)
|
||||
|
||||
// Error number returned for an invalid handle.
|
||||
const errnoInvalidHandle = 0x6
|
||||
|
||||
var (
|
||||
kernel = syscall.NewLazyDLL("kernel32.dll")
|
||||
getConsoleScreenBufferInfo = kernel.NewProc("GetConsoleScreenBufferInfo")
|
||||
setConsoleMode = kernel.NewProc("SetConsoleMode")
|
||||
)
|
||||
|
||||
// consoleScreenBufferInfo contains various fields for the terminal.
|
||||
type consoleScreenBufferInfo struct {
|
||||
size coord
|
||||
cursorPosition coord
|
||||
attributes uint16
|
||||
window smallRect
|
||||
maximumWindowSize coord
|
||||
}
|
||||
|
||||
// coord contains coords for positioning.
|
||||
type coord struct {
|
||||
x int16
|
||||
y int16
|
||||
}
|
||||
|
||||
// smallRect contains positions for the window edges.
|
||||
type smallRect struct {
|
||||
left int16
|
||||
top int16
|
||||
right int16
|
||||
bottom int16
|
||||
}
|
||||
|
||||
// terminalSize retrieves the cols/rows for the terminal connected to out.
|
||||
func terminalSize(out *os.File) (int, int, error) {
|
||||
csbi := new(consoleScreenBufferInfo)
|
||||
|
||||
ret, _, err := getConsoleScreenBufferInfo.Call(out.Fd(), uintptr(unsafe.Pointer(csbi)))
|
||||
if ret == 0 {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
// Results are always off by one.
|
||||
cols := csbi.window.right - csbi.window.left + 1
|
||||
rows := csbi.window.bottom - csbi.window.top + 1
|
||||
|
||||
return int(cols), int(rows), nil
|
||||
}
|
||||
|
||||
// isNotTerminal checks if an error is related to the input not being a terminal.
|
||||
func isNotTerminal(err error) bool {
|
||||
errno, ok := err.(syscall.Errno)
|
||||
|
||||
return ok && errno == errnoInvalidHandle
|
||||
}
|
||||
|
||||
// terminal contains the private fields for a Windows terminal.
|
||||
type terminal struct {
|
||||
supportsEditing bool
|
||||
fd uintptr
|
||||
origMode uint32
|
||||
}
|
||||
|
||||
// newTerminal creates a terminal and sets it to raw input mode.
|
||||
func newTerminal(in *os.File) (*terminal, error) {
|
||||
term := &terminal{fd: in.Fd()}
|
||||
|
||||
err := syscall.GetConsoleMode(syscall.Handle(term.fd), &term.origMode)
|
||||
if err != nil {
|
||||
return term, nil
|
||||
}
|
||||
mode := term.origMode
|
||||
term.supportsEditing = true
|
||||
|
||||
// Set new mode flags.
|
||||
mode &^= (echoInputFlag | insertModeFlag | lineInputFlag | mouseInputFlag |
|
||||
processedInputFlag | windowInputFlag)
|
||||
|
||||
ret, _, err := setConsoleMode.Call(term.fd, uintptr(mode))
|
||||
if ret == 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return term, nil
|
||||
}
|
||||
|
||||
// Close disables the terminals raw input.
|
||||
func (term *terminal) Close() error {
|
||||
if term.supportsEditing {
|
||||
ret, _, err := setConsoleMode.Call(term.fd, uintptr(term.origMode))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user