local overrides = require "custom.configs.overrides"

---@type NvPluginSpec[]
local plugins = {

  -- Override plugin definition options

  {
    "neovim/nvim-lspconfig",
    config = function()
      require "plugins.configs.lspconfig"
      require "custom.configs.lspconfig"
    end, -- Override to setup mason-lspconfig
  },
  -- override plugin configs
  {
    "williamboman/mason.nvim",
    opts = overrides.mason,
  },

  {
    "nvim-treesitter/nvim-treesitter",
    opts = overrides.treesitter,
  },

  {
    "nvim-tree/nvim-tree.lua",
    opts = overrides.nvimtree,
  },

  -- Install a plugin
  {
    -- exit insert mode with 'jk'
    "max397574/better-escape.nvim",
    enabled = true,
    event = "InsertEnter",
    config = function()
      require("better_escape").setup()
    end,
  },

  {
    "stevearc/conform.nvim",
    --  for users those who want auto-save conform + lazyloading!
    -- event = "BufWritePre"
    config = function()
      require "custom.configs.conform"
    end,
  },
  {
    "ggandor/leap.nvim",
    lazy = false,
    config = function()
      require("core.utils").load_mappings "leap"
    end,
  },
  {
    "ggandor/flit.nvim",
    lazy = false,
    config = function()
      require("flit").setup {
        keys = { f = "f", F = "F", t = "t", T = "T" },
        -- A string like "nv", "nvo", "o", etc.
        labeled_modes = "v",
        multiline = true,
        -- Like `leap`s similar argument (call-specific overrides).
        -- E.g.: opts = { equivalence_classes = {} }
        opts = {},
      }
    end,
  },
  {
    "kdheepak/lazygit.nvim",
    lazy = false,
    keys = { "<leader>gg" },
    cmd = "LazyGit",
    -- optional for floating window border decoration
    dependencies = {
      "nvim-lua/plenary.nvim",
    },
    init = function()
      require("core.utils").load_mappings "lazygit"
    end,
  },
  {
    "folke/which-key.nvim",
    keys = { "<leader>", "<localleader>", "<c-r>", "<c-w>", '"', "'", "`", "c", "v", "g" },
    defaults = {
      mode = { "n", "v" },
      [";"] = { name = "+telescope" },
      [";f"] = { name = "+find" },
      [";d"] = { name = "+lsp/todo" },
      ["g"] = { name = "+goto" },
      ["]"] = { name = "+next" },
      ["["] = { name = "+prev" },
      ["<leader>x"] = { name = "+diagnostics/quickfix" },
      ["<leader>d"] = { name = "+debug" },
      ["<leader>c"] = { name = "+code" },
      ["<leader>g"] = { name = "+git" },
      ["<leader>t"] = { name = "+toggle/tools" },
      ["<leader>w"] = { name = "+window/which" },
      ["<leader>f"] = { name = "+formatting" },
    },
  },
  {
    "echasnovski/mini.trailspace",
    lazy = false,
    event = { "BufReadPost", "BufNewFile" },
    opts = {},
  },
  {
    "itchyny/vim-cursorword",
    event = "FileType",
    init = function()
      vim.g.cursorword = 0
    end,
    config = function()
      local augroup = vim.api.nvim_create_augroup("plex_cursorword", {})
      vim.api.nvim_create_autocmd("FileType", {
        group = augroup,
        pattern = {
          "conf",
          "dosini",
          "json",
          "markdown",
          "nginx",
          "text",
          "yaml",
        },
        callback = function()
          if vim.wo.diff or vim.wo.previewwindow then
            vim.b.cursorword = 0
          else
            vim.b.cursorword = 1
          end
        end,
      })
      vim.api.nvim_create_autocmd("InsertEnter", {
        group = augroup,
        callback = function()
          if vim.b["cursorword"] == 1 then
            vim.b["cursorword"] = 0
          end
        end,
      })
      vim.api.nvim_create_autocmd("InsertLeave", {
        group = augroup,
        callback = function()
          if vim.b["cursorword"] == 0 then
            vim.b["cursorword"] = 1
          end
        end,
      })
    end,
  },

  {
    "RRethy/vim-illuminate",
    lazy = false,
    event = { "BufReadPost", "BufNewFile" },
    opts = {
      delay = 200,
      under_cursor = false,
      modes_allowlist = { "n", "no", "nt" },
      filetypes_denylist = {
        "DiffviewFileHistory",
        "DiffviewFiles",
        "SidebarNvim",
        "fugitive",
        "git",
        "minifiles",
        "neo-tree",
      },
    },
    keys = {
      { "]]", desc = "Next Reference" },
      { "[[", desc = "Prev Reference" },
    },
    config = function(_, opts)
      require("illuminate").configure(opts)

      local function map(key, dir, buffer)
        vim.keymap.set("n", key, function()
          require("illuminate")["goto_" .. dir .. "_reference"](false)
        end, {
          desc = dir:sub(1, 1):upper() .. dir:sub(2) .. " Reference",
          buffer = buffer,
        })
      end

      map("]]", "next")
      map("[[", "prev")

      -- also set it after loading ftplugins, since a lot overwrite [[ and ]]
      vim.api.nvim_create_autocmd("FileType", {
        group = vim.api.nvim_create_augroup("plex_illuminate", {}),
        callback = function()
          local buffer = vim.api.nvim_get_current_buf()
          map("]]", "next", buffer)
          map("[[", "prev", buffer)
        end,
      })
    end,
  },
  {
    "folke/todo-comments.nvim",
    lazy = false,
    dependencies = "nvim-telescope/telescope.nvim",
        -- stylua: ignore
        keys = {
            { ']t',              function() require('todo-comments').jump_next() end, desc = 'Next todo comment' },
            { '[t',              function() require('todo-comments').jump_prev() end, desc = 'Previous todo comment' },
            { '<LocalLeader>dt', '<cmd>TodoTelescope<CR>',                            desc = 'todo' },
            { '<leader>xt',      '<cmd>TodoTrouble<CR>',                              desc = 'Todo (Trouble)' },
            { '<leader>xT',      '<cmd>TodoTrouble keywords=TODO,FIX,FIXME<cr>',      desc = 'Todo/Fix/Fixme (Trouble)' },
        },
    opts = {
      signs = true,
      keywords = {
        FIX = {
          icon = " ", -- icon used for the sign, and in search results
          color = "error", -- can be a hex color, or a named color (see below)
          alt = { "FIXME", "BUG", "FIXIT", "ISSUE" }, -- a set of other keywords that all map to this FIX keywords
        },
        TODO = { icon = " ", color = "todo" },
        HACK = { icon = " ", color = "hack" },
        SECURITY = { icon = "󰒃 ", color = "security" },
        WARN = { icon = " ", color = "warning", alt = { "WARNING", "XXX" } },
        PERF = { icon = " ", color = "perf", alt = { "OPTIM", "PERFORMANCE", "OPTIMIZE" } },
        NOTE = { icon = " ", color = "hint", alt = { "INFO" } },
        TEST = { icon = "⏲ ", color = "test", alt = { "TESTING", "PASSED", "FAILED" } },
      },
      colors = {
        error = { "DiagnosticError", "ErrorMsg", "#DC2626" },
        warning = { "DiagnosticWarn", "WarningMsg", "#FBBF24" },
        todo = { "DiagnosticTodo", "#80e64d" },
        hint = { "DiagnosticHint", "#10B981" },
        hack = { "DiagnosticHack", "#FF33FF" },
        security = { "DiagnosticSecurity", "#FF6600" },
        default = { "Identifier", "#7C3AED" },
        test = { "DiagnosticTest", "#E6E600" },
        perf = { "DiagnosticPerf", "#9999ff" },
      },
    },
  },
  {
    "folke/trouble.nvim",
    cmd = { "Trouble", "TroubleToggle" },
    opts = { use_diagnostic_signs = true },
        -- stylua: ignore
        keys = {
            {
                '<leader>e',
                '<cmd>TroubleToggle document_diagnostics<CR>',
                noremap = true,
                desc =
                'Document Diagnostics'
            },
            {
                '<leader>r',
                '<cmd>TroubleToggle workspace_diagnostics<CR>',
                noremap = true,
                desc =
                'Workspace Diagnostics'
            },
            { '<leader>xx', '<cmd>TroubleToggle document_diagnostics<cr>',  desc = 'Document Diagnostics (Trouble)' },
            { '<leader>xX', '<cmd>TroubleToggle workspace_diagnostics<cr>', desc = 'Workspace Diagnostics (Trouble)' },
            { '<leader>xQ', '<cmd>TroubleToggle quickfix<cr>',              desc = 'Quickfix List (Trouble)' },
            { '<leader>xL', '<cmd>TroubleToggle loclist<cr>',               desc = 'Location List (Trouble)' },
            {
                '[q',
                function()
                    if require('trouble').is_open() then
                        require('trouble').previous({ skip_groups = true, jump = true })
                    else
                        vim.cmd.cprev()
                    end
                end,
                desc = 'Previous trouble/quickfix item',
            },
            {
                ']q',
                function()
                    if require('trouble').is_open() then
                        require('trouble').next({ skip_groups = true, jump = true })
                    else
                        vim.cmd.cnext()
                    end
                end,
                desc = 'Next trouble/quickfix item',
            },
        },
  },
  {
    "NvChad/nvterm",
    enabled = false,
  },
  {
    "akinsho/toggleterm.nvim",
    init = function()
      require("core.utils").load_mappings "toggleterm"
    end,
    cmd = "ToggleTerm",
    opts = {
      size = function(term)
        if term.direction == "horizontal" then
          return vim.o.lines * 0.35
        elseif term.direction == "vertical" then
          return vim.o.columns * 0.35
        else
          return 20
        end
      end,
      open_mapping = false,
      float_opts = {
        border = "curved",
      },
    },
  },
  -- lazy.nvim
  {
    "folke/noice.nvim",
    enabled = not vim.g.started_by_firenvim,
    event = "VeryLazy",
    -- config.lsp.signature.enabled = false
    dependencies = {
      -- if you lazy-load any plugin below, make sure to add proper `module="..."` entries
      "MunifTanjim/nui.nvim",
      -- OPTIONAL:
      --   `nvim-notify` is only needed, if you want to use the notification view.
      --   If not available, we use `mini` as the fallback
      "rcarriga/nvim-notify",
    },
    config = function()
      require("noice").setup {
        lsp = {
          override = {
            ["vim.lsp.util.convert_input_to_markdown_lines"] = true,
            ["vim.lsp.util.stylize_markdown"] = true,
            ["cmp.entry.get_documentation"] = true,
          },
          -- IDK how to disable the nvchad builtins for this, which would
          -- produce a conflict
          signature = { enabled = false },
          hover = { enabled = false },
        },
        -- you can enable a preset for easier configuration
        presets = {
          bottom_search = true, -- use a classic bottom cmdline for search
          command_palette = true, -- position the cmdline and popupmenu together
          long_message_to_split = true, -- long messages will be sent to a split
          inc_rename = true, -- enables an input dialog for inc-rename.nvim
          lsp_doc_border = true, -- add a border to hover docs and signature help
        },
        messages = {
          enabled = true,
          -- NOTE: we keep it with notify,
          -- change this to something else if you want
          view_error = "notify",
        },
        popupmenu = {
          enabled = true,
        },
        notify = {
          enabled = true,
        },
      }
    end,
  },
  {
    "goolord/alpha-nvim",
    enabled = false,
    lazy = false,
    dependencies = { "nvim-tree/nvim-web-devicons" },
    config = function()
      local dash = require "alpha.themes.dashboard"
      require("alpha").setup(dash.config)
    end,
  },
  {
    "stevearc/dressing.nvim",
    init = function()
      ---@diagnostic disable-next-line: duplicate-set-field
      vim.ui.select = function(...)
        require("lazy").load { plugins = { "dressing.nvim" } }
        return vim.ui.select(...)
      end
      ---@diagnostic disable-next-line: duplicate-set-field
      vim.ui.input = function(...)
        require("lazy").load { plugins = { "dressing.nvim" } }
        return vim.ui.input(...)
      end
    end,
  },
  {
    "chentoast/marks.nvim",
    lazy = false,
    dependencies = "lewis6991/gitsigns.nvim",
    event = "FileType",
    opts = {
      sign_priority = { lower = 10, upper = 15, builtin = 8, bookmark = 20 },
      bookmark_1 = { sign = "󰉀" }, -- ⚐ ⚑ 󰈻 󰈼 󰈽 󰈾 󰈿 󰉀
    },
  },
  {
    "kevinhwang91/nvim-bqf",
    ft = "qf",
    cmd = "BqfAutoToggle",
    event = "QuickFixCmdPost",
    opts = {
      auto_resize_height = false,
      func_map = {
        tab = "st",
        split = "sv",
        vsplit = "sg",

        stoggleup = "K",
        stoggledown = "J",
        stogglevm = "<Space>",

        ptoggleitem = "p",
        ptoggleauto = "P",
        ptogglemode = "zp",

        pscrollup = "<C-b>",
        pscrolldown = "<C-f>",

        prevfile = "gk",
        nextfile = "gj",

        prevhist = "<S-Tab>",
        nexthist = "<Tab>",
      },
      preview = {
        auto_preview = true,
        should_preview_cb = function(bufnr)
          -- file size greater than 100kb can't be previewed automatically
          local filename = vim.api.nvim_buf_get_name(bufnr)
          local fsize = vim.fn.getfsize(filename)
          if fsize > 100 * 1024 then
            return false
          end
          return true
        end,
      },
    },
  },
  {
    "uga-rosa/ccc.nvim",
    lazy = false,
    event = "FileType",
    keys = {
      { "<Leader>cp", "<cmd>CccPick<CR>", desc = "Color-picker" },
    },
    opts = {
      highlighter = {
        auto_enable = true,
        lsp = true,
        excludes = { "lazy", "mason", "help", "neo-tree" },
      },
    },
  },
  {
    "Bekaboo/deadcolumn.nvim",
    event = { "BufReadPre", "BufNewFile" },
  },
  {
    "rmagatti/goto-preview",
    event = "FileType",
    config = function()
      require("core.utils").load_mappings "goto_preview"
      require("goto-preview").setup {}
    end,
    dependencies = "nvim-telescope/telescope.nvim",
    opts = {
      width = 78,
      height = 15,
      default_mappings = false,
      opacity = 10,
    },
  },
  {
    "glacambre/firenvim",
    enabled = vim.g.started_by_firenvim,
    lazy = false,
    build = function()
      vim.fn["firenvim#install"](0)
    end,
    config = function()
      vim.g.firenvim_config = {
        localSettings = {
          [".*"] = {
            filename = "/tmp/{hostname}_{pathname%10}.{extension%5}",
            cmdline = "firenvim",
            takeover = "never", -- can't open it with never at all?
          },
        },
      }
    end,
  },
  {
    "sidebar-nvim/sidebar.nvim",
    cmd = { "SidebarNvimToggle", "SidebarNvimOpen" },
    config = function()
      require("sidebar-nvim").setup {
        bindings = {
          ["q"] = function()
            require("sidebar-nvim").close()
          end,
        },
      }
    end,
  },
  {
    "dhruvasagar/vim-table-mode",
    lazy = false,
    -- <Leader>tm is automatically set for toggle
    -- see <Leader>t menu
  },
  {
    "kevinhwang91/nvim-ufo",
    event = { "BufReadPost", "BufNewFile" },
        -- stylua: ignore
        keys = {
            { 'zR', function() require('ufo').openAllFolds() end },
            { 'zM', function() require('ufo').closeAllFolds() end },
        },
    dependencies = {
      "kevinhwang91/promise-async",
      "nvim-treesitter/nvim-treesitter",
      "neovim/nvim-lspconfig",
    },
    opts = function()
      -- fancy display function for folds (stolen from nvim-ufo readme)
      local handler = function(virtText, lnum, endLnum, width, truncate)
        local newVirtText = {}
        local suffix = (" 󰁂 %d "):format(endLnum - lnum)
        local sufWidth = vim.fn.strdisplaywidth(suffix)
        local targetWidth = width - sufWidth
        local curWidth = 0
        for _, chunk in ipairs(virtText) do
          local chunkText = chunk[1]
          local chunkWidth = vim.fn.strdisplaywidth(chunkText)
          if targetWidth > curWidth + chunkWidth then
            table.insert(newVirtText, chunk)
          else
            chunkText = truncate(chunkText, targetWidth - curWidth)
            local hlGroup = chunk[2]
            table.insert(newVirtText, { chunkText, hlGroup })
            chunkWidth = vim.fn.strdisplaywidth(chunkText)
            -- str width returned from truncate() may less than 2nd argument, need padding
            if curWidth + chunkWidth < targetWidth then
              suffix = suffix .. (" "):rep(targetWidth - curWidth - chunkWidth)
            end
            break
          end
          curWidth = curWidth + chunkWidth
        end
        table.insert(newVirtText, { suffix, "MoreMsg" })
        return newVirtText
      end
      require("ufo").setup {
        -- use treesitter to get the folds
        provider_selector = function(bufnr, filetype, buftype)
          return { "treesitter", "indent" }
        end,
        -- apply out fancy fold display
        fold_virt_text_handler = handler,
      }
    end,
  },
  {
    -- enables UNIX specific stuff in vim,
    -- specifically:
    -- :SudoWrite
    -- :SudoRead
    -- :Chmod
    -- and also some more, but those are easy done with shell
    "tpope/vim-eunuch",
    lazy = false,
  },
  {
    "nvimtools/none-ls.nvim",
    event = { "BufReadPre", "BufNewFile" },
    opts = function(_, opts)
      opts.sources = {}
      local nls = require "null-ls"
      local builtins = nls.builtins
      local sources = {
        builtins.formatting.djlint.with {
          filetypes = { "django", "jinja.html", "htmldjango", "tera", "html" },
        },
        builtins.diagnostics.djlint.with {
          filetypes = { "django", "jinja.html", "htmldjango", "tera", "html" },
        },
        builtins.formatting.shfmt,
        -- builtins.diagnostics.write_good.with {
        --   diagnostics_postprocess = function(diagnostic)
        --     diagnostic.severity = vim.diagnostic.severity.HINT
        --   end,
        -- },
      }
      for _, source in ipairs(sources) do
        table.insert(opts.sources, source)
      end
    end,
  },
  {
    "lvimuser/lsp-inlayhints.nvim",
    event = "LspAttach",
    opts = {
      inlay_hints = {
        parameter_hints = { show = true },
        type_hints = { show = true },
        only_current_line = false,
        -- highlight group
        highlight = "LspInlayHint",
        -- virt_text priority
        priority = 0,
      },
    },
    config = function(_, opts)
      require("lsp-inlayhints").setup(opts)
      vim.api.nvim_create_augroup("LspAttach_inlayhints", {})
      vim.api.nvim_create_autocmd("LspAttach", {
        group = vim.api.nvim_create_augroup("LspAttach_inlayhints", {}),
        callback = function(args)
          if not (args.data and args.data.client_id) then
            return
          end
          local client = vim.lsp.get_client_by_id(args.data.client_id)
          require("lsp-inlayhints").on_attach(client, args.buf)
        end,
      })
      -- change how the highlighting looks
      vim.cmd "hi LspInlayHint guibg=(bg*0.8) guifg=#6699b3"
    end,
  },
  { "kosayoda/nvim-lightbulb", event = { "BufReadPre", "BufNewFile" } },
  {
    "Wansmer/treesj",
    cmd = { "TSJJoin", "TSJSplit", "TSJSplit" },
    keys = {
      { "<C-s-j>", "<cmd>TSJJoin<CR>" },
      { "<C-s-s>", "<cmd>TSJSplit<CR>" },
    },
    opts = {
      use_default_keymaps = false,
    },
  },
  {
    "b0o/incline.nvim",
    event = "FileType",
    config = function()
      local function get_diagnostic_label(props)
        local icons = { error = "", warn = "", info = "", hint = "" }
        local label = {}

        for severity, icon in pairs(icons) do
          local n = #vim.diagnostic.get(props.buf, { severity = vim.diagnostic.severity[string.upper(severity)] })
          if n > 0 then
            table.insert(label, { icon .. " " .. n .. " ", group = "DiagnosticSign" .. severity })
          end
        end
        if #label > 0 then
          table.insert(label, { "| " })
        end
        return label
      end
      local function get_git_diff(props)
        local icons = { removed = "", changed = "", added = "" }
        local labels = {}
        -- local signs = vim.api.nvim_buf_get_var(props.buf, "gitsigns_status_dict")
        -- local signs = vim.b.gitsigns_status_dict
        -- for name, icon in pairs(icons) do
        --   if tonumber(signs[name]) and signs[name] > 0 then
        --     table.insert(labels, { icon .. " " .. signs[name] .. " ", group = "Diff" .. name })
        --   end
        -- end
        if #labels > 0 then
          table.insert(labels, { "| " })
        end
        return labels
      end

      require("incline").setup {
        render = function(props)
          local filename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(props.buf), ":t")
          local ft_icon, ft_color = require("nvim-web-devicons").get_icon_color(filename)
          local modified = vim.api.nvim_buf_get_option(props.buf, "modified") and "bold,italic" or "bold"

          local buffer = {
            { get_diagnostic_label(props) },
            { get_git_diff(props) },
            { ft_icon, guifg = ft_color },
            { " " },
            { filename, gui = modified },
          }
          return buffer
        end,
      }
    end,
  },
  {
    "mikesmithgh/kitty-scrollback.nvim",
    enabled = true,
    lazy = true,
    cmd = { "KittyScrollbackGenerateKittens", "KittyScrollbackCheckHealth" },
    event = { "User KittyScrollbackLaunch" },
    -- version = '*', -- latest stable version, may have breaking changes if major version changed
    -- version = '^3.0.0', -- pin major version, include fixes and features that do not have breaking changes
    config = function()
      require("kitty-scrollback").setup {
        myconfig = function()
          return { keymaps_enabled = false }
        end,
      }
    end,
  },
  {
    "hrsh7th/nvim-cmp",
    enabled = not vim.g.started_by_firenvim,
  },
  {
    "ziontee113/icon-picker.nvim",
    keys = {
      { "<C-I>", "<cmd>IconPickerNormal<CR>", desc = "pick icon" },
      { "y<C-I>", "<cmd>IconPickerYank<CR>", desc = "yank icon" },
    },
    cmd = { "IconPickerInsert", "IconPickerYank", "IconPickerNormal" },
    config = function()
      require("icon-picker").setup { disable_legacy_commands = true }
    end,
  },
  {
    "mfussenegger/nvim-dap",
    lazy = false,
    init = function()
      require("core.utils").load_mappings "debug"
    end,
    config = function()
      local dap = require "dap"
      local mason_registry = require "mason-registry"
      local codelldb_root = mason_registry.get_package("codelldb"):get_install_path() .. "/extension/"
      local codelldb_path = codelldb_root .. "adapter/codelldb"
      local liblldb_path = codelldb_root .. "lldb/lib/liblldb.so"
      dap.defaults.fallback.external_terminal = {
        command = "/home/plex/.local/bin/kitty",
        args = {},
      }
      dap.adapters.gdb = {
        type = "executable",
        command = "gdb",
        args = { "-i", "dap" },
      }
      dap.adapters.codelldb = {
        type = "server",
        port = "30333",
        executable = {
          command = codelldb_path,
          args = { "--port", "30333" },
          detached = false,
        },
      }
      dap.configurations.cpp = {
        {
          name = "Launch file",
          type = "codelldb",
          request = "launch",
          program = function()
            return vim.fn.input("Path to executable: ", vim.fn.getcwd() .. "/", "file")
          end,
          args = function()
            return require("custom.utils").tokenize_args(vim.fn.input "args: ")
          end,
          cwd = "${workspaceFolder}",
          -- FIXME: perhaps we can put the stdio somewhere more practical
          stopOnEntry = false,
        },
      }
      dap.configurations.c = dap.configurations.cpp
      dap.configurations.rust = dap.configurations.cpp
    end,
  },
  {
    "rcarriga/nvim-dap-ui",
    init = function()
      require("core.utils").load_mappings "debug"
    end,
    dependencies = {
      "mfussenegger/nvim-dap",
    },
    config = function(_, opts)
      local dap = require "dap"
      local dapui = require "dapui"
      dapui.setup(opts)
      dap.listeners.after.event_initialized["dapui_config"] = function()
        dapui.open {}
      end
      dap.listeners.before.event_terminated["dapui_config"] = function()
        -- dapui.close {}
      end
      dap.listeners.before.event_exited["dapui_config"] = function()
        -- dapui.close {}
      end
    end,
  },
  { "folke/neodev.nvim", opts = {} },
  {
    "mrcjkb/rustaceanvim",
    enabled = false,
    version = "^4", -- Recommended
    ft = { "rust" },
    config = function()
      local dap = require "dap"
      vim.g.rustaceanvim = {
        enable_clippy = true,
        -- Plugin configuration
        tools = {
          enable_clippy = true,
        },
        -- LSP configuration
        server = {
          on_attach = function(client, bufnr)
            -- you can also put keymaps in here
          end,
          settings = {
            -- rust-analyzer language server configuration
            ["rust-analyzer"] = {
              cargo = {
                features = "all",
              },
            },
          },
        },
        -- DAP configuration
        dap = {
          -- FIXME: the rustaceanvim debug config does not map the stdout/stderr to the
          -- opened terminal, effectively rendering debugging with it useless. Luckily,
          -- we can use the regular nvim-dap and nvim-dap-ui.
          adapter = dap.adapters.codelldb,
        },
      }
    end,
  },
  {
    "theHamsta/nvim-dap-virtual-text",
    lazy = false, -- PERF: this can be done more elegant
    config = function()
      require("nvim-dap-virtual-text").setup()
    end,
  },
  {
    "jvgrootveld/telescope-zoxide",
    dependencies = "nvim-telescope/telescope.nvim",
    config = function()
      -- Useful for easily creating commands
      local z_utils = require "telescope._extensions.zoxide.utils"

      require("telescope").setup {
        -- (other Telescope configuration...)
        extensions = {
          zoxide = {
            prompt_title = "[ Walking on the shoulders of TJ ]",
            mappings = {
              default = {
                after_action = function(selection)
                  print("Update to (" .. selection.z_score .. ") " .. selection.path)
                end,
              },
              ["<C-s>"] = {
                before_action = function(selection)
                  print "before C-s"
                end,
                action = function(selection)
                  vim.cmd.edit(selection.path)
                end,
              },
              -- Opens the selected entry in a new split
              ["<C-q>"] = { action = z_utils.create_basic_command "split" },
            },
          },
        },
      }
      require("telescope").load_extension "zoxide"
    end,
  },
  { "nanotee/zoxide.vim", lazy = false, enabled = false },
  {
    "iamcco/markdown-preview.nvim",
    cmd = { "MarkdownPreviewToggle", "MarkdownPreview", "MarkdownPreviewStop" },
    ft = { "markdown" },
    build = function()
      vim.fn["mkdp#util#install"]()
    end,
    config = function()
      -- Ugly fix for wsl not finding my browser
      -- I HATE windows
      vim.g.mkdp_echo_preview_url = 1
    end,
  },
  {
    "rhysd/vim-grammarous",
    enabled = false,
    -- TODO: figure out how i can login to languagetool.org
    lazy = false,
    config = function()
      vim.g["grammarous#jar_url"] = "https://www.languagetool.org/download/LanguageTool-5.9.zip"
      vim.g["grammarous#use_vim_spelllang"] = 1
      vim.cmd [[
        let g:grammarous#default_comments_only_filetypes = {
                    \ '*' : 1, 'help' : 0, 'markdown' : 0,
                    \ }
            ]]
    end,
  },
}

return plugins
