In the context of developing a plug-in, what is the most portable (various versions of vim, nvim, ...) and readable way to implement a "menu" similar to what :tselect gives i.e. that

  • appears in the bottom and takes as much screen as necessary
  • paginates the content if there are too many entries to fit on a single screen
  • implements the commands to navigate the list
  • enumerates and indexes the entries
  • waits for an input for the selected entry (or defaults to cancelling)

This could be hacked together using a buffer, remapping, etc. but there must be a simpler way to do such a common thing.

Ideally, I would like to pass the structured data and receive back the selected index.

1 Answer 1


Perhaps, you want inputlist(). It does not provide the item numbers, but it's quite easy to add them manually:

" MyChoice({list} [, {prompt}])
" Lets user choose an item from {list}. Returns the selected item index or -1.
" If {prompt} is omitted the default prompt is used.
function! MyChoice(list, ...)
    let l:prompt = a:0 ? a:1 : "Input number:"
    let l:idx = inputlist(insert(map(copy(a:list), '(1 + v:key) . ". " . v:val'), l:prompt))
    if l:idx >= 1 && l:idx <= len(a:list)
        return l:idx - 1
    return -1

" example usage
let choice = MyChoice(['foo', 'bar', 'baz'])
  • inputlist was indeed what I was after. Thanks
    – PiCTo
    Commented Sep 28, 2019 at 10:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.