return {
  {
    "neovim/nvim-lspconfig",
    dependencies = {
      "williamboman/mason.nvim",
      "williamboman/mason-lspconfig.nvim",
      "hrsh7th/cmp-nvim-lsp",
      "hrsh7th/cmp-buffer",
      "hrsh7th/cmp-path",
      "hrsh7th/cmp-cmdline",
      "hrsh7th/nvim-cmp",
      "L3MON4D3/LuaSnip",
      "saadparwaiz1/cmp_luasnip",
      "nvim-telescope/telescope-ui-select.nvim",
      "nvimtools/none-ls.nvim",
      "nvimdev/lspsaga.nvim",
      'nvim-treesitter/nvim-treesitter',
      'nvim-tree/nvim-web-devicons',
      "jay-babu/mason-null-ls.nvim",
    },
    config = function()
      -- autocomplete --

      local kind_icons = {
        Text = "",
        Method = "󰆧",
        Function = "󰊕",
        Constructor = "",
        Field = "󰇽",
        Variable = "󰂡",
        Class = "󰠱",
        Interface = "",
        Module = "",
        Property = "󰜢",
        Unit = "",
        Value = "󰎠",
        Enum = "",
        Keyword = "󰌋",
        Snippet = "",
        Color = "󰏘",
        File = "󰈙",
        Reference = "",
        Folder = "󰉋",
        EnumMember = "",
        Constant = "󰏿",
        Struct = "",
        Event = "",
        Operator = "󰆕",
        TypeParameter = "󰅲"
      }

      local has_words_before = function()
        unpack = unpack or table.unpack
        local line, col = unpack(vim.api.nvim_win_get_cursor(0))
        return col ~= 0 and
            vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
      end

      local luasnip = require("luasnip")
      local cmp = require("cmp")
      cmp.setup({
        formatting = {
          format = function(entry, vim_item)
            -- Kind icons
            vim_item.kind = string.format('%s %s', kind_icons[vim_item.kind], vim_item.kind) -- This concatonates the icons with the name of the item kind
            -- Source
            vim_item.menu = ({
              buffer = "",
              nvim_lsp = "",
              luasnip = "",
              nvim_lua = "",
              latex_symbols = "",
            })[entry.source.name]
            return vim_item
          end
        },
        snippet = {
          expand = function(args)
            require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
          end,
        },
        window = {
          completion = cmp.config.window.bordered(),
          documentation = cmp.config.window.bordered(),
        },
        mapping = cmp.mapping.preset.insert({
          ['<C-b>'] = cmp.mapping.scroll_docs(-4),
          ['<C-f>'] = cmp.mapping.scroll_docs(4),
          ['<C-e>'] = cmp.mapping(function(fallback)
            if cmp.visible() then
              cmp.abort()
            else
              cmp.complete()
            end
          end),
          ['<CR>'] = cmp.mapping.confirm({ select = false }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
          ["<Tab>"] = cmp.mapping(function(fallback)
            if cmp.visible() then
              cmp.select_next_item()
              -- You could replace the expand_or_jumpable() calls with expand_or_locally_jumpable()
              -- they way you will only jump inside the snippet region
            elseif luasnip.expand_or_jumpable() then
              luasnip.expand_or_jump()
            elseif has_words_before() then
              cmp.complete()
            else
              fallback()
            end
          end, { "i", "s" }),
          ["<S-Tab>"] = cmp.mapping(function(fallback)
            if cmp.visible() then
              cmp.select_prev_item()
            elseif luasnip.jumpable(-1) then
              luasnip.jump(-1)
            else
              fallback()
            end
          end, { "i", "s" }),
        }),
        sources = cmp.config.sources({
          { name = 'nvim_lsp' },
          { name = 'luasnip' }, -- For luasnip users.
          {
            name = 'buffer',
            option = {
              get_bufnrs = function()
                return vim.api.nvim_list_bufs()
              end
            },
          },
        }, {
        }),
        -- Set configuration for specific filetype.
        -- Use buffer source for `/` and `?` (if you enabled `native_menu`, this won't work anymore).
        cmp.setup.cmdline({ '/', '?' }, {
          mapping = cmp.mapping.preset.cmdline(),
          sources = {
            { name = 'buffer' }
          }
        }),
        -- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
        cmp.setup.cmdline(':', {
          mapping = cmp.mapping.preset.cmdline(),
          sources = cmp.config.sources({
            { name = 'path' }
          }, {
            { name = 'cmdline' }
          })
        })
      })


      -- setup --

      local client_capabilities = vim.lsp.protocol.make_client_capabilities()
      local cmp_capabilities = require('cmp_nvim_lsp').default_capabilities()

      local capabilities = vim.tbl_deep_extend(
        "force",
        client_capabilities,
        cmp_capabilities
      )

      -- mason --

      require("mason").setup({
        PATH = "append",
        ui = {
          border = "rounded",
          icons = {
            package_installed = "✔",
            package_pending = "➜",
            package_uninstalled = "✘"
          }
        }
      })

      -- mason lspconfig --

      require("mason-lspconfig").setup({
        ensure_installed = {
          "lua_ls",
          "clangd",
          "rust_analyzer",
        },
        handlers = {
          -- The first entry (without a key) will be the default handler
          -- and will be called for each installed server that doesn't have
          -- a dedicated handler.
          function(server_name) -- default handler (optional)
            require("lspconfig")[server_name].setup {
              capabilities = capabilities
            }
          end,
          clangd = function()
            require("lspconfig").clangd.setup {
              capabilities = capabilities,
              on_attach = function(client)
                client.server_capabilities.documentFormattingProvider = false
                client.server_capabilities.documentRangeFormattingProvider = false
              end,
            }
          end,
        }
      })

      -- telescope ui for null-ls

      require("telescope").setup {
        extensions = {
          ["ui-select"] = {
            -- require("telescope.themes").get_dropdown {
            --     -- even more opts
            -- }
          }
        }
      }
      require("telescope").load_extension("ui-select")


      -- null-ls (none-ls)

      local null_ls = require('null-ls')
      require("null-ls").setup({
        sources = {
          null_ls.builtins.diagnostics.trail_space.with {
            disabled_filetypes = { "lua" }
          },
          null_ls.builtins.diagnostics.sqlfluff.with({
            extra_args = { "--dialect", "sqlite" },
          }),
          null_ls.builtins.formatting.sqlfluff.with({
            extra_args = { "--dialect", "sqlite" },
          }),
          null_ls.builtins.formatting.clang_format.with({
            extra_args = { "-style={BasedOnStyle: llvm, IndentWidth: 2, BreakBeforeBraces: Linux, ColumnLimit: 0}" }
          })
        },
      })

      require("mason-null-ls").setup({
        ensure_installed = { "clang_format", "shellharden", "shfmt" }
      })


      -- lspsaga (pretty lsp-windows)

      require('lspsaga').setup({
        symbol_in_winbar = {
          enable = false,
          show_file = false
        },
        finder = {
          keys = {
            toggle_or_open = "<cr>",
            quit = { '<Esc>', 'q' }
          }
        },
        outline = {
          win_position = 'right',
          win_width = 32,
          auto_preview = true,
        },
        lightbulb = {
          enable = false
        },
        ui = {
          code_action = '',
          title = true,
          border = 'rounded',
        },
        rename = {
          in_select = false,
          keys = {
            quit = { '<Esc>', 'q' },
            select = '<Space>'
          }
        },
        hover_doc = {
          open_cmd = '!firefox'
        },
        code_action = {
          keys = {
            quit = { '<Esc>', 'q' }
          },
          extend_gitsigns = false,
        },
        definition = {
          keys = {
            quit = { '<Esc>', 'q' },
          },
        },
        diagnostic = {
          border_follow = true,
          extend_relatedInformation = true,
          keys = {
            quit = { '<Esc>', 'q' },
            quit_in_show = { '<Esc>', 'q' },
          }
        }
      })

      -- config --

      vim.diagnostic.config({
        update_in_insert = true,
        signs = { text = { [vim.diagnostic.severity.ERROR] = "✘ ", [vim.diagnostic.severity.WARN] = " ", [vim.diagnostic.severity.HINT] = " ", [vim.diagnostic.severity.INFO] = " " } },
        float = {
          focusable = false,
          style = "minimal",
          border = "rounded",
          source = "always",
          header = "",
          prefix = "",
        },
        virtual_text = {
          prefix = '●', -- Could be '●', '■', 'x', '▎', or anything else
        },
      })

      -- keymaps --

      local opts = { noremap = true, silent = true }
      vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
      vim.keymap.set('n', 'K', function() vim.lsp.buf.hover { border = "rounded" } end, opts)
      vim.keymap.set('n', '<leader>k', function() vim.lsp.buf.hover { border = "rounded" } end, opts)
      vim.keymap.set('n', '<space>cl', "<cmd>LspInfo<cr>", opts)
      vim.keymap.set('n', '<space>cd', vim.diagnostic.open_float, opts)
      vim.keymap.set('n', '[n', vim.diagnostic.goto_prev, opts)
      vim.keymap.set('n', ']n', vim.diagnostic.goto_next, opts)
      vim.keymap.set('n', '<space>gr', vim.lsp.buf.references, opts)
      vim.keymap.set('n', '<space>cf', function() vim.lsp.buf.format { async = true } end, opts)
      vim.keymap.set('v', '<space>cf', function() vim.lsp.buf.format { async = true } end, opts)
      vim.keymap.set("n", "<leader>fws", function() vim.lsp.buf.workspace_symbol() end, opts)
      vim.keymap.set("i", "<C-s>", function() vim.lsp.buf.signature_help { border = "rounded" } end, opts)
      vim.keymap.set('n', '<C-n>', "<cmd>Lspsaga term_toggle<cr>", opts)
      vim.keymap.set('t', '<C-n>', "<cmd>Lspsaga term_toggle<cr>", opts)
      vim.keymap.set('n', '<space>so', '<cmd>Lspsaga outline<cr>', opts)
      vim.keymap.set('n', '<space>sf', '<cmd>Lspsaga finder<cr>', opts)
      vim.keymap.set('n', '<space>sd', '<cmd>Lspsaga peek_definition<cr>', opts)
      vim.keymap.set('n', '<space>cw', "<cmd>Lspsaga rename mode=n<cr>", opts)
      vim.keymap.set('n', '<space>cA', vim.lsp.buf.code_action, opts)
      vim.keymap.set('n', '<space>ca', '<cmd>Lspsaga code_action<cr>', opts)
    end,
  }
}