*paq-nvim.txt*  Package manager for Neovim >= v0.7.
*paq-nvim*                                             Last change: 2023-10-20
*paq*

Author: Sergio Alejandro Vargas    <savargasqu+git@unal.edu.co>

License: MIT

==============================================================================
CONTENTS                                                        *paq-contents*

  Introduction                                           |paq-introduction|
  Usage                                                  |paq-usage|
  Functions and Commands                                 |paq-commands|
  Package options                                        |paq-options|
  Autocommands                                           |paq-autocommands|
  Paq directory                                          |paq-dir|
  Paq log                                                |paq-log|
  Troubleshooting                                        |paq-troubleshooting|
  Bootstrapping                                          |paq-bootstrapping|
  Miscellaneous                                          |paq-misc|
    Using local packages
    Lazy loading


==============================================================================
INTRODUCTION                                                *paq-introduction*

Paq is a Neovim package manager. It can install, update and remove packages
from any valid git repository, and it includes a familiar shorthand for
GitHub repositories.

Paq is written in Lua. It uses the |loop| API to install and update packages
asynchronously, and it stores packages in |packpath| directories.

Paq is for Neovim users who use Lua as their configuration language. It was
written to be a wrapper around existing Neovim features, and to have a simple
and familiar interface for declaring packages.

Paq doesn't modify the |runtimepath|. Nowadays Neovim provides more structured
ways to handle package loading, that can be used without any special
scripting.

NOTE: Requirements and installation instructions can be found in the README.


==============================================================================
USAGE                                                              *paq-usage*

To get started with Paq:

 1. Import the `paq` module:
 >lua
  local paq = require("paq")
<

 2. Call the paq module with a list of packages you want to install.
    Each entry in the list is a package repository, for example:
>lua
  paq {
    "savq/paq-nvim", -- Paq manages itself

    "neovim/nvim-lspconfig",
    "nvim-treesitter/nvim-treesitter",
    "lervag/vimtex",
  }
<

 3. Call the `:PaqInstall` command.

That's it!


==============================================================================
FUNCTIONS AND COMMANDS                                          *paq-commands*
                                                               *paq-functions*

The Paq module exports multiple functions. Most of these functions have a
command alias to make them easier to call on demand. Assuming the module is
imported as `paq`, the functions are:


|paq.__call|                                                      *paq.__call*

  The `paq` module is itself a callable object. It takes as argument a list of
  packages. Each element of the list can be a table or a string.

  When the element is a table, the first value has to be a string with the
  name of the repository, like: `'<GitHub-username>/<repository-name>'`.
  The other key-value pairs in the table have to be named explicitly, see
  |paq-options|. When the element is a string, it works as if it was the first
  value of the table, and all other options will be set to their default
  values.

  Note: Lua can elide parentheses when passing a single table argument to a
  function, so you can always call `paq` without parentheses.
  See |luaref-langFuncCalls|.


|paq.install|                                                    *paq.install*
                                                               *:PaqInstall*
  Installs all packages listed in your configuration. If a package is already
  installed, the function ignores it. If a package has a `build` argument,
  it'll be executed after the package is installed.


|paq.update|                                                      *paq.update*
                                                                *:PaqUpdate*
  Updates the installed packages listed in your configuration. If a package
  hasn't been installed with |PaqInstall|, the function ignores it. If a
  package had changes and it has a `build` argument, then the `build` argument
  will be executed.


|paq.clean|                                                        *paq.clean*
                                                                 *:PaqClean*
  Removes packages found on |paq-dir| that aren't listed in your
  configuration.


|paq.sync|                                                          *paq.sync*
                                                                  *:PaqSync*
  Executes |paq.clean|, |paq.update|, and |paq.install|. Note that all
  paq operations are performed asynchronously, so messages might be printed
  out of order.


|PaqBuild|                                                         *:PaqBuild*
  Takes as single argument with the name of a package. If the package has a
  `build` option (function or shell command), it will execute it. This can be
  used when a build fails, to run a build without a package having changed, or
  for other debugging purposes.


