Installation and Configuration Guide for Neovim, Zsh, NvChad, and LSP Debugging

Installation and Configuration Guide for Neovim, Zsh, NvChad, and LSP Debugging

Introduction

This guide sets up a powerful, modern development environment that combines:

  • Advanced text editing with IDE-like features (Neovim)
  • Enhanced shell capabilities (Zsh)
  • Beautiful and informative terminal interface (Powerlevel10k)
  • Intelligent code completion and analysis (LSP)
  • Integrated debugging capabilities (DAP)
  • Database management tools

Required Tools

Core Tools

  • Neovim - A modern, highly extensible text editor that improves upon Vim
  • Zsh - A shell with advanced features like improved tab completion and scripting capabilities
  • Oh My Zsh - A framework that makes Zsh configuration manageable and adds useful features
  • NvChad - A carefully crafted Neovim configuration that provides modern IDE features while remaining fast
  • Powerlevel10k - A Zsh theme that provides useful information while remaining responsive

Language Servers & Debugging

  • Mason - A package manager that makes it easy to install and manage LSP servers
  • nvim-dap - Implements the Debug Adapter Protocol, enabling interactive debugging
  • debugpy - Microsoft's debug adapter for Python, enables Python debugging in Neovim

Database Integration

  • vim-dadbod - Database interface that supports multiple database types
  • vim-dadbod-ui - User-friendly interface for database operations

Additional Dependencies

  • Node.js - Required by many LSP servers and development tools
  • Python - Needed for Python development and some Neovim plugins
  • Git - For version control and plugin management
  • build-essential - Provides necessary compilation tools

Installation Steps

1. Install Neovim

Why Neovim?

Neovim is a fork of Vim that adds modern features like:

  • Asynchronous plugin execution
  • Built-in LSP support
  • Lua-based configuration
  • Better default settings
  • Active community and development

System-wide Installation

# Download the latest Neovim AppImage
curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim.appimage

# Make it executable for all users
chmod a+x nvim.appimage

# Move to system bin directory for global access
sudo mv nvim.appimage /usr/bin/nvim

2. Install Required Fonts

Why Special Fonts?

We use special fonts (Nerd Fonts) because they include:

  • Icons used by file explorers
  • Git status symbols
  • LSP diagnostic icons
  • Special characters used by Powerlevel10k

Recommended fonts:

System-wide Font Installation

# Create font directory
sudo mkdir -p /usr/local/share/fonts/<font_name>

# Copy font files
sudo cp ~/Downloads/<font_files> /usr/local/share/fonts/<font_name>/

# Set correct ownership
sudo chown -R root: /usr/local/share/fonts/<font_name>

# Set correct permissions (readable by all users)
sudo chmod 644 /usr/local/share/fonts/<font_name>/*

# Update SELinux context if using SELinux
sudo restorecon -vFr /usr/local/share/fonts/<font_name>

# Update font cache
sudo fc-cache -v

3. Install Zsh and Powerlevel10k

Why Zsh?

Zsh provides several advantages over bash:

  • Better tab completion
  • Better history management
  • More customizable prompts
  • Extended globbing features
  • Spelling correction
  • Better array handling

System-wide Installation

  1. Install Zsh:
# Update package lists
sudo apt update

# Install Zsh
sudo apt install zsh
  1. Make Zsh default for new users:
sudo vim /etc/adduser.conf
# Set: DSHELL=/bin/zsh
# This ensures all new users get Zsh as their default shell
  1. Install Oh My Zsh system-wide:
# Clone Oh My Zsh to shared location
sudo git clone https://github.com/ohmyzsh/ohmyzsh.git /usr/share/oh-my-zsh

# Make it accessible to all users
sudo chmod -R 755 /usr/share/oh-my-zsh

# Configure system-wide Zsh settings
sudo vim /etc/zsh/zshrc

Add these lines to zshrc (enables Oh My Zsh for all users):

export ZSH="/usr/share/oh-my-zsh"
ZSH_THEME="robbyrussell"
plugins=(git)
source $ZSH/oh-my-zsh.sh
  1. Install Powerlevel10k system-wide:
# Clone Powerlevel10k to shared themes directory
sudo git clone --depth=1 https://github.com/romkatv/powerlevel10k.git /usr/share/oh-my-zsh/custom/themes/powerlevel10k

# Edit system Zsh configuration
sudo vim /etc/zsh/zshrc
# Change: ZSH_THEME="powerlevel10k/powerlevel10k"
  1. Install recommended plugins:
# Install supporting tools
sudo apt install git tmux python docker

# Install zsh-autosuggestions (provides Fish-like autosuggestions)
sudo git clone https://github.com/zsh-users/zsh-autosuggestions /usr/share/oh-my-zsh/custom/plugins/zsh-autosuggestions

# Update plugins in /etc/zsh/zshrc:
plugins=(git zsh-autosuggestions tmux python docker)

4. Install NvChad

Why NvChad?

NvChad is a carefully crafted Neovim configuration that provides:

  • Fast startup times (0.02-0.07 seconds)
  • Modern UI with beautiful themes
  • Intelligent code completion
  • Syntax highlighting
  • Built-in LSP configuration
  • File exploration and fuzzy finding
  • Git integration

Installation Steps

  1. Remove existing configurations:
# Clean out any existing Neovim configurations
rm -rf ~/.config/nvim
rm -rf ~/.local/state/nvim
rm -rf ~/.local/share/nvim
  1. Install NvChad:
# Clone the NvChad starter configuration
git clone https://github.com/NvChad/starter ~/.config/nvim
  1. Install dependencies:
# Install essential build tools
sudo apt install build-essential

# Install Node.js and npm (required for many LSP servers)
sudo apt install nodejs npm

# Install Python virtual environment support
sudo apt install python3.11-venv

# Install unzip (needed for some plugin installations)
sudo apt install unzip
  1. Initialize NvChad:
# Start Neovim (this will trigger initial plugin installation)
nvim

# Sync plugins
:Lazy sync

# Install language servers and tools
:MasonInstallAll
  1. Neovim folder structure:
init.lua
  • This is the entry point for the Neovim configuration.
  • It loads and initializes all the settings, plugins, and customizations defined in the other configuration files.
  • Typically includes calls like:
    require("options")
    require("mappings")
    require("plugins")
    require("chadrc")
    

lua/options.lua
  • Contains basic Neovim settings and options such as:
    • Line numbering.
    • Indentation.
    • Mouse support.
  • Example settings:
    vim.opt.number = true -- Show line numbers
    vim.opt.relativenumber = true -- Relative line numbers
    vim.opt.tabstop = 4 -- Tab width
    vim.opt.shiftwidth = 4 -- Indentation width
    

lua/mappings.lua
  • Defines custom key mappings (shortcuts) to enhance productivity.
  • Includes mappings for:
    • Opening file explorers.
    • Searching.
    • Navigating buffers.
  • Example mapping:
    vim.keymap.set("n", "<leader>ff", ":Telescope find_files<CR>", { desc = "Find Files" })
    

lua/chadrc.lua
  • This is a user-specific configuration file to override default settings.
  • It's the main customization point for users.
  • Example:
    return {
      ui = {
        theme = "gruvbox",
      },
      plugins = {
        user = function()
          -- Add custom plugins
          return {
            { "junegunn/vim-easy-align" }
          }
        end,
      },
    }
    

lua/configs/
  • Contains configurations for specific plugins or modules.
  • Each plugin may have its own configuration file here for modularity.
  • Example structure:
    lua/configs/
    ├── lspconfig.lua
    ├── treesitter.lua
    └── telescope.lua
    
  • These files often include calls to plugin-specific setup functions:
    require("nvim-treesitter.configs").setup {
      ensure_installed = "maintained",
      highlight = {
        enable = true,
      },
    }
    

lua/plugins/
  • Manages plugin specifications for the configuration.
  • Works with a plugin manager, usually lazy.nvim.
  • Includes the list of plugins to load and optional lazy-loading configurations.
  • Example:
    return {
      {
        "nvim-treesitter/nvim-treesitter",
        build = ":TSUpdate",
        event = "BufRead",
      },
      {
        "neovim/nvim-lspconfig",
        config = function()
          require("lspconfig").pyright.setup {}
        end,
      },
    }
    

Summary
  • init.lua: Main entry point, calls all configurations.
  • lua/options.lua: Core Neovim settings.
  • lua/mappings.lua: Custom key mappings.
  • lua/chadrc.lua: User-specific overrides for themes, plugins, and settings.
  • lua/configs/: Plugin configurations.
  • lua/plugins/: Plugin specifications for the manager.

This modular structure keeps the configuration clean, maintainable, and extensible. Each component has a well-defined purpose, making it easier to customize and manage your Neovim setup.

  1. Explanation of Mason and Its Integration with Neovim, Lazy, and Mason-LspConfig
What is Mason?
  • Mason is a Neovim plugin designed to simplify the installation and management of external tools, including:

    • Language Server Protocol (LSP) servers.
    • Linters and formatters.
    • Debugging tools.
  • Key Features:

    • Provides a graphical interface for managing tools.
    • Automatically handles downloading, installation, and updates.
    • Supports a wide range of tools across multiple programming languages.
  • Purpose:

    • It eliminates the need for manual installation of LSP servers, linters, and formatters.
    • Ensures that all required tools are available and correctly configured for use in Neovim.

How Mason Connects to Neovim
  • Mason works directly with Neovim's built-in LSP client, nvim-lspconfig.

  • It manages external tools required by Neovim to provide IDE-like features:

    • LSP servers: Enable code completion, diagnostics, and other language-specific features.
    • Formatters and Linters: Improve code quality and enforce consistent styles.
  • Example Workflow:

    1. Mason installs an LSP server (e.g., pyright for Python).
    2. Neovim uses nvim-lspconfig to configure and connect to the installed LSP server.
    3. Users can write and navigate code with LSP features seamlessly integrated.

How Mason Connects to Lazy
  • Lazy.nvim is a plugin manager for Neovim, which manages Mason itself.

  • Mason is added as a plugin in the Lazy configuration:

    return {
      {
        "williamboman/mason.nvim",
        build = ":MasonUpdate",
        config = function()
          require("mason").setup()
        end,
      },
    }
    
  • Lazy's Role:

    • Installs Mason and ensures it is only loaded when required.
    • Enables users to manage Mason through the same plugin management workflow as other Neovim plugins.

What is Mason-LspConfig?
  • Mason-LspConfig is a companion plugin to Mason.

  • It bridges the gap between Mason and nvim-lspconfig by:

    • Automatically configuring the LSP servers installed via Mason.
    • Ensuring that the servers are seamlessly integrated into Neovim's LSP client.
  • Key Features:

    • Simplifies LSP server setup with auto-configuration.
    • Allows for automatic installation of specified LSP servers.
  • Example Configuration:

    return {
      {
        "williamboman/mason-lspconfig.nvim",
        dependencies = { "williamboman/mason.nvim" },
        config = function()
          require("mason-lspconfig").setup({
            ensure_installed = { "pyright", "tsserver", "gopls" }, -- LSP servers to install
            automatic_installation = true,
          })
        end,
      },
    }
    
  • Workflow with Mason-LspConfig:

    1. Mason installs the tools (e.g., LSP servers).
    2. Mason-LspConfig ensures that the installed servers are correctly configured with nvim-lspconfig.
    3. Users gain IDE-like features without needing manual LSP setup.

Summary of Relationships
Component Role
Mason Manages installation and updates of LSP servers, formatters, and linters.
Lazy.nvim Handles installation and lazy-loading of Mason as a plugin.
Neovim Uses Mason-installed tools to provide LSP and formatting features.
Mason-LspConfig Connects Mason-installed LSP servers with nvim-lspconfig for seamless integration.

This ecosystem simplifies the process of setting up a fully functional Neovim environment with IDE-like capabilities.

7. Configure LSP Support

Why LSP?

The Language Server Protocol (LSP) provides:

  • Code completion
  • Go to definition
  • Find references
  • Symbol search
  • Diagnostics (errors and warnings)
  • Code formatting
  • Refactoring support

Install and Configure Mason LSP

Create lua/plugins/mason-lspconfig.lua:

return {
  {
    "williamboman/mason-lspconfig.nvim",
    dependencies = { "williamboman/mason.nvim" },
    config = function()
      require("mason-lspconfig").setup({
        -- Install these LSP servers automatically
        ensure_installed = { 
          "pylsp",    -- Python language server
          "typos-lsp", -- Spell checking
          "yamlls"    -- YAML support
        },
        automatic_installation = true,
      })
    end,
  },
}

Configure Language Servers

Update lua/config/lspconfig.lua:

-- Load NvChad's LSP defaults
require("nvchad.configs.lspconfig").defaults()

local lspconfig = require "lspconfig"
-- Basic servers that need minimal configuration
local servers = { "html", "cssls" }
local nvlsp = require "nvchad.configs.lspconfig"

-- Configure basic servers with default settings
for _, lsp in ipairs(servers) do
  lspconfig[lsp].setup {
    on_attach = nvlsp.on_attach,
    on_init = nvlsp.on_init,
    capabilities = nvlsp.capabilities,
  }
end

-- Python LSP Configuration
lspconfig.pylsp.setup {
  on_attach = nvlsp.on_attach,
  on_init = nvlsp.on_init,
  capabilities = nvlsp.capabilities,
  settings = {
    pylsp = {
      plugins = {
        -- Configure Python code style
        pycodestyle = { 
          enabled = true,
          maxLineLength = 200  -- Allow longer lines
        },
        -- Disable redundant linters
        pylint = { enabled = false },
        flake8 = { enabled = false },
      },
    },
  },
}

-- Code Formatting Configuration
local conform = require("conform")
conform.setup({
  formatters_by_ft = {
    python = { 
      "black",  -- Code formatter
      "isort"   -- Import sorter
    },
  },
  -- Format code when saving
  format_on_save = {
    lsp_fallback = true,
  },
})

-- Spell checking configuration
require('lspconfig').typos_lsp.setup({
  filetypes = { "*" }, -- Check spelling in all file types
})

8. Add Database Support

Why Database Integration?

Having database tools integrated into your editor allows you to:

  • Query databases directly from your editor
  • View and edit database structures
  • Execute SQL queries with completion
  • Save and organize database queries
  • Switch between different databases easily

Install required database engines:

sudo apt install sqlite3  # Start with SQLite support

Create lua/plugins/database-support.lua:

return {
  -- Core database support
  {
    "tpope/vim-dadbod",
    lazy = true,  -- Only load when needed
    cmd = { "DB", "DBUI", "DBUIToggle", "DBUIAddConnection" },
  },
  -- User interface for database operations
  {
    "kristijanhusak/vim-dadbod-ui",
    dependencies = { "tpope/vim-dadbod" },
    lazy = true,
    cmd = { "DBUI", "DBUIToggle" },
    config = function()
      -- Save queries in nvim config directory
      vim.g.db_ui_save_location = "~/.config/nvim/db_ui_queries"
      
      -- Automatically execute helper SQL statements
      vim.g.db_ui_auto_execute_table_helpers = 1
      
      -- Use Nerd Font icons
      vim.g.db_ui_use_nerd_fonts = 1
      
      -- Show database icons
      vim.g.db_ui_show_database_icon = 1
    end,
  },
  -- SQL completion support
  {
    "kristijanhusak/vim-dadbod-completion",
    dependencies = { "tpope/vim-dadbod" },
    lazy = true,
    ft = { "sql" },
    config = function()
      -- Enable SQL completion
      require("cmp").setup.buffer {
        sources = {
          { name = "vim-dadbod-completion" },
        },
      }
    end,
  },
}

9. Configure Debugging Support

Why Debug Integration?

Integrated debugging provides:

  • Interactive debugging within your editor
  • Breakpoint management
  • Variable inspection
  • Call stack navigation
  • Conditional breakpoints
  • Watch expressions

Create the following configuration files:

1. Base DAP Configuration (lua/plugins/nvim-dap.lua):

return {
  {
    "mfussenegger/nvim-dap",
    config = function (_, opts)
      local map = vim.keymap.set
      -- Create a shortcut to toggle breakpoints
      map("n", "<leader>db", "<cmd> DapToggleBreakpoint <CR>", 
          { desc = "Toggle breakpoint" })
    end
  }
}

2. Python Debug Support (lua/plugins/nvim-dap-python.lua):

return {
  {
    "mfussenegger/nvim-dap-python",
    ft = "python",  -- Only load for Python files
    dependencies = {
      "mfussenegger/nvim-dap",
      "rcarriga/nvim-dap-ui"
    },
    config = function (_, opts)
      -- Ensure debugpy is installed
      local mason_registry = require("mason-registry")
      local debugpy = "debugpy"
      if not mason_registry.is_installed(debugpy) then
        mason_registry.get_package(debugpy):install()
      end
      
      -- Set up Python debugging
      local package = mason_registry.get_package(debugpy)
      local install_path = package:get_install_path()
      local python_path = install_path .. "/venv/bin/python"
      require("dap-python").setup(python_path)
      
      local map = vim.keymap.set
      local dap_python = require('dap-python')
      
      -- Add keybinding for debugging Python tests
      map("n", "<leader>dpr", function()
        dap_python.test_method()
      end, { desc = "Debug Python test method" })
      
      -- Add keybinding to switch test runners
      map("n", "<leader>drt", function()
        if dap_python.test_runner == "pytest" then
          dap_python.test_runner = "unittest"
          print("Test runner switched to: unittest")
        else
          dap_python.test_runner = "pytest"
          print("Test runner switched to: pytest")
        end
      end, { desc = "Toggle Python test runner" })
    end
  }
}

3. Debug UI Configuration (lua/plugins/nvim-dap-ui.lua):

return {
  "rcarriga/nvim-dap-ui",
  dependencies = {
    "mfussenegger/nvim-dap",
    "nvim-neotest/nvim-nio"
  },
  config = function()
    local dap, dapui = require("dap"), require("dapui")
    dapui.setup()
    
    -- Automatically open UI when debugging starts
    dap.listeners.before.attach["dapui_config"] = function()
      dapui.open()
    end
    dap.listeners.before.launch["dapui_config"] = function()
      dapui.open()
    end
    
    local map = vim.keymap.set
    -- Add keybindings for UI control
    map("n", "<leader>du", function()
      dapui.toggle()
    end, { desc = "Toggle DAP UI" })
    map("n", "<leader>dc", function()
      dapui.close()
    end, { desc = "Close DAP UI" })
  end
}

10. Configure Custom Key Mappings

Add these custom key mappings to lua/mappings.lua:

10.1 Opening Command Palette

map('n', '<leader>cp', function()
    require('telescope.builtin').commands()
end, { noremap = true, silent = true })

11. Enable Volt Menu

Add the following to init.lua to enable Volt support:

-- Keyboard users
vim.keymap.set("n", "<C-t>", function()
  require("menu").open("default")
end, {})

-- Mouse users + NvimTree users!
vim.keymap.set("n", "<RightMouse>", function()
  vim.cmd.exec '"normal! <RightMouse>"'
  local options = vim.bo.ft == "NvimTree" and "nvimtree" or "default"
  require("menu").open(options, { mouse = true })
end, {})

Explanation: This enables Volt, a Neovim plugin, by adding key mappings for both keyboard (<C-t>) and mouse (<RightMouse>). Volt is used to provide context-sensitive menus in Neovim.

Key Mappings Reference

Mapping Description When to Use
<leader>db Toggle breakpoint When you want to pause execution at a specific line
<leader>dpr Debug Python test method When debugging a specific Python test
<leader>drt Toggle Python test runner To switch between pytest and unittest frameworks
<leader>du Toggle debug UI To show/hide the debugging interface
<leader>dc Close debug UI To close the debugging interface
<leader>cp Open command palette To access available commands quickly
<C-t> Open Volt menu (keyboard) To access context-sensitive actions
<RightMouse> Open Volt menu (context) To access context menu with mouse

Troubleshooting

Common Issues and Solutions

  1. gcc/C compiler missing:

    # Install build tools
    sudo apt install build-essential
    

    Why: Many plugins have C/C++ dependencies that need compilation.

  2. npm not found:

    # Install Node.js and npm
    sudo apt install npm nodejs
    

    Why: Required for many LSP servers and development tools.

  3. Python venv creation fails:

    # Install Python virtual environment support
    sudo apt install python3-venv python3.11-venv
    

    Why: Python LSP and debugger need virtual environments.

  4. Unzip not found:

    # Install unzip utility
    sudo apt install unzip
    

    Why: Required for extracting plugin files.

Verifying Installation

Run these commands to verify your setup:

  • :checkhealth in Neovim

    • Checks for common configuration issues
    • Verifies plugin health
    • Identifies missing dependencies
  • upgrade_oh_my_zsh

    • Verifies Oh My Zsh installation
    • Updates Oh My Zsh if needed
  • :LspInfo

    • Shows active language servers
    • Displays LSP configuration status
  • :ConformInfo

    • Lists available formatters
    • Shows formatter configuration

Additional Resources

For more detailed information and updates, visit: