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 version—LuaJIT 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", &#123; ... &#125;)
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
│ └── ...

In LazyVim​

LazyVim Context

While Neovim modernizes Vim with Lua and built-in LSP, LazyVim takes this a step further by providing a structured, opinionated way to organize this modern configuration. Instead of writing all the Lua yourself, you modify LazyVim's default tables.

AspectVanilla NeovimLazyVim
Config structureCompletely up to youOpinionated: lua/config/ for core, lua/plugins/ for specs
Adding pluginsWrite full lazy.nvim specsOften just enable an Extra via :LazyExtras
KeymapsYou map every keyComes with hundreds of pre-defined <leader> mappings
UpdatesYou manage plugin updates manuallyLazyVim provides safe updates and a lockfile

What's Next​