|paq.list|                                                          *paq.list*
                                                                  *:PaqList*
  Lists installed packages as well as packages that were recently removed.
  Recently installed or updated packages are marked with `+` and `*`,
  respectively.


|paq.log_open|                                                  *paq.log_open*
                                                               *:PaqLogOpen*
  Opens the |paq-log| file in a split window.


|paq.log_clean|                                                *paq.log_clean*
                                                              *:PaqLogClean*
  Deletes the |paq-log| file.


|paq:setup|                                                        *paq:setup*

  Method to configure specific global behavior.  It can take a table with the
  following keys:

    `path`
     String that determines where Paq should install packages. It overwrites
     the default value for |paq-dir|. `path` should still be a valid |packages|
     directory, Paq won't modify the 'runtimepath'. This option exists mainly
     to allow testing without altering a user's configuration.

     Default value: |paq-dir|

    `opt`
     Boolean that changes if, by default, plugins are eagerly loaded or lazy
     loaded. If set, the package will be in the optional packages directory.
     See |packages| and |packadd|.

     Default value: `false`

    `url_format`
     String that determines the format used for constructing the URL of a
     package repository. It uses the Lua format syntax, and should only
     receive a single string argument `"%s"` (`[1]` in |paq-options| below).

     This can be set to use SSH instead of HTTPS, to use a different forge
     than GitHub, etc.

     Default value: `"https://github.com/%s.git"`

    `verbose`
     Boolean that determines whether paq should print `(up-to-date) pkg` for
     packages that were not updated.

     Default value: `false`

    `log`
     Path to log file.

     Default value: neovim >= 8.0 `XDG_STATE_HOME/nvim/paq`
                    neovim <= 7.0 `XDG_CACHE_HOME/nvim/paq`

    `lock`
     Path to lock file. Paq uses a lockfile to represent the current state of
     the currently installed packages. If doesn't found any lockfile it will
     create a new one.

    `clone_args`
     Arguments passed to git clone when cloning a package.

     Default values: --depth=1 --recurse-submodules --shallow-submodules
                     --no-single-branch

  Note that unlike most Lua plugins, paq:setup is a method, not a function.
  This allows chaining it with the list of packages without needing to
  bind the module `"paq"` locally, for example:
>lua
  require("paq"):setup { verbose = false } {
    "savq/paq-nvim",
    "neovim/nvim-lspconfig",
    "nvim-treesitter/nvim-treesitter",
  }


==============================================================================
PACKAGE OPTIONS                                                  *paq-options*

Each element in the list of packages can be a table with named options.
These options don't need to be in any particular order, except for the package
string (see 1 below).

The options and their types are the following:

`[1]` : string
  The first field may be a shorthand indicating a GitHub repostory or a URL.
  If it's a shorthand of the form `"<GitHub-username>/<repo-name>"`, it'll be
  expanded to the URL of a GitHub repostory (this can be configured with the
  `url_format` setup option). If it's a URL, it'll act like the `url` option
  below. Either way, the local name of the package will be inferred based on
  the last component of the path.

  Default value: `nil`


`as` : string
  Determines the local name of the directory where Paq will download the
  package. If unset, Paq will try to infer a name from `url` or `[1]`.

  Default value: `nil`


`branch` : string
  Indicates the branch of the git repository. Paq will fetch and pull changes
  from this branch.

  Default value: `nil`


`build` : function | string
  Either a Lua function, a shell command, or an EX-command to be executed
  after installing or updating a package. Useful for packages that require
  a compiling step.

  If a string, Paq will execute the string as a shell command in the
  directory of the package (not in the current directory). If the first
  character of the string is a `:`, it will be execute as vim `:command`.

  If a function, Paq will execute the function right after installing
  the package. The function cannot take any arguments.

  Note that in Lua, you can use index notation to reference a VimL function
  that contains special characters:
>lua
  { "<name-of-package>", build = vim.fn["<name-of-viml-function>"] }
