local custom_headers = {
  sharp = {
    [[                                                                               ]],
    [[          █ ████████           █████    ███████    ████          ]],
    [[         ███ ██████             █████  █████████  ██████         ]],
    [[        █████ ██████████████████████ ████ ███████████████        ]],
    [[       ██ ██ █████     █████████████ ████ ████████████████       ]],
    [[      ████ ███████████████ █████████ ████ █████ ██████ ████      ]],
    [[     ██████ ██████     ███ █████████ ████ █████  █████  ████     ]],
    [[    ████████ ███████████████████ ████ ████ █████   ████   ████    ]],
    [[                                                                               ]],
    [[                      🛠️ Sharp tools make good work 🖥️                         ]],
    [[                                                                               ]],
  },
}

return {
  {
    'nvim-tree/nvim-tree.lua',
    cmd = { 'NvimTreeToggle', 'NvimTreeFocus' },

    opts = {
      filters = {
        dotfiles = false,
        exclude = { vim.fn.stdpath 'config' .. '/lua/custom' },
      },
      disable_netrw = true,
      hijack_netrw = true,
      hijack_cursor = true,
      hijack_unnamed_buffer_when_opening = false,
      sync_root_with_cwd = true,
      update_focused_file = {
        enable = true,
        update_root = false,
      },
      view = {
        adaptive_size = false,
        side = 'left',
        width = 30,
        preserve_window_proportions = true,
      },
      git = {
        enable = false,
        ignore = true,
      },
      filesystem_watchers = {
        enable = true,
      },
      actions = {
        open_file = {
          resize_window = true,
        },
      },
      renderer = {
        root_folder_label = false,
        highlight_git = false,
        highlight_opened_files = 'none',

        indent_markers = {
          enable = false,
        },

        icons = {
          show = {
            file = true,
            folder = true,
            folder_arrow = true,
            git = false,
          },

          glyphs = {
            default = '󰈚',
            symlink = '',
            folder = {
              default = '',
              empty = '',
              empty_open = '',
              open = '',
              symlink = '',
              symlink_open = '',
              arrow_open = '',
              arrow_closed = '',
            },
            git = {
              unstaged = '✗',
              staged = '✓',
              unmerged = '',
              renamed = '➜',
              untracked = '★',
              deleted = '',
              ignored = '◌',
            },
          },
        },
      },
    },
    config = function(_, opts)
      require('nvim-tree').setup(opts)
    end,
    keys = {
      { '<F5>', '<cmd> NvimTreeToggle <cr>', desc = '[T]oggle [F]ile explorer' },
      { '<leader>tf', '<cmd> NvimTreeToggle <cr>', desc = '[T]oggle [F]ile explorer' },
      { '<leader>fr', '<cmd> NvimTreeRefresh <cr>', desc = '[F]iles [R]efresh' },
      -- TODO: better map for cd
    },
  },
  {
    'ggandor/leap.nvim',
    lazy = false,
    opts = {},
    keys = {
      { 's', '<plug>(leap-forward)', desc = 'leap forward' },
      { 'S', '<plug>(leap-backward)', desc = 'leap backward' },
      { 'gs', '<plug>(leap-from-window)', desc = 'leap from window' },
    },
    config = function()
      -- idk why it doesn't work when I just define an opts table, but that is
      -- so

      local leap = require 'leap'

      leap.opts.safe_labels = 'asfghjkliztrewb'
      leap.opts.labels = 'sfnjklhodweimbuyvrgtaqpcxz'
      leap.opts.special_keys = {
        next_target = '<enter>',
        prev_target = '<tab>',
        next_group = '<space>',
        prev_group = '<tab>',
      }
    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,
  },
  { 'echasnovski/mini.trailspace', lazy = false, version = false, opts = { only_in_normal_buffers = true } },
  {
    'folke/which-key.nvim',
    event = 'VimEnter', -- Sets the loading event to 'VimEnter'
    opts = {
      triggers_nowait = {
        -- marks
        '`',
        "'",
        'g`',
        "g'",
        -- registers
        '"',
        '<c-r>',
        -- spelling
        'z=',
        'o',
        'O',
      },
      triggers_blacklist = {
        -- list of mode / prefixes that should never be hooked by WhichKey
        -- this is mostly relevant for keymaps that start with a native binding
        i = { 'j', 'k' },
        v = { 'j', 'k' },
        n = { 'o', 'O' },
      },
      -- plugins = {
      --   marks = true, -- shows a list of your marks on ' and `
      --   registers = true, -- shows your registers on " in NORMAL or <C-r> in INSERT mode
      --   -- the presets plugin, adds help for a bunch of default keybindings in Neovim
      --   -- No actual key bindings are created
      --   spelling = {
      --     enabled = true, -- enabling this will show WhichKey when pressing z= to select spelling suggestions
      --     suggestions = 20, -- how many suggestions should be shown in the list?
      --   },
      --   presets = {
      --     operators = true, -- adds help for operators like d, y, ...
      --     motions = true, -- adds help for motions
      --     text_objects = true, -- help for text objects triggered after entering an operator
      --     windows = true, -- default bindings on <c-w>
      --     nav = true, -- misc bindings to work with windows
      --     z = true, -- bindings for folds, spelling and others prefixed with z
      --     g = true, -- bindings for prefixed with g
      --   },
      -- },
      icons = {
        breadcrumb = '»', -- symbol used in the command line area that shows your active key combo
        separator = '➜', -- symbol used between a key and it's label
        group = '+', -- symbol prepended to a group
      },
    },
    config = function(opts)
      local wk = require 'which-key'
      local defaults = {
        mode = { 'n', 'v' },
        { '<leader>c', group = '[C]ode/[C]olor' },
        { '<leader>ct', group = '[T]rouble' },
        { '<leader>d', group = '[D]ebug' },
        { '<leader>dc', group = '[C]hange' },
        { '<leader>dw', group = '[W]indow' },
        { '<leader>f', group = '[F]ormatting' },
        { '<leader>g', group = '[G]ood tools' },
        { '<leader>r', group = '[R]ename' },
        { '<leader>t', group = '[T]oggle' },
        { '<leader>w', group = '[W]orkspace' },
        { '<leader>wb', group = 'buffer' },
        { '<localleader>', group = 'select' },
        { '<localleader>f', group = '[F]ind' },
        { '[', group = 'prev' },
        { ']', group = 'next' },
        { 'g', group = 'goto' },
      }
      wk.add(defaults, opts)
    end,
  },
  {
    'echasnovski/mini.trailspace',
    lazy = false,
    event = { 'BufReadPost', 'BufNewFile' },
    opts = {
      only_in_normal_buffers = true,
    },
  },
  {
    '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 = {
      -- providers: provider used to get references in the buffer, ordered by priority
      providers = {
        'lsp', -- useless for tex but still used
        'treesitter',
        'regex',
      },
      large_file_cutoff = 50000,
      delay = 200,
      under_cursor = true,
      modes_allowlist = { 'n', 'no', 'nt' },
      filetypes_denylist = {
        'DiffviewFileHistory',
        'DiffviewFiles',
        'SidebarNvim',
        'fugitive',
        'git',
        'minifiles',
        'neo-tree',
        'NvimTree_1',
        'dashboard',
      },
    },
    -- looks weird but is useful: put your cursor on a word and other occurences
    -- of the word in your buffer will be highlighted. You can then use
    --  '[[' and ']]' to go to the next or previous occurence.
    --
    --  Try it:
    --
    --  word #### word ###########
    --  ############## word ######
    --  #### word #### word word #
    --
    -- (Does only work if the regex source is currently active, otherwise the
    -- references are those your language server or treesitter gives out, so
    -- syntax aware)
    keys = {
      { ']]', desc = 'Next Reference' },
      { '[[', desc = 'Prev Reference' },
    },
    config = function(_, opts)
      local illuminate = require 'illuminate'
      illuminate.configure(opts)
      vim.keymap.set('n', '[[', function()
        illuminate.goto_prev_reference() -- try putting your cursor on `illuminate`
      end, { desc = 'Goto last occurence of current word' })
      vim.keymap.set('n', ']]', function()
        illuminate.goto_next_reference()
      end, { desc = 'Goto next occurence of current word' })
    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>fT', '<cmd>TodoTelescope<CR>',                            desc = 'todo' },
		},
    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', 'IDEA' } },
        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' },
      },
    },
  },
  {
    'akinsho/toggleterm.nvim',
    keys = {
      { '<F12>', mode = { 't', 'n', 'v' }, '<cmd>exe v:count1 "ToggleTerm direction=float"<cr>', desc = 'Toggle a big floating terminal' },
      { '<A-i>', mode = { 't', 'n', 'v' }, '<cmd>exe v:count1 "ToggleTerm direction=float"<cr>', desc = 'Toggle a big floating terminal' },
      { '<A-t>', mode = { 't', 'n', 'v' }, '<cmd>exe v:count1 "ToggleTerm direction=tab"<cr>', desc = 'Toggle a terminal in a new tab' },
      { '<A-h>', mode = { 't', 'n', 'v' }, '<cmd>exe v:count1 "ToggleTerm direction=horizontal"<cr>', desc = 'Toggle a horizontal terminal' },
      { '<A-v>', mode = { 't', 'n', 'v' }, '<cmd>exe v:count1 "ToggleTerm direction=vertical"<cr>', desc = 'Toggle a vertical terminal' },
    },
    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',
      },
    },
  },
  {
    '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('notify').setup {
        top_down = false,
      }
      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 },
          progress = {
            enabled = true,
            -- Lsp Progress is formatted using the builtins for lsp_progress. See config.format.builtin
            -- See the section on formatting for more details on how to customize.
            --- @type NoiceFormat|string
            format = 'lsp_progress',
            --- @type NoiceFormat|string
            format_done = 'lsp_progress_done',
            throttle = 1000 / 30, -- frequency to update lsp progress message
            view = 'mini', -- default: mini
          },
        },
        -- 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,
  },
  {
    '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 = '󰉀' }, -- ⚐ ⚑ 󰈻 󰈼 󰈽 󰈾 󰈿 󰉀
    },
  },
  {
    'Bekaboo/deadcolumn.nvim',
    event = { 'BufReadPre', 'BufNewFile' },
  },
  {
    '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',
    },
    config = 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,
  },
  {
    '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,
  },
  {
    'nvim-lualine/lualine.nvim',
    lazy = false,
    dependencies = {
      'nvim-tree/nvim-web-devicons',
      'yavorski/lualine-macro-recording.nvim',
    },
    config = function()
      require('lualine').setup {
        options = {
          theme = 'horizon',
        },
        sections = {
          lualine_a = { 'mode' },
          lualine_b = { 'branch', 'diff', 'diagnostics' },
          lualine_c = { { 'macro_recording', color = { fg = '#ff9e3b' } }, 'filename', 'locatoin' },
          lualine_x = { 'encoding', 'fileformat', 'filetype' },
          lualine_y = { 'progress' },
          lualine_z = { 'location' },
        },
      }
    end,
  },
  {
    'akinsho/bufferline.nvim',
    dependencies = {
      'nvim-tree/nvim-web-devicons',
      {
        'tiagovla/scope.nvim',
        config = function()
          require('scope').setup {}
          require('telescope').load_extension 'scope'
        end,
      },
    },
    config = function()
      vim.opt.termguicolors = true
      require('bufferline').setup {}
    end,
  },
  'sindrets/diffview.nvim',
  {
    'MeanderingProgrammer/dashboard.nvim',
    enable = true,
    event = 'VimEnter',
    dependencies = {
      'MaximilianLloyd/ascii.nvim',
    },
    init = function()
      vim.api.nvim_create_autocmd({ 'BufWinEnter', 'VimEnter' }, {
        pattern = { 'dashboard', 'text', 'help', '*' },
        callback = function()
          vim.b.minitrailspace_disable = true
          vim.opt_local.list = false
          vim.opt_local.spell = false
          vim.opt_local.colorcolumn = '0'
        end,
      })
    end,
    config = function()
      -- Do not show trailing space in unmodifiable types
      require('dashboard').setup {
        -- Dashboard header
        header = custom_headers.sharp,
        -- List of directory paths, or functions that return paths
        directories = {
          '~/.config/nvim',
          '~/Documents/code',
          '~/Documents/novel',
        },
        -- Format to display date in
        date_format = '%Y-%m-%d %H:%M:%S',
        -- Sections to add at bottom, these can be string references to
        -- functions in sections.lua, custom strings, or custom functions
        footer = {
          [[                                                                        ]],
          [[   Theme                                                           ;ft ]],
          [[   Git                                                             ␣gg ]],
          [[   Find File                                                       ;ff ]],
          [[ 󰈚  Recent Files                                                    ;fo ]],
          [[   Find Word                                                       ;fw ]],
          [[   Bookmarks                                                       ;fm ]],
          [[                                                                        ]],
          [[   Change Directory                                                ;cd ]],
          [[   Files                                                            F5 ]],
          [[   Terminal                                                        F12 ]],
        },

        -- Gets called after directory is changed and is provided with the
        -- directory path as an argument
        on_load = function(path)
          -- Do nothing
        end,
        -- Highlight groups to use for various components
        highlight_groups = {
          header = 'Constant',
          icon = 'Type',
          directory = 'Delimiter',
          hotkey = 'Statement',
        },
      }
    end,
  },
}
