Terminal GuideTerminal Guide
neovim icon

Neovim

Text Editors
macOSLinuxWindows
C

Modern Vim fork with Lua configuration and built-in LSP.

Official Website

Features

Lua ConfigurationBuilt-in LSPTree-sitterAsync Plugins

Installation

Homebrew
brew install neovim
APT (Debian/Ubuntu)
apt install neovim
Pacman (Arch)
pacman -S neovim
Cargo (Rust)
cargo install nvim

Why Use Neovim?

Neovim was born as a Vim fork in 2014 and actively incorporates features needed for modern development environments. While maintaining Vim compatibility, it provides innovative features like Lua configuration and built-in LSP.

Lua Configuration

Write configuration in Lua, a fast and readable language. More intuitive than VimScript, with a rich Lua ecosystem available.

Built-in LSP

Native Language Server Protocol support. Code completion, jump to definition, refactoring comparable to VSCode.

Asynchronous Processing

Plugins run in the background. Comfortable editing experience without freezing during heavy operations.

Tree-sitter

Accurate syntax highlighting through advanced parsing. Also improves code folding and text objects.

Installation

Installation
# macOS (Homebrew)
brew install neovim

# Ubuntu/Debian (stable)
sudo apt install neovim

# Ubuntu (latest - PPA)
sudo add-apt-repository ppa:neovim-ppa/unstable
sudo apt update
sudo apt install neovim

# Fedora
sudo dnf install neovim

# Arch Linux
sudo pacman -S neovim

# Windows (Chocolatey)
choco install neovim

# Windows (Scoop)
scoop install neovim

# AppImage (Linux)
curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim.appimage
chmod u+x nvim.appimage
./nvim.appimage

# Check version
nvim --version

Mode Explanation

Neovim is a modal editor like Vim. Basic modes are shared with Vim.

Normal Mode (Default)

Mode for navigation, text manipulation, and command execution.

Press Esc to return to this mode from other modes

Insert Mode

Mode for typing text. LSP completion also works in this mode.

Press i, I, a, A, o, or O to enter

Visual Mode

Mode for selecting text. Smart selection with Tree-sitter is also available.

Press v (character), V (line), or Ctrl+v (block) to enter

Terminal Mode

Mode that runs in the built-in terminal. This is unique to Neovim.

Open with :terminal, return to Normal mode with Ctrl+\ Ctrl+n

Basic Operations

Basic Operations
# Open a file
nvim filename.txt

# Open multiple files (tabs)
nvim -p file1.txt file2.txt

# Open in diff mode
nvim -d file1.txt file2.txt

# Skip configuration on startup
nvim --clean

# Use specific configuration file
nvim -u ~/.config/nvim/minimal.lua

# Health check (environment diagnostics)
nvim +checkhealth

# Execute commands in headless mode
nvim --headless -c 'echo "Hello"' -c 'qa'

Frequently Used Commands

Neovim-Specific Commands

CommandDescription
:checkhealthDiagnose environment and plugins
:terminalOpen built-in terminal
:lua print("hi")Execute Lua code
:LspInfoCheck LSP status
:LspStartStart LSP
:TSInstall langInstall Tree-sitter parser

LSP-Related Key Mappings (Common Configuration)

KeyDescription
gdJump to definition
grShow references
KShow hover documentation
<leader>rnRename
<leader>caCode action
[d / ]dMove to previous / next diagnostic

Configuration File

Write Neovim configuration in ~/.config/nvim/init.lua. The traditional init.vim is also available.

~/.config/nvim/init.lua
-- Basic settings
vim.opt.number = true           -- Show line numbers
vim.opt.relativenumber = true   -- Relative line numbers
vim.opt.cursorline = true       -- Highlight cursor line
vim.opt.termguicolors = true    -- True Color support
vim.opt.signcolumn = "yes"      -- Always show sign column

-- Indentation settings
vim.opt.tabstop = 2             -- Tab width
vim.opt.shiftwidth = 2          -- Auto-indent width
vim.opt.expandtab = true        -- Convert tabs to spaces
vim.opt.smartindent = true      -- Smart indent

