echasnovski / mini.nvim

Library of 40+ independent Lua modules improving overall Neovim (version 0.8 and higher) experience with minimal effort
MIT License
4.86k stars 183 forks source link

Expose mini.git internals for command impl / completion #1183

Open ibhagwan opened 2 weeks ago

ibhagwan commented 2 weeks ago

Contributing guidelines

Module(s)

mini.git

Description

Hi @echasnovski :-)

I'm attempting to replace vim-fugitive with mini.git so far the :Git command works great and is a great alterantive to the former.

But I also have another use-case where it gets a bit more tricky. To manage my dot files I use a git dir located at ~/dots/.git with it's work directory set to $HOME, which I then use with a simple shell alias similar to the git command, i.e. dot log/add/commit/etc, you get the idea.

alias dot="git -c status.showUntrackedFiles=no --git-dir=${HOME}/dot/.git -C ${HOME}"

Inside neovim I have a similar vim-fugitive command Yit which I use to manage my dot files, e.g. :Yit add %, Yit commit, etc.

To have the same with mini.git requires access to the internal implementation and completion:

  vim.api.nvim_create_user_command("Yit",
    function(t)
      table.insert(t, 1, "-c")
      table.insert(t, 2, "status.showUntrackedFiles=no")
      table.insert(t, 3, "--git-dir=$HOME/dots/.git")
      table.insert(t, 4, "-C=$HOME")
      require("mini.git").command_impl(t)
    end,
    {
      bang = true,
      nargs = "+",
      complete = require("mini.git").command_complete,
      desc = "Git command (yadm)"
    }
  )

While this would work, the completion would still be inaccurate, for example , with git switch, it would complete branches from the current git folder ignoring --git-dir, the same issue can be observed by running :Git --git-dir=$HOME/.git switch (while using a different git directory than the current buffer).

To solve this in fugutive you can define a custom completion with extra git flags:

From: https://github.com/ibhagwan/nvim-lua/blob/c86405726fc4b7782606864cd1ccc793eba34616/lua/plugins/fugitive.lua#L35

vim.cmd(([[
function! YadmComplete(A, L, P) abort
return fugitive#Complete(a:A, a:L, a:P, {'git_dir': expand("%s")})
endfunction
]]):format(yadm_repo))

Perhaps a better idea would be a way to generate both custom implementation and completion with extra git flags, that way we can also avoid the table.insert hack, something like:

  local flags = { "--git-dir", "$HOME/dots/.git", "-C", "$HOME" }
  -- or have the ability to send extra flags to command_impl/command_complete
  -- so I can wrap it in a `function() ... end`
  local impl = require("mini.git").gen_impl(flags)
  local complete = require("mini.git").gen_complete(flags)
  vim.api.nvim_create_user_command("Yit", impl, {
    bang = true,
    nargs = "+",
    complete = complete,
    desc = "Git command (yadm)"
  })
echasnovski commented 2 weeks ago

Thanks for the suggestion!

I am afraid, I'd like to avoid exporting too much from 'mini.git' (or any modules, for that matter). It can get convoluted pretty quickly.

I was hoping that vim.api.nvim_get_commands({}) can return both complete function and command implementation, but sadly (and confusingly) it does not :disappointed:

Currently my best suggestion for command_impl replacement would be to manually construct command string and use vim.cmd('Git ...') explicitly.

And as for command_complete()... I don't have any even remotely useful suggestions. Maybe try using string complete field from :h command-complete (like 'file_in_path' with adjusted 'path' option) or implement from scratch for most important for you cases.

Making completion support custom flags in this exact command (like --git-dir) is also non-trivial under current design.

I maybe ponder a bit over this, but I don't have high hopes for this.

ibhagwan commented 2 weeks ago

I was hoping that vim.api.nvim_get_commands({}) can return both complete function and command implementation, but sadly (and confusingly) it does not

I also looked at that but it only gives a reference to the complete function, it also requires iterating all commands as there is no vim.api.nvim_get_command for a single command

Currently my best suggestion for command_impl replacement would be to manually construct command string and use vim.cmd('Git ...') explicitly.

I thought about that too, perhaps with abbrev but I dislike this solution, it also feels less robust, not enough to warrant replacing the trusty vim-fugitive.

Making completion support custom flags in this exact command (like --git-dir) is also non-trivial under current design. I maybe ponder a bit over this, but I don't have high hopes for this.

Fair enough, I guess we can close this issue unless you need more pondering time :)

echasnovski commented 2 weeks ago

I also looked at that but it only gives a reference to the complete function, it also requires iterating all commands as there is no vim.api.nvim_get_command for a single commons.

It's a map (which is also not very consistent with other API methods). So it would be like vim.api.nvim_get_commands({}).Git.

Making completion support custom flags in this exact command (like --git-dir) is also non-trivial under current design. I maybe ponder a bit over this, but I don't have high hopes for this.

Fair enough, I guess we can close this issue unless you need more pondering time :)

Yes, let's keep this open for a bit. You never know.