Not exactly what OP asked but... maybe someone will find this useful.
There are countless plugins (commonly referred as "pickers") that allow user to pick an item from (vertical) popup menu and to execute some arbitrary command afterwards (vim-clap, nvim-telescope, you name it). Probably many of us also tried to create "fast buffer switch" or "colorscheme chooser" that works without even entering cmdline. Now with Vim8 +popupwin
it's easy!
The main disappointment is that (callback) lambdas are really awkward to re-use: imagine we have a dozen of individual "pickers" each of which calls a generic Pick()
function which in turn calls popup_menu()
. Now every "picker" wants to have specific callback lambda but every lambda should also have access to all locals in Pick()
too! Luckily, we can work around it using good old "substitute-eval-submatch" trick.
So the code for our generic Pick()
function is
" Pick({name} [, {items} [, {cmd}]])
" pick parameter and execute {cmd}
function! Pick(...) abort
let l:name = a:1
let l:items = a:0 > 1 ? a:2 : getcompletion(l:name..' ', 'cmdline')
let l:cmd = a:0 > 2 ? a:3 : '%{name} %{items[result - 1]}'
call popup_menu(l:items, #{title: printf('[%s]', l:name), maxheight: &pumheight ?
\ &pumheight : &lines / 2, minwidth: &pumwidth, callback: {id, result ->
\ (result < 1 || result > len(items)) ? v:null :
\ execute(substitute(l:cmd, '%{\([^}]\+\)}', '\=eval(submatch(1))', 'g'), '')}})
endfunction
So the third (optional) parameter is a String to evaluate and execute in the context of Pick()
's internal lambda. And inside our "special" %{...}
expression we can actually access all those local variables! That allows for super-easy writing of menu callbacks.
" Choosing :colorscheme is trivial
nnoremap <silent><plug>colorscheme <cmd>call Pick('colorscheme')<CR>
" Choosing from :scriptnames using custom items and cmd
nnoremap <silent><plug>scriptnames <cmd>call Pick('scriptnames',
\ map(split(execute('scriptnames'), "\n"), 'v:val[1:]'), '%{result}%{name}')<CR>
" Choosing buffer is a bit verbose as we have to prepare buffers list
nnoremap <silent><plug>buffers <cmd>call Pick('buffer', map(getbufinfo({'buflisted': 1}),
\ {_, v -> printf('%2d %s', v.bufnr, empty(v.name) ? gettext('[No Name]') :
\ fnamemodify(v.name, ':t'))}), '%{name} %{split(items[result - 1])[0]}')<CR>
And all others like "args", "find", "history", "marks", "oldfiles", "registers", "windows" and even "picker of pickers". The code is in my vimfiles repo. This gives us roughly a half of functionality of those plugin monsters such as nvim-telescope with only a few lines of "poor old" VimScript.
:tag
and you press Ctrl-D but only if you've done:set wop=tagfile
. Yeah, extremely limited.set wildoptions="pum,tagfile"
enabled, but i still get the horizontal menuset wildoptions="pum"
this is a neovim only addition. I don't think vim currently allows to use a vertical popup menu for the wildmenu.:set
that you ran should emit an error message because it is rejecting the value...:set wop?
shows no right-hand-side value. Now try it without the double quotes,:set wop=pum,tagfile
and you'll get an error. But anyways...if you want to see the completion format I mentioned in my first comment you'll have to type it just like I show.