From c01b7077ffcc3a0770004de06f69b26e99a1afc4 Mon Sep 17 00:00:00 2001
From: Luca Bilke <luca@asmara.fritz.box>
Date: Wed, 24 Jan 2024 00:48:37 +0100
Subject: [PATCH] Initial work on massive refactor

---
 .config/nvim/lua/config/icons.lua             |  43 +--
 .config/nvim/lua/config/keymaps.lua           | 337 ++++++++++++++----
 .config/nvim/lua/config/options.lua           |  88 ++---
 .config/nvim/lua/funcs.lua                    | 159 +++++----
 .config/nvim/lua/plugins/cmp/init.lua         |   4 +-
 .config/nvim/lua/plugins/dap/dap-ui.lua       |   5 -
 .config/nvim/lua/plugins/dap/dap.lua          |  88 -----
 .config/nvim/lua/plugins/lazy.lua             |   8 -
 .config/nvim/lua/plugins/lsp/aerial.lua       |  31 ++
 .config/nvim/lua/plugins/lsp/init.lua         |   5 +-
 .config/nvim/lua/plugins/lsp/lspconfig.lua    |  13 +
 .../nvim/lua/plugins/lsp/mason-lspconfig.lua  |  67 ++--
 .../nvim/lua/plugins/lsp/mason-null-ls.lua    |   7 +
 .config/nvim/lua/plugins/lsp/mason.lua        |  17 +-
 .config/nvim/lua/plugins/lsp/null-ls.lua      |  39 +-
 .config/nvim/lua/plugins/misc/alpha.lua       |   4 +-
 .config/nvim/lua/plugins/misc/bufferline.lua  | 109 +-----
 .config/nvim/lua/plugins/misc/comment.lua     |   5 -
 .config/nvim/lua/plugins/misc/gitsigns.lua    |  25 +-
 .config/nvim/lua/plugins/misc/init.lua        |   8 +-
 .config/nvim/lua/plugins/misc/lf.lua          |   8 +-
 .config/nvim/lua/plugins/misc/lualine.lua     |   6 +-
 .../lua/plugins/misc/telescope-fzf-native.lua |   5 +
 .config/nvim/lua/plugins/misc/telescope.lua   |  47 +++
 .config/nvim/lua/plugins/misc/toggleterm.lua  |  28 +-
 .config/nvim/lua/plugins/misc/ufo.lua         |  35 ++
 .config/nvim/lua/plugins/misc/which-key.lua   |  53 +--
 .config/nvim/todo                             |   3 +
 28 files changed, 717 insertions(+), 530 deletions(-)
 create mode 100644 .config/nvim/lua/plugins/lsp/aerial.lua
 create mode 100644 .config/nvim/lua/plugins/lsp/lspconfig.lua
 create mode 100644 .config/nvim/lua/plugins/lsp/mason-null-ls.lua
 create mode 100644 .config/nvim/lua/plugins/misc/telescope-fzf-native.lua
 create mode 100644 .config/nvim/lua/plugins/misc/telescope.lua
 create mode 100644 .config/nvim/lua/plugins/misc/ufo.lua
 create mode 100644 .config/nvim/todo

