folke / lazy.nvim

💤 A modern plugin manager for Neovim
https://lazy.folke.io/
Apache License 2.0
14.32k stars 344 forks source link

bug: plugins are no longer lazy-loadable after v11.13.4 if they require their module in a keys function #1700

Closed benelan closed 2 months ago

benelan commented 2 months ago

Did you check docs and existing issues?

Neovim version (nvim -v)

NVIM v0.10.1 Build type: Release LuaJIT 2.1.1713484068

Operating system/version

Pop_OS! 22.04

Describe the bug

Before v11.13.4 a plugin was lazy loadable when setting keys to a function that requires the plugin's module. Not sure if this is new, expected behavior, but now the plugin is loaded on start.

Steps To Reproduce

  1. Save/open the repro example
  2. Run :Lazy and notice telescope is loaded on start
  3. Optionally uncomment the lazy.nvim plugin spec and repeat step 2. Notice telescope has not loaded.

Expected Behavior

Plugins that require their module in the keys function spec are lazy loadable.

Repro

vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()

require("lazy.minit").repro({
  spec = {
    -- { "folke/lazy.nvim", tag = "v11.13.3" },
    {
      "nvim-telescope/telescope.nvim",
      lazy = true,
      cmd = "Telescope",
      keys = function()
        local has_builtin, builtin = pcall(require, "telescope.builtin")
        return has_builtin and { { "<C-p>", builtin.find_files } } or {}
      end,
    },
  },
})
max397574 commented 2 months ago

actually this is expected because in the keys function you require the telescope module which loads the plugin

I don't know how it's possible that this was different before because one would imagine that the keys function has to be executed at startup to be able to create the mappings to lazyload

the best way to fix this would be to just not do that check for builtin because there it no way how it wouldn't be available if telescope wouldn't be rewritten

benelan commented 2 months ago

Gotcha, thanks for the context. FWIW, that was a reductive example for repro purposes, my real use case is:

    keys = function()
      local has_builtin, builtin = pcall(require, "telescope.builtin")
      if not has_builtin then return {} end

      -- when a count N is given to a telescope mapping called through the following
      -- function, the search is started in the Nth parent directory
      local function telescope_cwd(picker, args)
        builtin[picker](
          vim.tbl_extend("error", args or {}, { cwd = ("../"):rep(vim.v.count) .. "." })
        )
      end

      return {
        {
          "<C-p>",
          function() telescope_cwd("find_files", { hidden = true }) end,
          desc = "Find files (telescope)",
        },
        ...
      }
    },
max397574 commented 2 months ago

well that will still load telescope on startup but I think you could just inline the require"telescope.builtin"