[vim/vim] [Feature Request] Synchronous version of popup_menu() as alternative to inputlist() (#6534)

25 views
Skip to first unread message

Ben Jackson

unread,
Jul 25, 2020, 11:21:56 AM7/25/20
to vim/vim, Subscribed

Is your feature request about something that is currently impossible or hard to do? Please describe the problem.

popup_menu is a nice UI for selecting from a list of things, but it's tricky to use due to the response only being delivered asynchronously via a callback. I'd like to be able to interchange inputlist with a popup menu version of that without significant code restructuring.

The precise use case is as follows:

currently in vimspector, when you start debugging, you get asked which debug configuration you wish to use. This uses inputlist():

Screenshot 2020-07-25 at 16 19 31

But from a UI perspective, it's attractive to look into something like this:

Screenshot 2020-07-25 at 16 19 01

The challenge being that Vimspector needs to ask for input and get the result synchronously (as you get with inputlist). The async callback progrming model for the menu requires quite significant restructuring of the code flows.

Describe the solution you'd like

I'd like to be able to do something like this:

if exists( '*popup_menu' )
  let selection = popup_inputlist( ... )
else
  let selection = inputlist( ... )
endif
let item_selected = list_of_options[ selection - 1 ] " or whatever
" etc.

On the face of it, this would seem plausible in the sense that the input is already being filtered by the filter function and so execution is logically synchronous, and that popup_menu and inputlist seem to share similar properties in terms of use case.

Describe alternatives you've considered*

I could restructure the vimspector code to always work as if asking for user input is async, rather than the way it is today expecting to get synchronous response.

Additional context

It looks like there is a precedent in some code for synchronously waiting for a menu result when mousemodel is popup and we get a right-click, or :popup... pum_show_popupmenu and friends.

If it is very hard to do, or very bad for other reasons, then i'm sure i can manage the flow in vimspector with some refactoring (or just stick to inputlist), but wonder if this is possible.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

Marco Trosi

unread,
Jul 14, 2022, 2:25:54 PM7/14/22
to vim/vim, Subscribed

I also need a "wait" option for the popup_menu() & Co. functions, to make them "synchronous".


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/6534/1184764889@github.com>

Maxim Kim

unread,
Jul 20, 2022, 9:21:15 AM7/20/22
to vim/vim, Subscribed

@puremourning a workaround, somewhat ugly, but should work:

vim9script

var winid = popup_create(['red', 'green', 'blue'], {})
while 1
    redraw
    var ch = nr2char(getchar(0))
    if ch == 'q' || ch == "\<ESC>"
        popup_close(winid)
        break
    endif
    sleep 15m
endwhile
echo "I should be visible after popup is closed!"


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/6534/1190279383@github.com>

Bram Moolenaar

unread,
Jul 26, 2022, 10:35:26 AM7/26/22
to vim/vim, Subscribed

Instead of using getchar(), it's better to have the callback store the result in a variable, and check that variable in the wait loop.
Then using the cursor to select an entry will work.


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/6534/1195565959@github.com>

Ben Jackson

unread,
Jul 26, 2022, 3:05:31 PM7/26/22
to vim/vim, Subscribed

both solutions use busy-waiting. wouldn't sleeping in select()/poll()/etc. waiting for input be better?


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/6534/1195871531@github.com>

Marco Trosi

unread,
Feb 22, 2023, 4:27:34 PM2/22/23
to vim/vim, Subscribed

Just stumbled upon my function that I wrote last year that I can't finish in a nice way because Vim doesn't have a synchronous popup_menu() or "wait" option for it. I'm just commenting again, hoping that it will be implemented.


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/6534/1440822090@github.com>

Bram Moolenaar

unread,
Feb 23, 2023, 9:32:32 AM2/23/23
to vim/vim, Subscribed

This can be useful. I wonder what implementation would work best. Simplest is to only do this for popup_menu(). But what if someone implements this in another way? We could add a "wait for any popup to be closed" function. That avoids the busy-waiting. It does require checking that the right popup was closed and it's callback was invoked. An even more generic way would be to wait for any callback to be invoked. Then you can also break out when a timer expires, for example.


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/6534/1441895758@github.com>

Ben Jackson

unread,
Feb 23, 2023, 4:02:36 PM2/23/23
to vim/vim, Subscribed

For me, as I put in the original I actually don't want a callback, just an API similar to inputlist(). The awkwardness with a callback in this case comes from managing global state to get the result.

Alternatively, we could take your second idea (eg a popup_wait(winid) that waits for that popup to close and returns the result of the close callback for winid. That would also work easily and obviously.


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/6534/1442426672@github.com>

Bram Moolenaar

unread,
Feb 23, 2023, 5:24:19 PM2/23/23
to vim/vim, Subscribed


> For me, as I put in the original I actually don't want a callback,
> just an API similar to inputlist(). The awkwardness with a callback in
> this case comes from managing global state to get the result.
>
> Alternatively, we could take your second idea (eg a
> `popup_wait(winid)` that waits for that popup to close and _returns
> the result of the close callback_ for winid. That would also work
> easily and obviously.

It still requires a close callback to handle the result.

If we only want to do this for popup_menu() it might be possible, but
that is a very specific solution. I am sure plugin writers will son
come up with reasons for a more generic solution.

Since Vim will be doing a blocking wait, using a global variable should
not be much of a problem. It should be possible to use a script-local
variable in most cases.

--
hundred-and-one symptoms of being an internet addict:
174. You know what a listserv is.

/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/6534/1442509545@github.com>

Marco Trosi

unread,
Feb 23, 2023, 11:38:19 PM2/23/23
to vim/vim, Subscribed

is a "wait" flag/parameter possible for popup_menu() and Co?


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/6534/1442799231@github.com>

Ben Jackson

unread,
Feb 24, 2023, 2:52:25 AM2/24/23
to vim/vim, Subscribed

It may be asking too much, or going too far. But this has the hallmarks of something that promises/futures were trying to solve. My proposed 'popup_wait(winid)' is not much different from a future_get(). And returning from the callback a value could be achieved with a 'promise_put()'.

Just a thought.


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/6534/1443005627@github.com>

Reply all
Reply to author
Forward
0 new messages