diff --git a/.config/nvim/lua/config/icons.lua b/.config/nvim/lua/config/icons.lua
index 47bc42a9..268b3360 100644
--- a/.config/nvim/lua/config/icons.lua
+++ b/.config/nvim/lua/config/icons.lua
@@ -1,4 +1,15 @@
 return {
+    Diagnostic = "󰒡",
+    DiagnosticError = "",
+    DiagnosticHint = "󰌵",
+    DiagnosticInfo = "󰋼",
+    DiagnosticWarn = "",
+    PackageInstalled = "",
+    PackagePending = "",
+    PackageUninstalled = "",
+    Selected = "❯",
+
+
     kind = {
         Array = "",
         Boolean = "",
@@ -70,15 +81,16 @@ return {
         Stacks = " ",
         Scopes = "",
         Watches = "󰂥",
-        DebugConsole = " ",
+        Debug = "",
         Calendar = "",
-        Check = "",
+        Check = "",
         ChevronRight = ">",
         ChevronShortDown = "",
         ChevronShortLeft = "",
         ChevronShortRight = "",
         ChevronShortUp = "",
         Circle = "",
+        Clear = "󰃢",
         Close = "󰅖",
         CloudDownload = "",
         CMD = "",
@@ -92,9 +104,10 @@ return {
         Ellipsis = "…",
         EmptyFolder = "",
         EmptyFolderOpen = "",
-        File = "",
-        FileSymlink = "",
+        EmptyFile = "",
+        File = "",
         Files = "",
+        FileSymlink = "",
         FindFile = "󰈞",
         FindText = "󰊄",
         Fire = "",
@@ -112,7 +125,6 @@ return {
         List = "",
         Lock = "",
         MinusCircle = "",
-        NewFile = "",
         Note = "",
         Package = "",
         Pencil = "󰏫",
@@ -122,11 +134,13 @@ return {
         SignIn = "",
         SignOut = "",
         Sleep = "󰒲",
-        Tab = "󰌒",
+        Save = "",
+        Tab = "󰓩",
         Table = "",
         Target = "",
         Telescope = "",
         Text = "",
+        Terminal = "",
         Tree = "",
         Triangle = "󰐊",
         triangleshortarrowdown = "",
@@ -134,21 +148,7 @@ return {
         triangleshortarrowright = "",
         triangleshortarrowup = "",
     },
-    diagnostics = {
-        BoldError = "",
-        Error = "",
-        BoldWarning = "",
-        Warning = "",
-        BoldInformation = "",
-        Information = "",
-        BoldQuestion = "",
-        Question = "",
-        BoldHint = "",
-        Hint = "󰌶",
-        Debug = "",
-        Trace = "✎",
-    },
-    progress = { "", "", "", "", "", "", "", "", "", "", "", "", "" },
+    -- progress = { "", "", "", "", "", "", "", "", "", "", "", "", "" },
     misc = {
         Robot = "󰚩",
         Squirrel = "",
@@ -158,5 +158,6 @@ return {
         Package = "",
         CircuitBoard = "",
         Vim = "",
+        Git = ""
     },
 }
diff --git a/.config/nvim/lua/config/keymaps.lua b/.config/nvim/lua/config/keymaps.lua
index 065daf8e..37815c07 100644
--- a/.config/nvim/lua/config/keymaps.lua
+++ b/.config/nvim/lua/config/keymaps.lua
@@ -1,72 +1,281 @@
-local maps = {
-    n = {
-        -- Navigate buffers
-        { "<C-l>", ":bnext<CR>" },
-        { "<C-h>", ":bprevious<CR>" },
-        -- lsp
-        { "gD", vim.lsp.buf.declaration },
-        { "gd", vim.lsp.buf.definition },
-        { "K",  vim.lsp.buf.hover },
-        { "gI", vim.lsp.buf.implementation },
-        { "gr", vim.lsp.buf.references },
-        { "gl", vim.diagnostic.open_float },
-    },
-    i = {
-        -- Delete last word with ctrl + del
-        { "<C-BS>", "<C-W>" },
-    },
-    v = {
-        -- Better paste
-        -- { "p", '"_dP' },
-    },
+local icons = require("config.icons")
+local funcs = require("funcs")
+
+local maps = funcs.empty_map_table()
+local sections = {
+    p = { desc = icons.ui.Package .. " Packages" },
+    b = { desc = icons.ui.Tab .. " Buffers" },
+    bs = { desc = icons.ui.Tab .. " Sort Buffers" },
+    d = { desc = icons.ui.Debug .. " Debugger" },
+    g = { desc = icons.misc.Git .. " Git" },
+    f = { desc = icons.ui.Search .. " Find" },
+    l = { desc = icons.ui.Note .. " LSP" },
+    u = { desc = icons.ui.Gear .. " Utility" },
+    t = { desc = icons.ui.Terminal .. " Terminal" },
 }
 
-local wkmaps = {
-    n = {
-        ["w"] = { "<cmd>w!<CR>", "Save" },
-        ["q"] = { require("funcs").buf_kill, "Close" },
-        ["h"] = { "<cmd>nohlsearch<CR>", "Clear Highlights" },
-        ["n"] = { "<cmd>ene<CR>", "New File" },
-        u = {
-            name = "Utility",
-            c = { "<cmd>w!<CR><cmd>!compiler \"%:p\"<CR>", "Compile" },
-        },
-        l = {
-            name = "LSP",
-            a = { vim.lsp.buf.code_action, "Code Action" },
-            f = { function() require("funcs").format({ async = true }) end, "Format" },
-            j = { vim.diagnostic.goto_next, "Next Diagnostic" },
-            k = { vim.diagnostic.goto_prev, "Prev Diagnostic" },
-            l = { vim.lsp.codelens.run, "CodeLens Action" },
-            q = { vim.diagnostic.setloclist, "Quickfix" },
-            r = { vim.lsp.buf.rename, "Rename" },
-        },
-    },
-}
+-- Standard --
+maps.n["j"] = { "v:count == 0 ? 'gj' : 'j'", expr = true, desc = "Move cursor down" }
+maps.n["k"] = { "v:count == 0 ? 'gk' : 'k'", expr = true, desc = "Move cursor up" }
+maps.n["<Leader>w"] = { "<Cmd>w<CR>", desc = "Write buffer" }
+maps.n["<Leader>q"] = { "<Cmd>conf q<CR>", desc = "Quit" }
+maps.n["<Leader>Q"] = { "<Cmd>conf qa<CR>", desc = "Quit all" }
+maps.n["<Leader>n"] = { "<Cmd>ene<CR>", desc = "New buffer" }
+maps.n["<C-s>"] = { "<cmd>w!<cr>", desc = "Force write buffer" }
+maps.n["<C-q>"] = { "<cmd>qa!<cr>", desc = "Force quit all" }
+maps.n["|"] = { "<cmd>vsplit<cr>", desc = "Vertical split" }
+maps.n["\\"] = { "<cmd>split<cr>", desc = "Horizontal split" }
+maps.v["<"] = { "<gv", desc = "Unindent line" }
+maps.v[">"] = { ">gv", desc = "Indent line" }
+maps.n["<Leader>c"] = { function() funcs.buf_close() end, desc = "Close buffer" }
+maps.n["<Leader>C"] = { function() funcs.buf_close(0, true) end, desc = "Force close buffer" }
+maps.n["<C-b>"] = { "<C-a>" }
+maps.n["<C-f>"] = { "<Nop>" }
+maps.i["<C-h>"] = { "<C-W>" }
 
-local whichkey = require('which-key')
+-- Window Navigation --
+maps.n["<C-h>"] = { "<C-w>h", desc = "Move to left split" }
+maps.n["<C-j>"] = { "<C-w>j", desc = "Move to below split" }
+maps.n["<C-k>"] = { "<C-w>k", desc = "Move to above split" }
+maps.n["<C-l>"] = { "<C-w>l", desc = "Move to right split" }
+maps.n["<C-Up>"] = { "<cmd>resize -2<CR>", desc = "Resize split up" }
+maps.n["<C-Down>"] = { "<cmd>resize +2<CR>", desc = "Resize split down" }
+maps.n["<C-Left>"] = { "<cmd>vertical resize -2<CR>", desc = "Resize split left" }
+maps.n["<C-Right>"] = { "<cmd>vertical resize +2<CR>", desc = "Resize split right" }
+maps.t["<C-h>"] = { "<cmd>wincmd h<cr>", desc = "Terminal left window navigation" }
+maps.t["<C-j>"] = { "<cmd>wincmd j<cr>", desc = "Terminal down window navigation" }
+maps.t["<C-k>"] = { "<cmd>wincmd k<cr>", desc = "Terminal up window navigation" }
+maps.t["<C-l>"] = { "<cmd>wincmd l<cr>", desc = "Terminal right window navigation" }
 
-for mode, binds in pairs(maps) do
-    for _, bind in pairs(binds) do
-        local key = bind[1]
-        local cmd = ""
-        local opt = { silent = true, noremap = true }
-        if type(bind[2]) == "string" then
-            cmd = bind[2]
-        elseif type(bind[2]) == "function" then
-            opt["callback"] = bind[2]
-        end
-        vim.api.nvim_set_keymap(mode, key, cmd, opt)
+-- Plugin Manager --
+maps.n["<Leader>p"] = sections.p
+maps.n["<Leader>ph"] = { function() require("lazy").home() end, desc = "Home" }
+maps.n["<Leader>pi"] = { function() require("lazy").install() end, desc = "Install" }
+maps.n["<Leader>pu"] = { function() require("lazy").update() end, desc = "Update" }
+maps.n["<Leader>ps"] = { function() require("lazy").sync() end, desc = "Sync" }
+maps.n["<Leader>px"] = { function() require("lazy").clean() end, desc = "Clean" }
+maps.n["<Leader>pc"] = { function() require("lazy").check() end, desc = "Check" }
+maps.n["<Leader>pl"] = { function() require("lazy").log() end, desc = "Log" }
+maps.n["<Leader>pr"] = { function() require("lazy").restore() end, desc = "Restore" }
+maps.n["<Leader>pp"] = { function() require("lazy").profile() end, desc = "Profile" }
+maps.n["<Leader>pd"] = { function() require("lazy").debug() end, desc = "Debug" }
+maps.n["<Leader>p?"] = { function() require("lazy").help() end, desc = "Help" }
+
+if funcs.is_available("bufferline.nvim") then
+    maps.n["<S-l>"] = { function() require("bufferline").cycle(1) end, desc = "Switch to next buffer" }
+    maps.n["<S-h>"] = { function() require("bufferline").cycle(-1) end, desc = "Switch to previous buffer" }
+    maps.n["<A-l>"] = { function() require("bufferline").move(1) end, desc = "Move buffer to next" }
+    maps.n["<A-h>"] = { function() require("bufferline").move(-1) end, desc = "Move buffer to previous" }
+    maps.n["<Leader>b"] = sections.b
+    maps.n["<Leader>bc"] = { function() require("bufferline").close_others() end, desc = "Close other buffers" }
+    maps.n["<Leader>bl"] = {
+        function() require("bufferline").close_in_direction("left") end,
+        desc = "Close lefthand buffers"
+    }
+    maps.n["<Leader>br"] = {
+        function() require("bufferline").close_in_direction("right") end,
+        desc = "Close righthand buffers"
+    }
+    maps.n["<Leader>bs"] = sections.bs
+    maps.n["<Leader>bse"] = { function() require("bufferline").sort_by("extension") end, desc = "By extension" }
+    maps.n["<Leader>bsd"] = { function() require("bufferline").sort_by("directory") end, desc = "By directory" }
+    maps.n["<Leader>bsr"] = {
+        function() require("bufferline").sort_by("relative_directory") end,
+        desc = "By relative directory"
+    }
+    maps.n["<Leader>bst"] = { function() require("bufferline").sort_by("tabs") end, desc = "By tabs" }
+end
+
+if funcs.is_available("Comment.nvim") then
+    maps.n["<Leader>/"] = {
+        function() require("Comment.api").toggle.linewise.count(vim.v.count > 0 and vim.v.count or 1) end,
+        desc = "Toggle comment line",
+    }
+    maps.v["<Leader>/"] = {
+        "<esc><cmd>lua require('Comment.api').toggle.linewise(vim.fn.visualmode())<cr>",
+        desc = "Toggle comment for selection",
+    }
+end
+
+if funcs.is_available("gitsigns.nvim") then
+    maps.n["<Leader>g"] = sections.g
+    maps.n["]g"] = { function() require("gitsigns").next_hunk() end, desc = "Next Git hunk" }
+    maps.n["[g"] = { function() require("gitsigns").prev_hunk() end, desc = "Previous Git hunk" }
+    maps.n["<Leader>gl"] = { function() require("gitsigns").blame_line() end, desc = "View Git blame" }
+    maps.n["<Leader>gL"] = { function() require("gitsigns").blame_line { full = true } end, desc = "View full Git blame" }
+    maps.n["<Leader>gp"] = { function() require("gitsigns").preview_hunk() end, desc = "Preview Git hunk" }
+    maps.n["<Leader>gh"] = { function() require("gitsigns").reset_hunk() end, desc = "Reset Git hunk" }
+    maps.n["<Leader>gr"] = { function() require("gitsigns").reset_buffer() end, desc = "Reset Git buffer" }
+    maps.n["<Leader>gs"] = { function() require("gitsigns").stage_hunk() end, desc = "Stage Git hunk" }
+    maps.n["<Leader>gS"] = { function() require("gitsigns").stage_buffer() end, desc = "Stage Git buffer" }
+    maps.n["<Leader>gu"] = { function() require("gitsigns").undo_stage_hunk() end, desc = "Unstage Git hunk" }
+    maps.n["<Leader>gd"] = { function() require("gitsigns").diffthis() end, desc = "View Git diff" }
+end
+
+if funcs.is_available("lf.nvim") then
+    maps.n["<Leader>e"] = { "<Cmd>Lf<CR>", desc = "File Manager" }
+end
+
+if funcs.is_available("mason.nvim") then
+    maps.n["<Leader>pm"] = { "<cmd>Mason<cr>", desc = "Mason" }
+    maps.n["<Leader>pM"] = { "<cmd>MasonUpdateAll<cr>", desc = "Update Mason Packages" }
+end
+
+if funcs.is_available "aerial.nvim" then
+    maps.n["<leader>l"] = sections.l
+    maps.n["<leader>lS"] = { function() require("aerial").toggle() end, desc = "Symbols outline" }
+end
+
+if funcs.is_available("telescope.nvim") then
+    maps.n["<Leader>f"] = sections.f
+    maps.n["<Leader>g"] = sections.g
+    maps.n["<Leader>gb"] = {
+        function() require("telescope.builtin").git_branches { use_file_path = true } end,
+        desc = "Git branches"
+    }
+    maps.n["<Leader>gc"] = {
+        function() require("telescope.builtin").git_commits { use_file_path = true } end,
+        desc = "Git commits (repository)",
+    }
+    maps.n["<Leader>gC"] = {
+        function() require("telescope.builtin").git_bcommits { use_file_path = true } end,
+        desc = "Git commits (current file)",
+    }
+    maps.n["<Leader>gt"] = {
+        function() require("telescope.builtin").git_status { use_file_path = true } end,
+        desc = "Git status"
+    }
+    maps.n["<Leader>f<CR>"] = { function() require("telescope.builtin").resume() end, desc = "Resume previous search" }
+    maps.n["<Leader>f'"] = { function() require("telescope.builtin").marks() end, desc = "Find marks" }
+    maps.n["<Leader>f/"] = {
+        function() require("telescope.builtin").current_buffer_fuzzy_find() end,
+        desc = "Find words in current buffer"
+    }
+    maps.n["<Leader>fb"] = { function() require("telescope.builtin").buffers() end, desc = "Find buffers" }
+    maps.n["<Leader>fc"] = { function() require("telescope.builtin").grep_string() end, desc = "Find word under cursor" }
+    maps.n["<Leader>fC"] = { function() require("telescope.builtin").commands() end, desc = "Find commands" }
+    maps.n["<Leader>ff"] = { function() require("telescope.builtin").find_files() end, desc = "Find files" }
+    maps.n["<Leader>fF"] = {
+        function() require("telescope.builtin").find_files { hidden = true, no_ignore = true } end,
+        desc = "Find all files",
+    }
+    maps.n["<Leader>fh"] = { function() require("telescope.builtin").help_tags() end, desc = "Find help" }
+    maps.n["<Leader>fk"] = { function() require("telescope.builtin").keymaps() end, desc = "Find keymaps" }
+    maps.n["<Leader>fm"] = { function() require("telescope.builtin").man_pages() end, desc = "Find man" }
+    maps.n["<Leader>fo"] = { function() require("telescope.builtin").oldfiles() end, desc = "Find history" }
+    maps.n["<Leader>fr"] = { function() require("telescope.builtin").registers() end, desc = "Find registers" }
+    maps.n["<Leader>fw"] = { function() require("telescope.builtin").live_grep() end, desc = "Find words" }
+    maps.n["<Leader>fW"] = {
+        function()
+            require("telescope.builtin").live_grep {
+                additional_args = function(args) return vim.list_extend(args, { "--hidden", "--no-ignore" }) end,
+            }
+        end,
+        desc = "Find words in all files",
+    }
+    maps.n["<Leader>l"] = sections.l
+    maps.n["<Leader>ls"] = {
+        function()
+            local aerial_avail, _ = pcall(require, "aerial")
+            if aerial_avail then
+                require("telescope").extensions.aerial.aerial()
+            else
+                require("telescope.builtin").lsp_document_symbols()
+            end
+        end,
+        desc = "Search symbols",
+    }
+end
+
+if funcs.is_available("toggleterm.nvim") then
+    maps.n["<leader>t"] = sections.t
+    if vim.fn.executable "lazygit" == 1 then
+        maps.n["<leader>g"] = sections.g
+        maps.n["<leader>gg"] = {
+            function()
+                local worktree = funcs.file_worktree()
+                local flags = worktree
+                    and (" --work-tree=%s --git-dir=%s"):format(worktree.toplevel, worktree.gitdir)
+                    or ""
+                funcs.toggle_term_cmd("lazygit " .. flags)
+            end,
+            desc = "ToggleTerm lazygit",
+        }
+        maps.n["<leader>tl"] = maps.n["<leader>gg"]
+    end
+    if vim.fn.executable "node" == 1 then
+        maps.n["<leader>tn"] = { function() funcs.toggle_term_cmd "node" end, desc = "ToggleTerm node" }
+    end
+    if vim.fn.executable("gdu") == 1 then
+        maps.n["<leader>tu"] = { function() funcs.toggle_term_cmd("gdu") end, desc = "ToggleTerm gdu" }
+    end
+    if vim.fn.executable "btm" == 1 then
+        maps.n["<leader>tt"] = { function() funcs.toggle_term_cmd "btm" end, desc = "ToggleTerm btm" }
+    end
+    local python = vim.fn.executable "python" == 1 and "python" or vim.fn.executable "python3" == 1 and "python3"
+    if python then maps.n["<leader>tp"] = { function() funcs.toggle_term_cmd(python) end, desc = "ToggleTerm python" } end
+    maps.n["<leader>tf"] = { "<cmd>ToggleTerm direction=float<cr>", desc = "ToggleTerm float" }
+    maps.n["<leader>th"] = { "<cmd>ToggleTerm size=10 direction=horizontal<cr>", desc = "ToggleTerm horizontal split" }
+    maps.n["<leader>tv"] = { "<cmd>ToggleTerm size=80 direction=vertical<cr>", desc = "ToggleTerm vertical split" }
+    maps.n["<F7>"] = { "<cmd>ToggleTerm<cr>", desc = "Toggle terminal" }
+    maps.t["<F7>"] = maps.n["<F7>"]
+    -- TODO: Patch st: https://st.suckless.org/patches/fix_keyboard_input/
+    -- maps.n["<C-'>"] = maps.n["<F7>"]
+    -- maps.t["<C-'>"] = maps.n["<F7>"]
+end
+
+if funcs.is_available "nvim-dap" then
+    local conditional_breakpoint = function()
+        vim.ui.input({ prompt = "Condition: " }, function(condition)
+            if condition then require("dap").set_breakpoint(condition) end
+        end)
+    end
+    maps.n["<leader>d"] = sections.d
+    maps.v["<leader>d"] = sections.d
+    maps.n["<F5>"] = { function() require("dap").continue() end, desc = "Debugger: Start" }
+    maps.n["<S-F5>"] = { function() require("dap").terminate() end, desc = "Debugger: Stop" }
+    maps.n["<S-F9>"] = { conditional_breakpoint, desc = "Debugger: Conditional Breakpoint" }
+    maps.n["<C-F5>"] = { function() require("dap").restart_frame() end, desc = "Debugger: Restart" }
+    maps.n["<F6>"] = { function() require("dap").pause() end, desc = "Debugger: Pause" }
+    maps.n["<F9>"] = { function() require("dap").toggle_breakpoint() end, desc = "Debugger: Toggle Breakpoint" }
+    maps.n["<F10>"] = { function() require("dap").step_over() end, desc = "Debugger: Step Over" }
+    maps.n["<F11>"] = { function() require("dap").step_into() end, desc = "Debugger: Step Into" }
+    maps.n["<S-F11>"] = { function() require("dap").step_out() end, desc = "Debugger: Step Out" }
+    maps.n["<leader>db"] = { function() require("dap").toggle_breakpoint() end, desc = "Toggle Breakpoint (F9)" }
+    maps.n["<leader>dB"] = { function() require("dap").clear_breakpoints() end, desc = "Clear Breakpoints" }
+    maps.n["<leader>dc"] = { function() require("dap").continue() end, desc = "Start/Continue (F5)" }
+    maps.n["<leader>dC"] = { conditional_breakpoint, desc = "Conditional Breakpoint (S-F9)" }
+    maps.n["<leader>di"] = { function() require("dap").step_into() end, desc = "Step Into (F11)" }
+    maps.n["<leader>do"] = { function() require("dap").step_over() end, desc = "Step Over (F10)" }
+    maps.n["<leader>dO"] = { function() require("dap").step_out() end, desc = "Step Out (S-F11)" }
+    maps.n["<leader>dq"] = { function() require("dap").close() end, desc = "Close Session" }
+    maps.n["<leader>dQ"] = { function() require("dap").terminate() end, desc = "Terminate Session (S-F5)" }
+    maps.n["<leader>dp"] = { function() require("dap").pause() end, desc = "Pause (F6)" }
+    maps.n["<leader>dr"] = { function() require("dap").restart_frame() end, desc = "Restart (C-F5)" }
+    maps.n["<leader>dR"] = { function() require("dap").repl.toggle() end, desc = "Toggle REPL" }
+    maps.n["<leader>ds"] = { function() require("dap").run_to_cursor() end, desc = "Run To Cursor" }
+
+    if funcs.is_available "nvim-dap-ui" then
+        maps.n["<leader>dE"] = {
+            function()
+                vim.ui.input({ prompt = "Expression: " }, function(expr)
+                    if expr then require("dapui").eval(expr, { enter = true }) end
+                end)
+            end,
+            desc = "Evaluate Input",
+        }
+        maps.v["<leader>dE"] = { function() require("dapui").eval() end, desc = "Evaluate Input" }
+        maps.n["<leader>du"] = { function() require("dapui").toggle() end, desc = "Toggle Debugger UI" }
+        maps.n["<leader>dh"] = { function() require("dap.ui.widgets").hover() end, desc = "Debugger Hover" }
     end
 end
 
-for mode, binds in pairs(wkmaps) do
-    whichkey.register(binds, {
-        mode = mode,
-        prefix = "<leader>",
-        buffer = nil,
-        silent = true,
-        noremap = true,
-        nowait = true,
-    })
+if funcs.is_available "nvim-ufo" then
+    maps.n["zR"] = { function() require("ufo").openAllFolds() end, desc = "Open all folds" }
+    maps.n["zM"] = { function() require("ufo").closeAllFolds() end, desc = "Close all folds" }
+    maps.n["zr"] = { function() require("ufo").openFoldsExceptKinds() end, desc = "Fold less" }
+    maps.n["zm"] = { function() require("ufo").closeFoldsWith() end, desc = "Fold more" }
+    maps.n["zp"] = { function() require("ufo").peekFoldedLinesUnderCursor() end, desc = "Peek fold" }
 end
+
+funcs.set_mappings(maps)
diff --git a/.config/nvim/lua/config/options.lua b/.config/nvim/lua/config/options.lua
index 28c7a096..a632a3c9 100644
--- a/.config/nvim/lua/config/options.lua
+++ b/.config/nvim/lua/config/options.lua
@@ -1,46 +1,52 @@
-local g          = vim.g
-local o          = vim.opt
-local d          = vim.diagnostic.config
+local g            = vim.g
+local o            = vim.opt
+local d            = vim.diagnostic.config
 
-g.mapleader      = " "
-g.maplocalleader = "	"
+g.mapleader        = " "
+g.maplocalleader   = "	"
 g.vim_json_conceal = 0
+g.git_worktrees    = {
+    { toplevel = vim.env.HOME, gitdir = vim.env.XDG_DATA_HOME .. "/dots" },
+}
+g.max_lines = 1000
+g.max_size = 1024 * 100
 
-o.undodir        = vim.fn.stdpath "cache" .. "/undo"
-o.clipboard      = "unnamedplus"
-o.conceallevel   = 0
-o.numberwidth    = 3
-o.hlsearch       = true
-o.ignorecase     = true
-o.showmode       = false
-o.smartindent    = true
-o.splitbelow     = true
-o.splitbelow     = true
-o.splitbelow     = true
-o.updatetime     = 250
-o.writebackup    = false
-o.expandtab      = true
-o.shiftwidth     = 4
-o.tabstop        = 4
-o.cursorline     = true
-o.signcolumn     = "yes"
-o.wrap           = false
-o.scrolloff      = 8
-o.sidescrolloff  = 8
-o.undofile       = true
-o.title          = true
-o.mouse          = ""
-
-o.termguicolors  = true
-o.timeoutlen     = 500
-o.foldmethod     = "expr"
-o.foldlevelstart = 99
-o.foldexpr       = "nvim_treesitter#foldexpr()"
-o.number         = true
-o.relativenumber = true
-o.laststatus     = 3
-o.modeline       = true
-o.modelines      = 3
-o.listchars      = "eol:$,tab:>-,trail:~,extends:>,precedes:<"
+o.undodir          = vim.fn.stdpath "cache" .. "/undo"
+o.clipboard        = "unnamedplus"
+o.conceallevel     = 0
+o.numberwidth      = 3
+o.hlsearch         = true
+o.ignorecase       = true
+o.showmode         = false
+o.smartindent      = true
+o.splitbelow       = true
+o.splitbelow       = true
+o.splitbelow       = true
+o.updatetime       = 250
+o.writebackup      = false
+o.expandtab        = true
+o.shiftwidth       = 4
+o.tabstop          = 4
+o.cursorline       = true
+o.signcolumn       = "yes"
+o.wrap             = false
+o.scrolloff        = 8
+o.sidescrolloff    = 8
+o.undofile         = true
+o.title            = true
+o.mouse            = ""
+o.backspace        = "indent,eol,start"
+o.termguicolors    = true
+o.timeoutlen       = 500
+o.foldenable       = true
+o.foldmethod       = "expr"
+o.foldlevelstart   = 99
+o.foldexpr         = "nvim_treesitter#foldexpr()"
+o.number           = true
+o.relativenumber   = true
+o.laststatus       = 3
+o.modeline         = true
+o.modelines        = 3
+o.listchars        = "eol:$,tab:>-,trail:~,extends:>,precedes:<"
 
 d({ virtual_text = false })
diff --git a/.config/nvim/lua/funcs.lua b/.config/nvim/lua/funcs.lua
index 50627d0c..a5ba7e0e 100644
--- a/.config/nvim/lua/funcs.lua
+++ b/.config/nvim/lua/funcs.lua
@@ -36,76 +36,115 @@ function M.format(opts)
     return vim.lsp.buf.format(opts)
 end
 
--- Modified version of a function stolen from LunarVim
-function M.buf_kill(kill_command, bufnr, force)
-    kill_command = kill_command or "bd"
+-- Ripped from AstroNvim
+function M.buf_close(bufnr, force)
+    if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
+    local buftype = vim.api.nvim_get_option_value("buftype", { buf = bufnr })
+    vim.cmd(("silent! %s %d"):format((force or buftype == "terminal") and "bdelete!" or "confirm bdelete", bufnr))
+end
 
-    local bo = vim.bo
-    local api = vim.api
-    local fmt = string.format
-    local fnamemodify = vim.fn.fnamemodify
+-- Ripped from AstroNvim
+function M.is_available(plugin)
+    local lazy_config_avail, lazy_config = pcall(require, "lazy.core.config")
+    return lazy_config_avail and lazy_config.spec.plugins[plugin] ~= nil
+end
 
-    if bufnr == 0 or bufnr == nil then
-        bufnr = api.nvim_get_current_buf()
+-- Ripped from AstroNvim
+-- TODO: Check this on 0.10.0 release
+function M.empty_map_table()
+    local maps = {}
+    for _, mode in ipairs { "", "n", "v", "x", "s", "o", "!", "i", "l", "c", "t" } do
+        maps[mode] = {}
     end
-
-    local bufname = api.nvim_buf_get_name(bufnr)
-
-    if not force then
-        local warning
-        if bo[bufnr].modified then
-            warning = fmt([[No write since last change for (%s)]], fnamemodify(bufname, ":t"))
-        elseif api.nvim_buf_get_option(bufnr, "buftype") == "terminal" then
-            warning = fmt([[Terminal %s will be killed]], bufname)
-        end
-        if warning then
-            vim.ui.input({
-                prompt = string.format([[%s. Close it anyway? [y]es or [n]o (default: no): ]], warning),
-            }, function(choice)
-                if choice:match "ye?s?" then force = true end
-            end)
-            if not force then return end
+    if vim.fn.has "nvim-0.10.0" == 1 then
+        for _, abbr_mode in ipairs { "ia", "ca", "!a" } do
+            maps[abbr_mode] = {}
         end
     end
+    return maps
+end
 
-    -- Get list of windows IDs with the buffer to close
-    local windows = vim.tbl_filter(function(win)
-        return api.nvim_win_get_buf(win) == bufnr
-    end, api.nvim_list_wins())
-
-    if #windows == 0 then return end
-
-    if force then
-        kill_command = kill_command .. "!"
+-- Ripped from AstroNvim and modified
+function M.toggle_term_cmd(opts)
+    if not vim.g.user_terminals then
+        vim.g.user_terminals = {}
     end
+    local terms = vim.g.user_terminals
+    -- if a command string is provided, create a basic table for Terminal:new() options
+    if type(opts) == "string" then opts = { cmd = opts, hidden = true } end
+    local num = vim.v.count > 0 and vim.v.count or 1
+    -- if terminal doesn't exist yet, create it
+    if not terms[opts.cmd] then terms[opts.cmd] = {} end
+    if not terms[opts.cmd][num] then
+        if not opts.count then opts.count = vim.tbl_count(terms) * 100 + num end
+        if not opts.on_exit then opts.on_exit = function() terms[opts.cmd][num] = nil end end
+        terms[opts.cmd][num] = require("toggleterm.terminal").Terminal:new(opts)
+    end
+    -- toggle the terminal
+    terms[opts.cmd][num]:toggle()
+end
 
-    -- Get list of active buffers
-    local buffers = vim.tbl_filter(function(buf)
-        return api.nvim_buf_is_valid(buf) and bo[buf].buflisted
-    end, api.nvim_list_bufs())
-
-    -- If there is only one buffer (which has to be the current one), vim will
-    -- create a new buffer on :bd.
-    -- For more than one buffer, pick the previous buffer (wrapping around if necessary)
-    if #buffers > 1 then
-        for i, v in ipairs(buffers) do
-            if v == bufnr then
-                local prev_buf_idx = i == 1 and (#buffers - 1) or (i - 1)
-                local prev_buffer = buffers[prev_buf_idx]
-                for _, win in ipairs(windows) do
-                    api.nvim_win_set_buf(win, prev_buffer)
-                end
-            end
+-- Ripped from AstroNvim and modified
+-- TODO: test this
+function M.file_worktree(file, worktrees)
+    worktrees = worktrees or vim.g.git_worktrees
+    if not worktrees then return end
+    file = file or vim.fn.expand("%")
+    for _, worktree in ipairs(worktrees) do
+        local r = vim.fn.system({
+            "git",
+            "--work-tree",
+            worktree.toplevel,
+            "--git-dir",
+            worktree.gitdir,
+            "ls-files",
+            "--error-unmatch",
+            file
+        }):wait()
+        if r.code == 0 then
+            return worktree
         end
-    else
-        vim.cmd('q!')
-    end
-
-    -- Check if buffer still exists, to ensure the target buffer wasn't killed
-    -- due to options like bufhidden=wipe.
-    if api.nvim_buf_is_valid(bufnr) and bo[bufnr].buflisted then
-        vim.cmd(string.format("%s %d", kill_command, bufnr))
     end
 end
 
+-- Ripped from AstroNvim
+function M.which_key_register()
+  if M.which_key_queue then
+    local wk_avail, wk = pcall(require, "which-key")
+    if wk_avail then
+      for mode, registration in pairs(M.which_key_queue) do
+        wk.register(registration, { mode = mode })
+      end
+      M.which_key_queue = nil
+    end
+  end
+end
+
+-- Ripped from AstroNvim
+function M.set_mappings(map_table, base)
+  base = base or {}
+  for mode, maps in pairs(map_table) do
+    for keymap, options in pairs(maps) do
+      if options then
+        local cmd = options
+        local keymap_opts = base
+        if type(options) == "table" then
+          cmd = options[1]
+          keymap_opts = vim.tbl_deep_extend("force", keymap_opts, options)
+          keymap_opts[1] = nil
+        end
+        if not cmd or keymap_opts.name then -- which-key mapping
+          if not keymap_opts.name then keymap_opts.name = keymap_opts.desc end
+          if not M.which_key_queue then M.which_key_queue = {} end
+          if not M.which_key_queue[mode] then M.which_key_queue[mode] = {} end
+          M.which_key_queue[mode][keymap] = keymap_opts
+        else -- not which-key mapping
+          vim.keymap.set(mode, keymap, cmd, keymap_opts)
+        end
+      end
+    end
+  end
+  if package.loaded["which-key"] then M.which_key_register() end
+end
+
 return M
diff --git a/.config/nvim/lua/plugins/cmp/init.lua b/.config/nvim/lua/plugins/cmp/init.lua
index ccf574e3..996eaa4f 100644
--- a/.config/nvim/lua/plugins/cmp/init.lua
+++ b/.config/nvim/lua/plugins/cmp/init.lua
@@ -1,4 +1,4 @@
 return {
-    require('plugins.cmp.luasnip'),
-    require('plugins.cmp.cmp'),
+--    require('plugins.cmp.luasnip'),
+--    require('plugins.cmp.cmp'),
 }
diff --git a/.config/nvim/lua/plugins/dap/dap-ui.lua b/.config/nvim/lua/plugins/dap/dap-ui.lua
index 877d7634..932ad445 100644
--- a/.config/nvim/lua/plugins/dap/dap-ui.lua
+++ b/.config/nvim/lua/plugins/dap/dap-ui.lua
@@ -2,11 +2,6 @@ local M = { "rcarriga/nvim-dap-ui" }
 
 local opts = {}
 
-M.keys = {
-    { "<leader>du", function() require("dapui").toggle({}) end, desc = "Dap UI" },
-    { "<leader>de", function() require("dapui").eval() end,     desc = "Eval",  mode = { "n", "v" } },
-}
-
 M.config = function()
     local dap = require("dap")
     local dapui = require("dapui")
diff --git a/.config/nvim/lua/plugins/dap/dap.lua b/.config/nvim/lua/plugins/dap/dap.lua
index 93ac87ea..b2d5e5e9 100644
--- a/.config/nvim/lua/plugins/dap/dap.lua
+++ b/.config/nvim/lua/plugins/dap/dap.lua
@@ -7,89 +7,6 @@ M.dependencies = {
 
 M.event = { "BufReadPre", "BufNewFile" }
 
-M.keys = {
-    {
-        "<leader>dB",
-        function() require("dap").set_breakpoint(vim.fn.input('Breakpoint condition: ')) end,
-        desc = "Breakpoint Condition"
-    },
-    {
-        "<leader>db",
-        function() require("dap").toggle_breakpoint() end,
-        desc = "Toggle Breakpoint"
-    },
-    {
-        "<leader>dc",
-        function() require("dap").continue() end,
-        desc = "Continue"
-    },
-    {
-        "<leader>dC",
-        function() require("dap").run_to_cursor() end,
-        desc = "Run to Cursor"
-    },
-    {
-        "<leader>dg",
-        function() require("dap").goto_() end,
-        desc = "Go to line (no execute)"
-    },
-    {
-        "<leader>di",
-        function() require("dap").step_into() end,
-        desc = "Step Into"
-    },
-    {
-        "<leader>dj",
-        function() require("dap").down() end,
-        desc = "Down"
-    },
-    {
-        "<leader>dk",
-        function() require("dap").up() end,
-        desc = "Up"
-    },
-    {
-        "<leader>dl",
-        function() require("dap").run_last() end,
-        desc = "Run Last"
-    },
-    {
-        "<leader>do",
-        function() require("dap").step_out() end,
-        desc = "Step Out"
-    },
-    {
-        "<leader>dO",
-        function() require("dap").step_over() end,
-        desc = "Step Over"
-    },
-    {
-        "<leader>dp",
-        function() require("dap").pause() end,
-        desc = "Pause"
-    },
-    {
-        "<leader>dr",
-        function() require("dap").repl.toggle() end,
-        desc = "Toggle REPL"
-    },
-    {
-        "<leader>ds",
-        function() require("dap").session() end,
-        desc = "Session"
-    },
-    {
-        "<leader>dt",
-        function() require("dap").terminate() end,
-        desc = "Terminate"
-    },
-    {
-        "<leader>dw",
-        function() require("dap.ui.widgets").hover() end,
-        desc = "Widgets"
-    },
-}
-
 M.config = function()
     local icons = require('config.icons')
     vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" })
@@ -102,11 +19,6 @@ M.config = function()
             numhl = "",
         }
     )
-    require('which-key').register({
-        d = {
-            name = "+debug",
-        },
-    }, { prefix = "<leader>" })
 end
 
 return M
diff --git a/.config/nvim/lua/plugins/lazy.lua b/.config/nvim/lua/plugins/lazy.lua
index 8a9b3d7b..d524fc79 100644
--- a/.config/nvim/lua/plugins/lazy.lua
+++ b/.config/nvim/lua/plugins/lazy.lua
@@ -31,12 +31,4 @@ M.opts = {
     },
 }
 
--- M.keys = {
---     { "<leader>pu", require("lazy").check,   desc = "Check for updates" },
---     { "<leader>pc", require("lazy").clear,   desc = "Clear finished tasks" },
---     { "<leader>pd", require("lazy").debug,   desc = "Show debug information" },
---     { "<leader>pp", require("lazy").profile, desc = "Show profiling information" },
---     { "<leader>ps", require("lazy").sync,    desc = "Install, clean and update plugins" },
--- }
-
 return M
diff --git a/.config/nvim/lua/plugins/lsp/aerial.lua b/.config/nvim/lua/plugins/lsp/aerial.lua
new file mode 100644
index 00000000..a86437a9
--- /dev/null
+++ b/.config/nvim/lua/plugins/lsp/aerial.lua
@@ -0,0 +1,31 @@
+local M = { "stevearc/aerial.nvim" }
+
+M.event = { "BufReadPre", "BufNewFile" }
+
+M.opts = {
+    attach_mode = "global",
+    backends = { "lsp", "treesitter", "markdown", "man" },
+    disable_max_lines = vim.g.max_lines,
+    disable_max_size = vim.g.max_size,
+    layout = { min_width = 28 },
+    show_guides = true,
+    filter_kind = false,
+    guides = {
+        mid_item = "├ ",
+        last_item = "└ ",
+        nested_top = "│ ",
+        whitespace = "  ",
+    },
+    keymaps = {
+        ["[y"] = "actions.prev",
+        ["]y"] = "actions.next",
+        ["[Y"] = "actions.prev_up",
+        ["]Y"] = "actions.next_up",
+        ["{"] = false,
+        ["}"] = false,
+        ["[["] = false,
+        ["]]"] = false,
+    },
+}
+
+return M
diff --git a/.config/nvim/lua/plugins/lsp/init.lua b/.config/nvim/lua/plugins/lsp/init.lua
index 573653fa..2adccc35 100644
--- a/.config/nvim/lua/plugins/lsp/init.lua
+++ b/.config/nvim/lua/plugins/lsp/init.lua
@@ -1,6 +1,9 @@
 return {
-    { "neovim/nvim-lspconfig" },
+    { "folke/neodev.nvim", lazy = true },
+    require('plugins.lsp.lspconfig'),
     require('plugins.lsp.mason'),
     require('plugins.lsp.mason-lspconfig'),
+    require('plugins.lsp.mason-null-ls'),
     require('plugins.lsp.null-ls'),
+    require('plugins.lsp.aerial'),
 }
diff --git a/.config/nvim/lua/plugins/lsp/lspconfig.lua b/.config/nvim/lua/plugins/lsp/lspconfig.lua
new file mode 100644
index 00000000..d802a936
--- /dev/null
+++ b/.config/nvim/lua/plugins/lsp/lspconfig.lua
@@ -0,0 +1,13 @@
+local M = { "neovim/nvim-lspconfig" }
+
+M.dependencies = { "folke/neoconf.nvim", "mason-lspconfig.nvim" }
+
+M.event = { "BufReadPre", "BufNewFile" }
+
+M.cmd = function(_, cmds)
+    if require("funcs").is_available("neoconf.nvim") then
+        table.insert(cmds, "Neoconf")
+    end
+end
+
+return M
diff --git a/.config/nvim/lua/plugins/lsp/mason-lspconfig.lua b/.config/nvim/lua/plugins/lsp/mason-lspconfig.lua
index 66df3f8a..75dd0c42 100644
--- a/.config/nvim/lua/plugins/lsp/mason-lspconfig.lua
+++ b/.config/nvim/lua/plugins/lsp/mason-lspconfig.lua
@@ -2,24 +2,7 @@ local M = { "williamboman/mason-lspconfig.nvim" }
 
 M.dependencies = { "mason.nvim" }
 
-M.event = { "BufReadPre", "BufNewFile" }
-
-M.keys = {
-    { "<leader>li", "<cmd>LspInfo<cr>",      desc = "LSP Info" },
-    { "<leader>la", vim.lsp.buf.code_action, desc = "Code Action" },
-    {
-        "<leader>lf",
-        function()
-            require("funcs").format({ async = true })
-        end,
-        desc = "Format",
-    },
-    { "<leader>lj", vim.diagnostic.goto_next,  desc = "Next Diagnostic" },
-    { "<leader>lk", vim.diagnostic.goto_prev,  desc = "Prev Diagnostic" },
-    { "<leader>ll", vim.lsp.codelens.run,      desc = "CodeLens Action" },
-    { "<leader>lq", vim.diagnostic.setloclist, desc = "Quickfix" },
-    { "<leader>lr", vim.lsp.buf.rename,        desc = "Rename" },
-}
+M.cmd = { "LspInstall", "LspUninstall" }
 
 local opts = {
     ensure_installed = { "lua_ls", "bashls" },
@@ -62,18 +45,50 @@ local opts = {
 }
 
 M.config = function()
-    local icons = require("config.icons").diagnostics
+    local icons = require("config.icons")
     local signs = {
-        DiagnosticSignError = icons.BoldError,
-        DiagnosticSignWarn = icons.BoldWarning,
-        DiagnosticSignHint = icons.BoldHint,
-        DiagnosticSignInfo = icons.BoldInformation,
+        { name = "DiagnosticSignError", text = icons.DiagnosticError, texthl = "DiagnosticSignError" },
+        { name = "DiagnosticSignWarn", text = icons.DiagnosticWarn, texthl = "DiagnosticSignWarn" },
+        { name = "DiagnosticSignHint", text = icons.DiagnosticHint, texthl = "DiagnosticSignHint" },
+        { name = "DiagnosticSignInfo", text = icons.DiagnosticInfo, texthl = "DiagnosticSignInfo" },
+        { name = "DapStopped", text = icons.DapStopped, texthl = "DiagnosticWarn" },
+        { name = "DapBreakpoint", text = icons.DapBreakpoint, texthl = "DiagnosticInfo" },
+        { name = "DapBreakpointRejected", text = icons.DapBreakpointRejected, texthl = "DiagnosticError" },
+        { name = "DapBreakpointCondition", text = icons.DapBreakpointCondition, texthl = "DiagnosticInfo" },
+        { name = "DapLogPoint", text = icons.DapLogPoint, texthl = "DiagnosticInfo" },
     }
-    for type, icon in pairs(signs) do
-        local hl = type
-        vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = "" })
+    for _, sign in ipairs(signs) do
+        vim.fn.sign_define(sign.name, sign)
     end
 
+    vim.diagnostic.config({
+        virtual_text = true,
+        signs = {
+            text = {
+                [vim.diagnostic.severity.ERROR] = icons.DiagnosticError,
+                [vim.diagnostic.severity.HINT] = icons.DiagnosticHint,
+                [vim.diagnostic.severity.WARN] = icons.DiagnosticWarn,
+                [vim.diagnostic.severity.INFO] = icons.DiagnosticInfo,
+            },
+            active = signs,
+        },
+        update_in_insert = true,
+        underline = true,
+        severity_sort = true,
+        float = {
+            focused = false,
+            style = "minimal",
+            border = "rounded",
+            source = "always",
+            header = "",
+            prefix = "",
+        },
+    })
+
+    vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { border = "rounded", silent = true })
+    vim.lsp.handlers["textDocument/signatureHelp"] =
+        vim.lsp.with(vim.lsp.handlers.signature_help, { border = "rounded", silent = true })
+
     local mlsp = require('mason-lspconfig')
     mlsp.setup({ ensure_installed = opts.ensure_installed })
     mlsp.setup_handlers(opts.handlers)
diff --git a/.config/nvim/lua/plugins/lsp/mason-null-ls.lua b/.config/nvim/lua/plugins/lsp/mason-null-ls.lua
new file mode 100644
index 00000000..7a394914
--- /dev/null
+++ b/.config/nvim/lua/plugins/lsp/mason-null-ls.lua
@@ -0,0 +1,7 @@
+local M = { "jay-babu/mason-null-ls.nvim" }
+
+M.cmd = { "NullLsInstall", "NullLsUninstall" }
+
+M.opts = { handlers = {} }
+
+return M
diff --git a/.config/nvim/lua/plugins/lsp/mason.lua b/.config/nvim/lua/plugins/lsp/mason.lua
index fb1ea85c..73fc149c 100644
--- a/.config/nvim/lua/plugins/lsp/mason.lua
+++ b/.config/nvim/lua/plugins/lsp/mason.lua
@@ -2,15 +2,26 @@ local M = { "williamboman/mason.nvim" }
 
 local icons = require('config.icons')
 
+M.cmd = {
+    "Mason",
+    "MasonInstall",
+    "MasonUninstall",
+    "MasonUninstallAll",
+    "MasonLog",
+    "MasonUpdate",
+}
+
+M.build = ":MasonUpdate"
+
 M.keys = { { "<leader>lI", "<cmd>Mason<cr>", desc = "Mason" } }
 
 M.opts = {
     ui = {
         border = "none",
         icons = {
-            package_installed = icons.ui.Check,
-            package_pending = icons.ui.BoldArrowRight,
-            package_uninstalled = icons.ui.BoldClose,
+            package_installed = icons.PackageInstalled,
+            package_pending = icons.PackagePending,
+            package_uninstalled = icons.PackageUninstalled,
         },
     },
     log_level = vim.log.levels.INFO,
diff --git a/.config/nvim/lua/plugins/lsp/null-ls.lua b/.config/nvim/lua/plugins/lsp/null-ls.lua
index 054ae88b..79692d1c 100644
--- a/.config/nvim/lua/plugins/lsp/null-ls.lua
+++ b/.config/nvim/lua/plugins/lsp/null-ls.lua
@@ -1,8 +1,44 @@
 local M = { "nvimtools/none-ls.nvim" }
+local f = require("funcs")
 
 M.event = { "BufReadPre", "BufNewFile" }
 
-M.dependencies = { "mason.nvim" }
+M.dependencies = { "mason-null-ls.nvim" }
+
+local lsp_maps = function(client, bufnr)
+    local lsp_mappings = f.empty_map_table()
+
+    -- TODO: CONDITIONALLY GATE THIS
+    lsp_mappings.n["<leader>lf"] = { function() vim.lsp.buf.format() end, desc = "Format" }
+
+    lsp_mappings.n["<leader>ld"] = { function() vim.diagnostic.open_float() end, desc = "Hover diagnostics" }
+    lsp_mappings.n["[d"] = { function() vim.diagnostic.goto_prev() end, desc = "Previous diagnostic" }
+    lsp_mappings.n["]d"] = { function() vim.diagnostic.goto_next() end, desc = "Next diagnostic" }
+    lsp_mappings.n["gl"] = { function() vim.diagnostic.open_float() end, desc = "Hover diagnostics" }
+
+    if f.is_available("telescope.nvim") then
+        lsp_mappings.n["<leader>lD"] = {
+            function() require("telescope.builtin").diagnostics() end,
+            desc = "Search diagnostics",
+        }
+    end
+
+    if f.is_available "mason-lspconfig.nvim" then
+        lsp_mappings.n["<leader>li"] = { "<cmd>LspInfo<cr>", desc = "LSP information" }
+    end
+
+    if f.is_available "null-ls.nvim" then
+        lsp_mappings.n["<leader>lI"] = { "<cmd>NullLsInfo<cr>", desc = "Null-ls information" }
+    end
+
+    if client.supports_method "textDocument/codeAction" then
+        lsp_mappings.n["<leader>la"] = {
+            function() vim.lsp.buf.code_action() end,
+            desc = "LSP code action",
+        }
+        lsp_mappings.v["<leader>la"] = lsp_mappings.n["<leader>la"]
+    end
+end
 
 M.opts = function()
     local nls = require("null-ls")
@@ -19,6 +55,7 @@ M.opts = function()
             -- Various (yaml, markdown, json among others)
             nls.builtins.formatting.prettierd,
         },
+        on_attach = lsp_maps
     }
 end
 
diff --git a/.config/nvim/lua/plugins/misc/alpha.lua b/.config/nvim/lua/plugins/misc/alpha.lua
index 83187add..3ec61782 100644
--- a/.config/nvim/lua/plugins/misc/alpha.lua
+++ b/.config/nvim/lua/plugins/misc/alpha.lua
@@ -1,8 +1,8 @@
 local M = { "goolord/alpha-nvim" }
+local icons = require('config.icons')
 
 M.opts = function()
     local dashboard = require('alpha.themes.dashboard')
-    local icons = require('config.icons')
 
     local banner = {
         "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣶⣿⣿⣿⣷⣶⣤⡀⠀⠀⠀⠀⠀⠀",
@@ -36,7 +36,7 @@ M.opts = function()
     dashboard.section.header.val = banner
 
     dashboard.section.buttons.val = {
-        dashboard.button("n", icons.ui.NewFile .. " New file", "<CMD>ene<CR>"),
+        dashboard.button("n", icons.ui.EmptyFile .. " New file", "<CMD>ene<CR>"),
         dashboard.button("e", icons.ui.FindFile .. " Open file", "<CMD>Lf<CR>"),
         dashboard.button("q", icons.ui.SignOut .. " Quit", "<CMD>qa<CR>"),
     }
diff --git a/.config/nvim/lua/plugins/misc/bufferline.lua b/.config/nvim/lua/plugins/misc/bufferline.lua
index 02496759..b53e541b 100644
--- a/.config/nvim/lua/plugins/misc/bufferline.lua
+++ b/.config/nvim/lua/plugins/misc/bufferline.lua
@@ -2,51 +2,23 @@ local M = { "akinsho/bufferline.nvim" }
 
 M.event = { "BufRead", "BufNewFile" }
 
-M.keys = {
-    { "<C-l>", "<cmd>BufferLineCycleNext<CR>", desc = "Switch to next buffer" },
-    { "<C-h>", "<cmd>BufferLineCyclePrev<CR>", desc = "Switch to previous buffer" },
-    { "<A-l>", "<cmd>BufferLineMoveNext<CR>",  desc = "Move buffer to next" },
-    { "<A-h>", "<cmd>BufferLineMovePrev<CR>",  desc = "Move buffer to previous" },
-}
-
 M.opts = function()
     local icons = require('config.icons')
 
-    local function is_ft(b, ft)
-        return vim.bo[b].filetype == ft
-    end
-
     local function diagnostics_indicator(_, _, diagnostics, _)
         local result = {}
         local symbols = {
-            error = icons.diagnostics.Error,
-            warning = icons.diagnostics.Warning,
-            info = icons.diagnostics.Information,
+            error = icons.DiagnosticError,
+            warning = icons.DiagnosticWarning,
+            info = icons.DiagnosticInformation,
         }
         for name, count in pairs(diagnostics) do
             if symbols[name] and count > 0 then
                 table.insert(result, symbols[name] .. " " .. count)
             end
         end
-        result = table.concat(result, " ")
-        return #result > 0 and result or ""
-    end
-
-    local function custom_filter(buf, buf_nums)
-        local logs = vim.tbl_filter(function(b)
-            return is_ft(b, "log")
-        end, buf_nums)
-        if vim.tbl_isempty(logs) then
-            return true
-        end
-        local tab_num = vim.fn.tabpagenr()
-        local last_tab = vim.fn.tabpagenr "$"
-        local is_log = is_ft(buf, "log")
-        if last_tab == 1 then
-            return true
-        end
-        -- only show log buffers in secondary tabs
-        return (tab_num == last_tab and is_log) or (tab_num ~= last_tab and not is_log)
+        local result_str = table.concat(result, " ")
+        return #result_str > 0 and result_str or ""
     end
 
     local config = {
@@ -61,87 +33,22 @@ M.opts = function()
             },
         },
         options = {
-            mode = "buffers",                        -- set to "tabs" to only show tabpages instead
-            numbers = "none",                        -- can be "none" | "ordinal" | "buffer_id" | "both" | function
-            close_command = "bdelete! %d",           -- can be a string | function, see "Mouse actions"
-            right_mouse_command = "vert sbuffer %d", -- can be a string | function, see "Mouse actions"
-            left_mouse_command = "buffer %d",        -- can be a string | function, see "Mouse actions"
-            middle_mouse_command = nil,              -- can be a string | function, see "Mouse actions"
             indicator = {
-                -- icon = icons.ui.DoubleChevronRight, -- this should be omitted if indicator style is not 'icon'
-                style = "none", -- can also be 'underline'|'none',
+                style = "none",
             },
             buffer_close_icon = icons.ui.Close,
             modified_icon = icons.ui.Circle,
             close_icon = icons.ui.BoldClose,
             left_trunc_marker = icons.ui.ArrowCircleLeft,
             right_trunc_marker = icons.ui.ArrowCircleRight,
-            --- name_formatter can be used to change the buffer's label in the bufferline.
-            --- Please note some names can/will break the
-            --- bufferline so use this at your discretion knowing that it has
-            --- some limitations that will *NOT* be fixed.
-            name_formatter = function(buf) -- buf contains a "name", "path" and "bufnr"
-                -- remove extension from markdown files for example
-                if buf.name:match "%.md" then
-                    return vim.fn.fnamemodify(buf.name, ":t:r")
-                end
-            end,
-            max_name_length = 18,
-            max_prefix_length = 15, -- prefix used when a buffer is de-duplicated
-            truncate_names = true,  -- whether or not tab names should be truncated
-            tab_size = 18,
             diagnostics = "nvim_lsp",
-            diagnostics_update_in_insert = false,
             diagnostics_indicator = diagnostics_indicator,
-            -- NOTE: this will be called a lot so don't do any heavy processing here
-            custom_filter = custom_filter,
-            offsets = {
-                {
-                    filetype = "undotree",
-                    text = "Undotree",
-                    highlight = "PanelHeading",
-                    padding = 1,
-                },
-                {
-                    filetype = "NvimTree",
-                    text = "Explorer",
-                    highlight = "PanelHeading",
-                    padding = 1,
-                },
-                {
-                    filetype = "DiffviewFiles",
-                    text = "Diff View",
-                    highlight = "PanelHeading",
-                    padding = 1,
-                },
-                {
-                    filetype = "flutterToolsOutline",
-                    text = "Flutter Outline",
-                    highlight = "PanelHeading",
-                },
-                {
-                    filetype = "packer",
-                    text = "Packer",
-                    highlight = "PanelHeading",
-                    padding = 1,
-                },
-            },
-            color_icons = true,       -- whether or not to add the filetype icon highlights
-            show_buffer_icons = true, -- disable filetype icons for buffers
+            offsets = {},
             show_buffer_close_icons = false,
             show_close_icon = false,
-            show_tab_indicators = true,
-            persist_buffer_sort = true, -- whether or not custom sorted buffers should persist
-            -- can also be a table containing 2 custom separators
-            -- [focused and unfocused]. eg: { '|', '|' }
             separator_style = { '', '' },
-            enforce_regular_tabs = false,
+            move_wraps_at_ends = true,
             always_show_bufferline = false,
-            hover = {
-                enabled = false, -- requires nvim 0.8+
-                delay = 200,
-                reveal = { "close" },
-            },
             sort_by = "id",
         },
     }
diff --git a/.config/nvim/lua/plugins/misc/comment.lua b/.config/nvim/lua/plugins/misc/comment.lua
index cb0202eb..3894f172 100644
--- a/.config/nvim/lua/plugins/misc/comment.lua
+++ b/.config/nvim/lua/plugins/misc/comment.lua
@@ -2,11 +2,6 @@ local M = { "numToStr/Comment.nvim" }
 
 M.event = { "BufReadPre", "BufNewFile" }
 
-M.keys = {
-    { "<leader>/", "<Plug>(comment_toggle_linewise_current)", desc = "Comment toggle current line", },
-    { "<leader>/", "<Plug>(comment_toggle_linewise_visual)",  desc = "Comment toggle linewise",     mode = { "v" }, },
-}
-
 M.opts = {
     mappings = {
         basic = false,
diff --git a/.config/nvim/lua/plugins/misc/gitsigns.lua b/.config/nvim/lua/plugins/misc/gitsigns.lua
index 58423f4d..fcc87699 100644
--- a/.config/nvim/lua/plugins/misc/gitsigns.lua
+++ b/.config/nvim/lua/plugins/misc/gitsigns.lua
@@ -2,23 +2,9 @@ local M = { "lewis6991/gitsigns.nvim" }
 
 M.event = { "BufReadPre", "BufNewFile" }
 
-M.keys = {
-    { "<leader>gj", function() require("gitsigns").next_hunk() end,       desc = "Next Hunk" },
-    { "<leader>gk", function() require("gitsigns").prev_hunk() end,       desc = "Prev Hunk" },
-    { "<leader>gb", function() require("gitsigns").blame_line() end,      desc = "Blame" },
-    { "<leader>gp", function() require("gitsigns").preview_hunk() end,    desc = "Preview Hunk" },
-    { "<leader>gr", function() require("gitsigns").reset_hunk() end,      desc = "Reset Hunk" },
-    { "<leader>gR", function() require("gitsigns").reset_buffer() end,    desc = "Reset Buffer" },
-    { "<leader>gs", function() require("gitsigns").stage_hunk() end,      desc = "Stage Hunk" },
-    { "<leader>gu", function() require("gitsigns").undo_stage_hunk() end, desc = "Undo Stage Hunk" },
-    { "<leader>gd", "<cmd>Gitsigns diffthis HEAD<cr>",                    desc = "Git Diff" },
-}
-
-M.ft = { "gitcommit" }
-
 local icons = require('config.icons')
 
-local opts = {
+M.opts = {
     signs = {
         add          = { text = icons.git.LineAdded },
         change       = { text = icons.git.LineModified },
@@ -29,13 +15,4 @@ local opts = {
     },
 }
 
-M.config = function()
-    require('gitsigns').setup(opts)
-    require('which-key').register({
-        g = {
-            name = "Git",
-        },
-    }, { prefix = "<leader>" })
-end
-
 return M
diff --git a/.config/nvim/lua/plugins/misc/init.lua b/.config/nvim/lua/plugins/misc/init.lua
index 040a8414..a0b54eb9 100644
--- a/.config/nvim/lua/plugins/misc/init.lua
+++ b/.config/nvim/lua/plugins/misc/init.lua
@@ -1,6 +1,7 @@
 return {
-    { "nvim-lua/plenary.nvim" },
-    { "kyazdani42/nvim-web-devicons" },
+    { "nvim-lua/plenary.nvim", lazy = true },
+    { "kyazdani42/nvim-web-devicons", lazy = true },
+    { "NMAC427/guess-indent.nvim" },
     require('plugins.misc.alpha'),
     require('plugins.misc.autopairs'),
     require('plugins.misc.bufferline'),
@@ -11,7 +12,10 @@ return {
     require('plugins.misc.indent-blankline'),
     require('plugins.misc.lf'),
     require('plugins.misc.lualine'),
+    require('plugins.misc.ufo'),
     require('plugins.misc.surround'),
+    require('plugins.misc.telescope'),
+    require('plugins.misc.telescope-fzf-native'),
     require('plugins.misc.todo-comments'),
     require('plugins.misc.toggleterm'),
     require('plugins.misc.tokyonight'),
diff --git a/.config/nvim/lua/plugins/misc/lf.lua b/.config/nvim/lua/plugins/misc/lf.lua
index eb902eb1..07238c74 100644
--- a/.config/nvim/lua/plugins/misc/lf.lua
+++ b/.config/nvim/lua/plugins/misc/lf.lua
@@ -1,17 +1,11 @@
 local M = { "lmburns/lf.nvim" }
 
--- M.commit = "383429497292dd8a84271e74a81c6db6993ca7ab"
-
 M.cmd = { "Lf" }
 
 M.opts = {
     mappings = false,
-    winblend = 0,
+    winblend = 5,
     border = "rounded",
 }
 
-M.keys = {
-    { "<leader>e", function() require('lf').start() end, "File Picker" },
-}
-
 return M
diff --git a/.config/nvim/lua/plugins/misc/lualine.lua b/.config/nvim/lua/plugins/misc/lualine.lua
index cbc9011b..9091a3d8 100644
--- a/.config/nvim/lua/plugins/misc/lualine.lua
+++ b/.config/nvim/lua/plugins/misc/lualine.lua
@@ -179,9 +179,9 @@ M.opts = function()
         'diagnostics',
         sources = { 'nvim_diagnostic' },
         symbols = {
-            error = icons.diagnostics.BoldError .. ' ',
-            warn = icons.diagnostics.BoldWarning .. ' ',
-            info = icons.diagnostics.BoldInformation
+            error = icons.DiagnosticError .. ' ',
+            warn = icons.DiagnosticWarn .. ' ',
+            info = icons.DiagnosticInfo .. ' ',
         },
         diagnostics_color = {
             color_error = { fg = colors.red },
diff --git a/.config/nvim/lua/plugins/misc/telescope-fzf-native.lua b/.config/nvim/lua/plugins/misc/telescope-fzf-native.lua
new file mode 100644
index 00000000..9b40ca3f
--- /dev/null
+++ b/.config/nvim/lua/plugins/misc/telescope-fzf-native.lua
@@ -0,0 +1,5 @@
+local M = { "nvim-telescope/telescope-fzf-native.nvim" }
+
+M.build = "make"
+
+return M
diff --git a/.config/nvim/lua/plugins/misc/telescope.lua b/.config/nvim/lua/plugins/misc/telescope.lua
new file mode 100644
index 00000000..9a48b1a9
--- /dev/null
+++ b/.config/nvim/lua/plugins/misc/telescope.lua
@@ -0,0 +1,47 @@
+local M = { "nvim-telescope/telescope.nvim" }
+local icons = require("config.icons")
+
+M.dependencies = { "telescope-fzf-native.nvim" }
+
+M.cmd = "Telescope"
+
+local opts = function()
+    local actions = require("telescope.actions")
+    return {
+        defaults = {
+            git_worktrees = vim.g.git_worktrees,
+            prompt_prefix = icons.Selected,
+            path_display = { "truncate" },
+            sorting_startegy = "ascending",
+            layout_config = {
+                horizontal = { prompt_position = "top", preview_width = 0.5 },
+                vertical = { mirror = false },
+                width = 0.87,
+                height = 0.80,
+                preview_cutoff = 120,
+            },
+            mappings = {
+                i = {
+                    ["<C-n>"] = actions.cycle_history_next,
+                    ["<C-p>"] = actions.cycle_history_prev,
+                    ["<C-j>"] = actions.move_selection_next,
+                    ["<C-k>"] = actions.move_selection_previous,
+                },
+                n = { q = actions.close },
+            },
+        },
+    }
+end
+
+M.config = function()
+    local telescope = require("telescope")
+    telescope.setup(opts())
+    if pcall(require, "aerial") then
+        telescope.load_extension("aerial")
+    end
+    if require("funcs").is_available("telescope-fzf-native.nvim") then
+        telescope.load_extension("fzf")
+    end
+end
+
+return M
diff --git a/.config/nvim/lua/plugins/misc/toggleterm.lua b/.config/nvim/lua/plugins/misc/toggleterm.lua
index 384c1f90..3d92dbcf 100644
--- a/.config/nvim/lua/plugins/misc/toggleterm.lua
+++ b/.config/nvim/lua/plugins/misc/toggleterm.lua
@@ -1,32 +1,20 @@
 local M = { "akinsho/toggleterm.nvim" }
 
+M.cmd = { "ToggleTerm", "TermExec" }
+
 M.opts = {
     size = 20,
-    open_mapping = [[<c-\>]],
-    hide_numbers = true,
-    shade_terminals = true,
     shading_factor = 2,
-    start_in_insert = true,
-    insert_mappings = true,
-    persist_size = true,
     direction = "float",
-    close_on_exit = true,
-    shell = vim.o.shell,
+    open_mapping = [[<F7>]],
     float_opts = {
-        winblend = 0,
-        highlights = {
-            border = "Normal",
-            background = "Normal",
-        },
+        winblend = 5,
         border = "rounded",
     },
+    on_create = function()
+        vim.opt.foldcolumn = "0"
+        vim.opt.signcolumn = "no"
+    end,
 }
 
---local Terminal = require("toggleterm.terminal").Terminal
---local lazygit = Terminal:new({ cmd = "lazygit", hidden = true })
---
---function _LAZYGIT_TOGGLE()
---    lazygit:toggle()
---end
-
 return M
diff --git a/.config/nvim/lua/plugins/misc/ufo.lua b/.config/nvim/lua/plugins/misc/ufo.lua
new file mode 100644
index 00000000..6c556c35
--- /dev/null
+++ b/.config/nvim/lua/plugins/misc/ufo.lua
@@ -0,0 +1,35 @@
+local M = { "nvim-treesitter/nvim-treesitter" }
+
+M.event = { "InsertEnter" }
+
+M.dependencies = { "kevinhwang91/promise-async" }
+
+M.opts = {
+    preview = {
+        mappings = {
+            scrollB = "<C-b>",
+            scrollF = "<C-f>",
+            scrollU = "<C-u>",
+            scrollD = "<C-d>",
+        },
+    },
+    provider_selector = function(_, filetype, buftype)
+        local function handleFallbackException(bufnr, err, providerName)
+            if type(err) == "string" and err:match "UfoFallbackException" then
+                return require("ufo").getFolds(bufnr, providerName)
+            else
+                return require("promise").reject(err)
+            end
+        end
+
+        return (filetype == "" or buftype == "nofile") and "indent" -- only use indent until a file is opened
+            or function(bufnr)
+                return require("ufo")
+                    .getFolds(bufnr, "lsp")
+                    :catch(function(err) return handleFallbackException(bufnr, err, "treesitter") end)
+                    :catch(function(err) return handleFallbackException(bufnr, err, "indent") end)
+            end
+    end,
+}
+
+return M
diff --git a/.config/nvim/lua/plugins/misc/which-key.lua b/.config/nvim/lua/plugins/misc/which-key.lua
index 09cd7a9d..09ecfd29 100644
--- a/.config/nvim/lua/plugins/misc/which-key.lua
+++ b/.config/nvim/lua/plugins/misc/which-key.lua
@@ -2,75 +2,36 @@ local M = { "folke/which-key.nvim" }
 
 local icons = require('config.icons')
 
-M.lazy = false
+M.event = "VeryLazy"
 
 M.init = function()
     vim.o.timeout = true
     vim.o.timeoutlen = 300
 end
 
-local opts = {
+M.opts = {
     plugins = {
-        marks = false,
-        registers = false,
         presets = {
             operators = false,
             motions = false,
-            text_objects = false,
-            windows = false,
-            nav = false,
-            z = false,
-            g = false,
         }
     },
-    spelling = {
-        enabled = false,
-        suggestions = 20,
-    },
     icons = {
         breadcrumb = icons.ui.DoubleChevronRight,
         separator = icons.ui.BoldArrowRight,
         group = icons.ui.Plus,
     },
-    popup_mappings = {
-        scroll_down = "<c-d>",
-        scroll_up = "<c-u>",
-    },
-    window = {
-        border = "none",
-        position = "bottom",
-        winblend = 0,
-    },
-    layout = {
-        height = { min = 4, max = 25 },
-        width = { min = 20, max = 50 },
-        spacing = 3,
-        align = "left",
-    },
     hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "call", "lua", "^:", "^ " },
     triggers = "auto",
     triggers_blacklist = {
-        i = { "j", "k" },
+        i = { "j", "k", "v", "y" },
         v = { "j", "k", "y" },
     },
-    defaults = {
-        ["<leader>u"] = { name = "Utility" },
-        ["<leader>p"] = { name = "Plugins" },
-    }
 }
 
-M.keys = {
-    { "<leader>w",  "<cmd>w!<CR>",                           desc = "Save" },
-    { "<leader>q",  require('funcs').buf_kill,               desc = "Close" },
-    { "<leader>h",  "<cmd>nohlsearch<CR>",                   desc = "Clear Highlights" },
-    { "<leader>n",  "<cmd>ene<CR>",                          desc = "New File" },
-    { "<leader>uc", "<cmd>w!<CR><cmd>!compiler \"%:p\"<CR>", desc = "Compile" },
-    -- WARN:
-    { "<leader>pu", require("lazy").check,   desc = "Check for updates" },
-    { "<leader>pc", require("lazy").clear,   desc = "Clear finished tasks" },
-    { "<leader>pd", require("lazy").debug,   desc = "Show debug information" },
-    { "<leader>pp", require("lazy").profile, desc = "Show profiling information" },
-    { "<leader>ps", require("lazy").sync,    desc = "Install, clean and update plugins" },
-}
+M.config = function(_, opts)
+  require("which-key").setup(opts)
+  require("funcs").which_key_register()
+end
 
 return M
diff --git a/.config/nvim/todo b/.config/nvim/todo
new file mode 100644
index 00000000..b2267b56
--- /dev/null
+++ b/.config/nvim/todo
@@ -0,0 +1,3 @@
+continue porting lsp_maps https://github.com/AstroNvim/AstroNvim/blob/8a019756cf45cb8f08dc11ce0396a577bd716936/lua/astronvim/utils/lsp.lua#L139
+Configure Todo Telescope integration
+Figure out why the theme breaks when you install a plugin