Skip to content

A collection of utilities and handlers for BirdeeHub/lze

License

Notifications You must be signed in to change notification settings

BirdeeHub/lzextras

Repository files navigation

lzextras

This repository contains extensions for lze

See there for more info on how to use the things here.

This repository contains some custom handlers you may register, and some utilities you can use to make your life easier, (or harder but more exciting, in the case of the merge handler)

Downloading

via paq-nvim:

require "paq" {
    { "BirdeeHub/lzextras" }
}
Nix examples
  • Home Manager:
programs.neovim = {
  enable = true;
  plugins = with pkgs.vimPlugins [
    {
      plugin = lze;
      config = /*lua*/''
        -- optional, add extra handlers
        require("lze").register_handlers(require("lzextras").lsp)
      '';
      type = "lua";
    }
    lzextras
  ];
};
  • Not on nixpkgs-unstable?

If your neovim is not on the nixpkgs-unstable channel, vimPlugins.lzextras may not yet be in nixpkgs for you. You may instead get it from this flake!

# in your flake inputs:
inputs = {
  lzextras.url = "github:BirdeeHub/lzextras";
};

Then, pass your config your inputs from your flake, and retrieve lzextras with:

inputs.lzextras.packages.${pkgs.system}.default`:

LSP handler

In the lsp field you can declare:

  • A function to run for all LSP specs, that receives the plugin object, (mostly for lspconfig)

OR

  • A table of LSP settings for the LSP implementations. It makes sure the above function type specs load first, and the function type spec will run for all table type LSP specs

It auto populates file types from lspconfig if you don't include any under plugin.lsp.filetypes

It will make sure all specs with functions load before the specs with tables.

  • Example useage:
require('lze').register_handlers(require('lzextras').lsp)
require('lze').load {
  {
    "nvim-lspconfig",
    -- the on require handler will be needed if you want to use the
    -- fallback method of getting filetypes if you don't provide any
    on_require = { "lspconfig" },
    -- define a function to run over all type(plugin.lsp) == table
    -- when their filetype trigger loads them
    lsp = function(plugin)
      require('lspconfig')[plugin.name].setup(vim.tbl_extend("force",{
        capabilities = GET_YOUR_SERVER_CAPABILITIES(plugin.name),
        on_attach = YOUR_ON_ATTACH,
      }, plugin.lsp or {}))
    end,
  },
  {
    "mason.nvim",
    -- dep_of handler ensures we have mason-lspconfig set up before nvim-lspconfig
    dep_of = { "nvim-lspconfig" },
    load = function(name)
      vim.cmd.packadd(name)
      vim.cmd.packadd("mason-lspconfig.nvim")
      require('mason').setup()
      -- auto install will make it install servers when lspconfig is called on them.
      require('mason-lspconfig').setup { automatic_installation = true, }
    end,
  },
  {
    "lua_ls",
    lsp = {
      -- if you include a filetype, it doesnt call lspconfig for the list of filetypes (faster)
      filetypes = { 'lua' },
      settings = {
        Lua = {
          runtime = { version = 'LuaJIT' },
          formatters = {
            ignoreComments = true,
          },
          signatureHelp = { enabled = true },
          diagnostics = {
            globals = { "vim", },
            disable = { 'missing-fields' },
          },
          workspace = {
            checkThirdParty = false,
            library = {
              -- '${3rd}/luv/library',
              -- unpack(vim.api.nvim_get_runtime_file('', true)),
            },
          },
          completion = {
            callSnippet = 'Replace',
          },
          telemetry = { enabled = false },
        },
      },
    },
  },
  {
    "bashls",
    -- can fall back to using lspconfig to find filetypes
    -- as long as it can be required
    lsp = { },
  },
  {
    "pylsp",
    lsp = {
      -- these lsp "specs" are ran by that function above in the nvim-lspconfig spec
      -- only the filetype trigger is handled by the handler.
      filetypes = { "python" },
      settings = {
        pylsp = {
          plugins = {
            -- formatter options
            black = { enabled = false },
            autopep8 = { enabled = false },
            yapf = { enabled = false },
            -- linter options
            pylint = { enabled = true, executable = "pylint" },
            pyflakes = { enabled = false },
            pycodestyle = { enabled = false },
            -- type checker
            pylsp_mypy = { enabled = true },
            -- auto-completion options
            jedi_completion = { fuzzy = true },
            -- import sorting
            pyls_isort = { enabled = true },
          },
        },
      },
    },
  },
}

The default fallback for getting filetypes calls lspconfig for the list of filetypes, but you can change it.

You can get the current fallback function for getting filetypes using:

  ---@type fun():(fun(name: string):string[])
  require('lze').h.lsp.get_ft_fallback()

and you may set the fallback function for getting filetypes using:

  ---@type fun(f: fun(name: string):string[])
  require('lze').h.lsp.set_ft_fallback(your_new_function)

In addition, you may provide a function instead of a list to lsp.filetypes and it will be the fallback function for that lsp only

key2spec

converts the normal vim.keymap.set syntax into an item to put in the list of keys in a lze spec

require("lze").load {
    name = plugin_name,
    keys = {
        require("lzextras").key2spec(mode, lhs, rhs, opts),
    },
}

keymap

Allows you to add keymap triggers to plugins from outside of their specs, after the spec has been added to lze. Useful for if you have a lot of keymaps that involve plugins but you don't want to rewrite them all.

local keymap = require("lzextras").keymap {
    name = plugin_name,
    lazy = true,
}

-- The normal keymap.set syntax
keymap.set("n", "<leader>l", function()end, { desc = "Lazy" })

-- OR

-- if the spec has already been loaded into state
require("lze").load {
    name = plugin_name,
    lazy = true,
}

local keymap = require("lzextras").keymap(plugin_name)

-- The normal keymap.set syntax
keymap.set("n", "<leader>l", function()end, { desc = "Lazy" })

make_load_with_afters

This is primarily useful for lazily loading nvim-cmp sources, as they often rely on the after directory to work

vim.cmd.packadd(plugin_name) does not load the after directory of plugins but we can replace the load function used by our specs!

You could also use rtp.nvim instead of this function.

This function receives the names of directories from a plugin's after directory that you wish to source files from.

Will return load function that can take a name, or list of names, and will load a plugin and its after directories. The function returned is a suitable substitute for the load field of a plugin spec.

e.g. in the following example: load_with_after_plugin will load the plugin names it is given, along with their after/plugin and after/ftplugin directories.

local load_with_after_plugin = require('lzextras').make_load_with_afters({ 'plugin', 'ftplugin', })
require("lze").load {
    name = plugin_name,
    lazy = true,
    load = load_with_after_plugin,
}
require("lze").trigger_load(plugin_name)
  • signature:

It is a function that returns a customized load function.

---@overload fun(dirs: string[]|string): fun(names: string|string[])
---It also optionally recieves a function that should load a plugin and return its path
---for if the plugin is not on the packpath, or return nil
---to load from the packpath as normal
---@overload fun(dirs: string[]|string, load: fun(name: string):string|nil): fun(names: string|string[])

--- dirs can also be a function that takes the path to the after directory and name of the plugin and returns a list of files to load.
---@overload fun(dirs: fun(afterpath: string, name: string):string[]): fun(names: string|string[])
---@overload fun(dirs: fun(afterpath: string, name: string):string[], load: fun(name: string):string|nil): fun(names: string|string[])

Note

If you use nixCats, you should provide the following load function as the second argument for better performance because nixCats provides us information that allows us to avoid searching the whole packpath

local function faster_get_path(name)
  local path = vim.tbl_get(package.loaded, "nixCats", "pawsible", "allPlugins", "opt", name)
  if path then
    vim.cmd.packadd(name)
    return path
  end
  return nil -- nil will make it default to normal behavior
end
local load_with_after_plugin = require('lzextras').make_load_with_afters({ 'plugin' }, faster_get_path)

merge

require("lze").register_handlers(require("lzextras").merge)

Warning

must be registered before all other handlers with a modify hook such as the lsp handler

collects and merges all plugins added with truthy plugin.merge until triggered to load it into lze's state

can be triggered for a single plugin by explicitly passing merge = false for a plugin, or by calling require("lze").h.merge.trigger():

require("lze").load {
  "merge_target",
  merge = false,
}
-- OR
require("lze").h.merge.trigger()

In other words, doing the following would not queue it to be triggered yet, but rather cause the merge handler to collect and merge them.

require("lze").load({
  {
    "merge_target",
    merge = true,
    dep_of = { "lspconfig" },
    lsp = { filetypes = {} },
  },
  {
    "merge_target",
    merge = true,
    dep_of = { "not_lspconfig" },
    lsp = { settings = {} },
  },
})

Then, to enter the merged plugin into lze, you may either use require("lze").h.merge.trigger() to finalize all plugins currently collected by the merge handler, or you may finalize them individually by passing a spec with merge = false explicitly like so:

require("lze").load({
  {
    "merge_target",
    merge = false,
  }
})

the resulting plugin merge_target from these examples entered into state will be:

{
  name = "merge_target",
  dep_of = { "not_lspconfig" },
  lsp = {
    settings = {},
    filetypes = {},
  },
}

If you enter a plugin with no merge field into lze that shares the name of one currently held in the merge handler, it will refuse the duplicate plugin when you trigger the merge handler to add it to lze.

So be sure to know which plugins you allow to be merged and which ones you do not!

About

A collection of utilities and handlers for BirdeeHub/lze

Resources

License

Stars

Watchers

Forks

Packages

No packages published