-- Search settings
vim.opt.hlsearch = true         -- Highlight search results
vim.opt.incsearch = true        -- Incremental search
vim.opt.ignorecase = true       -- Case-insensitive search
vim.opt.smartcase = true        -- Case-sensitive if uppercase present

-- Clipboard
vim.opt.clipboard = "unnamedplus"

-- Backup
vim.opt.backup = false
vim.opt.swapfile = false
vim.opt.undofile = true

-- Scroll
vim.opt.scrolloff = 8           -- Keep 8 lines above/below cursor
vim.opt.sidescrolloff = 8

-- Key mappings
vim.g.mapleader = " "           -- Set leader key to space
vim.g.maplocalleader = " "

-- Keymap helper function
local keymap = vim.keymap.set
local opts = { noremap = true, silent = true }

-- Save and quit
keymap("n", "<leader>w", ":w<CR>", opts)
keymap("n", "<leader>q", ":q<CR>", opts)

-- Window navigation
keymap("n", "<C-h>", "<C-w>h", opts)
keymap("n", "<C-j>", "<C-w>j", opts)
keymap("n", "<C-k>", "<C-w>k", opts)
keymap("n", "<C-l>", "<C-w>l", opts)

-- Buffer navigation
keymap("n", "<S-l>", ":bnext<CR>", opts)
keymap("n", "<S-h>", ":bprevious<CR>", opts)

-- Clear search highlight
keymap("n", "<Esc>", ":nohlsearch<CR>", opts)

-- Move lines (Visual mode)
keymap("v", "J", ":m '>+1<CR>gv=gv", opts)
keymap("v", "K", ":m '<-2<CR>gv=gv", opts)

-- Escape to Normal mode in Terminal mode
keymap("t", "<Esc>", "<C-\><C-n>", opts)

Plugin Management (lazy.nvim)

lazy.nvim is currently the most popular Neovim plugin manager. It features lazy loading and fast startup.

Setting up lazy.nvim

~/.config/nvim/init.lua
-- lazy.nvim bootstrap
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable",
    lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)

