Skip to main content

Neovim vs Vim — Key Differences

If you have Vim experience, this lesson clarifies what changed in Neovim. If you are starting fresh, it explains what to expect when reading Vim documentation — and what applies vs what is Neovim-specific.

Core Idea

Every Vim command works in Neovim (for practical purposes). Neovim adds new capabilities — Lua config, built-in LSP, Treesitter — it does not remove Vim behavior.

Side-by-Side Comparison

FeatureVimNeovim
Config languageVimscript (.vimrc)Lua (init.lua) or Vimscript (init.vim)
Plugin ecosystemVimscript / old-styleModern Lua-native plugins
LSP supportVia third-party plugins (coc.nvim)Built-in vim.lsp API
TreesitterVia plugin, limitedBuilt-in, first-class
Async jobsVia channels, complexNative vim.loop (libuv)
RPC APIBasicFull Msgpack RPC
Terminal emulator:terminal (limited):terminal (improved)
UI multiplexingNoMultiple UIs can connect
Popup menusLimitedFull nvim_open_win API
Float windowsNoYes (floating windows)
Lua versionLuaJIT 2.1
Default config path~/.vimrc~/.config/nvim/init.lua
Plugin managersVundle, Pluglazy.nvim, packer.nvim

Configuration: Vimscript vs Lua

Vim uses Vimscript for configuration. Neovim supports both but Lua is preferred:

Vim (.vimrc)

set number
set tabstop=4
set expandtab

nnoremap <leader>f :Files<CR>

function! MyFunction()
echo "Hello"
endfunction

Neovim (init.lua)

vim.opt.number = true
vim.opt.tabstop = 4
vim.opt.expandtab = true

vim.keymap.set('n', '<leader>f', '<cmd>Telescope find_files<cr>')

local function my_function()
print("Hello")
end
tip

Lua is a real programming language with proper data structures, functions, and modules. Vimscript was designed exclusively for Vim and is harder to reuse and test.

The Lua API

Neovim exposes all of its functionality to Lua through the vim global namespace:

-- Options
vim.opt.number = true -- equivalent to :set number
vim.bo.filetype -- buffer-local options
vim.wo.wrap -- window-local options

-- Key mappings
vim.keymap.set(mode, lhs, rhs, opts)

-- Commands
vim.cmd("colorscheme habamax")

-- API calls
vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)

-- Autocommands
vim.api.nvim_create_autocmd("BufWritePre", { ... })

-- User commands
vim.api.nvim_create_user_command("MyCmd", function() ... end, {})

Plugin Difference: Old vs New Ecosystem

Old (Vim) plugin format

" Installed via vim-plug
" Configured with Vimscript
let g:airline_theme = 'dark'

New (Neovim) plugin format

-- Installed via lazy.nvim
-- Configured as Lua tables
{
"nvim-lualine/lualine.nvim",
opts = {
options = {
theme = "auto",
},
},
}

Built-in LSP vs coc.nvim

ApproachVim / old NeovimModern Neovim
LSP providercoc.nvim (full Node.js runtime)nvim-lspconfig (built-in Neovim LSP)
Memory overheadHigh (Node + extensions)Low (native)
Config styleJSON (coc-settings.json)Lua
SpeedSlowerFaster

When You Read Vim Documentation

When you find Vim documentation or StackOverflow answers:

Vim syntaxNeovim equivalent
:set option=valuevim.opt.option = value
:let g:var = valuevim.g.var = value
:map <leader>x :cmd<CR>vim.keymap.set('n', '<leader>x', ':cmd<CR>')
autocmd Event * cmdvim.api.nvim_create_autocmd("Event", { ... })
function! Foo()local function foo() (Lua)

Files You Will Create in Neovim Config

~/.config/nvim/
├── init.lua ← entry point
├── lua/
│ ├── config/
│ │ ├── options.lua ← vim.opt settings
│ │ ├── keymaps.lua ← vim.keymap.set
│ │ └── autocmds.lua ← vim.api.nvim_create_autocmd
│ └── plugins/
│ ├── telescope.lua ← Telescope config
│ ├── lsp.lua ← LSP config
│ └── ...

What's Next