Bläddra i källkod

perf: lazy load most plugins (#3750)

* perf: lazy load most plugins

* fix(lazy): suggested fixes for pref/lazyloading branch (#3754)

fix(lazy): Suggested fixes from previous comments

fix(lazy): applying suggestions from code review

Co-authored-by: LostNeophyte <lostneophyte@tuta.io>

Co-authored-by: Pratyush Bharati <pbharati@Pratyushs-MacBook-Pro.local>
Co-authored-by: LostNeophyte <lostneophyte@tuta.io>

* chore: format

* move lazy utils to modules.lua

* simplify telescope actions

* refactor: cmp_window local name

* feat: more lazy loading cmds

* refactor(cmp): minor clean up

* perf: set lazy loading by default

* refactor(alpha): remove broken lazy load

* revert: explictily set lazy loading

This reverts commit ba38193e4ebfa5acc8afa2b35247c5420d9a2739.

* test: enable lazy-loading for bigfile

* perf: defer projects and alpha to VimEnter

* refactor(bufferline): add comment

* perf: better lazy load dap/dapui

* perf: lazy load ts-commentstring with Comment.nvim pre_hook

---------

Co-authored-by: pr-313 <46706232+pr-313@users.noreply.github.com>
Co-authored-by: Pratyush Bharati <pbharati@Pratyushs-MacBook-Pro.local>
Co-authored-by: opalmay <opal.mizrahi2@gmail.com>
Co-authored-by: kylo252 <59826753+kylo252@users.noreply.github.com>
LostNeophyte 2 år sedan
förälder
incheckning
60c7ad77fd

+ 0 - 2
init.lua

@@ -23,5 +23,3 @@ Log:debug "Starting LunarVim"
 
 local commands = require "lvim.core.commands"
 commands.load(commands.defaults)
-
-require("lvim.lsp").setup()

+ 0 - 1
lua/lvim/config/settings.lua

@@ -26,7 +26,6 @@ M.load_default_options = function()
     mouse = "a", -- allow the mouse to be used in neovim
     pumheight = 10, -- pop up menu height
     showmode = false, -- we don't need to see things like -- INSERT -- anymore
-    showtabline = 2, -- always show tabs
     smartcase = true, -- smart case
     splitbelow = true, -- force all horizontal splits to go below current window
     splitright = true, -- force all vertical splits to go to the right of current window

+ 29 - 0
lua/lvim/core/autocmds.lua

@@ -119,6 +119,35 @@ function M.load_defaults()
         end,
       },
     },
+    { -- taken from AstroNvim
+      "BufEnter",
+      {
+        group = "_dir_opened",
+        once = true,
+        callback = function(args)
+          local bufname = vim.api.nvim_buf_get_name(args.buf)
+          if require("lvim.utils").is_directory(bufname) then
+            vim.api.nvim_del_augroup_by_name "_dir_opened"
+            vim.cmd "do User DirOpened"
+            vim.api.nvim_exec_autocmds("BufEnter", {})
+          end
+        end,
+      },
+    },
+    { -- taken from AstroNvim
+      { "BufRead", "BufWinEnter", "BufNewFile" },
+      {
+        group = "_file_opened",
+        once = true,
+        callback = function(args)
+          local buftype = vim.api.nvim_get_option_value("buftype", { buf = args.buf })
+          if not (vim.fn.expand "%" == "" or buftype == "nofile") then
+            vim.cmd "do User FileOpened"
+            require("lvim.lsp").setup()
+          end
+        end,
+      },
+    },
   }
 
   M.define_autocmds(definitions)

+ 3 - 0
lua/lvim/core/bufferline.lua

@@ -152,6 +152,9 @@ M.setup = function()
     return
   end
 
+  -- can't be set in settings.lua because default tabline would flash before bufferline is loaded
+  vim.opt.showtabline = 2
+
   bufferline.setup {
     options = lvim.builtin.bufferline.options,
     highlights = lvim.builtin.bufferline.highlights,

+ 29 - 26
lua/lvim/core/cmp.lua

@@ -118,14 +118,17 @@ end
 M.methods.jumpable = jumpable
 
 M.config = function()
-  local status_cmp_ok, cmp = pcall(require, "cmp")
+  local status_cmp_ok, cmp_types = pcall(require, "cmp.types.cmp")
   if not status_cmp_ok then
     return
   end
-  local status_luasnip_ok, luasnip = pcall(require, "luasnip")
-  if not status_luasnip_ok then
-    return
-  end
+  local ConfirmBehavior = cmp_types.ConfirmBehavior
+  local SelectBehavior = cmp_types.SelectBehavior
+
+  local cmp = require("lvim.utils.modules").require_on_index "cmp"
+  local luasnip = require("lvim.utils.modules").require_on_index "luasnip"
+  local cmp_window = require "cmp.config.window"
+  local cmp_mapping = require "cmp.config.mapping"
 
   lvim.builtin.cmp = {
     active = true,
@@ -138,7 +141,7 @@ M.config = function()
       return lvim.builtin.cmp.active
     end,
     confirm_opts = {
-      behavior = cmp.ConfirmBehavior.Replace,
+      behavior = ConfirmBehavior.Replace,
       select = false,
     },
     completion = {
@@ -214,12 +217,12 @@ M.config = function()
     },
     snippet = {
       expand = function(args)
-        require("luasnip").lsp_expand(args.body)
+        luasnip.lsp_expand(args.body)
       end,
     },
     window = {
-      completion = cmp.config.window.bordered(),
-      documentation = cmp.config.window.bordered(),
+      completion = cmp_window.bordered(),
+      documentation = cmp_window.bordered(),
     },
     sources = {
       {
@@ -255,7 +258,7 @@ M.config = function()
       {
         name = "nvim_lsp",
         entry_filter = function(entry, ctx)
-          local kind = require("cmp.types").lsp.CompletionItemKind[entry:get_kind()]
+          local kind = require("cmp.types.lsp").CompletionItemKind[entry:get_kind()]
           if kind == "Snippet" and ctx.prev_context.filetype == "java" then
             return false
           end
@@ -277,24 +280,24 @@ M.config = function()
       { name = "crates" },
       { name = "tmux" },
     },
-    mapping = cmp.mapping.preset.insert {
-      ["<C-k>"] = cmp.mapping(cmp.mapping.select_prev_item(), { "i", "c" }),
-      ["<C-j>"] = cmp.mapping(cmp.mapping.select_next_item(), { "i", "c" }),
-      ["<Down>"] = cmp.mapping(cmp.mapping.select_next_item { behavior = cmp.SelectBehavior.Select }, { "i" }),
-      ["<Up>"] = cmp.mapping(cmp.mapping.select_prev_item { behavior = cmp.SelectBehavior.Select }, { "i" }),
-      ["<C-d>"] = cmp.mapping.scroll_docs(-4),
-      ["<C-f>"] = cmp.mapping.scroll_docs(4),
-      ["<C-y>"] = cmp.mapping {
-        i = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = false },
+    mapping = cmp_mapping.preset.insert {
+      ["<C-k>"] = cmp_mapping(cmp_mapping.select_prev_item(), { "i", "c" }),
+      ["<C-j>"] = cmp_mapping(cmp_mapping.select_next_item(), { "i", "c" }),
+      ["<Down>"] = cmp_mapping(cmp_mapping.select_next_item { behavior = SelectBehavior.Select }, { "i" }),
+      ["<Up>"] = cmp_mapping(cmp_mapping.select_prev_item { behavior = SelectBehavior.Select }, { "i" }),
+      ["<C-d>"] = cmp_mapping.scroll_docs(-4),
+      ["<C-f>"] = cmp_mapping.scroll_docs(4),
+      ["<C-y>"] = cmp_mapping {
+        i = cmp_mapping.confirm { behavior = ConfirmBehavior.Replace, select = false },
         c = function(fallback)
           if cmp.visible() then
-            cmp.confirm { behavior = cmp.ConfirmBehavior.Replace, select = false }
+            cmp.confirm { behavior = ConfirmBehavior.Replace, select = false }
           else
             fallback()
           end
         end,
       },
-      ["<Tab>"] = cmp.mapping(function(fallback)
+      ["<Tab>"] = cmp_mapping(function(fallback)
         if cmp.visible() then
           cmp.select_next_item()
         elseif luasnip.expand_or_locally_jumpable() then
@@ -308,7 +311,7 @@ M.config = function()
           fallback()
         end
       end, { "i", "s" }),
-      ["<S-Tab>"] = cmp.mapping(function(fallback)
+      ["<S-Tab>"] = cmp_mapping(function(fallback)
         if cmp.visible() then
           cmp.select_prev_item()
         elseif luasnip.jumpable(-1) then
@@ -317,16 +320,16 @@ M.config = function()
           fallback()
         end
       end, { "i", "s" }),
-      ["<C-Space>"] = cmp.mapping.complete(),
-      ["<C-e>"] = cmp.mapping.abort(),
-      ["<CR>"] = cmp.mapping(function(fallback)
+      ["<C-Space>"] = cmp_mapping.complete(),
+      ["<C-e>"] = cmp_mapping.abort(),
+      ["<CR>"] = cmp_mapping(function(fallback)
         if cmp.visible() then
           local confirm_opts = vim.deepcopy(lvim.builtin.cmp.confirm_opts) -- avoid mutating the original opts below
           local is_insert_mode = function()
             return vim.api.nvim_get_mode().mode:sub(1, 1) == "i"
           end
           if is_insert_mode() then -- prevent overwriting brackets
-            confirm_opts.behavior = cmp.ConfirmBehavior.Insert
+            confirm_opts.behavior = ConfirmBehavior.Insert
           end
           if cmp.confirm(confirm_opts) then
             return -- success, exit early

+ 6 - 6
lua/lvim/core/comment.lua

@@ -1,11 +1,6 @@
 local M = {}
 
 function M.config()
-  local pre_hook
-  local loaded, ts_comment = pcall(require, "ts_context_commentstring.integrations.comment_nvim")
-  if loaded and ts_comment then
-    pre_hook = ts_comment.create_pre_hook()
-  end
   lvim.builtin.comment = {
     active = true,
     on_config_done = nil,
@@ -66,7 +61,12 @@ function M.config()
 
     ---Pre-hook, called before commenting the line
     ---@type function|nil
-    pre_hook = pre_hook,
+    pre_hook = function(...)
+      local loaded, ts_comment = pcall(require, "ts_context_commentstring.integrations.comment_nvim")
+      if loaded and ts_comment then
+        return ts_comment.create_pre_hook()(...)
+      end
+    end,
 
     ---Post-hook, called after commenting is done
     ---@type function|nil

+ 7 - 14
lua/lvim/core/lir.lua

@@ -1,22 +1,14 @@
 local M = {}
 
 M.config = function()
+  local utils = require "lvim.utils.modules"
+  local actions = utils.require_on_exported_call "lir.actions"
+  local clipboard_actions = utils.require_on_exported_call "lir.clipboard.actions"
+
   lvim.builtin.lir = {
     active = true,
     on_config_done = nil,
     icon = "",
-  }
-
-  local status_ok, _ = pcall(require, "lir")
-  if not status_ok then
-    return
-  end
-
-  local actions = require "lir.actions"
-  local mark_actions = require "lir.mark.actions"
-  local clipboard_actions = require "lir.clipboard.actions"
-
-  lvim.builtin.lir = vim.tbl_extend("force", lvim.builtin.lir, {
     show_hidden_files = false,
     ignore = {}, -- { ".DS_Store" "node_modules" } etc.
     devicons = {
@@ -42,7 +34,7 @@ M.config = function()
       ["d"] = actions.delete,
 
       ["J"] = function()
-        mark_actions.toggle_mark()
+        require("lir.mark.actions").toggle_mark()
         vim.cmd "normal! j"
       end,
       ["c"] = clipboard_actions.copy,
@@ -79,7 +71,7 @@ M.config = function()
         { noremap = true, silent = true }
       )
     end,
-  })
+  }
 end
 
 function M.icon_setup()
@@ -118,6 +110,7 @@ function M.setup()
   end
 
   lir.setup(lvim.builtin.lir)
+  M.icon_setup()
 
   if lvim.builtin.lir.on_config_done then
     lvim.builtin.lir.on_config_done(lir)

+ 9 - 13
lua/lvim/core/telescope.lua

@@ -7,21 +7,11 @@ local M = {}
 ---| "center"   # retain the default telescope theme
 
 function M.config()
-  -- Define this minimal config so that it's available if telescope is not yet available.
-
+  local actions = require("lvim.utils.modules").require_on_exported_call "telescope.actions"
   lvim.builtin.telescope = {
     ---@usage disable telescope completely [not recommended]
     active = true,
     on_config_done = nil,
-  }
-
-  local ok, actions = pcall(require, "telescope.actions")
-  if not ok then
-    return
-  end
-  lvim.builtin.telescope = {
-    active = true,
-    on_config_done = nil,
     theme = "dropdown", ---@type telescope_themes
     defaults = {
       prompt_prefix = lvim.icons.ui.Telescope .. " ",
@@ -51,13 +41,19 @@ function M.config()
           ["<C-c>"] = actions.close,
           ["<C-j>"] = actions.cycle_history_next,
           ["<C-k>"] = actions.cycle_history_prev,
-          ["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
+          ["<C-q>"] = function(...)
+            actions.smart_send_to_qflist(...)
+            actions.open_qflist(...)
+          end,
           ["<CR>"] = actions.select_default,
         },
         n = {
           ["<C-n>"] = actions.move_selection_next,
           ["<C-p>"] = actions.move_selection_previous,
-          ["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
+          ["<C-q>"] = function(...)
+            actions.smart_send_to_qflist(...)
+            actions.open_qflist(...)
+          end,
         },
       },
       file_ignore_patterns = {},

+ 6 - 2
lua/lvim/core/theme.lua

@@ -85,8 +85,12 @@ M.setup = function()
   vim.g.colors_name = lvim.colorscheme
   vim.cmd("colorscheme " .. lvim.colorscheme)
 
-  require("lvim.core.lualine").setup()
-  require("lvim.core.lir").icon_setup()
+  if package.loaded.lualine then
+    require("lvim.core.lualine").setup()
+  end
+  if package.loaded.lir then
+    require("lvim.core.lir").icon_setup()
+  end
 end
 
 return M

+ 6 - 6
lua/lvim/core/which-key.lua

@@ -205,20 +205,20 @@ M.config = function()
         a = { "<cmd>lua vim.lsp.buf.code_action()<cr>", "Code Action" },
         d = { "<cmd>Telescope diagnostics bufnr=0 theme=get_ivy<cr>", "Buffer Diagnostics" },
         w = { "<cmd>Telescope diagnostics<cr>", "Diagnostics" },
-        f = { require("lvim.lsp.utils").format, "Format" },
+        f = { "<cmd>lua require('lvim.lsp.utils').format()<cr>", "Format" },
         i = { "<cmd>LspInfo<cr>", "Info" },
         I = { "<cmd>Mason<cr>", "Mason Info" },
         j = {
-          vim.diagnostic.goto_next,
+          "<cmd>lua vim.diagnostic.goto_next()<cr>",
           "Next Diagnostic",
         },
         k = {
-          vim.diagnostic.goto_prev,
+          "<cmd>lua vim.diagnostic.goto_prev()<cr>",
           "Prev Diagnostic",
         },
-        l = { vim.lsp.codelens.run, "CodeLens Action" },
-        q = { vim.diagnostic.setloclist, "Quickfix" },
-        r = { vim.lsp.buf.rename, "Rename" },
+        l = { "<cmd>lua vim.lsp.codelens.run()<cr>", "CodeLens Action" },
+        q = { "<cmd>lua vim.diagnostic.setloclist()<cr>", "Quickfix" },
+        r = { "<cmd>lua vim.lsp.buf.rename()<cr>", "Rename" },
         s = { "<cmd>Telescope lsp_document_symbols<cr>", "Document Symbols" },
         S = {
           "<cmd>Telescope lsp_dynamic_workspace_symbols<cr>",

+ 6 - 6
lua/lvim/lsp/config.lua

@@ -96,12 +96,12 @@ return {
   },
   buffer_mappings = {
     normal_mode = {
-      ["K"] = { vim.lsp.buf.hover, "Show hover" },
-      ["gd"] = { vim.lsp.buf.definition, "Goto Definition" },
-      ["gD"] = { vim.lsp.buf.declaration, "Goto declaration" },
-      ["gr"] = { vim.lsp.buf.references, "Goto references" },
-      ["gI"] = { vim.lsp.buf.implementation, "Goto Implementation" },
-      ["gs"] = { vim.lsp.buf.signature_help, "show signature help" },
+      ["K"] = { "<cmd>lua vim.lsp.buf.hover()<cr>", "Show hover" },
+      ["gd"] = { "<cmd>lua vim.lsp.buf.definition()<cr>", "Goto Definition" },
+      ["gD"] = { "<cmd>lua vim.lsp.buf.declaration()<cr>", "Goto declaration" },
+      ["gr"] = { "<cmd>lua vim.lsp.buf.references()<cr>", "Goto references" },
+      ["gI"] = { "<cmd>lua vim.lsp.buf.implementation()<cr>", "Goto Implementation" },
+      ["gs"] = { "<cmd>lua vim.lsp.buf.signature_help()<cr>", "show signature help" },
       ["gl"] = {
         function()
           local config = lvim.lsp.diagnostics.float

+ 8 - 0
lua/lvim/plugin-loader.lua

@@ -39,6 +39,10 @@ function plugin_loader.init(opts)
         snapshot["lazy.nvim"].commit,
       }
     end
+
+    vim.schedule(function()
+      require("lvim.lsp").setup()
+    end)
   end
 
   vim.opt.runtimepath:append(lazy_install_dir)
@@ -118,6 +122,10 @@ function plugin_loader.load(configurations)
           reset = false,
         },
       },
+      defaults = {
+        lazy = false,
+        version = nil,
+      },
       readme = {
         root = join_paths(get_runtime_dir(), "lazy", "readme"),
       },

+ 39 - 13
lua/lvim/plugins.lua

@@ -6,25 +6,34 @@ local core_plugins = {
     lazy = true,
     dependencies = { "mason-lspconfig.nvim", "nlsp-settings.nvim" },
   },
-  { "williamboman/mason-lspconfig.nvim", lazy = true },
-  { "tamago324/nlsp-settings.nvim", lazy = true },
+  {
+    "williamboman/mason-lspconfig.nvim",
+    cmd = { "LspInstall", "LspUninstall" },
+    lazy = true,
+    dependencies = "mason.nvim",
+  },
+  { "tamago324/nlsp-settings.nvim", cmd = "LspSettings", lazy = true },
   { "jose-elias-alvarez/null-ls.nvim", lazy = true },
   {
     "williamboman/mason.nvim",
     config = function()
       require("lvim.core.mason").setup()
     end,
+    cmd = { "Mason", "MasonInstall", "MasonUninstall", "MasonUninstallAll", "MasonLog" },
+    lazy = true,
   },
   {
     "folke/tokyonight.nvim",
+    lazy = not vim.startswith(lvim.colorscheme, "tokyonight"),
   },
   {
     "lunarvim/lunar.nvim",
+    lazy = lvim.colorscheme ~= "lunar",
   },
-  { "Tastyep/structlog.nvim" },
+  { "Tastyep/structlog.nvim", lazy = true },
 
-  { "nvim-lua/popup.nvim" },
-  { "nvim-lua/plenary.nvim" },
+  { "nvim-lua/popup.nvim", lazy = true },
+  { "nvim-lua/plenary.nvim", cmd = { "PlenaryBustedFile", "PlenaryBustedDirectory" }, lazy = true },
   -- Telescope
   {
     "nvim-telescope/telescope.nvim",
@@ -113,21 +122,24 @@ local core_plugins = {
       vim.opt.rtp:prepend(path) -- treesitter needs to be before nvim's runtime in rtp
       require("lvim.core.treesitter").setup()
     end,
+    cmd = { "TSInstall", "TSUninstall", "TSUpdate", "TSInstallInfo", "TSInstallSync", "TSInstallFromGrammar" },
+    event = "User FileOpened",
   },
   {
+    -- Lazy loaded by Comment.nvim pre_hook
     "JoosepAlviste/nvim-ts-context-commentstring",
-    event = "VeryLazy",
+    lazy = true,
   },
 
   -- NvimTree
   {
     "kyazdani42/nvim-tree.lua",
-    -- event = "BufWinOpen",
-    -- cmd = "NvimTreeToggle",
     config = function()
       require("lvim.core.nvimtree").setup()
     end,
     enabled = lvim.builtin.nvimtree.active,
+    cmd = { "NvimTreeToggle", "NvimTreeOpen", "NvimTreeFocus", "NvimTreeFindFileToggle" },
+    event = "User DirOpened",
   },
   -- Lir
   {
@@ -136,13 +148,15 @@ local core_plugins = {
       require("lvim.core.lir").setup()
     end,
     enabled = lvim.builtin.lir.active,
+    event = "User DirOpened",
   },
   {
     "lewis6991/gitsigns.nvim",
     config = function()
       require("lvim.core.gitsigns").setup()
     end,
-    event = "BufRead",
+    event = "User FileOpened",
+    cmd = "Gitsigns",
     enabled = lvim.builtin.gitsigns.active,
   },
 
@@ -152,6 +166,7 @@ local core_plugins = {
     config = function()
       require("lvim.core.which-key").setup()
     end,
+    cmd = "WhichKey",
     event = "VeryLazy",
     enabled = lvim.builtin.which_key.active,
   },
@@ -159,10 +174,11 @@ local core_plugins = {
   -- Comments
   {
     "numToStr/Comment.nvim",
-    event = "BufRead",
     config = function()
       require("lvim.core.comment").setup()
     end,
+    keys = { { "gc", mode = { "n", "v" } }, { "gb", mode = { "n", "v" } } },
+    event = "User FileOpened",
     enabled = lvim.builtin.comment.active,
   },
 
@@ -173,12 +189,15 @@ local core_plugins = {
       require("lvim.core.project").setup()
     end,
     enabled = lvim.builtin.project.active,
+    event = "VimEnter",
+    cmd = "Telescope projects",
   },
 
   -- Icons
   {
     "nvim-tree/nvim-web-devicons",
     enabled = lvim.use_icons,
+    lazy = true,
   },
 
   -- Status Line and Bufferline
@@ -189,6 +208,7 @@ local core_plugins = {
     config = function()
       require("lvim.core.lualine").setup()
     end,
+    event = "VimEnter",
     enabled = lvim.builtin.lualine.active,
   },
 
@@ -198,6 +218,7 @@ local core_plugins = {
     config = function()
       require("lvim.core.breadcrumbs").setup()
     end,
+    event = "User FileOpened",
     enabled = lvim.builtin.breadcrumbs.active,
   },
 
@@ -207,16 +228,17 @@ local core_plugins = {
       require("lvim.core.bufferline").setup()
     end,
     branch = "main",
+    event = "User FileOpened",
     enabled = lvim.builtin.bufferline.active,
   },
 
   -- Debugging
   {
     "mfussenegger/nvim-dap",
-    -- event = "BufWinEnter",
     config = function()
       require("lvim.core.dap").setup()
     end,
+    lazy = true,
     enabled = lvim.builtin.dap.active,
   },
 
@@ -226,6 +248,7 @@ local core_plugins = {
     config = function()
       require("lvim.core.dap").setup_ui()
     end,
+    lazy = true,
     enabled = lvim.builtin.dap.active,
   },
 
@@ -236,6 +259,7 @@ local core_plugins = {
       require("lvim.core.alpha").setup()
     end,
     enabled = lvim.builtin.alpha.active,
+    event = "VimEnter",
   },
 
   -- Terminal
@@ -260,7 +284,7 @@ local core_plugins = {
     config = function()
       require("lvim.core.illuminate").setup()
     end,
-    event = "VeryLazy",
+    event = "User FileOpened",
     enabled = lvim.builtin.illuminate.active,
   },
 
@@ -269,6 +293,7 @@ local core_plugins = {
     config = function()
       require("lvim.core.indentlines").setup()
     end,
+    event = "User FileOpened",
     enabled = lvim.builtin.indentlines.active,
   },
 
@@ -283,7 +308,7 @@ local core_plugins = {
         end
       end)
     end,
-    enabled = lvim.colorscheme == "onedarker",
+    lazy = lvim.colorscheme ~= "onedarker",
   },
 
   {
@@ -294,6 +319,7 @@ local core_plugins = {
       end)
     end,
     enabled = lvim.builtin.bigfile.active,
+    event = { "FileReadPre", "BufReadPre", "User FileOpened" },
   },
 }
 

+ 24 - 0
lua/lvim/utils/modules.lua

@@ -95,4 +95,28 @@ M.reload = function(mod)
   return old
 end
 
+-- code from <https://github.com/tjdevries/lazy-require.nvim/blob/bb626818ebc175b8c595846925fd96902b1ce02b/lua/lazy-require.lua#L25>
+function M.require_on_index(require_path)
+  return setmetatable({}, {
+    __index = function(_, key)
+      return require(require_path)[key]
+    end,
+
+    __newindex = function(_, key, value)
+      require(require_path)[key] = value
+    end,
+  })
+end
+
+-- code from <https://github.com/tjdevries/lazy-require.nvim/blob/bb626818ebc175b8c595846925fd96902b1ce02b/lua/lazy-require.lua#L25>
+function M.require_on_exported_call(require_path)
+  return setmetatable({}, {
+    __index = function(_, k)
+      return function(...)
+        return require(require_path)[k](...)
+      end
+    end,
+  })
+end
+
 return M