MunifTanjim / nui.nvim

UI Component Library for Neovim.
MIT License
1.63k stars 57 forks source link

Feature request: dialogs #104

Open xeluxee opened 2 years ago

xeluxee commented 2 years ago

Hi @MunifTanjim, first of all thanks for maintaining this plugin

It'd be really cool to have message box/dialogs, something like QT message box or GTK message dialog

So user needs only to specify text message to be displayed and choices. Sample choices could be "Yes/No" and "Ok/Cancel", but a user should also be able to specify custom option like "Apple/Banana/Cherry". And every option should be reachable by a keymap, for example pressing a for Apple or b for Banana or y for Yes or a custom keymap for a custom choice.

What do you think about that?

xeluxee commented 2 years ago

Off topic: I've published a new plugin made with nui.nvim, how to add it here?

MunifTanjim commented 2 years ago

Off topic: I've published a new plugin made with nui.nvim, how to add it here?

Great! Glad this library helped! You can just edit that page and add your repository link. The list is sorted by repository name (not the username).

image

It'd be really cool to have message box/dialogs, something like QT message box or GTK message dialog

So user needs only to specify text message to be displayed and choices. Sample choices could be "Yes/No" and "Ok/Cancel", but a user should also be able to specify custom option like "Apple/Banana/Cherry". And every option should be reachable by a keymap, for example pressing a for Apple or b for Banana or y for Yes or a custom keymap for a custom choice.

What do you think about that?

That is a common use-case. So we can definitely add it.

We'll just need to figure out how to give total control of how it'll be rendered to the nui.nvim user. For example, user should be able to:

You can easily create such a dialog component for a specific use-case. But doing it in a generalized way that can serve all the use-cases is a bit hard to do.

But I'll definitely look into it. If you have any ideas/suggestions, those are welcomed too! 😃

cseickel commented 2 years ago

@MunifTanjim One simplified solution would be to just allow the Input to include a message in addition to the title. I had hacked in a version of this that I didn't end up using but could satisfy the use case here. The message would be a NuiText object or objects. In that case the user would type in an answer like a TUI prompt.

Another alternative that is closer to the request is to create a generic MessageBox or Alert style popup that takes a title and message but does not have any prompt, and just let the developer add mappings to the window to represent the choices they want.

I actually created my own simple alert method here: https://github.com/nvim-neo-tree/neo-tree.nvim/blob/1020de30e09dad63fc59fbbddbe3387913ad3fa5/lua/neo-tree/ui/popups.lua#L65

It automatically sizes to content, which should probably have some restrictions but it has worked out so far in my usage.

MunifTanjim commented 2 years ago

One simplified solution would be to just allow the Input to include a message in addition to the title.

I think that wouldn't be a dialog component. We're talking about something like this:

image

Another alternative that is closer to the request is to create a generic MessageBox or Alert style popup that takes a title and message but does not have any prompt, and just let the developer add mappings to the window to represent the choices they want.

Well rendering the choices is the real challenge. We can already open a Popup, add some text to it easily.

But taking a list of choices (e.g. Don't Save, Cancel, Save buttons in the image above) and rendering those in a nice way is tricky, because those choices can have various length, so they won't always fit in the width.

Then comes the challenge of alignment - user provides 3 choices, wants 1 of them to be rendered on the left, and the other 2 on the right... or maybe wants them to rendered with equal spacing between them. (Then the first challenge again, what happens if one of those choices are too long and all of them doesn't fit in the same line).

You get the idea. 😂 Kinda hard to do.

cseickel commented 2 years ago

Oh yeah, that's super hard. I was thinking of a simpler solution where the user has to format the text they want displayed before creating the popup. Creating buttons in a tui is really going above and beyond and maybe more than anyone really needs.

xeluxee commented 2 years ago

Take the following example code, made using vim's confirm

local choice = vim.fn.confirm("What's your favourite fruit?", "&Apple\n&Banana\n&Cherry")
if choice == 1 then
  print("User chose Apple")
elseif choice == 2 then
  print("User chose Banana")
elseif choice == 3 then
  print("User chose Cherry")
end

The issue with this is that it's synchronous, so Vim is stopped until user chooses an option.

A nui dialog should be async instead, maybe opening a popup in the middle of the screen with a message to be displayed and some choices to select from. Well, I agree with you, this is a hard task, but I think in most cases we don't need rigid spacing rules. I thought to something like word wrapping in a text editor: when space isn't enough other choices goes on a new line.

Take a look at this draft (handmade ascii art, ignore indent guides) choose

Since all the choices are too wide they are split into lines. Also a keymap is associated to every choice: the keymap is shown between brackets (like in Vim's confirm), and it can be specified by user (It doesn't have to be necessarily the starting letter).

xeluxee commented 2 years ago

Then comes the challenge of alignment - user provides 3 choices, wants 1 of them to be rendered on the left, and the other 2 on the right... or maybe wants them to rendered with equal spacing between them. (Then the first challenge again, what happens if one of those choices are too long and all of them doesn't fit in the same line).

Creating buttons in a tui is really going above and beyond and maybe more than anyone really needs.

I think that we need something simplified, something that fits for a general use-case.

We're not aiming to do something like this

folke commented 1 year ago

I do something similar in Noice for confirm dialogs:

image

xeluxee commented 1 year ago

I do something similar in Noice for confirm dialogs:

image

This looks noice

danielo515 commented 1 year ago

I do something similar in Noice for confirm dialogs:

image

Is that based on nui primitives or fully custom?