Hi there, I currently use minpac and I’m eager to test out and use packer.nvim.
I have the following conf structure under ~/.config/nvim :
- Modules
- X
- packages.lua
- Y
- packages.lua
- Z
- ...
With minpac I have add-calls in packages.lua, which gets loaded whenever I want to update or install packages and call util.update_packages().
— Example content of packages.lua
vim.cmd"call minpac#add('vim-jp/syntax-vim-ex"
I wonder how to achieve the similar result with packer.nvim?
I’d deeply appreciate a code snippet to get me started. 🙏 Thanks a lot, hope it okay it to post how to here.
Sure - I can help with a more complete snippet if need be, but this is actually quite easy with packer:
init.vim (or anywhere that gets sourced before your modules), call packer.init().packages.lua files, call packer.use for each plugin you want to add.util.update_packages(), call packer.sync() or packer.update().That should be it! Let me know if you run into trouble, if this is confusing, or if it doesn't work as expected.
Hay, @wbthomason thanks so much for laying out how to do it like this. I'm considering changing my package loading strategy, and I'd like to hear your thoughts on it: Given that I want all my plugin to be lazy loaded, I defined a function that will let me skip having to maintain modules/*/pkgs.lua and also add packages to packpath and if not installed call packer.use then add to packpath:
local util.add = function(package)
local _ = vim.fn
local packagename = _.get(_.split(package, '/'),1)
local base = '%s/pack/packer/opt'
local packpath = _.printf(base, _.stdpath('cache'))
local plugin_dir = packpath .. "/" ..packagename
print(plugin_dir)
if _.isdirectory(plugin_dir) ~= 1 then
vim.cmd [[packadd packer.nvim]]
if not packer then
packer = require("packer")
packer.init()
packer.use({"wbthomason/packer.nvim", opt = true})
end
packer.use(package)
packer.update()
vim.cmd('packadd ' .. packagename)
else
vim.cmd('packadd ' .. packagename)
end
end
I'm sure this has many holes in, but do you think its performant to use this wrapper as both for installing packages and loading them?
Edit: how to make it cover packer options?, how to make update or install silent?
Also, is using packer as opt, and using init, use (also opt), and update, makes configuration such as cmd, ft, require unusable?
I tried doing packer.use({ 'mboughaba/vim-lessmess', opt = true, cmd = {'LessmessExecute'}}) however, the command didn't get identified and I had to do packadd vim-lessmess.
EDIT: I think I know what going on, without startup function, options to like cmd and opt={ture or false}, doesn't have any influence what so ever? I also tried packer.use({"norcalli/nvim-base16.lua", opt = false}), but even though it is in start/ it didn't get loaded. see reload function,
Sorry, there are a lot of things to reply to here, so if I miss something, please let me know.
Given that I want all my plugin to be lazy loaded, I defined a function that will let me skip having to maintain modules/*/pkgs.lua and also add packages to packpath and if not installed call packer.use then add to packpath
The snippet you posted should work, though I'll note you only need the use(...packer.nvim...) line when you're trying to manage packer.nvim (i.e. not every invocation of this function). There are three other things to note - first, it appears from your local packpath value that you're using a non-standard package location (i.e. not packer's default), so you'll need to set the appropriate option for packer in your call to init. Second, you can pass a plugin name directly to packer, e.g. packer.install(NAME) to install/update only that plugin (after the plugin specification has been passed to a use call). Third, you'll need to be careful here that all of your plugins are added with use before you call packer.sync() or packer.clean() - otherwise, packer will think that they are unmanaged and ask to delete them. I would suggest changing your logic to conditionally load packer, but always call packer.use(package).
Edit: how to make it cover packer options?, how to make update or install silent?
Please see the docs for information on passing options to packer via init(). Unfortunately, there's currently no option to make updates/installs silent (assuming this means not opening a progress display window); please feel free to open a new issue (or, better still, a PR) to add this feature.
Also, is using packer as opt, and using init, use (also opt), and update, makes configuration such as cmd, ft, require unusable?
I tried doing
packer.use({ 'mboughaba/vim-lessmess', opt = true, cmd = {'LessmessExecute'}})however, the command didn't get identified and I had to dopackadd vim-lessmess.
I'm guessing one of a couple of things happened here:
packpath. Make sure you're telling packer where you want it to install plugins.packer.compile() or packer.sync() at any point? This is necessary to compile the lazy-loading code that generates a "fake" LessMessExecute command which will load vim-lessmess, delete itself, and then run the actual command.You also do not need to manually specify opt = true if you've specified a keyword that implies lazy-loading, such as cmd.
EDIT: I think I know what going on, without startup function, options to like cmd and opt={ture or false}, doesn't have any influence what so ever? I also tried packer.use({"norcalli/nvim-base16.lua", opt = false}), but even though it is in start/ it didn't get loaded. see reload function,
No, this is not correct. You don't need the startup function if you don't want to use it; init will do fine (startup mostly just creates some convenient commands for you). If packer correctly cloned nvim-base16.lua into a start/ directory for you, then the reason it isn't getting loaded is probably due to nuances of the native packages feature. Are you trying to call functions from this package in your init.vim? This is known not to work with native packages (see e.g. https://github.com/wbthomason/packer.nvim/issues/4). If that's not the case, then is your plugin install location on the default packpath? If not, you need to modify packpath so that Neovim can find the plugin.
I hope this helps!
Thanks so much for your detailed reply to my inquiry. I appreciate deeply. So from what I understood:
_The custom function should get the job done with some exceptions you mentioned. But was a bit unclear to me that should I pass the package name to packer.install() or packer.use or both_ EDIT: From what I understood, I need to use both, first one for setting the options with packer.use and the second for cloning with packer.install, and do not call packer.sync, or update as it may result of deleting other packages. Correct?
packer.init() is necessary to be called at startup? in order for options passed to packer.use() to work? or there is another condition must be met? _Also, I long change my packpath to the default .local/*/*/nvim/site, additionally base16 didn't work because it need to be called during init.vim, while start/ get called after init.vim finishes_
Finally, question: does packer.compile() apply to my use case? and when do I need to call it in my management workflow if it does, for example with packer.sync()?
Again thanks so much, and for the PR I'll try to hack the source code and see what I can do to enable the user to pass silent = true.
To your first point: the general "flow" with packer is this: you call use() with some plugin specifications. This lets packer know to manage these plugins. Then, later, you call packer.install() or packer.update() or packer.sync(), which will install missing plugins (and, in the case of update or sync, also update installed plugins).
What I was saying with passing the plugin name to packer.install() is that you can optionally tell packer to install a single missing plugin rather than checking for and installing all missing plugins. If you want to do ad hoc installs like this rather than installing everything at once, then you do need to call first use and then install, both with the plugin name. Otherwise, just call use with the plugin name, and later call install with no arguments to install everything missing.
To your second point: currently, yes, packer.init() must be called before doing any other operations with packer (it's not necessary if you're just loading plugins, though). That could potentially change if it's annoying.
packer.compile() is necessary if you are doing any lazy-loading that you expect packer to manage for you, e.g. your cmd example above. packer.sync() calls packer.compile() for you.
I would suggest that you take a look at the docs in README or the docs/ folder (vimdocs) - there's a lot more information on how this works and how you can use packer there.
Thanks!
Thanks a lot for the your amazing input and help till now, I will look into the docs before continuing on with my adhock way of installation.
packer.init() must be called before doing any other operations with packer (it's not necessary if you're just loading plugins, though). That could potentially change if it's annoying.
yes I think it better be changed, however, for now I will call it with my initialization of neovim
Hay @wbthomason, hope you are having a great week so far.
What I was saying with passing the plugin name to packer.install() is that you can optionally tell packer to install a single missing plugin rather than checking for and installing all missing plugins.
I had an error while trying to pass a plugin name to packer.install a single plugin:
[packer] Error in coroutine: .../site/pack/packer/opt/packer.nvim/lua/packer/install.lua:39: attempt to index a nil value
I basically did in command line:
lua require('packer').init()lua require('packer').install('nikvdp/neomux'), use('nikvdp/neomux') first then install('nikvdp/neomux'), but gotten the same error.I endup just using use(plugin) then install().
Thanks
Ah, I'm sorry - I should have been more clear. You must always call use first, to add the plugin to the managed set. You can then call install either with no arguments (to install every missing plugin) or one argument, the name of a plugin in the managed set. The following should work (though I admit this is an infrequently-tested use case, so there may be bugs):
local packer = require('packer')
packer.init()
packer.use('nikvdp/neomux')
packer.install('neomux')
Again, I'm sorry - I don't think it's made clear anywhere that you pass just the name, not the full path, to install.
Hey @wbthomason, thanks for your fast response this time. I had to skip using packer.install because I couldn’t make it work check out this commit , However I managed to get my new use case working, “please read commit message” and I’m thinking of opening a PR soon and work on it more if this would be something other user will appreciate as it enabled me to have a more use-package experience.
I'm glad your new use case is working. What were you unable to get working with packer.install(), though? The example I posted above seems to work for me.
The reason that use/install are separated like this (as opposed to the ensure tag in use-package) is because packer does other things - specifically, compiling lazy-loading code - that require the plugin specification, whereas we wouldn't want to run install every time.
I'd be happy to add a "silent" option to prevent the status window from opening, which might make packer more useful for your use case. In particular, I expect that packer is faster than what you're doing, because it does installs in parallel using the jobs system. Additionally, your manual packadd code should be unnecessary via the combination of native packages (i.e. plugins in start get loaded automatically) and packer's compiled lazy-loaders (which trigger packadd, etc. on the conditions you specify).
I'm not sure if I missed some parts of your use case in the commit message; please let me know if I did. Thanks!
What were you unable to get working with packer.install()
@wbthomason it installs okay but I get an error package not available in pack path because packadd get executed or get blocked before packer.install() finishes
Yes, silent option will be so amazing thank you looking forward for it.
And for packadd as an option, as far as I know start doesn't load until init.vim finish loading. It is useful when the package is needed to load during initialization like in my case of using base16.
Also, if its not to much to ask, do u have any idea on how to check if a package is written in lua and to get it module name so I can pass it require.
Thanks a lot for both developing the package and help me set up my use case🙏🙏🙏🙏
packadd get executed or get blocked before packer.install() finishes
Strange - packer.install() is a synchronous operation, so running packadd after it completes should have worked.
Yes, silent option will be so amazing thank you looking forward for it.
It's in progress; just need to debug some edge cases.
And for packadd as an option, as far as I know start doesn't load until init.vim finish loading. It is useful when the package is needed to load during initialization like in my case of using base16.
Ah, right, this is unfortunately true of the Neovim native packages feature.
Also, if its not to much to ask, do u have any idea on how to check if a package is written in lua and to get it module name so I can pass it require.
I unfortunately don't have any great ideas for this - my best guess would be to (1) look for a lua/ dir in the plugin directory and then (2) look for either top-level Lua files in that directory or a sub-directory containing Lua files (the module name(s) should be the same as the path, starting at the lua directory, to each Lua file).
Thanks a lot for both developing the package and help me set up my use case
Happy to help! Sorry for some of my responses being pretty slow.
@wbthomason Thanks a lot. Don’t worry I’m sure you have a lot going on. Looking forward for the silent option.
@tami5: sorry about how long this took, but there's now a non_interactive option added in #109 that should serve as a "silent mode"
@wbthomason nice thanks.