wbthomason / packer.nvim

A use-package inspired plugin manager for Neovim. Uses native packages, supports Luarocks dependencies, written in Lua, allows for expressive config
MIT License
7.82k stars 266 forks source link

Lazy-load on specific directory #973

Closed koalagang closed 1 year ago

koalagang commented 2 years ago

I'd like to suggest two features but I'll post them both in this one issue because they're very similar so I figure I might as well.

There should be an option to lazy-load plugins based on the directory which the current buffer is in. So for example, I should be able to say that if I am editing a file anywhere under /home/user/Documents/vimwiki then vimwiki is loaded but otherwise it is not. This would be particularly useful if, for example, you like using something like vimwiki with markdown for general notes but don't want to load vimwiki when editing a README.md file. I think it would potentially be useful for packer to have the ability to lazy-load in such a manner for singular files, directories or recursively like in the aforementioned example. To imply lazy-loading, you could use the key dir = [insert string or list] in your use '{[insert package repo]}' section.

The other idea which is somewhat related is loading specific plugins only when in a git directory. So, for example, I might want to set packer to only load gitsigns and/or vim-fugitive in a git directory. To imply lazy-loading, you could use the key git = [insert string or list].

I also think adding the feature mentioned in #951 could work nicely with these two features because it would then allow you to do things like loading when two conditions such as the following are met:

  1. the file is a markdown file
  2. the file is in a git directory

If the ideas which I have put forth here are already features then please do let me know but I don't believe they are because I can't seem to find them by looking through packer's documentation.

nat-418 commented 1 year ago

This is already possible using the opt feature of Packer and builtin Neovim functionality. See this issue for more details: https://github.com/wbthomason/packer.nvim/discussions/946 .

koalagang commented 1 year ago

@nat-418 Sorry for the delayed reply. I fail to see how this issue you mentioned relates to lazy-loading on particular directories.

nat-418 commented 1 year ago

@koalagang you can already lazy-load opt plugins per directory using autocommands, just like you can load them per filetype:

autocmd BufRead */home/user/Documents/vimwiki* <load plugin code>
koalagang commented 1 year ago

@nat-418 Oh. That's really useful. event = "BufRead $HOME/Documents*" does the trick. However, the problem then is that vimwiki is also loaded for non-markdown files under $HOME/Documents. This issue could be resolved with adding .md to the end (i.e. event = "BufRead $HOME/Documents*.md"). However, a better way - in my humble opinion - would be to pursue the idea mentioned here #951 because that feature would be useful in other cases too.

Also, I could not figure out how to check if my root directory had a file pattern (e.g. .git). This isn't a big deal for me since I store all my git directories under a single directory (so I can just lazy-load gitsigns with event = "BufRead *$HOME/Desktop/git*") but I still think it would be convenient to have packer be able to selectively load plugins with specific patterns in the root directory (unless that's already possible?).

nat-418 commented 1 year ago

So let's take another look at the README:

use {
  'myusername/example',        -- The plugin location string
  -- The following keys are all optional
  disable = boolean,           -- Mark a plugin as inactive
  as = string,                 -- Specifies an alias under which to install the plugin
  installer = function,        -- Specifies custom installer. See "custom installers" below.
  updater = function,          -- Specifies custom updater. See "custom installers" below.
  after = string or list,      -- Specifies plugins to load before this plugin. See "sequencing" below
  rtp = string,                -- Specifies a subdirectory of the plugin to add to runtimepath.
  opt = boolean,               -- Manually marks a plugin as optional.
  bufread = boolean,           -- Manually specifying if a plugin needs BufRead after being loaded
  branch = string,             -- Specifies a git branch to use
  tag = string,                -- Specifies a git tag to use. Supports '*' for "latest tag"
  commit = string,             -- Specifies a git commit to use
  lock = boolean,              -- Skip updating this plugin in updates/syncs. Still cleans.
  run = string, function, or table, -- Post-update/install hook. See "update/install hooks".
  requires = string or list,   -- Specifies plugin dependencies. See "dependencies".
  rocks = string or list,      -- Specifies Luarocks dependencies for the plugin
  config = string or function, -- Specifies code to run after this plugin is loaded.
  -- The setup key implies opt = true
  setup = string or function,  -- Specifies code to run before this plugin is loaded.
  -- The following keys all imply lazy-loading and imply opt = true
  cmd = string or list,        -- Specifies commands which load this plugin. Can be an autocmd pattern.
  ft = string or list,         -- Specifies filetypes which load this plugin.
  keys = string or list,       -- Specifies maps which load this plugin. See "Keybindings".
  event = string or list,      -- Specifies autocommand events which load this plugin.
  fn = string or list          -- Specifies functions which load this plugin.
  cond = string, function, or list of strings/functions,   -- Specifies a conditional test to load this plugin
  module = string or list      -- Specifies Lua module names for require. When requiring a string which starts
                               -- with one of these module names, the plugin will be loaded.
  module_pattern = string/list -- Specifies Lua pattern of Lua module names for require. When requiring a string which matches one of these patterns, the plugin will be loaded.
}

We can see that event, ft, and cond, all have some relevance here. To be honest, I don't do anything this fancy. But, it looks like cond gives you the ability to do what you want.

If you will allow me some pseudo-code:

...
cond = function()
  if <check directory is good> and <check file extension is good> then
    return require('foo').setup()
  end
end
koalagang commented 1 year ago

Yes, I am aware of cond. However, (correct me if I'm wrong but) I believe this is more so intended for people who wish to do more fancy things. Something as simple as having two different conditions met should not require a custom function. Afterall, a big part of packer's reason for existence is to make lazy-loading easier. Anyway, in regards to loading based on two different conditions, #951 is the place for further discussion. In fact you did post there @nat-418 so no need for that comment here.

Anyway, I digress. I think having the option to use dir = would be more convenient because then a lua table could be passed in. Also, packer should have the ability to check for root directories and file patterns (e.g. being able to detect that the current buffer is in a git directory by checking for .git folders).

Edit: I forgot to mention that using the following code:

cond = function()
    vim.cmd(
        "autocmd BufRead */home/user/Documents/* source /home/user/.local/share/nvim/site/pack/packer/opt/vimwiki/plugin/vimwiki.vim"
    )
end,

(where user is my system name) does nothing. Instead vimwiki just loads regardless of the directory or filetype.

koalagang commented 1 year ago

There seems to be no interest in this and I personally don't really care anymore so I'm closing the issue.