<
  Default value: `nil`


`opt` : boolean
  Indicates whether the package is optional or not. If set, the package will
  be in the optional packages directory. See |packages| and |packadd|.

  Default value: `false`


`pin` : boolean
  Indicates whether the package is pinned or not. If a package is pinned then
  it will be installed, but it will not be updated when calling |PaqUpdate|.

  Default value: `false`


`run` : string | function
  Deprecated. Use `build` instead.


`url` : string
  Indicates the URL of the git repository. If `url` is set, it'll take
  precedence over `[1]`, and Paq will try to infer the name of the repository
  from it. For example, for `url = "https://example.com/path/to/repo-vim.git"`
  it would be `repo-vim`. Otherwise, Paq will try to find the remote
  repository based on `[1]`.

  Default value: `"https://github.com/" .. "<GitHub-username>/<repo-name>"`


------------------------------------------------------------------------------
Package Name Inference~

You might have noticed the local name of the package may depend on three of
the options given above. To reiterate, the precedence order of these options is:

  1. `as`
  2. `url`
  3. `[1]`

`as` has the highest precedence, but it doesn't inform Paq about the origin of
the package, so you always have to use it alongside `[1]` or `url`.
Either `[1]` or `url` may be used on their own; both will set the local name
of the package to the last component in the path of the URL. In practice, this
means you never have to use all three together, and most of the time `[1]`
will be enough.


------------------------------------------------------------------------------
Example~

The language client `coc.nvim` recommends installing the release branch of
their repository. If we also wanted to install it as an optional package,
we could call `paq` like:
>lua
  require("paq") {
    "savq/paq-nvim",
    { "neoclide/coc.nvim", branch = "release", opt = true },
  }
<

==============================================================================
PAQ AUTOCOMMANDS                                            *paq-autocommands*
                                                              *PaqDoneInstall*
                                                               *PaqDoneUpdate*

Paq provides |User| events for its async operations, each event has the name
`PaqDone` followed by the name of an operation:

    `PaqDoneInstall` run after `PaqInstall`
    `PaqDoneUpdate` runs after `PaqUpdate`
    `PaqDoneSync` runs after `PaqSync`

You can define an |autocmd| for these events using the usual syntax:
>vim
    autocmd User PaqDoneInstall <your-commands>
<
This is useful for bootstrapping or calling Paq in headless mode. See the
section on |paq-bootstrapping|.

NOTE: `PaqClean` is currently synchronous so there's no autocommand for it.


==============================================================================
PAQ DIRECTORY                                                        *paq-dir*

Paq installs packages using Neovim's |packages| convention, which itself
follows the XDG Base Directory specification. You can find the default
directory where Paq installs packages by running the command:
>vim
    :echo stdpath('data') .. '/site/pack/paqs'
<

If you have packages that aren't managed by Paq, you shouldn't put them in
Paq's directory, since |paq.clean| could delete them.


==============================================================================
PAQ LOG                                                              *paq-log*

Paq writes the `stderr` output of external processes to a log file.
The log file can be found at:
>vim
    :echo stdpath('cache') .. '/paq.log'
<

==============================================================================
TROUBLESHOOTING                                          *paq-troubleshooting*

Here's a list of steps to take when something goes wrong with Paq:

1. Check Paq's previous messages with |:messages|

2. Check the list of installed and recently removed packages with |:PaqList|.

3. If you see an error message or a package isn't listed as expected, check
  Paq's log with |:PaqLogOpen|. The log records everything written to `stderr`
  so you might want to look from the bottom up.

4. If you think the error wasn't caused by git (or another external program
  called with `build`), consider opening an issue on the paq-nvim GitHub
  repository.

Some common issues are listed below.

------------------------------------------------------------------------------
GitHub Credentials~

Paq clones repositories using HTTPS, which might require you to provide your
GitHub credentials. It's _strongly_ encouraged to set-up your GitHub
credentials before using Paq. Consult the relevant git and GitHub
documentation.


==============================================================================
BOOTSTRAPPING                                              *paq-bootstrapping*

