From c9e2adbbc8fd7a5398c8c66d21f0e02dc7b60203 Mon Sep 17 00:00:00 2001
From: Gustaf Rydholm <gustaf.rydholm@gmail.com>
Date: Mon, 8 Nov 2021 23:13:05 +0100
Subject: Add new lunarvin updates

---
 .config/nvim/lua/core/autocmds.lua           | 154 ++++++++++-----------------
 .config/nvim/lua/core/autopairs.lua          |  21 ++--
 .config/nvim/lua/core/builtins/init.lua      |   2 -
 .config/nvim/lua/core/cmp.lua                |  78 ++++++++++----
 .config/nvim/lua/core/commands.lua           |   4 +
 .config/nvim/lua/core/dap.lua                |  75 -------------
 .config/nvim/lua/core/dashboard.lua          |  14 ++-
 .config/nvim/lua/core/info.lua               | 148 +++++++++++++------------
 .config/nvim/lua/core/log.lua                | 113 ++++++++++++++++----
 .config/nvim/lua/core/lualine/components.lua |  13 ++-
 .config/nvim/lua/core/telescope.lua          | 126 ++++++++++++++--------
 .config/nvim/lua/core/treesitter.lua         |  20 +++-
 .config/nvim/lua/core/which-key.lua          |  34 +++---
 13 files changed, 418 insertions(+), 384 deletions(-)
 delete mode 100644 .config/nvim/lua/core/dap.lua

(limited to '.config/nvim/lua/core')

diff --git a/.config/nvim/lua/core/autocmds.lua b/.config/nvim/lua/core/autocmds.lua
index 9ee9e90..1f50308 100644
--- a/.config/nvim/lua/core/autocmds.lua
+++ b/.config/nvim/lua/core/autocmds.lua
@@ -1,110 +1,68 @@
-local autocommands = {}
-local config = require "config"
+local M = {}
 
