This is an automated archive made by the Lemmit Bot.

The original was posted on /r/neovim by /u/neoneo451 on 2024-11-07 09:55:21+00:00.


I have been working on feed.nvim for the past 2 months, and It is getting more and more stable and mature. Writing its commands api made me reflect on the current state of the plugin systems, especially on the fact that users do not have a clear expectation of what a plugin’s command will do.

For example in Neorg, there is a very nice pattern that I am following in feed.nvim. If you only type Neorg, it will use the builtin vim.ui.select to prompt user for what subcommand they what to invoke, and the items to select is based on the current context, like if you are not in a .norg file, it will not have options like export to markdown.

But for commands like Neorg workspace, this command alone echos the current workspace, but you also get completions if you are in command line, add these args will switch the workspace:

but if you just use the ui.select way of invoking the workspace sub command, it only ever echos, and never will let you select your work spaces.

My initial thoughts on this issue are, for plugins with complex sub commands, authors should:

  1. preferably follow the pattern of Commands and sub commands. for more discussion, see:
  2. a list of sub commands and their context should be provided for both user command’s completion and vim.ui.select, so that users can do both MainCmd and MainCmdand get all available actions.
  3. sub commands should not have multiple meanings like no args means echoing a message and with args means open a file, if there must be, it should be followed by a modifier like ? or !, following the vim tradition, like Neorg workspace? echos the current workspace.
  4. sub commands should just be simple functions that can be both invoked from the command line or a series of vim.ui.input or vim.ui.select. users should never see a message like not enough arguments or just get the awkward silence after trying out a subcommand.

a subcommand in my plugin now looks like this

cmds.add_feed = {
   impl = function(url, name, tags)
      url = url or ui_input { prompt = "Feed url: " }
      name = name or ui_input { prompt = "Feed name (optional): " }
      tags = tags or ui_input { prompt = "Feed tags (optional, comma seperated): " } 
      -- more logic
   end,
   context = { all = true },
}

ps: ui\_input is just a wrapped version of the vim.ui.input, with libraries like nvim-nio or plenary or coerce.nvim

this allows to both pass arguments one by one on the cmdline, and a prompt style command, so no matter when the user pressed enter they never feels confused.

  1. this is pretty personal and immature opinion but, a new DSL in the commands and having a bunch of modifiers often means that I will never end up using them, so a prompt style command is just much more clear to me for complex actions.

These are just some initial thoughts after refactoring my own plugin, I would like to hear what others think.