Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REQUEST] Allow to filter :menu candidates #4396

Open
krobelus opened this issue Oct 23, 2021 · 2 comments
Open

[REQUEST] Allow to filter :menu candidates #4396

krobelus opened this issue Oct 23, 2021 · 2 comments

Comments

@krobelus
Copy link
Contributor

krobelus commented Oct 23, 2021

Feature

:menu takes a list of labeled commands and allows to select a command to
run with Tab. Almost no other keys are mapped in menu mode.

When there are many menu options, I want to filter the labels with a fuzzy
search, similar to how completions are filtered (in prompt mode).

The notable difference to prompt completions is that menu mode automatically selects
the first option (no need to press Tab).
When filtering, the menu should always select the "next" matching option
(but still allow to cycle with Tab).

Usecase

image

Some language servers (rust-analyzer) provide many code actions / assists for the cursor position.

It is possible to workaround this by replacing :menu with a command like
the one below, but that doesn't select the first matching option automatically,
making the common case (few code actions) worse.

define-command fake-menu -params 1.. %{
    # This is a really convoluted way of saying "menu %arg{@}". The difference is that by using
    # prompt instead of menu mode, this adds fuzzy search.
    evaluate-commands %sh{
        shellquote() {
                printf "'"
                printf %s "$1" | sed "s/'/'\\\\''/g; s/§/§§/g; $2"
                printf "'"
        }
        cases=
        completion=
        nl=$(printf '\n.'); nl=${nl%.}
        while [ $# -gt 0 ]; do
            title=$1; shift
            command=$1; shift
            completion="${completion}${title}${nl}"
            cases="${cases}
            $(shellquote "$title" s/¶/¶¶/g))
                printf '%s\\n' $(shellquote "$command" s/¶/¶¶/g)
                ;;"
        done
        printf "\
        define-command -override fake-menu-menu -params 1 %%§
            evaluate-commands %%sh¶
                case \"\$1\" in%s
                *) echo fail no such code action: \"\$1\" ;;
                esac

        §" "$cases" | tee /dev/stderr
        printf ' -shell-script-candidates %%§
            printf %%s %s
            §' "$(shellquote "$completion")" | tee /dev/stderr
    }
    execute-keys %{: fake-menu-menu }
}
@mawww
Copy link
Owner

mawww commented Oct 23, 2021

Not sure how well this is documented, but :menu can be filtered with the / key that then takes a regex and <c-n> / <c-p> will only cycle through entries that match it.

@Screwtapello
Copy link
Contributor

...but that doesn't select the first matching option automatically...

If you're using a scratch command to provide completion, you can use the -menu switch when defining the command so that if the user hits Enter without typing anything, they get the first option automatically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants