Skip to main content
This configuration includes comprehensive UI enhancements through statusline, tabline, and various visual helper plugins.

Statusline (Lualine)

A fast and highly customizable statusline powered by lualine.nvim.

Configuration

lua/plugins/statusline.lua
{
  "nvim-lualine/lualine.nvim",
  dependencies = { 
    "nvim-mini/mini.nvim", 
    "lewis6991/gitsigns.nvim", 
    "sainnhe/gruvbox-material" 
  },
  opts = {
    options = {
      theme = "gruvbox-material",
      section_separators = { left = "", right = "" },
      component_separators = { left = "", right = "" },
      icons_enabled = true,
    },
  },
}

Sections

Left

Mode indicator and git branch

Center

Relative file path

Right

Filetype, search count, and cursor position

Section A: Mode

lua/plugins/statusline.lua
lualine_a = { "mode" }
Displays current Neovim mode (NORMAL, INSERT, VISUAL, etc.).

Section B: Git status

lua/plugins/statusline.lua
lualine_b = {
  {
    "branch",
    icon = "",
  },
  {
    "diff",
    colored = true,
    symbols = { added = " ", modified = " ", removed = " " },
    source = function()
      local gitsigns = vim.b.gitsigns_status_dict
      if gitsigns then
        return {
          added = gitsigns.added,
          modified = gitsigns.changed,
          removed = gitsigns.removed,
        }
      end
    end,
  },
}
Git diff counts are pulled directly from Gitsigns for accurate, real-time statistics.

Section C: File path

lua/plugins/statusline.lua
lualine_c = { { "filename", path = 1 } }
Shows relative path to current file.

Section X: File type

lua/plugins/statusline.lua
lualine_x = { "filetype" }

Section Y: Dynamic LSP/Search info

Intelligently switches between search count and LSP status:
lua/plugins/statusline.lua
lualine_y = {
  {
    function()
      -- Show search count when searching
      if vim.v.hlsearch == 1 and vim.fn.getreg("/") ~= "" then
        local ok, result = pcall(vim.fn.searchcount, { maxcount = 999, timeout = 100 })
        if ok and result and result.total > 0 then
          local current = result.current
          local total = result.total
          
          if result.incomplete == 1 then
            return string.format(" ?/%d", total)
          elseif result.incomplete == 2 then
            return string.format(" %d/>%d", current, total)
          else
            return string.format(" %d/%d", current, total)
          end
        end
      end
      
      -- Show LSP name when no search is active
      local clients = vim.lsp.get_clients({ bufnr = 0 })
      clients = vim.tbl_filter(function(client)
        return client.name ~= "copilot"
      end, clients)
      if #clients == 0 then
        return ""
      end
      
      local lsp_count = #clients
      if lsp_count == 1 then
        return " " .. clients[1].name
      else
        return " " .. clients[1].name .. " (" .. lsp_count .. ")"
      end
    end,
    color = function()
      -- Orange for search, default for LSP
      if vim.v.hlsearch == 1 and vim.fn.getreg("/") ~= "" then
        return { fg = "#ff9e64" }
      else
        return nil
      end
    end,
  },
}
When searching, shows: 3/15 (match 3 of 15)
  • Orange color for visibility
  • Shows incomplete results with ? or >

Section Z: Position

lua/plugins/statusline.lua
lualine_z = { "location", "spelunk" }
  • location: Line and column number
  • spelunk: Additional navigation info (if available)

Tabline (Barbar)

Bufferline with tabs for easy buffer navigation:
lua/plugins/tabline.lua
{
  "romgrk/barbar.nvim",
  version = "^1.0.0",
  dependencies = { "nvim-mini/mini.nvim" },
}

Buffer navigation

KeyActionDescription
<A-,>Previous bufferMove to previous buffer
<A-.>Next bufferMove to next buffer
<A-<>Move leftReorder buffer left
<A->>Move rightReorder buffer right
<A-c>Close bufferClose current buffer
<A-p>Pin bufferPin/unpin buffer

Jump to buffer

lua/plugins/tabline.lua
map("n", "<leader>1", "<Cmd>BufferGoto 1<CR>")
map("n", "<leader>2", "<Cmd>BufferGoto 2<CR>")
-- ... up to <leader>9
map("n", "<leader>0", "<Cmd>BufferLast<CR>")
Quickly jump to buffer by position with <leader>1 through <leader>9.

Buffer picking

lua/plugins/tabline.lua
map("n", "<C-p>", "<Cmd>BufferPick<CR>")
map("n", "<C-s-p>", "<Cmd>BufferPickDelete<CR>")
  • <C-p>: Magic buffer picking mode (shows letters for each buffer)
  • <C-s-p>: Pick buffer to delete

Sorting buffers

KeySort byDescription
<Space>bbBuffer numberSort by buffer ID
<Space>bnNameSort alphabetically
<Space>bdDirectorySort by directory
<Space>blLanguageSort by filetype
<Space>bwWindow numberSort by window

Configuration

