{
  config,
  pkgs,
  lib,
  ...
}: let
  inherit (lib.options) mkEnableOption mkOption;
  inherit (lib.modules) mkIf mkMerge;
  inherit (lib.meta) getExe;
  inherit (lib.lists) isList;
  inherit (lib.types) either listOf package str;
  inherit (lib.nvim.types) mkGrammarOption;
  inherit (lib.nvim.lua) expToLua;
  inherit (lib.nvim.dag) entryBefore;

  cfg = config.vim.languages.lua;
in {
  imports = [
    (lib.mkRemovedOptionModule ["vim" "languages" "lua" "lsp" "neodev"] ''
      neodev has been replaced by lazydev
    '')
  ];

  options.vim.languages.lua = {
    enable = mkEnableOption "Lua language support";
    treesitter = {
      enable = mkEnableOption "Lua Treesitter support" // {default = config.vim.languages.enableTreesitter;};
      package = mkGrammarOption pkgs "lua";
    };

    lsp = {
      enable = mkEnableOption "Lua LSP support via LuaLS" // {default = config.vim.languages.enableLSP;};

      package = mkOption {
        description = "LuaLS package, or the command to run as a list of strings";
        type = either package (listOf str);
        default = pkgs.lua-language-server;
      };

      lazydev.enable = mkEnableOption "lazydev.nvim integration, useful for neovim plugin developers";
    };
  };

  config = mkMerge [
    (mkIf cfg.treesitter.enable {
      vim.treesitter.enable = true;
      vim.treesitter.grammars = [cfg.treesitter.package];
    })

    (mkIf cfg.enable (mkMerge [
      (mkIf cfg.lsp.enable {
        vim.lsp.lspconfig.enable = true;
        vim.lsp.lspconfig.sources.lua-lsp = ''
          lspconfig.lua_ls.setup {
            capabilities = capabilities;
            on_attach = default_on_attach;
            cmd = ${
            if isList cfg.lsp.package
            then expToLua cfg.lsp.package
            else ''{"${getExe cfg.lsp.package}"}''
          };
          }
        '';
      })

      (mkIf cfg.lsp.lazydev.enable {
        vim.startPlugins = ["lazydev-nvim"];
        vim.pluginRC.lazydev = entryBefore ["lua-lsp"] ''
          require("lazydev").setup({
            enabled = function(root_dir)
              return not vim.uv.fs_stat(root_dir .. "/.luarc.json")
            end,
            library = { { path = "''${3rd}/luv/library", words = { "vim%.uv" } } },
          })
        '';
      })
    ]))
  ];
}