Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

Commit

Permalink
(fix): fallback to ReadLine when not using "auto complete"
Browse files Browse the repository at this point in the history
  • Loading branch information
lucassabreu committed Jun 29, 2021
1 parent 42156f1 commit fa313ed
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 45 deletions.
105 changes: 69 additions & 36 deletions input.go
@@ -1,6 +1,8 @@
package survey

import (
"errors"

"github.com/AlecAivazis/survey/v2/core"
"github.com/AlecAivazis/survey/v2/terminal"
)
Expand Down Expand Up @@ -58,46 +60,79 @@ var InputQuestionTemplate = `
{{- if and .Suggest }}{{color "cyan"}}{{ print .Config.SuggestInput }} for suggestions{{end -}}
]{{color "reset"}} {{end}}
{{- if .Default}}{{color "white"}}({{.Default}}) {{color "reset"}}{{end}}
{{- .Answer -}}
{{- end}}`

func (i *Input) OnSpecialKey(config *PromptConfig) func(rune) bool {
return func(key rune) bool {
if key == terminal.KeyArrowUp && len(i.options) > 0 {
func (i *Input) onRune(config *PromptConfig) terminal.OnRuneFn {
return terminal.OnRuneFn(func(key rune, line []rune) ([]rune, bool, error) {
if i.options != nil && (key == terminal.KeyEnter || key == '\n') {
return []rune(i.answer), true, nil
} else if key == terminal.KeyArrowUp && len(i.options) > 0 {
if i.selectedIndex == 0 {
i.selectedIndex = len(i.options) - 1
} else {
i.selectedIndex--
}
i.answer = i.options[i.selectedIndex].Value
return true
} else if (key == terminal.KeyArrowDown || key == terminal.KeyTab) && len(i.options) > 0 {
if i.selectedIndex == len(i.options)-1 {
i.selectedIndex = 0
} else {
i.selectedIndex++
}
i.answer = i.options[i.selectedIndex].Value
return true
} else if key == terminal.KeyTab && i.Suggest != nil {
i.answer = string(line)
options := i.Suggest(i.answer)
i.selectedIndex = 0
i.typedAnswer = i.answer
if len(options) > 0 {
i.answer = options[0]
if len(options) == 1 {
i.options = nil
} else {
i.options = core.OptionAnswerList(options)
}
if len(options) == 0 {
return line, false, nil
}

i.answer = options[0]
if len(options) == 1 {
i.typedAnswer = i.answer
i.options = nil
} else {
i.options = core.OptionAnswerList(options)
}
return true
} else {
if i.options == nil {
return line, false, nil
}

if key >= terminal.KeySpace {
i.answer += string(key)
i.typedAnswer = i.answer
}

i.options = nil
}

return false
}
pageSize := config.PageSize
opts, idx := paginate(pageSize, i.options, i.selectedIndex)
err := i.Render(
InputQuestionTemplate,
InputTemplateData{
Input: *i,
Answer: i.answer,
ShowHelp: i.showingHelp,
SelectedIndex: idx,
PageEntries: opts,
Config: config,
},
)

if err == nil {
err = readLineAgain
}

return []rune(i.typedAnswer), true, err
})
}

var readLineAgain = errors.New("read line again")

func (i *Input) Prompt(config *PromptConfig) (interface{}, error) {
// render the template
err := i.Render(
Expand All @@ -123,10 +158,25 @@ func (i *Input) Prompt(config *PromptConfig) (interface{}, error) {
defer cursor.Show() // show the cursor when we're done
}

line, err := rr.ReadLine(0, i.OnSpecialKey(config))
if err != nil {
return "", err
var line []rune

for {
if i.options != nil {
line = []rune{}
}

line, err = rr.ReadLineWithDefault(0, line, i.onRune(config))
if err == readLineAgain {
continue
}

if err != nil {
return "", err
}

break
}

i.answer = string(line)
// readline print an empty line, go up before we render the follow up
cursor.Up(1)
Expand All @@ -138,23 +188,6 @@ func (i *Input) Prompt(config *PromptConfig) (interface{}, error) {
return i.Prompt(config)
}

pageSize := config.PageSize
opts, idx := paginate(pageSize, i.options, i.selectedIndex)
err = i.Render(
InputQuestionTemplate,
InputTemplateData{
Input: *i,
Answer: i.answer,
ShowHelp: i.showingHelp,
SelectedIndex: idx,
PageEntries: opts,
Config: config,
},
)
if err != nil {
return "", err
}

// if the line is empty
if len(i.answer) == 0 {
// use the default value
Expand Down
9 changes: 0 additions & 9 deletions input_test.go
Expand Up @@ -102,15 +102,6 @@ func TestInputRender(t *testing.T) {
defaultIcons().Question.Text, defaultPromptConfig().Icons.SelectFocus.Text,
),
},
{
"Test Input question output with suggestion complemented",
Input{Message: "What is your favorite month:", Suggest: suggestFn},
InputTemplateData{Answer: "February and"},
fmt.Sprintf(
"%s What is your favorite month: [%s for suggestions] February and",
defaultIcons().Question.Text, defaultPromptConfig().SuggestInput,
),
},
}

for _, test := range tests {
Expand Down

0 comments on commit fa313ed

Please sign in to comment.