lua/plugins/tabline.lua
opts = {
  animation = true,
  tabpages = true,
  focus_on_close = "left",
  hide = { extensions = true, inactive = false },
  icons = {
    buffer_index = true,
    button = "",
    diagnostics = {
      [vim.diagnostic.severity.ERROR] = { enabled = true, icon = " " },
      [vim.diagnostic.severity.WARN] = { enabled = true, icon = " " },
    },
    modified = { button = "●" },
    pinned = { button = "", filename = true },
  },
  maximum_length = 25,
}

Animations

Smooth transitions when switching buffers

Diagnostics

Shows error and warning counts in tabs

Pin support

Pin important buffers to prevent closing

Buffer indices

Shows numbers for quick jumping

Which-key

Displays popup with available keybindings:
lua/plugins/ui.lua
{
  "folke/which-key.nvim",
  event = "VeryLazy",
  opts = {
    delay = 1000, -- ms before popup shows
  },
}

Usage

  • Type any key sequence and wait 1 second
  • Which-key shows all available completions
  • Example: Press <leader> and wait to see all leader mappings

Buffer-local keymaps

<leader>?
Shows keymaps specific to current buffer.

Color highlighter

Highlights color codes inline:
lua/plugins/ui.lua
{
  "norcalli/nvim-colorizer.lua",
  event = "VeryLazy",
  config = function()
    require("colorizer").setup({
      "*",
      css = { css = true },
      scss = { css = true },
      html = { css = true },
      javascript = { css = true },
      javascriptreact = { css = true },
      typescript = { css = true },
      typescriptreact = { css = true },
    }, {
      RGB = true,      -- #RGB
      RRGGBB = true,   -- #RRGGBB
      RRGGBBAA = true, -- #RRGGBBAA
      rgb_fn = true,   -- rgb(), rgba()
      hsl_fn = true,   -- hsl(), hsla()
      css = true,      -- All CSS features
      mode = "background",
    })
  end,
}

Supported formats

Hex colors

#RGB, #RRGGBB, #RRGGBBAA

CSS functions

rgb(), rgba(), hsl(), hsla()

Tailwind

Tailwind color classes in JSX/TSX

Comfy line numbers

Enhanced line numbers with automatic relative/absolute switching:
lua/plugins/ui.lua
{
  "snehilshah/comfy-line-numbers.nvim",
  opts = {
    up_key = "k",
    down_key = "j",
    hidden_file_types = { "undotree" },
    hidden_buffer_types = { "terminal", "nofile" },
    hide_in_insert_mode = true,
  },
}
Line numbers automatically switch to absolute in insert mode and relative in normal mode.

Visual whitespace

Shows whitespace characters in visual mode:
lua/plugins/ui.lua
{
  "mcauley-penney/visual-whitespace.nvim",
  event = "ModeChanged *:[vV\22]",
  opts = {
    list_chars = {
      space = "·",
      tab = " ",
      nbsp = "0 ",
      lead = "‹",
      trail = "›",
    },
    fileformat_chars = {
      unix = " 1 ",
      mac = " 1 ",
      dos = " 1 ",
    },
  },
}

Toggle

<leader>tw
Toggle visual whitespace display.

UFO folding

Improved code folding with LSP and Treesitter support:
lua/plugins/ui.lua
{
  "kevinhwang91/nvim-ufo",
  dependencies = { "kevinhwang91/promise-async" },
  event = "BufReadPost",
  config = true,
}

LSP folding

Uses LSP for accurate fold ranges

Treesitter fallback

Falls back to Treesitter when LSP unavailable

Preview

Hover over folds to preview content

Performance

Efficient folding for large files

Default fold keybindings

KeyActionDescription
zaToggle foldOpen/close fold under cursor
zAToggle allToggle all nested folds
zcClose foldClose fold under cursor
zCClose allClose all nested folds
zoOpen foldOpen fold under cursor
zOOpen allOpen all nested folds
zMClose all foldsClose every fold in buffer
zROpen all foldsOpen every fold in buffer
zjNext foldJump to next fold
zkPrevious foldJump to previous fold

Additional UI toggles

Provided by Snacks.nvim:
KeyToggleDescription
<leader>ulLine numbersToggle line numbers
<leader>uLRelative numbersToggle relative line numbers
<leader>uwWrapToggle line wrapping
<leader>usSpellingToggle spell check
<leader>ucConcealToggle conceallevel
See Snacks.nvim documentation for complete list.

Theme integration

All UI components use the gruvbox-material theme for consistency:
  • Lualine: theme = "gruvbox-material"
  • Barbar: Inherits from colorscheme
  • Which-key: Inherits from colorscheme
  • UFO: Custom fold highlighting

Performance considerations

Lazy loading

Most UI plugins load on VeryLazy event

Efficient updates

Statusline updates only on relevant events

Conditional features

Some features disabled in specific contexts (terminal, large files)

Caching

Git status and LSP info cached to reduce recomputation

Build docs developers (and LLMs) love