-- Plugin configuration
require("lazy").setup({
  -- Color scheme
  {
    "folke/tokyonight.nvim",
    lazy = false,
    priority = 1000,
    config = function()
      vim.cmd([[colorscheme tokyonight]])
    end,
  },

  -- File explorer
  {
    "nvim-neo-tree/neo-tree.nvim",
    branch = "v3.x",
    dependencies = {
      "nvim-lua/plenary.nvim",
      "nvim-tree/nvim-web-devicons",
      "MunifTanjim/nui.nvim",
    },
    keys = {
      { "<leader>e", "<cmd>Neotree toggle<cr>", desc = "Toggle Explorer" },
    },
  },

  -- Fuzzy finder
  {
    "nvim-telescope/telescope.nvim",
    branch = "0.1.x",
    dependencies = { "nvim-lua/plenary.nvim" },
    keys = {
      { "<leader>ff", "<cmd>Telescope find_files<cr>", desc = "Find Files" },
      { "<leader>fg", "<cmd>Telescope live_grep<cr>", desc = "Live Grep" },
      { "<leader>fb", "<cmd>Telescope buffers<cr>", desc = "Buffers" },
      { "<leader>fh", "<cmd>Telescope help_tags<cr>", desc = "Help Tags" },
    },
  },

  -- Git integration
  {
    "lewis6991/gitsigns.nvim",
    event = { "BufReadPre", "BufNewFile" },
    config = true,
  },

  -- Status line
  {
    "nvim-lualine/lualine.nvim",
    dependencies = { "nvim-tree/nvim-web-devicons" },
    config = function()
      require("lualine").setup({
        options = { theme = "tokyonight" },
      })
    end,
  },

  -- Tree-sitter (syntax highlighting)
  {
    "nvim-treesitter/nvim-treesitter",
    build = ":TSUpdate",
    event = { "BufReadPost", "BufNewFile" },
    config = function()
      require("nvim-treesitter.configs").setup({
        ensure_installed = {
          "lua", "vim", "vimdoc", "javascript", "typescript",
          "python", "rust", "go", "html", "css", "json", "yaml",
        },
        highlight = { enable = true },
        indent = { enable = true },
      })
    end,
  },

  -- LSP configuration
  {
    "neovim/nvim-lspconfig",
    dependencies = {
      "williamboman/mason.nvim",
      "williamboman/mason-lspconfig.nvim",
    },
    config = function()
      require("mason").setup()
      require("mason-lspconfig").setup({
        ensure_installed = { "lua_ls", "tsserver", "pyright" },
      })

      local lspconfig = require("lspconfig")
      local on_attach = function(_, bufnr)
        local opts = { buffer = bufnr }
        vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts)
        vim.keymap.set("n", "K", vim.lsp.buf.hover, opts)
        vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename, opts)
        vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, opts)
      end

      lspconfig.lua_ls.setup({ on_attach = on_attach })
      lspconfig.tsserver.setup({ on_attach = on_attach })
      lspconfig.pyright.setup({ on_attach = on_attach })
    end,
  },

  -- Auto-completion
  {
    "hrsh7th/nvim-cmp",
    event = "InsertEnter",
    dependencies = {
      "hrsh7th/cmp-nvim-lsp",
      "hrsh7th/cmp-buffer",
      "hrsh7th/cmp-path",
      "L3MON4D3/LuaSnip",
      "saadparwaiz1/cmp_luasnip",
    },
    config = function()
      local cmp = require("cmp")
      cmp.setup({
        snippet = {
          expand = function(args)
            require("luasnip").lsp_expand(args.body)
          end,
        },
        mapping = cmp.mapping.preset.insert({
          ["<C-b>"] = cmp.mapping.scroll_docs(-4),
          ["<C-f>"] = cmp.mapping.scroll_docs(4),
          ["<C-Space>"] = cmp.mapping.complete(),
          ["<CR>"] = cmp.mapping.confirm({ select = true }),
        }),
        sources = cmp.config.sources({
          { name = "nvim_lsp" },
          { name = "luasnip" },
        }, {
          { name = "buffer" },
        }),
      })
    end,
  },
})

lazy.nvim Commands

lazy.nvim Commands
:Lazy           " Open plugin management UI
:Lazy install   " Install plugins
:Lazy update    " Update plugins
:Lazy sync      " Install, update, and clean in one command
:Lazy clean     " Remove unused plugins
:Lazy health    " Health check
:Lazy profile   " Profile startup time

Configuration Directory Structure

When your configuration grows, it's recommended to organize files separately.

Directory Structure
~/.config/nvim/
├── init.lua              # Entry point
├── lua/
   ├── config/
   ├── options.lua   # vim.opt settings
   ├── keymaps.lua   # Key mappings
   ├── autocmds.lua  # Auto commands
   └── lazy.lua      # lazy.nvim bootstrap
   └── plugins/
       ├── colorscheme.lua
       ├── telescope.lua
       ├── treesitter.lua
       ├── lsp.lua
       └── cmp.lua
└── after/
    └── ftplugin/         # File type-specific settings
        ├── lua.lua
        └── python.lua

Tips

  • Run :checkhealth regularly to discover environment issues early.
  • Mason makes it easy to install LSP servers, formatters, and linters. Open the UI with :Mason.
  • Take advantage of lazy.nvim's lazy loading (event, keys, ft) to reduce startup time.
  • Starting with Kickstart or curated distributions (LazyVim, AstroNvim, NvChad) is also a good choice.
  • With Tree-sitter, you can install major languages all at once with :TSInstall all.
  • Identify startup time bottlenecks with :Lazy profile.
  • Since it's compatible with Vim, you can also load existing .vimrc files with source ~/.vimrc.
Written by Dai AokiPublished: 2026-01-20

Related Articles

Explore More