mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
394 lines
16 KiB
Plaintext
394 lines
16 KiB
Plaintext
*pack.txt* Nvim
|
|
|
|
NVIM REFERENCE MANUAL
|
|
|
|
Extending Nvim
|
|
|
|
|
|
Type |gO| to see the table of contents.
|
|
|
|
==============================================================================
|
|
Using Vim packages *packages*
|
|
|
|
A Vim "package" is a directory that contains |plugin|s. Compared to normal
|
|
plugins, a package can...
|
|
- be downloaded as an archive and unpacked in its own directory, so the files
|
|
are not mixed with files of other plugins.
|
|
- be a git, mercurial, etc. repository, thus easy to update.
|
|
- contain multiple plugins that depend on each other.
|
|
- contain plugins that are automatically loaded on startup ("start" packages,
|
|
located in "pack/*/start/*") and ones that are only loaded when needed with
|
|
|:packadd| ("opt" packages, located in "pack/*/opt/*").
|
|
|
|
*runtime-search-path*
|
|
Nvim searches for |:runtime| files in:
|
|
- 1. all paths in 'runtimepath'
|
|
- 2. all "pack/*/start/*" dirs
|
|
|
|
Note that the "pack/*/start/*" paths are not explicitly included in
|
|
'runtimepath', so they will not be reported by ":set rtp" or "echo &rtp".
|
|
Scripts can use |nvim_list_runtime_paths()| to list all used directories, and
|
|
|nvim_get_runtime_file()| to query for specific files or sub-folders within
|
|
the runtime path. Example: >
|
|
" List all runtime dirs and packages with Lua paths.
|
|
:echo nvim_get_runtime_file("lua/", v:true)
|
|
|
|
Using a package and loading automatically ~
|
|
|
|
Let's assume your Nvim files are in "~/.local/share/nvim/site" and you want to
|
|
add a package from a zip archive "/tmp/foopack.zip": >
|
|
% mkdir -p ~/.local/share/nvim/site/pack/foo
|
|
% cd ~/.local/share/nvim/site/pack/foo
|
|
% unzip /tmp/foopack.zip
|
|
|
|
The directory name "foo" is arbitrary, you can pick anything you like.
|
|
|
|
You would now have these files under ~/.local/share/nvim/site: >
|
|
pack/foo/README.txt
|
|
pack/foo/start/foobar/plugin/foo.vim
|
|
pack/foo/start/foobar/syntax/some.vim
|
|
pack/foo/opt/foodebug/plugin/debugger.vim
|
|
|
|
On startup after processing your |config|, Nvim scans all directories in
|
|
'packpath' for plugins in "pack/*/start/*", then loads the plugins.
|
|
|
|
To allow for calling into package functionality while parsing your |vimrc|,
|
|
|:colorscheme| and |autoload| will both automatically search under 'packpath'
|
|
as well in addition to 'runtimepath'. See the documentation for each for
|
|
details.
|
|
|
|
In the example Nvim will find "pack/foo/start/foobar/plugin/foo.vim" and load
|
|
it.
|
|
|
|
If the "foobar" plugin kicks in and sets the 'filetype' to "some", Nvim will
|
|
find the syntax/some.vim file, because its directory is in the runtime search
|
|
path.
|
|
|
|
Nvim will also load ftdetect files, if there are any.
|
|
|
|
Note that the files under "pack/foo/opt" are not loaded automatically, only the
|
|
ones under "pack/foo/start". See |pack-add| below for how the "opt" directory
|
|
is used.
|
|
|
|
Loading packages automatically will not happen if loading plugins is disabled,
|
|
see |load-plugins|.
|
|
|
|
To load packages earlier, so that plugin/ files are sourced:
|
|
:packloadall
|
|
This also works when loading plugins is disabled. The automatic loading will
|
|
only happen once.
|
|
|
|
If the package has an "after" directory, that directory is added to the end of
|
|
'runtimepath', so that anything there will be loaded later.
|
|
|
|
|
|
Using a single plugin and loading it automatically ~
|
|
|
|
If you don't have a package but a single plugin, you need to create the extra
|
|
directory level: >
|
|
% mkdir -p ~/.local/share/nvim/site/pack/foo/start/foobar
|
|
% cd ~/.local/share/nvim/site/pack/foo/start/foobar
|
|
% unzip /tmp/someplugin.zip
|
|
|
|
You would now have these files: >
|
|
pack/foo/start/foobar/plugin/foo.vim
|
|
pack/foo/start/foobar/syntax/some.vim
|
|
|
|
From here it works like above.
|
|
|
|
|
|
Optional plugins ~
|
|
*pack-add*
|
|
To load an optional plugin from a pack use the `:packadd` command: >
|
|
:packadd foodebug
|
|
This searches for "pack/*/opt/foodebug" in 'packpath' and will find
|
|
~/.local/share/nvim/site/pack/foo/opt/foodebug/plugin/debugger.vim and source
|
|
it.
|
|
|
|
This could be done if some conditions are met. For example, depending on
|
|
whether Nvim supports a feature or a dependency is missing.
|
|
|
|
You can also load an optional plugin at startup, by putting this command in
|
|
your |config|: >
|
|
:packadd! foodebug
|
|
The extra "!" is so that the plugin isn't loaded if Nvim was started with
|
|
|--noplugin|.
|
|
|
|
It is perfectly normal for a package to only have files in the "opt"
|
|
directory. You then need to load each plugin when you want to use it.
|
|
|
|
|
|
Where to put what ~
|
|
|
|
Since color schemes, loaded with `:colorscheme`, are found below
|
|
"pack/*/start" and "pack/*/opt", you could put them anywhere. We recommend
|
|
you put them below "pack/*/opt", for example
|
|
"~/.config/nvim/pack/mycolors/opt/dark/colors/very_dark.vim".
|
|
|
|
Filetype plugins should go under "pack/*/start", so that they are always
|
|
found. Unless you have more than one plugin for a file type and want to
|
|
select which one to load with `:packadd`. E.g. depending on the compiler
|
|
version: >
|
|
if foo_compiler_version > 34
|
|
packadd foo_new
|
|
else
|
|
packadd foo_old
|
|
endif
|
|
|
|
The "after" directory is most likely not useful in a package. It's not
|
|
disallowed though.
|
|
|
|
==============================================================================
|
|
Creating Vim packages *package-create*
|
|
|
|
This assumes you write one or more plugins that you distribute as a package.
|
|
|
|
If you have two unrelated plugins you would use two packages, so that Vim
|
|
users can choose what they include or not. Or you can decide to use one
|
|
package with optional plugins, and tell the user to add the preferred ones with
|
|
`:packadd`.
|
|
|
|
Decide how you want to distribute the package. You can create an archive or
|
|
you could use a repository. An archive can be used by more users, but is a
|
|
bit harder to update to a new version. A repository can usually be kept
|
|
up-to-date easily, but it requires a program like "git" to be available.
|
|
You can do both, github can automatically create an archive for a release.
|
|
|
|
Your directory layout would be like this: >
|
|
start/foobar/plugin/foo.vim " always loaded, defines commands
|
|
start/foobar/plugin/bar.vim " always loaded, defines commands
|
|
start/foobar/autoload/foo.vim " loaded when foo command used
|
|
start/foobar/doc/foo.txt " help for foo.vim
|
|
start/foobar/doc/tags " help tags
|
|
opt/fooextra/plugin/extra.vim " optional plugin, defines commands
|
|
opt/fooextra/autoload/extra.vim " loaded when extra command used
|
|
opt/fooextra/doc/extra.txt " help for extra.vim
|
|
opt/fooextra/doc/tags " help tags
|
|
<
|
|
This allows for the user to do: >
|
|
mkdir ~/.local/share/nvim/site/pack
|
|
cd ~/.local/share/nvim/site/pack
|
|
git clone https://github.com/you/foobar.git myfoobar
|
|
|
|
Here "myfoobar" is a name that the user can choose, the only condition is that
|
|
it differs from other packages.
|
|
|
|
In your documentation you explain what the plugins do, and tell the user how
|
|
to load the optional plugin: >
|
|
:packadd! fooextra
|
|
|
|
You could add this packadd command in one of your plugins, to be executed when
|
|
the optional plugin is needed.
|
|
|
|
Run the `:helptags` command to generate the doc/tags file. Including this
|
|
generated file in the package means that the user can drop the package in the
|
|
pack directory and the help command works right away. Don't forget to re-run
|
|
the command after changing the plugin help: >
|
|
:helptags path/start/foobar/doc
|
|
:helptags path/opt/fooextra/doc
|
|
|
|
|
|
Dependencies between plugins ~
|
|
*packload-two-steps*
|
|
Suppose you have two plugins that depend on the same functionality. You can
|
|
put the common functionality in an autoload directory, so that it will be
|
|
found automatically. Your package would have these files:
|
|
|
|
pack/foo/start/one/plugin/one.vim >
|
|
call foolib#getit()
|
|
pack/foo/start/two/plugin/two.vim >
|
|
call foolib#getit()
|
|
pack/foo/start/lib/autoload/foolib.vim >
|
|
func foolib#getit()
|
|
|
|
This works, because start packages will be searched for autoload files, when
|
|
sourcing the plugins.
|
|
|
|
==============================================================================
|
|
Plugin manager *vim.pack*
|
|
|
|
WORK IN PROGRESS built-in plugin manager! Early testing of existing features
|
|
is appreciated, but expect breaking changes without notice.
|
|
|
|
Manages plugins only in a dedicated *vim.pack-directory* (see |packages|):
|
|
`$XDG_DATA_HOME/nvim/site/pack/core/opt`. Plugin's subdirectory name matches
|
|
plugin's name in specification. It is assumed that all plugins in the
|
|
directory are managed exclusively by `vim.pack`.
|
|
|
|
Uses Git to manage plugins and requires present `git` executable of at least
|
|
version 2.36. Target plugins should be Git repositories with versions as named
|
|
tags following semver convention `v<major>.<minor>.<patch>`.
|
|
|
|
Example workflows ~
|
|
|
|
Basic install and management:
|
|
• Add |vim.pack.add()| call(s) to 'init.lua': >lua
|
|
|
|
vim.pack.add({
|
|
-- Install "plugin1" and use default branch (usually `main` or `master`)
|
|
'https://github.com/user/plugin1',
|
|
|
|
-- Same as above, but using a table (allows setting other options)
|
|
{ src = 'https://github.com/user/plugin1' },
|
|
|
|
-- Specify plugin's name (here the plugin will be called "plugin2"
|
|
-- instead of "generic-name")
|
|
{ src = 'https://github.com/user/generic-name', name = 'plugin2' },
|
|
|
|
-- Specify version to follow during install and update
|
|
{
|
|
src = 'https://github.com/user/plugin3',
|
|
-- Version constraint, see |vim.version.range()|
|
|
version = vim.version.range('1.0'),
|
|
},
|
|
{
|
|
src = 'https://github.com/user/plugin4',
|
|
-- Git branch, tag, or commit hash
|
|
version = 'main',
|
|
},
|
|
})
|
|
|
|
-- Plugin's code can be used directly after `add()`
|
|
plugin1 = require('plugin1')
|
|
<
|
|
• Restart Nvim (for example, with |:restart|). Plugins that were not yet
|
|
installed will be available on disk in target state after `add()` call.
|
|
• To update all plugins with new changes:
|
|
• Execute |vim.pack.update()|. This will download updates from source and
|
|
show confirmation buffer in a separate tabpage.
|
|
• Review changes. To confirm all updates execute |:write|. To discard
|
|
updates execute |:quit|.
|
|
|
|
Switch plugin's version:
|
|
• Update 'init.lua' for plugin to have desired `version`. Let's say, plugin
|
|
named 'plugin1' has changed to `vim.version.range('*')`.
|
|
• |:restart|. The plugin's actual state on disk is not yet changed.
|
|
• Execute `vim.pack.update({ 'plugin1' })`.
|
|
• Review changes and either confirm or discard them. If discarded, revert any
|
|
changes in 'init.lua' as well or you will be prompted again next time you
|
|
run |vim.pack.update()|.
|
|
|
|
Freeze plugin from being updated:
|
|
• Update 'init.lua' for plugin to have `version` set to current commit hash.
|
|
You can get it by running `vim.pack.update({ 'plugin-name' })` and yanking
|
|
the word describing current state (looks like `abc12345`).
|
|
• |:restart|.
|
|
|
|
Unfreeze plugin to start receiving updates:
|
|
• Update 'init.lua' for plugin to have `version` set to whichever version you
|
|
want it to be updated.
|
|
• |:restart|.
|
|
|
|
Remove plugins from disk:
|
|
• Use |vim.pack.del()| with a list of plugin names to remove. Make sure their
|
|
specs are not included in |vim.pack.add()| call in 'init.lua' or they will
|
|
be reinstalled.
|
|
|
|
Available events to hook into ~
|
|
• *PackChangedPre* - before trying to change plugin's state.
|
|
• *PackChanged* - after plugin's state has changed.
|
|
|
|
Each event populates the following |event-data| fields:
|
|
• `kind` - one of "install" (install on disk), "update" (update existing
|
|
plugin), "delete" (delete from disk).
|
|
• `spec` - plugin's specification.
|
|
• `path` - full path to plugin's directory.
|
|
|
|
|
|
*vim.pack.Spec*
|
|
|
|
Fields: ~
|
|
• {src} (`string`) URI from which to install and pull updates. Any
|
|
format supported by `git clone` is allowed.
|
|
• {name}? (`string`) Name of plugin. Will be used as directory name.
|
|
Default: `src` repository name.
|
|
• {version}? (`string|vim.VersionRange`) Version to use for install and
|
|
updates. Can be:
|
|
• `nil` (no value, default) to use repository's default
|
|
branch (usually `main` or `master`).
|
|
• String to use specific branch, tag, or commit hash.
|
|
• Output of |vim.version.range()| to install the
|
|
greatest/last semver tag inside the version constraint.
|
|
|
|
|
|
add({specs}, {opts}) *vim.pack.add()*
|
|
Add plugin to current session
|
|
• For each specification check that plugin exists on disk in
|
|
|vim.pack-directory|:
|
|
• If exists, do nothin in this step.
|
|
• If doesn't exist, install it by downloading from `src` into `name`
|
|
subdirectory (via `git clone`) and update state to match `version`
|
|
(via `git checkout`).
|
|
• For each plugin execute |:packadd| making them reachable by Nvim.
|
|
|
|
Notes:
|
|
• Installation is done in parallel, but waits for all to finish before
|
|
continuing next code execution.
|
|
• If plugin is already present on disk, there are no checks about its
|
|
present state. The specified `version` can be not the one actually
|
|
present on disk. Execute |vim.pack.update()| to synchronize.
|
|
• Adding plugin second and more times during single session does nothing:
|
|
only the data from the first adding is registered.
|
|
|
|
Parameters: ~
|
|
• {specs} (`(string|vim.pack.Spec)[]`) List of plugin specifications.
|
|
String item is treated as `src`.
|
|
• {opts} (`table?`) A table with the following fields:
|
|
• {load}? (`boolean`) Load `plugin/` files and `ftdetect/`
|
|
scripts. If `false`, works like `:packadd!`. Default
|
|
`true`.
|
|
|
|
del({names}) *vim.pack.del()*
|
|
Remove plugins from disk
|
|
|
|
Parameters: ~
|
|
• {names} (`string[]`) List of plugin names to remove from disk. Must
|
|
be managed by |vim.pack|, not necessarily already added to
|
|
current session.
|
|
|
|
get() *vim.pack.get()*
|
|
Get data about all plugins managed by |vim.pack|
|
|
|
|
Return: ~
|
|
(`table[]`) A list of objects with the following fields:
|
|
• {spec} (`vim.pack.SpecResolved`) A |vim.pack.Spec| with defaults
|
|
made explicit.
|
|
• {path} (`string`) Plugin's path on disk.
|
|
• {active} (`boolean`) Whether plugin was added via |vim.pack.add()|
|
|
to current session.
|
|
|
|
update({names}, {opts}) *vim.pack.update()*
|
|
Update plugins
|
|
• Download new changes from source.
|
|
• Infer update info (current/target state, changelog, etc.).
|
|
• Depending on `force`:
|
|
• If `false`, show confirmation buffer. It lists data about all set to
|
|
update plugins. Pending changes starting with `>` will be applied
|
|
while the ones starting with `<` will be reverted. It has special
|
|
in-process LSP server attached to provide more interactive features.
|
|
Currently supported methods:
|
|
• 'textDocument/documentSymbol' (`gO` via |lsp-defaults| or
|
|
|vim.lsp.buf.document_symbol()|) - show structure of the buffer.
|
|
• 'textDocument/hover' (`K` via |lsp-defaults| or
|
|
|vim.lsp.buf.hover()|) - show more information at cursor. Like
|
|
details of particular pending change or newer tag.
|
|
Execute |:write| to confirm update, execute |:quit| to discard the
|
|
update.
|
|
• If `true`, make updates right away.
|
|
|
|
Notes:
|
|
• Every actual update is logged in "nvim-pack.log" file inside "log"
|
|
|stdpath()|.
|
|
|
|
Parameters: ~
|
|
• {names} (`string[]?`) List of plugin names to update. Must be managed
|
|
by |vim.pack|, not necessarily already added to current
|
|
session. Default: names of all plugins added to current
|
|
session via |vim.pack.add()|.
|
|
• {opts} (`table?`) A table with the following fields:
|
|
• {force}? (`boolean`) Whether to skip confirmation and make
|
|
updates immediately. Default `false`.
|
|
|
|
|
|
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
|