You can use Paq programmatically to install your packages. This is useful if
you want to install packages automatically at startup or in |--headless| mode.

If you want to ensure Paq and your packages are always installed, you can
write a helper function that clones Paq if it's not in your system, and then
installs all your packages. This doesn't require restarting your Neovim
session. For example:
>lua
  -- In ~/.config/nvim/init.lua
  local function clone_paq()
    local path = vim.fn.stdpath("data") .. "/site/pack/paqs/start/paq-nvim"
    local is_installed = vim.fn.empty(vim.fn.glob(path)) == 0
    if not is_installed then
      vim.fn.system { "git", "clone", "--depth=1", "https://github.com/savq/paq-nvim.git", path }
      return true
    end
  end

  local function bootstrap_paq(packages)
    local first_install = clone_paq()
    vim.cmd.packadd("paq-nvim")
    local paq = require("paq")
    if first_install then
      vim.notify("Installing plugins... If prompted, hit Enter to continue.")
    end

    -- Read and install packages
    paq(packages)
    paq.install()
  end

  -- Call helper function
  bootstrap_paq {
    "savq/paq-nvim",
    -- List your packages
  }
<
Alternatively, you could write the same functions in a separate module to run
in headless mode, adding an autocommand that closes `Neovim` when done.
>lua
  -- In ~/.config/nvim/lua/bootstrap.lua

  -- ... write the same function definitions as above ...

  local function headless_paq()
    -- Set to exit nvim after installing plugins
    vim.cmd("autocmd User PaqDoneInstall quit")
    bootstrap_paq {
      "savq/paq-nvim",
      -- List your packages
    }
  end

  return {
    headless_paq = headless_paq,
  }
<

In this case, installing your packages should only require calling the
`headless_paq` function from your shell:
>
  nvim --headless -u NONE -c 'lua require("bootstrap").headless_paq()'
<
You can adjust either script to suit your needs. You might only want to clone
Paq automatically without installing packages, or clone packages only if Paq
is already installed.


==============================================================================
MISCELLANEOUS                                                       *paq-misc*

These are some features related to using packages, which probably don't
require Paq. Either because there's already a way to do it in Neovim, or
because they're out of scope for the project.


------------------------------------------------------------------------------
Using local packages~

You don't need Paq to use local packages. Neovim already provides ways to
load a local plugin, namely:

- Add it to a directory in |packpath| (different from |paq-dir|)
- Modify the |runtimepath| directly

The first option is the easiest, though your plugin can end up pretty deep
in a directory hierarchy.

The second option just requires you to concatenate the path to the plugin to
your `runtimepath`. In Lua, this looks like:
>lua
  vim.opt.runtimepath:append("~/path/to/your/plugin")
<
Remember to use an absolute path.


------------------------------------------------------------------------------
Lazy loading~

Paq doesn't provide a mechanism to lazy load packages. Before considering
if a package needs to be lazy loaded:

1. Be sure to profile your startup time with the |--startuptime| flag.
2. For VimL plugins, check if the package uses the |autoload| feature.
3. For Lua plugins, check if the package is properly modularized in the `lua/`
   directory.

If the package doesn't do 2. or 3. consider opening an issue in that package's
issue tracker rather than Paq's. It'll help users of other package managers
too.

If you've checked all that and still think that the package _has_ to be lazy
loaded, you can declare the package as optional, and call |packadd| when
needed.

Since Neovim version 0.7, you can use an |autocommand| to do the lazy loading.
For example:
>lua
  require("paq") {
    "savq/paq-nvim",
    { "author/heavy-plugin", opt = true },
  }

  vim.api.nvim_create_autocmd("FileType", {
    group = vim.api.nvim_create_augroup("paq-ft-augroup"),
    pattern = "ruby",
    command = "packadd! heavy-plugin",
    desc = "Loads heavy-plugin when filetype is ruby",
  })
<

==============================================================================
 vim:tw=78:ts=8:noet:ft=help:norl:
