Banner of The Developer’s Dashboard: Completion, Treesitter, and the Plugin Ecosystem

The Developer’s Dashboard: Completion, Treesitter, and the Plugin Ecosystem


Category: vim

📅 May 15, 2026   |   👁️ Views: 1

Author:   mosaid

Plugins with Purpose

A Neovim configuration can easily drown in plugins. This setup takes the opposite approach: every plugin must solve a problem that cannot be addressed with a few lines of Lua. The result is a lean dashboard where Treesitter provides structural understanding, nvim‑cmp offers intelligent completion, LuaSnip gives programmable snippets, and bufferline keeps tabs visible without visual clutter.

In this final article we open lua/plugins/core.lua – the single file that defines the entire plugin set. We’ll examine why each plugin was chosen, how it’s configured, and how it integrates with the custom functions and snippets we’ve built throughout the series.

The Complete Plugin Specification

Below is the full plugins/core.lua file, broken into sections for discussion.

Themes: Nordic and Tokyonight

Two themes are loaded with lazy = false and high priority, ensuring they are available when colors.lua runs its scheduled setup. Both are configured with transparent backgrounds – Nordic via its transparent option, Tokyonight via transparent = true. The fallback logic (Article #5) means the editor is never without a colourscheme.


{
  "AlexvZyl/nordic.nvim",
  lazy = false,
  priority = 1000,
  config = function()
    require("nordic").setup({
      transparent = {
        bg = true,
        float = true,
      },
    })
    require("nordic").load()
  end,
},

{
  "folke/tokyonight.nvim",
  lazy = false,
  priority = 1000,
  opts = {
    style = "storm",
    transparent = true,
    styles = {
      comments = { italic = true },
      keywords = { italic = true },
    },
  },
},

    

Telescope: Fuzzy Everything

Telescope is loaded on the Telescope command (not at startup) and provides three essential fuzzy finders: files, live grep, and buffers. The keymaps (<leader>ff, <leader>fg, <leader>fb) are defined in its config callback.


{
  "nvim-telescope/telescope.nvim",
  dependencies = { "nvim-lua/plenary.nvim" },
  cmd = "Telescope",
  config = function()
    local builtin = require("telescope.builtin")
    vim.keymap.set("n", "ff", builtin.find_files)
    vim.keymap.set("n", "fg", builtin.live_grep)
    vim.keymap.set("n", "fb", builtin.buffers)
    vim.keymap.set("n", "fh", builtin.help_tags)
  end,
},

    

Treesitter: The Backbone

Treesitter provides structural syntax highlighting and indentation. It’s loaded on BufReadPost and BufNewFile – never at startup – and a minimal set of parsers is installed. The highlight and indent modules are enabled; both are non‑negotiable for accurate editing.


{
  "nvim-treesitter/nvim-treesitter",
  build = ":TSUpdate",
  event = { "BufReadPost", "BufNewFile" },
  config = function()
    require("nvim-treesitter.configs").setup({
      ensure_installed = {
        "lua", "python", "javascript", "html", "css", "bash", "c", "cpp", "json", "yaml",
      },
      highlight = { enable = true },
      indent = { enable = true },
    })
  end,
},

    

nvim-cmp and LuaSnip: The Completion Engine

Completion is the most complex subsystem. nvim-cmp is loaded on InsertEnter and configured with four sources: LSP, LuaSnip, buffer text, and file paths. The snippet expansion is handled by LuaSnip; the Tab key is overloaded to both cycle completion items and expand/advance snippets.

Critically, after cmp.setup(), the configuration loads the snippet files we analysed in Article #4 – config.tex_snippets and config.html_snippets – ensuring snippets are registered before the user starts typing.


{
  "hrsh7th/nvim-cmp",
  dependencies = {
    "hrsh7th/cmp-nvim-lsp",
    "hrsh7th/cmp-buffer",
    "hrsh7th/cmp-path",
    "saadparwaiz1/cmp_luasnip",
    "L3MON4D3/LuaSnip",
  },
  event = "InsertEnter",
  config = function()
    local cmp = require("cmp")
    local luasnip = require("luasnip")

    vim.o.completeopt = "menu,menuone,noselect"

    cmp.setup({
      snippet = {
        expand = function(args)
          luasnip.lsp_expand(args.body)
        end,
      },
      mapping = cmp.mapping.preset.insert({
        [''] = cmp.mapping.complete(),
        [''] = cmp.mapping.confirm({ select = true }),
        [''] = cmp.mapping(function(fallback)
          if cmp.visible() then
            cmp.select_next_item()
          elseif luasnip.expand_or_jumpable() then
            luasnip.expand_or_jump()
          else
            fallback()
          end
        end, { "i", "s" }),
        [''] = cmp.mapping(function(fallback)
          if cmp.visible() then
            cmp.select_prev_item()
          elseif luasnip.jumpable(-1) then
            luasnip.jump(-1)
          else
            fallback()
          end
        end, { "i", "s" }),
      }),
      sources = cmp.config.sources({
        { name = 'nvim_lsp' },
        { name = 'luasnip' },
        { name = 'buffer' },
        { name = 'path' },
      }),
    })

    -- Load LaTeX snippets
    require("config.tex_snippets")
    -- Load HTML snippets
    require("config.html_snippets")
  end,
},

    

Mason: LSP Without the Pain

Mason manages LSP servers, linters, and formatters. It’s loaded with build = ":MasonUpdate" to ensure the registry is up‑to‑date. The configuration is minimal – just require("mason").setup(). The LSP servers are currently commented out in this configuration, but the infrastructure is ready to be uncommented when needed. Keeping Mason in the plugin list even without active LSP servers means :MasonInstall is always available.


{
  "williamboman/mason.nvim",
  build = ":MasonUpdate",
  config = function() require("mason").setup() end,
},

    

Bufferline: Visible Tabs, Minimalist

Bufferline shows open buffers as tabs. It’s configured to be as minimal as possible: no close icons, no diagnostics, no numbers, just separator characters between buffer names. always_show_bufferline = true prevents it from disappearing when only one buffer is open.


{
  "akinsho/bufferline.nvim",
  version = "*",
  config = function()
    require("bufferline").setup({
      options = {
        mode = "buffers",
        show_buffer_close_icons = false,
        show_close_icon = false,
        show_tab_indicators = false,
        truncate_names = false,
        diagnostics = false,
        indicator = { style = "none" },
        separator_style = { "|", "|" },
        always_show_bufferline = true,
        numbers = "none",
      },
    })
  end,
},

    

The Plugin Philosophy: What’s Missing

Equally important is what’s not in this configuration:

  • No file‑tree plugin – ranger (Article #6) and Telescope cover file navigation without a permanent sidebar.
  • No statusline plugin – Neovim’s built‑in statusline is sufficient, and custom highlights keep it readable.
  • No Git gutter – Git operations are handled in the terminal, keeping the editor free of constant change‑tracking visual noise.
  • No AI completion – completion is limited to deterministic sources: LSP, snippets, buffer words, and file paths.

Every omission is a deliberate choice. Each plugin that is included must justify itself every time the editor starts, and none is loaded until needed.

How the Dashboard Comes Together

When Neovim starts:

  1. init.lua sets options, loads lazy.nvim, and schedules the colour setup.
  2. Lazy.nvim parses plugins/core.lua and begins loading plugins by their lazy‑load triggers (events, commands, keys).
  3. The scheduled callback applies the theme, defines global keymaps and commands.
  4. When a buffer is opened, Treesitter attaches, the appropriate ftplugin fires, and snippets register for that filetype.
  5. On InsertEnter, nvim‑cmp activates with all snippet and LSP sources ready.

At no point does the user wait for a progress bar. The entire plugin set, once cached, starts in under 100 milliseconds. The dashboard is ready before you can think about it.

Closing the Series

Over seven articles, we’ve dissected a Neovim configuration from the bootstrapping layer through filetype engines, automation functions, snippet systems, visual theming, keymaps, and finally the plugin ecosystem. The configuration is fully reproducible: clone the repository, run :Lazy sync, and every file, every function, and every colour is exactly as intended.

The real takeaway is not the specific keybindings or colours, but the engineering mindset: treat your editor as a programmable platform, not a settings file. Build functions, not just mappings. Prefer determinism over convenience defaults. And always be able to explain why every plugin is there.

This configuration will continue to evolve, but the principles documented here are timeless. Happy engineering.


← The Toolbelt: Keymaps, User Commands, and File‑Operation Pipelines Snippets as Code: LuaSnip, Dynamic Expansion, and File‑Based Snippet Injection →