update dependencies

This commit is contained in:
Cory Bennett
2017-09-06 11:35:00 -07:00
parent 9453179251
commit aa876cd588
308 changed files with 46154 additions and 33733 deletions
+1 -1
View File
@@ -20,4 +20,4 @@ tests:
command: go test {{.files}}
variables:
files: '$(go list -v ./... | grep -iEv "github.com/AlecAivazis/survey/(tests|examples)")'
files: '$(go list -v ./... | grep -iEv "tests|examples")'
+2
View File
@@ -1,5 +1,7 @@
language: go
go_import_path: gopkg.in/AlecAivazis/survey.v1
before_install:
- go get github.com/AlecAivazis/run
+4 -5
View File
@@ -1,6 +1,6 @@
# Survey
[![Build Status](https://travis-ci.org/AlecAivazis/survey.svg?branch=feature%2Fpretty)](https://travis-ci.org/AlecAivazis/survey)
[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg)](https://godoc.org/github.com/AlecAivazis/survey)
[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg)](https://github.com/AlecAivazis/survey)
A library for building interactive prompts. Heavily inspired by the great [inquirer.js](https://github.com/SBoudrias/Inquirer.js/).
@@ -77,7 +77,7 @@ Examples can be found in the `examples/` directory. Run them
to see basic behavior:
```bash
go get github.com/AlecAivazis/survey
go get gopkg.in/AlecAivazis/survey.v1
# ... navigate to the repo in your GOPATH
@@ -280,9 +280,8 @@ in `survey/core`:
## Versioning
This project tries to maintain semantic GitHub releases as closely as possible. As such, services
like [gopkg.in](http://labix.org/gopkg.in) work very well to ensure non-breaking changes whenever
you build your application. For example, importing v1 of survey could look something like
This project tries to maintain semantic GitHub releases as closely as possible. And relies on [gopkg.in](http://labix.org/gopkg.in)
to maintain those releasees. Importing v1 of survey could look something like
```golang
package main
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"os"
"regexp"
"github.com/AlecAivazis/survey/core"
"github.com/AlecAivazis/survey/terminal"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
// Confirm is a regular text input that accept yes/no answers. Response type is a bool.
+2 -2
View File
@@ -4,9 +4,9 @@ import (
"bytes"
"testing"
"github.com/AlecAivazis/survey/core"
"github.com/AlecAivazis/survey/terminal"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
func init() {
+1 -1
View File
@@ -3,7 +3,7 @@ package core
import (
"strings"
"github.com/AlecAivazis/survey/terminal"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
type Renderer struct {
+39 -2
View File
@@ -109,6 +109,16 @@ func findFieldIndex(s reflect.Value, name string) (int, error) {
return -1, fmt.Errorf("could not find field matching %v", name)
}
// isList returns true if the element is something we can Len()
func isList(v reflect.Value) bool {
switch v.Type().Kind() {
case reflect.Array, reflect.Slice:
return true
default:
return false
}
}
// Write takes a value and copies it to the target
func copy(t reflect.Value, v reflect.Value) (err error) {
// if something ends up panicing we need to catch it in a deferred func
@@ -125,7 +135,7 @@ func copy(t reflect.Value, v reflect.Value) (err error) {
}
}()
// attempt to copy the underlying value to the target
// if we are copying from a string result to something else
if v.Kind() == reflect.String && v.Type() != t.Type() {
var castVal interface{}
var casterr error
@@ -202,7 +212,34 @@ func copy(t reflect.Value, v reflect.Value) (err error) {
return
}
t.Set(v)
// if we are copying from one slice or array to another
if isList(v) && isList(t) {
// loop over every item in the desired value
for i := 0; i < v.Len(); i++ {
// write to the target given its kind
switch t.Kind() {
// if its a slice
case reflect.Slice:
// an object of the correct type
obj := reflect.Indirect(reflect.New(t.Type().Elem()))
// write the appropriate value to the obj and catch any errors
if err := copy(obj, v.Index(i)); err != nil {
return err
}
// just append the value to the end
t.Set(reflect.Append(t, obj))
// otherwise it could be an array
case reflect.Array:
// set the index to the appropriate value
copy(t.Slice(i, i+1).Index(0), v.Index(i))
}
}
} else {
// set the value to the target
t.Set(v)
}
// we're done
return
+27 -18
View File
@@ -55,24 +55,7 @@ func TestWrite_canWriteSlice(t *testing.T) {
WriteAnswer(&ptr, "", []string{"hello", "world"})
// make sure there are two entries
if len(ptr) != 2 {
// the test failed
t.Errorf("Incorrect number of entries in written list. Expected 2, found %v.", len(ptr))
// dont move on
return
}
// make sure the first entry is hello
if ptr[0] != "hello" {
// the test failed
t.Errorf("incorrect first value in written pointer. expected hello found %v.", ptr[0])
}
// make sure the second entry is world
if ptr[1] != "world" {
// the test failed
t.Errorf("incorrect second value in written pointer. expected world found %v.", ptr[0])
}
assert.Equal(t, []string{"hello", "world"}, ptr)
}
func TestWrite_recoversInvalidReflection(t *testing.T) {
@@ -154,6 +137,32 @@ func TestWrite_returnsErrorIfInvalidMapType(t *testing.T) {
}
}
func TestWrite_writesStringSliceToIntSlice(t *testing.T) {
// make a slice of int to write to
target := []int{}
// write the answer
err := WriteAnswer(&target, "name", []string{"1", "2", "3"})
// make sure there was no error
assert.Nil(t, err, "WriteSlice to Int Slice")
// and we got what we wanted
assert.Equal(t, []int{1, 2, 3}, target)
}
func TestWrite_writesStringArrayToIntArray(t *testing.T) {
// make an array of int to write to
target := [3]int{}
// write the answer
err := WriteAnswer(&target, "name", [3]string{"1", "2", "3"})
// make sure there was no error
assert.Nil(t, err, "WriteArray to Int Array")
// and we got what we wanted
assert.Equal(t, [3]int{1, 2, 3}, target)
}
func TestWriteAnswer_returnsErrWhenFieldNotFound(t *testing.T) {
// the struct to hold the answer
ptr := struct{ Name string }{}
+168
View File
@@ -0,0 +1,168 @@
package survey
import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"runtime"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
/*
Editor launches an instance of the users preferred editor on a temporary file.
The editor to use is determined by reading the $VISUAL or $EDITOR environment
variables. If neither of those are present, notepad (on Windows) or vim
(others) is used.
The launch of the editor is triggered by the enter key. Since the response may
be long, it will not be echoed as Input does, instead, it print <Received>.
Response type is a string.
message := ""
prompt := &survey.Editor{ Message: "What is your commit message?" }
survey.AskOne(prompt, &message, nil)
*/
type Editor struct {
core.Renderer
Message string
Default string
Help string
}
// data available to the templates when processing
type EditorTemplateData struct {
Editor
Answer string
ShowAnswer bool
ShowHelp bool
}
// Templates with Color formatting. See Documentation: https://github.com/mgutz/ansi#style-format
var EditorQuestionTemplate = `
{{- if .ShowHelp }}{{- color "cyan"}}{{ HelpIcon }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}}
{{- color "green+hb"}}{{ QuestionIcon }} {{color "reset"}}
{{- color "default+hb"}}{{ .Message }} {{color "reset"}}
{{- if .ShowAnswer}}
{{- color "cyan"}}{{.Answer}}{{color "reset"}}{{"\n"}}
{{- else }}
{{- if and .Help (not .ShowHelp)}}{{color "cyan"}}[{{ HelpInputRune }} for help]{{color "reset"}} {{end}}
{{- if .Default}}{{color "white"}}({{.Default}}) {{color "reset"}}{{end}}
{{- color "cyan"}}[Enter to launch editor] {{color "reset"}}
{{- end}}`
var (
bom = []byte{0xef, 0xbb, 0xbf}
editor = "vim"
)
func init() {
if runtime.GOOS == "windows" {
editor = "notepad"
}
if v := os.Getenv("VISUAL"); v != "" {
editor = v
} else if e := os.Getenv("EDITOR"); e != "" {
editor = e
}
}
func (e *Editor) Prompt() (interface{}, error) {
// render the template
err := e.Render(
EditorQuestionTemplate,
EditorTemplateData{Editor: *e},
)
if err != nil {
return "", err
}
// start reading runes from the standard in
rr := terminal.NewRuneReader(os.Stdin)
rr.SetTermMode()
defer rr.RestoreTermMode()
terminal.CursorHide()
defer terminal.CursorShow()
for {
r, _, err := rr.ReadRune()
if err != nil {
return "", err
}
if r == '\r' || r == '\n' {
break
}
if r == terminal.KeyInterrupt {
return "", terminal.InterruptErr
}
if r == terminal.KeyEndTransmission {
break
}
if r == core.HelpInputRune && e.Help != "" {
err = e.Render(
EditorQuestionTemplate,
EditorTemplateData{Editor: *e, ShowHelp: true},
)
if err != nil {
return "", err
}
}
continue
}
// prepare the temp file
f, err := ioutil.TempFile("", "survey")
if err != nil {
return "", err
}
defer os.Remove(f.Name())
// write utf8 BOM header
// The reason why we do this is because notepad.exe on Windows determines the
// encoding of an "empty" text file by the locale, for example, GBK in China,
// while golang string only handles utf8 well. However, a text file with utf8
// BOM header is not considered "empty" on Windows, and the encoding will then
// be determined utf8 by notepad.exe, instead of GBK or other encodings.
if _, err := f.Write(bom); err != nil {
return "", err
}
// close the fd to prevent the editor unable to save file
if err := f.Close(); err != nil {
return "", err
}
// open the editor
cmd := exec.Command(editor, f.Name())
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
terminal.CursorShow()
if err := cmd.Run(); err != nil {
return "", err
}
// raw is a BOM-unstripped UTF8 byte slice
raw, err := ioutil.ReadFile(f.Name())
if err != nil {
return "", err
}
// strip BOM header
text := string(bytes.TrimPrefix(raw, bom))
// check length, return default value on empty
if len(text) == 0 {
return e.Default, nil
}
return text, nil
}
func (e *Editor) Cleanup(val interface{}) error {
return e.Render(
EditorQuestionTemplate,
EditorTemplateData{Editor: *e, Answer: "<Recieved>", ShowAnswer: true},
)
}
+83
View File
@@ -0,0 +1,83 @@
package survey
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
func init() {
// disable color output for all prompts to simplify testing
core.DisableColor = true
}
func TestEditorRender(t *testing.T) {
tests := []struct {
title string
prompt Editor
data EditorTemplateData
expected string
}{
{
"Test Editor question output without default",
Editor{Message: "What is your favorite month:"},
EditorTemplateData{},
"? What is your favorite month: [Enter to launch editor] ",
},
{
"Test Editor question output with default",
Editor{Message: "What is your favorite month:", Default: "April"},
EditorTemplateData{},
"? What is your favorite month: (April) [Enter to launch editor] ",
},
{
"Test Editor answer output",
Editor{Message: "What is your favorite month:"},
EditorTemplateData{Answer: "October", ShowAnswer: true},
"? What is your favorite month: October\n",
},
{
"Test Editor question output without default but with help hidden",
Editor{Message: "What is your favorite month:", Help: "This is helpful"},
EditorTemplateData{},
"? What is your favorite month: [? for help] [Enter to launch editor] ",
},
{
"Test Editor question output with default and with help hidden",
Editor{Message: "What is your favorite month:", Default: "April", Help: "This is helpful"},
EditorTemplateData{},
"? What is your favorite month: [? for help] (April) [Enter to launch editor] ",
},
{
"Test Editor question output without default but with help shown",
Editor{Message: "What is your favorite month:", Help: "This is helpful"},
EditorTemplateData{ShowHelp: true},
`ⓘ This is helpful
? What is your favorite month: [Enter to launch editor] `,
},
{
"Test Editor question output with default and with help shown",
Editor{Message: "What is your favorite month:", Default: "April", Help: "This is helpful"},
EditorTemplateData{ShowHelp: true},
`ⓘ This is helpful
? What is your favorite month: (April) [Enter to launch editor] `,
},
}
outputBuffer := bytes.NewBufferString("")
terminal.Stdout = outputBuffer
for _, test := range tests {
outputBuffer.Reset()
test.data.Editor = test.prompt
err := test.prompt.Render(
EditorQuestionTemplate,
test.data,
)
assert.Nil(t, err, test.title)
assert.Equal(t, test.expected, outputBuffer.String(), test.title)
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/AlecAivazis/survey"
"gopkg.in/AlecAivazis/survey.v1"
)
// the questions to ask
+1 -1
View File
@@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/AlecAivazis/survey"
"gopkg.in/AlecAivazis/survey.v1"
)
// the questions to ask
+1 -1
View File
@@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/AlecAivazis/survey"
"gopkg.in/AlecAivazis/survey.v1"
)
// the questions to ask
+1 -1
View File
@@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/AlecAivazis/survey"
"gopkg.in/AlecAivazis/survey.v1"
)
// the questions to ask
+2 -2
View File
@@ -3,8 +3,8 @@ package survey
import (
"os"
"github.com/AlecAivazis/survey/core"
"github.com/AlecAivazis/survey/terminal"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
/*
+2 -2
View File
@@ -4,9 +4,9 @@ import (
"bytes"
"testing"
"github.com/AlecAivazis/survey/core"
"github.com/AlecAivazis/survey/terminal"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
func init() {
+3 -4
View File
@@ -2,12 +2,11 @@ package survey
import (
"errors"
"fmt"
"os"
"strings"
"github.com/AlecAivazis/survey/core"
"github.com/AlecAivazis/survey/terminal"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
/*
@@ -170,7 +169,7 @@ func (m *MultiSelect) Prompt() (interface{}, error) {
break
}
if r == terminal.KeyInterrupt {
return "", fmt.Errorf("interrupt")
return "", terminal.InterruptErr
}
if r == terminal.KeyEndTransmission {
break
+2 -2
View File
@@ -4,9 +4,9 @@ import (
"bytes"
"testing"
"github.com/AlecAivazis/survey/core"
"github.com/AlecAivazis/survey/terminal"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
func init() {
+2 -2
View File
@@ -3,8 +3,8 @@ package survey
import (
"os"
"github.com/AlecAivazis/survey/core"
"github.com/AlecAivazis/survey/terminal"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
/*
+1 -1
View File
@@ -3,8 +3,8 @@ package survey
import (
"testing"
"github.com/AlecAivazis/survey/core"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
)
func init() {
+3 -4
View File
@@ -2,11 +2,10 @@ package survey
import (
"errors"
"fmt"
"os"
"github.com/AlecAivazis/survey/core"
"github.com/AlecAivazis/survey/terminal"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
/*
@@ -170,7 +169,7 @@ func (s *Select) Prompt() (interface{}, error) {
break
}
if r == terminal.KeyInterrupt {
return "", fmt.Errorf("interrupt")
return "", terminal.InterruptErr
}
if r == terminal.KeyEndTransmission {
break
+2 -2
View File
@@ -4,9 +4,9 @@ import (
"bytes"
"testing"
"github.com/AlecAivazis/survey/core"
"github.com/AlecAivazis/survey/terminal"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
func init() {
+1 -1
View File
@@ -3,7 +3,7 @@ package survey
import (
"errors"
"github.com/AlecAivazis/survey/core"
"gopkg.in/AlecAivazis/survey.v1/core"
)
// PageSize is the default maximum number of items to show in select/multiselect prompts
+1 -1
View File
@@ -4,8 +4,8 @@ import (
"fmt"
"testing"
"github.com/AlecAivazis/survey/core"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
)
func init() {
+9
View File
@@ -0,0 +1,9 @@
package terminal
import (
"errors"
)
var (
InterruptErr = errors.New("interrupt")
)
+1 -2
View File
@@ -1,7 +1,6 @@
package terminal
import (
"fmt"
"os"
"unicode"
)
@@ -47,7 +46,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
Print("\r\n")
// we're done processing the input, and treat interrupt like an error
return line, fmt.Errorf("interrupt")
return line, InterruptErr
}
// allow for backspace/delete editing of inputs
+1 -1
View File
@@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/AlecAivazis/survey"
"gopkg.in/AlecAivazis/survey.v1"
)
// the questions to ask
+2 -2
View File
@@ -1,8 +1,8 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
"gopkg.in/AlecAivazis/survey.v1"
"gopkg.in/AlecAivazis/survey.v1/tests/util"
)
var answer = false
+1 -1
View File
@@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/AlecAivazis/survey"
"gopkg.in/AlecAivazis/survey.v1"
)
var simpleQs = []*survey.Question{
+26
View File
@@ -0,0 +1,26 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
)
var answer = ""
var goodTable = []TestUtil.TestTableEntry{
{
"should open in editor", &survey.Editor{
Message: "should open",
}, &answer,
},
{
"has help", &survey.Editor{
Message: "press ? to see message",
Help: "Does this work?",
}, &answer,
},
}
func main() {
TestUtil.RunTable(goodTable)
}
+2 -2
View File
@@ -1,8 +1,8 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
"gopkg.in/AlecAivazis/survey.v1"
"gopkg.in/AlecAivazis/survey.v1/tests/util"
)
var (
+2 -2
View File
@@ -1,8 +1,8 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
"gopkg.in/AlecAivazis/survey.v1"
"gopkg.in/AlecAivazis/survey.v1/tests/util"
)
var val = ""
+1 -1
View File
@@ -1,6 +1,6 @@
package main
import "github.com/AlecAivazis/survey"
import "gopkg.in/AlecAivazis/survey.v1"
func main() {
color := ""
+2 -2
View File
@@ -1,8 +1,8 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
"gopkg.in/AlecAivazis/survey.v1"
"gopkg.in/AlecAivazis/survey.v1/tests/util"
)
var answer = []string{}
+2 -2
View File
@@ -1,8 +1,8 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
"gopkg.in/AlecAivazis/survey.v1"
"gopkg.in/AlecAivazis/survey.v1/tests/util"
)
var value = ""
+2 -2
View File
@@ -1,8 +1,8 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
"gopkg.in/AlecAivazis/survey.v1"
"gopkg.in/AlecAivazis/survey.v1/tests/util"
)
var answer = ""
+1 -1
View File
@@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/AlecAivazis/survey"
"gopkg.in/AlecAivazis/survey.v1"
)
// the questions to ask
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"reflect"
"github.com/AlecAivazis/survey"
"gopkg.in/AlecAivazis/survey.v1"
)
type TestTableEntry struct {