AlecAivazis / survey

A golang library for building interactive and accessible prompts with full support for windows and posix terminals.
MIT License
4.07k stars 349 forks source link

Remove "select all" option from Multiselect #393

Closed ces131 closed 1 year ago

ces131 commented 2 years ago

Hi there!

For our use case, we want to prevent users from being able to select "all options" (using right right arrow) for Mulitselect. It seems like this could be easily done by adding a field to the PromptConfig struct that defaults to still give the "Select All" option, but can be toggled to turn it off (and the template can be updated accordingly as well)

I was going to patch the package but thought that this may be a valid use case for other users as well. I can put up a pull request for it, but wanted to see whether this was of interest :)

Thanks!!

mislav commented 2 years ago

I'm interested. Thank you for the feature idea! How would you envision this to be configured?

ces131 commented 2 years ago

I think it falls sort of in the same category as the KeepFilter config (I noticed it also only applies to MulitSelect also) and could be implemented in pretty much the same way - I chose RemoveSelectAll for my patch, but we could just make this SelectAll or something and set the default to true (just wouldn't follow the "configs being false by default" pattern that's there is so far):

type PromptConfig struct {
    PageSize     int
    Icons        IconSet
    HelpInput    string
    SuggestInput string
    Filter       func(filter string, option string, index int) bool
    KeepFilter   bool
    ShowCursor   bool
    RemoveSelectAll bool
}
// WithRemoveSelectAll - removes the "select all" option in Multiselect
func WithRemoveSelectAll(RemoveSelectAll bool) AskOpt {
    return func(options *AskOptions) error {
        // set the page size
        options.PromptConfig.RemoveSelectAll = RemoveSelectAll

        // nothing went wrong
        return nil
    }
}

(and set the default to false in the defaultAskOptions)

Then in multiselect, we can just skip the KeyRight binding with:

} else if !config.RemoveSelectAll && key == terminal.KeyArrowRight {
        for _, v := range options {
            m.checked[v.Index] = true
        }
        if !config.KeepFilter {
            m.filter = ""
        }

and remove it from the template with:

... space to select, {{- if not .Config.RemoveSelectAll }}<right> to all,{{end}} <left> to none, ...
mislav commented 2 years ago

That sounds like a great plan. I would encourage you to submit a PR, since you've already identified all the places that need the change 👍

AlecAivazis commented 1 year ago

Closing this since #439 has been merged