-options.autocommands = {
-  _general_settings = {
-    {
-      "Filetype",
-      "*",
-      "lua require('utils.ft').do_filetype(vim.fn.expand(\"<amatch>\"))",
-    },
-    {
-      "FileType",
-      "qf",
-      "nnoremap <silent> <buffer> q :q<CR>",
+--- Load the default set of autogroups and autocommands.
+function M.load_augroups()
+  local user_config_file = vim.fn.resolve(require("config"):get_user_config_path())
+
+  return {
+    _general_settings = {
+      { "FileType", "qf,help,man", "nnoremap <silent> <buffer> q :close<CR>" },
+      {
+        "TextYankPost",
+        "*",
+        "lua require('vim.highlight').on_yank({higroup = 'Search', timeout = 200})",
+      },
+      {
+        "BufWinEnter",
+        "dashboard",
+        "setlocal cursorline signcolumn=yes cursorcolumn number",
+      },
+      { "BufWritePost", user_config_file, "lua require('config'):reload()" },
+      { "FileType", "qf", "set nobuflisted" },
+      -- { "VimLeavePre", "*", "set title set titleold=" },
     },
-    {
-      "FileType",
-      "lsp-installer",
-      "nnoremap <silent> <buffer> q :q<CR>",
+    _formatoptions = {
+      {
+        "BufWinEnter,BufRead,BufNewFile",
+        "*",
+        "setlocal formatoptions-=c formatoptions-=r formatoptions-=o",
+      },
     },
-    {
-      "TextYankPost",
-      "*",
-      "lua require('vim.highlight').on_yank({higroup = 'Search', timeout = 200})",
+    _filetypechanges = {
+      { "BufWinEnter", ".tf", "setlocal filetype=terraform" },
+      { "BufRead", "*.tf", "setlocal filetype=terraform" },
+      { "BufNewFile", "*.tf", "setlocal filetype=terraform" },
+      { "BufWinEnter", ".zsh", "setlocal filetype=sh" },
+      { "BufRead", "*.zsh", "setlocal filetype=sh" },
+      { "BufNewFile", "*.zsh", "setlocal filetype=sh" },
     },
-    {
-      "BufWinEnter",
-      "*",
-      "setlocal formatoptions-=c formatoptions-=r formatoptions-=o",
+    _git = {
+      { "FileType", "gitcommit", "setlocal wrap" },
+      { "FileType", "gitcommit", "setlocal spell" },
     },
-    {
-      "BufWinEnter",
-      "dashboard",
-      "setlocal cursorline signcolumn=yes cursorcolumn number",
+    _markdown = {
+      { "FileType", "markdown", "setlocal wrap" },
+      { "FileType", "markdown", "setlocal spell" },
     },
-    {
-      "BufRead",
-      "*",
-      "setlocal formatoptions-=c formatoptions-=r formatoptions-=o",
+    _buffer_bindings = {
+      { "FileType", "floaterm", "nnoremap <silent> <buffer> q :q<CR>" },
     },
-    {
-      "BufNewFile",
-      "*",
-      "setlocal formatoptions-=c formatoptions-=r formatoptions-=o",
+    _auto_resize = {
+      -- will cause split windows to be resized evenly if main window is resized
+      { "VimResized", "*", "tabdo wincmd =" },
     },
-    { "BufWritePost", config.path, "lua require('utils').reload_config()" },
-    {
-      "FileType",
-      "qf",
-      "set nobuflisted",
+    _general_lsp = {
+      {
+        "FileType",
+        "lspinfo,lsp-installer,null-ls-info",
+        "nnoremap <silent> <buffer> q :close<CR>",
+      },
     },
-    -- { "VimLeavePre", "*", "set title set titleold=" },
-  },
-  _filetypechanges = {
-    { "BufWinEnter", ".tf", "setlocal filetype=terraform" },
-    { "BufRead", "*.tf", "setlocal filetype=terraform" },
-    { "BufNewFile", "*.tf", "setlocal filetype=terraform" },
-    { "BufWinEnter", ".zsh", "setlocal filetype=sh" },
-    { "BufRead", "*.zsh", "setlocal filetype=sh" },
-    { "BufNewFile", "*.zsh", "setlocal filetype=sh" },
-  },
-  -- _solidity = {
-  --     {'BufWinEnter', '.sol', 'setlocal filetype=solidity'}, {'BufRead', '*.sol', 'setlocal filetype=solidity'},
-  --     {'BufNewFile', '*.sol', 'setlocal filetype=solidity'}
-  -- },
-  -- _gemini = {
-  --     {'BufWinEnter', '.gmi', 'setlocal filetype=markdown'}, {'BufRead', '*.gmi', 'setlocal filetype=markdown'},
-  --     {'BufNewFile', '*.gmi', 'setlocal filetype=markdown'}
-  -- },
-  _git = {
-    { "FileType", "gitcommit", "setlocal wrap" },
-    { "FileType", "gitcommit", "setlocal spell" },
-  },
-  _markdown = {
-    { "FileType", "markdown", "setlocal wrap" },
-    { "FileType", "markdown", "setlocal spell" },
-  },
-  _buffer_bindings = {
-    { "FileType", "floaterm", "nnoremap <silent> <buffer> q :q<CR>" },
-  },
-  _auto_resize = {
-    -- will cause split windows to be resized evenly if main window is resized
-    { "VimResized", "*", "wincmd =" },
-  },
-  _packer_compile = {
-    -- will run PackerCompile after writing plugins.lua
-    { "BufWritePost", "plugins.lua", "PackerCompile" },
-  },
-  _general_lsp = {
-    { "FileType", "lspinfo", "nnoremap <silent> <buffer> q :q<CR>" },
-  },
-
-  -- _fterm_lazygit = {
-  --   -- will cause esc key to exit lazy git
-  --   {"TermEnter", "*", "call LazyGitNativation()"}
-  -- },
-  -- _mode_switching = {
-  --   -- will switch between absolute and relative line numbers depending on mode
-  --   {'InsertEnter', '*', 'if &relativenumber | let g:ms_relativenumberoff = 1 | setlocal number norelativenumber | endif'},
-  --   {'InsertLeave', '*', 'if exists("g:ms_relativenumberoff") | setlocal relativenumber | endif'},
-  --   {'InsertEnter', '*', 'if &cursorline | let g:ms_cursorlineoff = 1 | setlocal nocursorline | endif'},
-  --   {'InsertLeave', '*', 'if exists("g:ms_cursorlineoff") | setlocal cursorline | endif'},
-  -- },
-  custom_groups = {},
-}
+    custom_groups = {},
+  }
+end
 
-function autocommands.define_augroups(definitions) -- {{{1
+function M.define_augroups(definitions) -- {{{1
   -- Create autocommand groups based on the passed definitions
   --
   -- The key will be the name of the group, and each definition
@@ -126,4 +84,4 @@ function autocommands.define_augroups(definitions) -- {{{1
   end
 end
 
-return autocommands
+return M
diff --git a/.config/nvim/lua/core/autopairs.lua b/.config/nvim/lua/core/autopairs.lua
index 630f3de..ec7f651 100644
--- a/.config/nvim/lua/core/autopairs.lua
+++ b/.config/nvim/lua/core/autopairs.lua
@@ -4,8 +4,6 @@ function M.config()
   options.builtin.autopairs = {
     active = true,
     on_config_done = nil,
-    ---@usage auto insert after select function or method item
-    map_complete = true,
     ---@usage  -- modifies the function or method delimiter by filetypes
     map_char = {
       all = "(",
@@ -52,19 +50,12 @@ M.setup = function()
     end),
   }
 
-  if package.loaded["cmp"] then
-    require("nvim-autopairs.completion.cmp").setup {
-      map_cr = false,
-      map_complete = options.builtin.autopairs.map_complete,
-      map_char = options.builtin.autopairs.map_char,
-    }
-    -- we map CR explicitly in cmp.lua but we still need to setup the autopairs CR keymap
-    vim.api.nvim_set_keymap(
-      "i",
-      "<CR>",
-      "v:lua.MPairs.autopairs_cr()",
-      { expr = true, noremap = true }
-    )
+  local cmp_status_ok, cmp = pcall(require, "cmp")
+  if cmp_status_ok then
+    -- If you want insert `(` after select function or method item
+    local cmp_autopairs = require "nvim-autopairs.completion.cmp"
+    local map_char = options.builtin.autopairs.map_char
+    cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done { map_char = map_char })
   end
 
   require("nvim-treesitter.configs").setup { autopairs = { enable = true } }
diff --git a/.config/nvim/lua/core/builtins/init.lua b/.config/nvim/lua/core/builtins/init.lua
index c3b3618..10ce680 100644
--- a/.config/nvim/lua/core/builtins/init.lua
+++ b/.config/nvim/lua/core/builtins/init.lua
@@ -1,12 +1,10 @@
 local M = {}
 
 local builtins = {
-  "keymappings",
   "core.which-key",
   "core.gitsigns",
   "core.cmp",
   "core.dashboard",
-  "core.dap",
   "core.terminal",
   "core.telescope",
   "core.treesitter",
diff --git a/.config/nvim/lua/core/cmp.lua b/.config/nvim/lua/core/cmp.lua
index fd9e96c..36d85fb 100644
--- a/.config/nvim/lua/core/cmp.lua
+++ b/.config/nvim/lua/core/cmp.lua
@@ -1,14 +1,29 @@
 local M = {}
+M.methods = {}
 
+---checks if the character preceding the cursor is a space character
+---@return boolean true if it is a space character, false otherwise
 local check_backspace = function()
   local col = vim.fn.col "." - 1
   return col == 0 or vim.fn.getline("."):sub(col, col):match "%s"
 end
+M.methods.check_backspace = check_backspace
 
 local function T(str)
   return vim.api.nvim_replace_termcodes(str, true, true, true)
 end
 
+---wraps vim.fn.feedkeys while replacing key codes with escape codes
+---Ex: feedkeys("<CR>", "n") becomes feedkeys("^M", "n")
+---@param key string
+---@param mode string
+local function feedkeys(key, mode)
+  vim.fn.feedkeys(T(key), mode)
+end
+M.methods.feedkeys = feedkeys
+
+---checks if emmet_ls is available and active in the buffer
+---@return boolean true if available, false otherwise
 local is_emmet_active = function()
   local clients = vim.lsp.buf_get_clients()
 
@@ -19,16 +34,17 @@ local is_emmet_active = function()
   end
   return false
 end
+M.methods.is_emmet_active = is_emmet_active
 
-M.config = function()
-  local status_cmp_ok, cmp = pcall(require, "cmp")
-  if not status_cmp_ok then
-    return
-  end
-  local status_luasnip_ok, luasnip = pcall(require, "luasnip")
-  if not status_luasnip_ok then
+---when inside a snippet, seeks to the nearest luasnip field if possible, and checks if it is jumpable
+---@param dir number 1 for forward, -1 for backward; defaults to 1
+---@return boolean true if a jumpable luasnip field is found while inside a snippet
+local function jumpable(dir)
+  local luasnip_ok, luasnip = pcall(require, "luasnip")
+  if not luasnip_ok then
     return
   end
+
   local win_get_cursor = vim.api.nvim_win_get_cursor
   local get_current_buf = vim.api.nvim_get_current_buf
 
@@ -124,16 +140,39 @@ M.config = function()
     return false
   end
 
+  if dir == -1 then
+    return inside_snippet() and luasnip.jumpable(-1)
+  else
+    return inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable()
+  end
+end
+M.methods.jumpable = jumpable
+
+M.config = function()
+  local status_cmp_ok, cmp = pcall(require, "cmp")
+  if not status_cmp_ok then
+    return
+  end
+  local status_luasnip_ok, luasnip = pcall(require, "luasnip")
+  if not status_luasnip_ok then
+    return
+  end
+
   options.builtin.cmp = {
     confirm_opts = {
       behavior = cmp.ConfirmBehavior.Replace,
       select = false,
     },
+    completion = {
+      ---@usage The minimum length of a word to complete on.
+      keyword_length = 1,
+    },
     experimental = {
       ghost_text = true,
       native_menu = false,
     },
     formatting = {
+      fields = { "kind", "abbr", "menu" },
       kind_icons = {
         Class = " ",
         Color = " ",
@@ -163,7 +202,6 @@ M.config = function()
       },
       source_names = {
         nvim_lsp = "(LSP)",
-        emoji = "(Emoji)",
         path = "(Path)",
         calc = "(Calc)",
         cmp_tabnine = "(Tabnine)",
@@ -200,33 +238,30 @@ M.config = function()
       { name = "luasnip" },
       { name = "cmp_tabnine" },
       { name = "nvim_lua" },
-      { name = "buffer" },
+      { name = "buffer", keyword_length = 5 },
       { name = "calc" },
-      { name = "emoji" },
       { name = "treesitter" },
       { name = "crates" },
     },
     mapping = {
+      ["<C-k>"] = cmp.mapping.select_prev_item(),
+      ["<C-j>"] = cmp.mapping.select_next_item(),
       ["<C-d>"] = cmp.mapping.scroll_docs(-4),
       ["<C-f>"] = cmp.mapping.scroll_docs(4),
       -- TODO: potentially fix emmet nonsense
-      ["<Tab>"] = cmp.mapping(function()
+      ["<Tab>"] = cmp.mapping(function(fallback)
         if cmp.visible() then
           cmp.select_next_item()
         elseif luasnip.expandable() then
           luasnip.expand()
-        elseif
-          inside_snippet()
-          and seek_luasnip_cursor_node()
-          and luasnip.jumpable()
-        then
+        elseif jumpable() then
           luasnip.jump(1)
         elseif check_backspace() then
-          vim.fn.feedkeys(T "<Tab>", "n")
+          fallback()
         elseif is_emmet_active() then
           return vim.fn["cmp#complete"]()
         else
-          vim.fn.feedkeys(T "<Tab>", "n")
+          fallback()
         end
       end, {
         "i",
@@ -235,7 +270,7 @@ M.config = function()
       ["<S-Tab>"] = cmp.mapping(function(fallback)
         if cmp.visible() then
           cmp.select_prev_item()
-        elseif inside_snippet() and luasnip.jumpable(-1) then
+        elseif jumpable(-1) then
           luasnip.jump(-1)
         else
           fallback()
@@ -246,13 +281,13 @@ M.config = function()
       }),
 
       ["<C-Space>"] = cmp.mapping.complete(),
-      ["<C-e>"] = cmp.mapping.close(),
+      ["<C-e>"] = cmp.mapping.abort(),
       ["<CR>"] = cmp.mapping(function(fallback)
         if cmp.visible() and cmp.confirm(options.builtin.cmp.confirm_opts) then
           return
         end
 
-        if inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable() then
+        if jumpable() then
           if not luasnip.jump(1) then
             fallback()
           end
@@ -265,7 +300,6 @@ M.config = function()
 end
 
 M.setup = function()
-  require("luasnip/loaders/from_vscode").lazy_load()
   require("cmp").setup(options.builtin.cmp)
 end
 
diff --git a/.config/nvim/lua/core/commands.lua b/.config/nvim/lua/core/commands.lua
index 8a56c40..ce635ad 100644
--- a/.config/nvim/lua/core/commands.lua
+++ b/.config/nvim/lua/core/commands.lua
@@ -10,8 +10,12 @@ M.defaults = {
     endif
   endfunction
   ]],
+  -- :NvimInfo
   [[ command! NvimInfo lua require('core.info').toggle_popup(vim.bo.filetype) ]],
   [[ command! NvimCacheReset lua require('utils.hooks').reset_cache() ]],
+  [[ command! NvimUpdate lua require('bootstrap').update() ]],
+  [[ command! NvimSyncCorePlugins lua require('plugin-loader'):sync_core_plugins() ]],
+  [[ command! NvimReload lua require('config'):reload() ]],
 }
 
 M.load = function(commands)
diff --git a/.config/nvim/lua/core/dap.lua b/.config/nvim/lua/core/dap.lua
deleted file mode 100644
index fb56f82..0000000
--- a/.config/nvim/lua/core/dap.lua
+++ /dev/null
@@ -1,75 +0,0 @@
-local M = {}
-
-M.config = function()
-  options.builtin.dap = {
-    active = false,
-    on_config_done = nil,
-    breakpoint = {
-      text = "",
-      texthl = "LspDiagnosticsSignError",
-      linehl = "",
-      numhl = "",
-    },
-    breakpoint_rejected = {
-      text = "",
-      texthl = "LspDiagnosticsSignHint",
-      linehl = "",
-      numhl = "",
-    },
-    stopped = {
-      text = "",
-      texthl = "LspDiagnosticsSignInformation",
-      linehl = "DiagnosticUnderlineInfo",
-      numhl = "LspDiagnosticsSignInformation",
-    },
-  }
-end
-
-M.setup = function()
-  local dap = require "dap"
-
-  vim.fn.sign_define("DapBreakpoint", options.builtin.dap.breakpoint)
-  vim.fn.sign_define("DapBreakpointRejected", options.builtin.dap.breakpoint_rejected)
-  vim.fn.sign_define("DapStopped", options.builtin.dap.stopped)
-  dap.defaults.fallback.terminal_win_cmd = "50vsplit new"
-
-  options.builtin.which_key.mappings["d"] = {
-    name = "Debug",
-    t = { "<cmd>lua require'dap'.toggle_breakpoint()<cr>", "Toggle Breakpoint" },
-    b = { "<cmd>lua require'dap'.step_back()<cr>", "Step Back" },
-    c = { "<cmd>lua require'dap'.continue()<cr>", "Continue" },
-    C = { "<cmd>lua require'dap'.run_to_cursor()<cr>", "Run To Cursor" },
-    d = { "<cmd>lua require'dap'.disconnect()<cr>", "Disconnect" },
-    g = { "<cmd>lua require'dap'.session()<cr>", "Get Session" },
-    i = { "<cmd>lua require'dap'.step_into()<cr>", "Step Into" },
-    o = { "<cmd>lua require'dap'.step_over()<cr>", "Step Over" },
-    u = { "<cmd>lua require'dap'.step_out()<cr>", "Step Out" },
-    p = { "<cmd>lua require'dap'.pause.toggle()<cr>", "Pause" },
-    r = { "<cmd>lua require'dap'.repl.toggle()<cr>", "Toggle Repl" },
-    s = { "<cmd>lua require'dap'.continue()<cr>", "Start" },
-    q = { "<cmd>lua require'dap'.close()<cr>", "Quit" },
-  }
-
-  if options.builtin.dap.on_config_done then
-    options.builtin.dap.on_config_done(dap)
-  end
-end
-
--- TODO put this up there ^^^ call in ftplugin
-
--- M.dap = function()
---   if options.plugin.dap.active then
---     local dap_install = require "dap-install"
---     dap_install.config("python_dbg", {})
---   end
--- end
---
--- M.dap = function()
---   -- gem install readapt ruby-debug-ide
---   if options.plugin.dap.active then
---     local dap_install = require "dap-install"
---     dap_install.config("ruby_vsc_dbg", {})
---   end
--- end
-
-return M
diff --git a/.config/nvim/lua/core/dashboard.lua b/.config/nvim/lua/core/dashboard.lua
index 0f27ccf..20edd22 100644
--- a/.config/nvim/lua/core/dashboard.lua
+++ b/.config/nvim/lua/core/dashboard.lua
@@ -31,24 +31,28 @@ M.config = function(config)
 
     custom_section = {
       a = {
-        description = { "  Find File          " },
+        description = { "  Find File          " },
         command = "Telescope find_files",
       },
       b = {
+        description = { "  New File           " },
+        command = ":ene!",
+      },
+      c = {
         description = { "  Recent Projects    " },
         command = "Telescope projects",
       },
-      c = {
+      d = {
         description = { "  Recently Used Files" },
         command = "Telescope oldfiles",
       },
-      d = {
+      e = {
         description = { "  Find Word          " },
         command = "Telescope live_grep",
       },
-      e = {
+      f = {
         description = { "  Configuration      " },
-        command = ":e " .. config.path,
+        command = ":e " .. config.user_config_file,
       },
     },
   }
diff --git a/.config/nvim/lua/core/info.lua b/.config/nvim/lua/core/info.lua
index cf4387e..d448492 100644
--- a/.config/nvim/lua/core/info.lua
+++ b/.config/nvim/lua/core/info.lua
@@ -17,55 +17,37 @@ local function str_list(list)
   return fmt("[ %s ]", table.concat(list, ", "))
 end
 
-local function get_formatter_suggestion_msg(ft)
-  local config = require "config"
+local function make_formatters_info(ft)
   local null_formatters = require "lsp.null-ls.formatters"
+  local registered_formatters = null_formatters.list_registered_providers(ft)
   local supported_formatters = null_formatters.list_available(ft)
   local section = {
-    " HINT ",
-    "",
-    fmt("* List of supported formatters: %s", str_list(supported_formatters)),
+    "Formatters info",
+    fmt(
+      "* Active: %s%s",
+      table.concat(registered_formatters, "  , "),
+      vim.tbl_count(registered_formatters) > 0 and "  " or ""
+    ),
+    fmt("* Supported: %s", str_list(supported_formatters)),
   }
 
-  if not vim.tbl_isempty(supported_formatters) then
-    vim.list_extend(section, {
-      "* Configured formatter needs to be installed and executable.",
-      fmt("* Enable installed formatter(s) with following config in %s", config.path),
-      "",
-      fmt(
-        "  options.lang.%s.formatters = { { exe = '%s' } }",
-        ft,
-        table.concat(supported_formatters, "│")
-      ),
-    })
-  end
-
   return section
 end
 
-local function get_linter_suggestion_msg(ft)
-  local config = require "config"
+local function make_linters_info(ft)
   local null_linters = require "lsp.null-ls.linters"
   local supported_linters = null_linters.list_available(ft)
+  local registered_linters = null_linters.list_registered_providers(ft)
   local section = {
-    " HINT ",
-    "",
-    fmt("* List of supported linters: %s", str_list(supported_linters)),
+    "Linters info",
+    fmt(
+      "* Active: %s%s",
+      table.concat(registered_linters, "  , "),
+      vim.tbl_count(registered_linters) > 0 and "  " or ""
+    ),
+    fmt("* Supported: %s", str_list(supported_linters)),
   }
 
-  if not vim.tbl_isempty(supported_linters) then
-    vim.list_extend(section, {
-      "* Configured linter needs to be installed and executable.",
-      fmt("* Enable installed linter(s) with following config in %s", config.path),
-      "",
-      fmt(
-        "  options.lang.%s.linters = { { exe = '%s' } }",
-        ft,
-        table.concat(supported_linters, "│")
-      ),
-    })
-  end
-
   return section
 end
 
@@ -79,14 +61,21 @@ local function make_client_info(client)
   local client_enabled_caps = lsp_utils.get_client_capabilities(client.id)
   local name = client.name
   local id = client.id
+  local filetypes = lsp_utils.get_supported_filetypes(name)
   local document_formatting = client.resolved_capabilities.document_formatting
+  local attached_buffers_list = table.concat(
+    vim.lsp.get_buffers_by_client_id(client.id),
+    ", "
+  )
   local client_info = {
-    fmt("* Name:                 %s", name),
-    fmt("* Id:                   %s", tostring(id)),
-    fmt("* Supports formatting:  %s", tostring(document_formatting)),
+    fmt("* Name:                      %s", name),
+    fmt("* Id:                        [%s]", tostring(id)),
+    fmt("* filetype(s):               [%s]", table.concat(filetypes, ", ")),
+    fmt("* Attached buffers:          [%s]", tostring(attached_buffers_list)),
+    fmt("* Supports formatting:       %s", tostring(document_formatting)),
   }
   if not vim.tbl_isempty(client_enabled_caps) then
-    local caps_text = "* Capabilities list:    "
+    local caps_text = "* Capabilities list:         "
     local caps_text_len = caps_text:len()
     local enabled_caps = text.format_table(client_enabled_caps, 3, " | ")
     enabled_caps = text.shift_right(enabled_caps, caps_text_len)
@@ -100,18 +89,29 @@ end
 function M.toggle_popup(ft)
   local clients = lsp_utils.get_active_clients_by_ft(ft)
   local client_names = {}
-
+  local bufnr = vim.api.nvim_get_current_buf()
+  local ts_active_buffers = vim.tbl_keys(vim.treesitter.highlighter.active)
+  local is_treesitter_active = function()
+    local status = "inactive"
+    if vim.tbl_contains(ts_active_buffers, bufnr) then
+      status = "active"
+    end
+    return status
+  end
   local header = {
-    fmt("Detected filetype:      %s", ft),
-    fmt(
-      "Treesitter active:      %s",
-      tostring(next(vim.treesitter.highlighter.active) ~= nil)
-    ),
+    fmt("Detected filetype:           %s", ft),
+    fmt("Current buffer number:       [%s]", bufnr),
+  }
+
+  local ts_info = {
+    "Treesitter info",
+    fmt("* current buffer:            %s", is_treesitter_active()),
+    fmt("* list:                      [%s]", table.concat(ts_active_buffers, ", ")),
   }
 
   local lsp_info = {
     "Language Server Protocol (LSP) info",
-    fmt "* Associated server(s):",
+    fmt "* Active server(s):",
   }
 
   for _, client in pairs(clients) do
@@ -119,22 +119,9 @@ function M.toggle_popup(ft)
     table.insert(client_names, client.name)
   end
 
-  local null_formatters = require "lsp.null-ls.formatters"
-  local null_linters = require "lsp.null-ls.linters"
-  local registered_formatters = null_formatters.list_supported_names(ft)
-  local registered_linters = null_linters.list_supported_names(ft)
-  local registered_providers = {}
-  vim.list_extend(registered_providers, registered_formatters)
-  vim.list_extend(registered_providers, registered_linters)
-  local registered_count = vim.tbl_count(registered_providers)
-  local null_ls_info = {
-    "Formatters and linters",
-    fmt(
-      "* Configured providers: %s%s",
-      table.concat(registered_providers, "  , "),
-      registered_count > 0 and "  " or ""
-    ),
-  }
+  local formatters_info = make_formatters_info(ft)
+
+  local linters_info = make_linters_info(ft)
 
   local content_provider = function(popup)
     local content = {}
@@ -145,15 +132,13 @@ function M.toggle_popup(ft)
       { "" },
       header,
       { "" },
-      lsp_info,
-      { "" },
-      null_ls_info,
-      { "" },
+      ts_info,
       { "" },
-      get_formatter_suggestion_msg(ft),
+      lsp_info,
       { "" },
+      formatters_info,
       { "" },
-      get_linter_suggestion_msg(ft),
+      linters_info,
     } do
       vim.list_extend(content, section)
     end
@@ -162,14 +147,27 @@ function M.toggle_popup(ft)
   end
 
   local function set_syntax_hl()
-    vim.cmd [[highlight nvimInfoIdentifier gui=bold]]
-    vim.cmd [[highlight link nvimInfoHeader Type]]
-    vim.cmd [[let m=matchadd("nvimInfoHeader", "Language Server Protocol (LSP) info")]]
-    vim.cmd [[let m=matchadd("nvimInfoHeader", "Formatters and linters")]]
-    vim.cmd('let m=matchadd("nvimInfoIdentifier", " ' .. ft .. '$")')
+    vim.cmd [[highlight NvimInfoIdentifier gui=bold]]
+    vim.cmd [[highlight link NvimInfoHeader Type]]
+    vim.cmd [[let m=matchadd("NvimInfoHeader", "Treesitter info")]]
+    vim.cmd [[let m=matchadd("NvimInfoHeader", "Language Server Protocol (LSP) info")]]
+    vim.cmd [[let m=matchadd("NvimInfoHeader", "Formatters info")]]
+    vim.cmd [[let m=matchadd("NvimInfoHeader", "Linters info")]]
+    vim.cmd('let m=matchadd("NvimInfoIdentifier", " ' .. ft .. '$")')
     vim.cmd 'let m=matchadd("string", "true")'
+    vim.cmd 'let m=matchadd("string", "active")'
+    vim.cmd 'let m=matchadd("boolean", "inactive")'
+    vim.cmd 'let m=matchadd("string", "")'
     vim.cmd 'let m=matchadd("error", "false")'
-    tbl_set_highlight(registered_providers, "nvimInfoIdentifier")
+    -- tbl_set_highlight(registered_providers, "NvimInfoIdentifier")
+    tbl_set_highlight(
+      require("lsp.null-ls.formatters").list_available(ft),
+      "NvimInfoIdentifier"
+    )
+    tbl_set_highlight(
+      require("lsp.null-ls.linters").list_available(ft),
+      "NvimInfoIdentifier"
+    )
   end
 
   local Popup = require("interface.popup"):new {
diff --git a/.config/nvim/lua/core/log.lua b/.config/nvim/lua/core/log.lua
index de03521..c44808f 100644
--- a/.config/nvim/lua/core/log.lua
+++ b/.config/nvim/lua/core/log.lua
@@ -1,60 +1,127 @@
 local Log = {}
 
+local logfile = string.format("%s/%s.log", vim.fn.stdpath "cache", "nvim")
+
+Log.levels = {
+  TRACE = 1,
+  DEBUG = 2,
+  INFO = 3,
+  WARN = 4,
+  ERROR = 5,
+}
+
+vim.tbl_add_reverse_lookup(Log.levels)
+
+function Log:init()
+  local status_ok, structlog = pcall(require, "structlog")
+  if not status_ok then
+    return nil
+  end
+
+  local log_level = Log.levels[(options.log.level):upper() or "WARN"]
+  local nvim_log = {
+    nvim = {
+      sinks = {
+        structlog.sinks.Console(log_level, {
+          async = false,
+          processors = {
+            structlog.processors.Namer(),
+            structlog.processors.StackWriter(
+              { "line", "file" },
+              { max_parents = 0, stack_level = 2 }
+            ),
+            structlog.processors.Timestamper "%H:%M:%S",
+          },
+          formatter = structlog.formatters.FormatColorizer( --
+            "%s [%-5s] %s: %-30s",
+            { "timestamp", "level", "logger_name", "msg" },
+            { level = structlog.formatters.FormatColorizer.color_level() }
+          ),
+        }),
+        structlog.sinks.File(Log.levels.TRACE, logfile, {
+          processors = {
+            structlog.processors.Namer(),
+            structlog.processors.StackWriter(
+              { "line", "file" },
+              { max_parents = 3, stack_level = 2 }
+            ),
+            structlog.processors.Timestamper "%H:%M:%S",
+          },
+          formatter = structlog.formatters.Format( --
+            "%s [%-5s] %s: %-30s",
+            { "timestamp", "level", "logger_name", "msg" }
+          ),
+        }),
+      },
+    },
+  }
+
+  structlog.configure(nvim_log)
+
+  local logger = structlog.get_logger "nvim"
+
+  return logger
+end
+
 --- Adds a log entry using Plenary.log
----@param msg any
+---@fparam msg any
 ---@param level string [same as vim.log.log_levels]
-function Log:add_entry(msg, level)
-  assert(type(level) == "string")
+function Log:add_entry(level, msg, event)
   if self.__handle then
-    -- plenary uses lower-case log levels
-    self.__handle[level:lower()](msg)
+    self.__handle:log(level, vim.inspect(msg), event)
     return
   end
-  local status_ok, plenary = pcall(require, "plenary")
-  if status_ok then
-    local default_opts = { plugin = "nvim", level = options.log.level }
-    local handle = plenary.log.new(default_opts)
-    handle[level:lower()](msg)
-    self.__handle = handle
+
+  local logger = self:init()
+  if not logger then
+    return
   end
-  -- don't do anything if plenary is not available
+
+  self.__handle = logger
+  self.__handle:log(level, vim.inspect(msg), event)
 end
 
 ---Retrieves the path of the logfile
 ---@return string path of the logfile
 function Log:get_path()
-  return string.format("%s/%s.log", vim.fn.stdpath "cache", "nvim")
+  return logfile
 end
 
 ---Add a log entry at TRACE level
 ---@param msg any
-function Log:trace(msg)
-  self:add_entry(msg, "TRACE")
+---@param event any
+function Log:trace(msg, event)
+  self:add_entry(self.levels.TRACE, msg, event)
 end
 
 ---Add a log entry at DEBUG level
 ---@param msg any
-function Log:debug(msg)
-  self:add_entry(msg, "DEBUG")
+---@param event any
+function Log:debug(msg, event)
+  self:add_entry(self.levels.DEBUG, msg, event)
 end
 
 ---Add a log entry at INFO level
 ---@param msg any
-function Log:info(msg)
-  self:add_entry(msg, "INFO")
+---@param event any
+function Log:info(msg, event)
+  self:add_entry(self.levels.INFO, msg, event)
 end
 
 ---Add a log entry at WARN level
 ---@param msg any
-function Log:warn(msg)
-  self:add_entry(msg, "WARN")
+---@param event any
+function Log:warn(msg, event)
+  self:add_entry(self.levels.WARN, msg, event)
 end
 
 ---Add a log entry at ERROR level
 ---@param msg any
-function Log:error(msg)
-  self:add_entry(msg, "ERROR")
+---@param event any
+function Log:error(msg, event)
+  self:add_entry(self.levels.ERROR, msg, event)
 end
 
 setmetatable({}, Log)
+
 return Log
diff --git a/.config/nvim/lua/core/lualine/components.lua b/.config/nvim/lua/core/lualine/components.lua
index 9333a17..6ef1cff 100644
--- a/.config/nvim/lua/core/lualine/components.lua
+++ b/.config/nvim/lua/core/lualine/components.lua
@@ -117,12 +117,12 @@ return {
 
       -- add formatter
       local formatters = require "lsp.null-ls.formatters"
-      local supported_formatters = formatters.list_supported_names(buf_ft)
+      local supported_formatters = formatters.list_registered_providers(buf_ft)
       vim.list_extend(buf_client_names, supported_formatters)
 
       -- add linter
       local linters = require "lsp.null-ls.linters"
-      local supported_linters = linters.list_supported_names(buf_ft)
+      local supported_linters = linters.list_registered_providers(buf_ft)
       vim.list_extend(buf_client_names, supported_linters)
 
       return table.concat(buf_client_names, ", ")
@@ -135,11 +135,14 @@ return {
   progress = { "progress", cond = conditions.hide_in_width, color = {} },
   spaces = {
     function()
-      local label = "Spaces: "
       if not vim.api.nvim_buf_get_option(0, "expandtab") then
-        label = "Tab size: "
+        return "Tab size: " .. vim.api.nvim_buf_get_option(0, "tabstop") .. " "
       end
-      return label .. vim.api.nvim_buf_get_option(0, "shiftwidth") .. " "
+      local size = vim.api.nvim_buf_get_option(0, "shiftwidth")
+      if size == 0 then
+        size = vim.api.nvim_buf_get_option(0, "tabstop")
+      end
+      return "Spaces: " .. size .. " "
     end,
     color = {},
     cond = conditions.hide_in_width,
diff --git a/.config/nvim/lua/core/telescope.lua b/.config/nvim/lua/core/telescope.lua
index 108b6f3..7ef2e58 100644
--- a/.config/nvim/lua/core/telescope.lua
+++ b/.config/nvim/lua/core/telescope.lua
@@ -15,14 +15,6 @@ function M.config()
 
   options.builtin.telescope = vim.tbl_extend("force", options.builtin.telescope, {
     defaults = {
-      find_command = {
-        "rg",
-        "--no-heading",
-        "--with-filename",
-        "--line-number",
-        "--column",
-        "--smart-case",
-      },
       prompt_prefix = " ",
       selection_caret = " ",
       entry_prefix = "  ",
@@ -37,55 +29,55 @@ function M.config()
         horizontal = { mirror = false },
         vertical = { mirror = false },
       },
-      file_sorter = require("telescope.sorters").get_fzy_sorter,
-      file_ignore_patterns = {},
-      generic_sorter = require("telescope.sorters").get_generic_fuzzy_sorter,
-      path_display = { "shorten" },
-      winblend = 0,
-      border = {},
-      borderchars = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" },
-      color_devicons = true,
-      use_less = true,
-      set_env = { ["CoptionsLoptionsRTERM"] = "truecolor" }, -- default = nil,
-      file_previewer = require("telescope.previewers").vim_buffer_cat.new,
-      grep_previewer = require("telescope.previewers").vim_buffer_vimgrep.new,
-      qflist_previewer = require("telescope.previewers").vim_buffer_qflist.new,
-
-      -- Developer configurations: Not meant for general override
-      -- buffer_previewer_maker = require("telescope.previewers").buffer_previewer_maker,
+      vimgrep_arguments = {
+        "rg",
+        "--color=never",
+        "--no-heading",
+        "--with-filename",
+        "--line-number",
+        "--column",
+        "--smart-case",
+        "--hidden",
+      },
       mappings = {
         i = {
-          -- ["<C-n>"] = actions.cycle_history_next,
-          -- ["<C-p>"] = actions.cycle_history_prev,
+          ["<C-n>"] = actions.move_selection_next,
+          ["<C-p>"] = actions.move_selection_previous,
           ["<C-c>"] = actions.close,
-          ["<C-j>"] = actions.move_selection_next,
-          ["<C-k>"] = actions.move_selection_previous,
+          ["<C-j>"] = actions.cycle_history_next,
+          ["<C-k>"] = actions.cycle_history_prev,
           ["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
           ["<CR>"] = actions.select_default + actions.center,
-          -- To disable a keymap, put [map] = false
-          -- So, to not map "<C-n>", just put
-          -- ["<c-t>"] = trouble.open_with_trouble,
-          -- ["<c-x>"] = false,
-          -- ["<esc>"] = actions.close,
-          -- optionstherwise, just set the mapping to the function that you want it to be.
-          -- ["<C-i>"] = actions.select_horizontal,
-          -- Add up multiple actions
-          -- You can perform as many actions in a row as you like
-          -- ["<CR>"] = actions.select_default + actions.center + my_cool_custom_action,
         },
         n = {
-          ["<C-j>"] = actions.move_selection_next,
-          ["<C-k>"] = actions.move_selection_previous,
+          ["<C-n>"] = actions.move_selection_next,
+          ["<C-p>"] = actions.move_selection_previous,
           ["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
-          -- ["<c-t>"] = trouble.open_with_trouble,
-          -- ["<C-i>"] = my_cool_custom_action,
+        },
+      },
+      file_ignore_patterns = {},
+      path_display = { shorten = 5 },
+      winblend = 0,
+      border = {},
+      borderchars = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" },
+      color_devicons = true,
+      set_env = { ["COLORTERM"] = "truecolor" }, -- default = nil,
+      pickers = {
+        find_files = {
+          find_command = { "fd", "--type=file", "--hidden", "--smart-case" },
+        },
+        live_grep = {
+          --@usage don't include the filename in the search results
+          only_sort_text = true,
         },
       },
     },
     extensions = {
-      fzy_native = {
-        override_generic_sorter = false,
-        override_file_sorter = true,
+      fzf = {
+        fuzzy = true, -- false will only do exact matching
+        override_generic_sorter = true, -- override the generic sorter
+        override_file_sorter = true, -- override the file sorter
+        case_mode = "smart_case", -- or "ignore_case" or "respect_case"
       },
     },
   })
@@ -108,20 +100,60 @@ function M.code_actions()
     previewer = false,
     shorten_path = false,
   }
-  require("telescope.builtin").lsp_code_actions(require("telescope.themes").get_dropdown(opts))
+  require("telescope.builtin").lsp_code_actions(
+    require("telescope.themes").get_dropdown(opts)
+  )
 end
 
 function M.setup()
+  local previewers = require "telescope.previewers"
+  local sorters = require "telescope.sorters"
+  local actions = require "telescope.actions"
+
+  options.builtin.telescope = vim.tbl_extend("keep", {
+    file_previewer = previewers.vim_buffer_cat.new,
+    grep_previewer = previewers.vim_buffer_vimgrep.new,
+    qflist_previewer = previewers.vim_buffer_qflist.new,
+    file_sorter = sorters.get_fuzzy_file,
+    generic_sorter = sorters.get_generic_fuzzy_sorter,
+    ---@usage Mappings are fully customizable. Many familiar mapping patterns are setup as defaults.
+    mappings = {
+      i = {
+        ["<C-n>"] = actions.move_selection_next,
+        ["<C-p>"] = actions.move_selection_previous,
+        ["<C-c>"] = actions.close,
+        ["<C-j>"] = actions.cycle_history_next,
+        ["<C-k>"] = actions.cycle_history_prev,
+        ["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
+        ["<CR>"] = actions.select_default + actions.center,
+      },
+      n = {
+        ["<C-n>"] = actions.move_selection_next,
+        ["<C-p>"] = actions.move_selection_previous,
+        ["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
+      },
+    },
+  }, options.builtin.telescope)
+
   local telescope = require "telescope"
 
   telescope.setup(options.builtin.telescope)
+
   if options.builtin.project.active then
-    telescope.load_extension "projects"
+    pcall(function()
+      require("telescope").load_extension "projects"
+    end)
   end
 
   if options.builtin.telescope.on_config_done then
     options.builtin.telescope.on_config_done(telescope)
   end
+
+  if
+    options.builtin.telescope.extensions and options.builtin.telescope.extensions.fzf
+  then
+    require("telescope").load_extension "fzf"
+  end
 end
 
 return M
diff --git a/.config/nvim/lua/core/treesitter.lua b/.config/nvim/lua/core/treesitter.lua
index 59adda4..b56c245 100644
--- a/.config/nvim/lua/core/treesitter.lua
+++ b/.config/nvim/lua/core/treesitter.lua
@@ -1,4 +1,3 @@
-
 local M = {}
 local Log = require "core.log"
 
@@ -17,8 +16,17 @@ M.config = function()
       disable = { "latex" },
     },
     context_commentstring = {
-      enable = false,
-      config = { css = "// %s" },
+      enable = true,
+      config = {
+        -- Languages that have a single comment style
+        typescript = "// %s",
+        css = "/* %s */",
+        scss = "/* %s */",
+        html = "<!-- %s -->",
+        svelte = "<!-- %s -->",
+        vue = "<!-- %s -->",
+        json = "",
+      },
     },
     -- indent = {enable = true, disable = {"python", "html", "javascript"}},
     -- TODO seems to be broken
@@ -72,7 +80,11 @@ M.setup = function()
     return
   end
 
-  treesitter_configs.setup(options.builtin.treesitter)
+  local opts = vim.deepcopy(options.builtin.treesitter)
+
+  -- avoid running any installers in headless mode since it's harder to detect failures
+  opts.ensure_installed = #vim.api.nvim_list_uis() == 0 and {} or opts.ensure_installed
+  treesitter_configs.setup(opts)
 
   if options.builtin.treesitter.on_config_done then
     options.builtin.treesitter.on_config_done(treesitter_configs)
diff --git a/.config/nvim/lua/core/which-key.lua b/.config/nvim/lua/core/which-key.lua
index fe38358..ccf0c2d 100644
--- a/.config/nvim/lua/core/which-key.lua
+++ b/.config/nvim/lua/core/which-key.lua
@@ -61,7 +61,7 @@ M.config = function()
     -- NOTE: Prefer using : over <cmd> as the latter avoids going back in normal-mode.
     -- see https://neovim.io/doc/user/map.html#:map-cmd
     vmappings = {
-      ["k"] = { "<ESC><CMD>lua ___comment_gc(vim.fn.visualmode())<CR>", "Comment" },
+      ["/"] = { "<ESC><CMD>lua ___comment_gc(vim.fn.visualmode())<CR>", "Comment" },
     },
     mappings = {
       ["w"] = { "<cmd>w!<CR>", "Save" },
@@ -69,7 +69,7 @@ M.config = function()
       ["k"] = { "<cmd>lua require('Comment').toggle()<CR>", "Comment" },
       ["c"] = { "<cmd>BufferClose!<CR>", "Close Buffer" },
       ["f"] = { "<cmd>Telescope find_files<CR>", "Find File" },
-      ["n"] = { "<cmd>nohlsearch<CR>", "No Highlight" },
+      ["h"] = { "<cmd>nohlsearch<CR>", "No Highlight" },
       b = {
         name = "Buffers",
         j = { "<cmd>BufferPick<cr>", "Jump" },
@@ -98,7 +98,7 @@ M.config = function()
         name = "Packer",
         c = { "<cmd>PackerCompile<cr>", "Compile" },
         i = { "<cmd>PackerInstall<cr>", "Install" },
-        r = { "<cmd>lua require('utils').reload_config()<cr>", "Reload" },
+        r = { "<cmd>lua require('plugin-loader').recompile()<cr>", "Re-compile" },
         s = { "<cmd>PackerSync<cr>", "Sync" },
         S = { "<cmd>PackerStatus<cr>", "Status" },
         u = { "<cmd>PackerUpdate<cr>", "Update" },
@@ -139,7 +139,10 @@ M.config = function()
 
       l = {
         name = "LSP",
-        a = { "<cmd>lua require('core.telescope').code_actions()<cr>", "Code Action" },
+        a = {
+          "<cmd>lua require('core.telescope').code_actions()<cr>",
+          "Code Action",
+        },
         d = {
           "<cmd>Telescope lsp_document_diagnostics<cr>",
           "Document Diagnostics",
@@ -148,15 +151,15 @@ M.config = function()
           "<cmd>Telescope lsp_workspace_diagnostics<cr>",
           "Workspace Diagnostics",
         },
-        -- f = { "<cmd>silent FormatWrite<cr>", "Format" },
         f = { "<cmd>lua vim.lsp.buf.formatting()<cr>", "Format" },
         i = { "<cmd>LspInfo<cr>", "Info" },
+        I = { "<cmd>LspInstallInfo<cr>", "Installer Info" },
         j = {
-          "<cmd>lua vim.lsp.diagnostic.goto_next({popup_opts = {border = options.lsp.popup_border}})<cr>",
+          "<cmd>lua vim.lsp.diagnostic.goto_next({popup_opts = {border = lsp.popup_border}})<cr>",
           "Next Diagnostic",
         },
         k = {
-          "<cmd>lua vim.lsp.diagnostic.goto_prev({popup_opts = {border = options.lsp.popup_border}})<cr>",
+          "<cmd>lua vim.lsp.diagnostic.goto_prev({popup_opts = {border = lsp.popup_border}})<cr>",
           "Prev Diagnostic",
         },
         l = { "<cmd>lua vim.lsp.codelens.run()<cr>", "CodeLens Action" },
@@ -180,19 +183,23 @@ M.config = function()
           "Workspace Symbols",
         },
       },
-      i = {
-        name = "+nvim",
+      L = {
+        name = "+NeoVim",
         c = {
-          "<cmd>edit ~/.config/nvim/config.lua<cr>",
+          "<cmd>edit " .. get_config_dir() .. "/config.lua<cr>",
           "Edit config.lua",
         },
         k = {
           "<cmd>lua require('keymappings').print()<cr>",
-          "View LunarVim's default keymappings",
+          "View NeoVim's default keymappings",
         },
         i = {
           "<cmd>lua require('core.info').toggle_popup(vim.bo.filetype)<cr>",
-          "Toggle nvim Info",
+          "Toggle NeoVim Info",
+        },
+        I = {
+          "<cmd>lua require('core.telescope.custom-finders').view_lunarvim_changelog()<cr>",
+          "View NeoVim's changelog",
         },
         l = {
           name = "+logs",
@@ -226,7 +233,8 @@ M.config = function()
             "Open the Packer logfile",
           },
         },
-        r = { "<cmd>lua require('utils').reload_config()<cr>", "Reload configurations" },
+        r = { "<cmd>NvimReload<cr>", "Reload Neovim's configuration" },
+        u = { "<cmd>NvimUpdate<cr>", "Update NeoVim" },
       },
       s = {
         name = "Search",
-- 
cgit v1.2.3-70-g09d2