survey icon indicating copy to clipboard operation
survey copied to clipboard

Add option to remove filters from select-type prompts

Open zimeg opened this issue 2 years ago • 2 comments

Summary

This PR provides an option to remove the filter from the Select and MultiSelect prompts. This is given as an option to restrict selection movement to the arrow keys to prevent options from being hidden by accidental keystrokes. 👻

Preview

Select

color := ""
prompt := &survey.Select{
    Message:    "Select a color:",
    Options:    []string{"red", "blue", "green"},
    HideFilter: true,
}

survey.AskOne(prompt, &color)
The select prompt without an option to filter

MultiSelect

days := []string{}
prompt := &survey.MultiSelect{
    Message:    "What days do you prefer:",
    Options:    []string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
    HideFilter: true,
}
survey.AskOne(prompt, &days)
The multiselect prompt without an option to filter

Notes

  • A HideFilter option was not added to the global PromptConfig. This was (not) done since HideFilter: true in the PromptConfig would be overridden by the default value of HideFilter: false in prompts where this value is not defined.
  • HelpInput isn't impacted by the removal of filtering, meaning .Help text will still be shown after pressing the help key.

zimeg avatar Oct 31 '22 03:10 zimeg

Just wanted to ping this PR, as this would be really helpful in a CLI I'm developing where the list of options can be extremely long, but generally filtering is disruptive to a users workflow.

samcofer avatar Apr 05 '23 18:04 samcofer

@samcofer This same effect can be achieved with a permissive Filter and some adjustments to the selection template. The following snippet can be used to match the first preview:

package main

import (
	"github.com/AlecAivazis/survey/v2"
)

func main() {
	survey.SelectQuestionTemplate = `
{{- define "option"}}
    {{- if eq .SelectedIndex .CurrentIndex }}{{color .Config.Icons.SelectFocus.Format }}{{ .Config.Icons.SelectFocus.Text }} {{else}}{{color "default"}}  {{end}}
    {{- .CurrentOpt.Value}}{{ if ne ($.GetDescription .CurrentOpt) "" }} - {{color "cyan"}}{{ $.GetDescription .CurrentOpt }}{{end}}
    {{- color "reset"}}
{{end}}
{{- if .ShowHelp }}{{- color .Config.Icons.Help.Format }}{{ .Config.Icons.Help.Text }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}}
{{- color .Config.Icons.Question.Format }}{{ .Config.Icons.Question.Text }} {{color "reset"}}
{{- color "default+hb"}}{{ .Message }}{{color "reset"}}
{{- if .ShowAnswer}}{{color "cyan"}} {{.Answer}}{{color "reset"}}{{"\n"}}
{{- else}}
  {{- "  "}}{{- color "cyan"}}[Use arrows to move{{- if and .Help (not .ShowHelp)}}, {{ .Config.HelpInput }} for more help{{end}}]{{color "reset"}}
  {{- "\n"}}
  {{- range $ix, $option := .PageEntries}}
    {{- template "option" $.IterateOption $ix $option}}
  {{- end}}
{{- end}}`

	color := ""
	prompt := &survey.Select{
		Message: "Select a color:",
		Options: []string{"red", "blue", "green"},
		Filter: func(filterValue string, optValue string, optIndex int) bool {
			return true
		},
	}
	survey.AskOne(prompt, &color)
}

The Filter that always returns true means every option will match the filtering value, so typing won't change the results shown. The updates to the template hide any input provided to the filter. Both of these together remove filtering effects!

This dropdown shows the differences between the default template and this one.
{{- define "option"}}
    {{- if eq .SelectedIndex .CurrentIndex }}{{color .Config.Icons.SelectFocus.Format }}{{ .Config.Icons.SelectFocus.Text }} {{else}}{{color "default"}}  {{end}}
    {{- .CurrentOpt.Value}}{{ if ne ($.GetDescription .CurrentOpt) "" }} - {{color "cyan"}}{{ $.GetDescription .CurrentOpt }}{{end}}
    {{- color "reset"}}
{{end}}
{{- if .ShowHelp }}{{- color .Config.Icons.Help.Format }}{{ .Config.Icons.Help.Text }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}}
{{- color .Config.Icons.Question.Format }}{{ .Config.Icons.Question.Text }} {{color "reset"}}
-{{- color "default+hb"}}{{ .Message }}{{ .FilterMessage }}{{color "reset"}}
+{{- color "default+hb"}}{{ .Message }}{{color "reset"}}
{{- if .ShowAnswer}}{{color "cyan"}} {{.Answer}}{{color "reset"}}{{"\n"}}
{{- else}}
-  {{- "  "}}{{- color "cyan"}}[Use arrows to move, type to filter{{- if and .Help (not .ShowHelp)}}, {{ .Config.HelpInput }} for more help{{end}}]{{color "reset"}}
+  {{- "  "}}{{- color "cyan"}}[Use arrows to move{{- if and .Help (not .ShowHelp)}}, {{ .Config.HelpInput }} for more help{{end}}]{{color "reset"}}
  {{- "\n"}}
  {{- range $ix, $option := .PageEntries}}
    {{- template "option" $.IterateOption $ix $option}}
  {{- end}}
{{- end}}

zimeg avatar Sep 14 '23 22:09 zimeg