Skip to content

feat: modern menu #549

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

Merged
merged 18 commits into from
May 11, 2023
Merged

Conversation

danilshvalov
Copy link
Contributor

Hello everyone I don't really like the way the selection menu is made now. Therefore, I suggest updating it.

Now I have the following developments:

Screenshot 2023-04-29 at 13 47 55

@kristijanhusak
Copy link
Member

Hey, I don't plan to change the current built in view because it looks similar to Emacs prompt. There are 2 options this can be tackled:

  • Add a config option to define your own menu, and default it to current utils.menu. That way you can override the functionality in your config
  • Monkey patch orgmode.utils.menu with your implementation. This is more hacky way, but I think it could work.

@danilshvalov
Copy link
Contributor Author

danilshvalov commented May 1, 2023

I've redone the menu. Now the user can customize the menu himself. emacs and modern presets are also available. Examples:

Emacs style
require("orgmode").setup({
  ui = {
    menu = {
      preset = "emacs",
    },
  },
})
Screenshot 2023-05-01 at 18 45 28
Modern style
require("orgmode").setup({
  ui = {
    menu = {
      preset = "modern",
    },
  },
})
Screenshot 2023-05-01 at 18 45 15
Custom style
require("orgmode").setup({
  ui = {
    menu = {
      custom = function(title)
        vim.print("Just print title...")
        vim.print("Title is '" .. title .. "'")
      end,
    },
  },
})
Screenshot 2023-05-01 at 18 46 54

@danilshvalov danilshvalov marked this pull request as ready for review May 1, 2023 15:51
@jgollenz
Copy link
Contributor

jgollenz commented May 1, 2023

Hm, I think this opens up a larger question of UI changes and where they belong. Could this (and any UI specifics) be made accessible via the API and enable @danilshvalov and everybody else to write their own UI overhaul of the whole plugin?

edit: @danilshvalov don't get me wrong, I really like your take on it :) but I think it might be worthwhile to discuss thinking big here, before we start doing UI customization in the core plugin

@danilshvalov
Copy link
Contributor Author

@jgollenz If I understood what was written correctly, right now it is impossible to customize the UI through the API. This PR provides one of the ways of such customization (the custom option).

Copy link
Member

@kristijanhusak kristijanhusak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

The general idea is fine, but I don't think there's a need to have presets part of the plugin.
We can either have the default one, or a custom one that the user provides.
Comments on code will explain what's missing.
If you want to expose the modern menu to more people, I would suggest creating a small plugin and just attach it through the config.

Edit: It would also be great to update the documentation with this new option so other users know how to set up a custom menu.

@danilshvalov
Copy link
Contributor Author

I have redone the code, created some classes that internally check the correctness of the entered data. So now there are two types that can be used in the menu: MenuItem and MenuSeparator.

If everything is fine in the code, I am ready to add documentation.

Copy link
Member

@kristijanhusak kristijanhusak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, you can proceed with docs.

@danilshvalov
Copy link
Contributor Author

I now thought a little and decided that it would be nice to pass data to the menu not through function arguments, but through a table. For example:

Menu.open({
  title = 'Some title',
  items = { ... },
  prompt = 'Prompt',
})

What do you think about it? In the future, with possible expansion, this will make refactoring easier.

@jgollenz
Copy link
Contributor

jgollenz commented May 2, 2023

pass data to the menu not through function arguments, but through a table

I second this, but please let's document that table somewhere 👍

@kristijanhusak
Copy link
Member

I now thought a little and decided that it would be nice to pass data to the menu not through function arguments, but through a table. For example:

Menu.open({
  title = 'Some title',
  items = { ... },
  prompt = 'Prompt',
})

What do you think about it? In the future, with possible expansion, this will make refactoring easier.

I agree with this. Additionally, I would also expose option and separator methods on the menu so the menu can be built. Something like this:

local menu = Menu:new({ 
  title = 'Some title',
  items = { ... }, -- optional
  prompt = 'Prompt',
  separator = '-',
})

menu:option(label, key, action)
menu:separator(length, char_override)
menu:option(label, key, action)

return menu:open()

@danilshvalov
Copy link
Contributor Author

@kristijanhusak This is a great idea! But maybe it would be better to name the methods add_option and add_separator instead of option and separator for more clarity? For example, separator might appear to change the value of the separator itself rather than adding it to the menu.

@danilshvalov
Copy link
Contributor Author

And it's probably better to pass a delimiter to the Menu constructor like this:

local menu = Menu:new({
  -- ...
  separator = {
    icon = '~', -- optional, default is `-`
    length = 1, -- optional, default is 80
  },
})

@kristijanhusak
Copy link
Member

kristijanhusak commented May 2, 2023

@kristijanhusak This is a great idea! But maybe it would be better to name the methods add_option and add_separator instead of option and separator for more clarity? For example, separator might appear to change the value of the separator itself rather than adding it to the menu.

Sure, that also works.

And it's probably better to pass a delimiter to the Menu constructor like this:

local menu = Menu:new({
  -- ...
  separator = {
    icon = '~', -- optional, default is `-`
    length = 1, -- optional, default is 80
  },
})

This is also ok. add_separator method should accept both of these options as an override, length and then icon because we have situations where we have different length separators in the menu.

@danilshvalov
Copy link
Contributor Author

I did what we discussed. Review please.

Copy link
Member

@kristijanhusak kristijanhusak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just few small changes regarding the arguments.

@danilshvalov
Copy link
Contributor Author

Ready for review

@danilshvalov
Copy link
Contributor Author

I also did a minor refactoring in the default menu.

Copy link
Member

@kristijanhusak kristijanhusak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks!

@kristijanhusak kristijanhusak merged commit 1c46d8e into nvim-orgmode:master May 11, 2023
SlayerOfTheBad pushed a commit to SlayerOfTheBad/orgmode that referenced this pull request Aug 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants