Neovim Lua
Lua API for Neovim configuration, autocommands, keymaps, and plugin patterns.
vim.keymap.set
Set keymaps — the modern Neovim API
-- Basic keymap: mode, lhs, rhs, opts
vim.keymap.set('n', '<leader>w', ':w<CR>', { desc = 'Save file' })
-- Silent and non-recursive (default is noremap)
vim.keymap.set('n', '<leader>q', ':q<CR>', { silent = true })
-- Map to a Lua function
vim.keymap.set('n', '<leader>e', function()
vim.diagnostic.open_float()
end, { desc = 'Open diagnostic float' })
-- Multiple modes at once
vim.keymap.set({ 'n', 'v' }, '<leader>y', '"+y', { desc = 'Yank to clipboard' })
-- Buffer-local keymap
vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = bufnr })
vim.opt
Set Vim options from Lua
vim.opt.number = true -- :set number
vim.opt.relativenumber = true -- :set relativenumber
vim.opt.tabstop = 4 -- :set tabstop=4
vim.opt.shiftwidth = 4 -- :set shiftwidth=4
vim.opt.expandtab = true -- :set expandtab
vim.opt.wrap = false -- :set nowrap
vim.opt.ignorecase = true -- :set ignorecase
vim.opt.smartcase = true -- :set smartcase
vim.opt.termguicolors = true -- :set termguicolors
vim.opt.signcolumn = 'yes' -- :set signcolumn=yes
vim.opt.scrolloff = 8 -- :set scrolloff=8
vim.opt.updatetime = 250 -- :set updatetime=250
List and map options
vim.opt.completeopt = { 'menu', 'menuone', 'noselect' }
vim.opt.clipboard:append('unnamedplus') -- append to existing value
Global, window, and buffer options
vim.g.mapleader = ' ' -- global variable (let g:mapleader)
vim.g.maplocalleader = ',' -- local leader
vim.wo.number = true -- window-local option
vim.bo.filetype = 'lua' -- buffer-local option
vim.api
Core Neovim API functions
-- Get and set buffer lines
vim.api.nvim_buf_get_lines(0, 0, -1, false) -- get all lines in current buffer
vim.api.nvim_buf_set_lines(0, 0, 0, false, { 'new first line' })
-- Get current buffer, window, cursor
local buf = vim.api.nvim_get_current_buf()
local win = vim.api.nvim_get_current_win()
local pos = vim.api.nvim_win_get_cursor(0) -- { row, col } (1-indexed row)
-- Set cursor position
vim.api.nvim_win_set_cursor(0, { 10, 0 }) -- go to line 10, column 0
-- Execute Vim commands
vim.api.nvim_command('write') -- same as :write
vim.cmd('write') -- shorthand for nvim_command
vim.cmd.write() -- method syntax (Neovim 0.8+)
vim.fn
Call Vimscript functions from Lua
local home = vim.fn.expand('~')
local exists = vim.fn.filereadable('/etc/hosts') -- 1 or 0
local lines = vim.fn.line('$') -- last line number
local cwd = vim.fn.getcwd()
local input = vim.fn.input('Enter name: ') -- prompt user
local choice = vim.fn.confirm('Continue?', '&Yes\n&No', 1)
Autocommands
Create autocommands in Lua
vim.api.nvim_create_autocmd('BufWritePre', {
pattern = '*.lua',
callback = function()
vim.lsp.buf.format({ async = false })
end,
desc = 'Format Lua files on save',
})
-- Autocommand group (prevents duplicates on re-source)
local group = vim.api.nvim_create_augroup('MyGroup', { clear = true })
vim.api.nvim_create_autocmd('TextYankPost', {
group = group,
callback = function()
vim.highlight.on_yank({ timeout = 200 })
end,
desc = 'Highlight yanked text',
})
-- FileType autocommand
vim.api.nvim_create_autocmd('FileType', {
pattern = { 'python', 'lua' },
callback = function()
vim.opt_local.shiftwidth = 4
end,
})
User Commands
Create custom commands
vim.api.nvim_create_user_command('Greet', function(opts)
vim.notify('Hello, ' .. opts.args .. '!')
end, {
nargs = 1, -- exactly one argument
desc = 'Greet someone',
})
-- Command with completion
vim.api.nvim_create_user_command('SetTheme', function(opts)
vim.cmd.colorscheme(opts.args)
end, {
nargs = 1,
complete = 'color', -- complete with colorscheme names
})
vim.notify
Send notifications
vim.notify('Operation complete') -- info level
vim.notify('Something went wrong', vim.log.levels.ERROR) -- error level
vim.notify('Check this', vim.log.levels.WARN) -- warning level
If nvim-notify is installed, it renders these as floating popups.
vim.loop (libuv)
Asynchronous operations via libuv
-- Timer
local timer = vim.loop.new_timer()
timer:start(1000, 0, vim.schedule_wrap(function()
vim.notify('1 second passed')
end))
-- Read file asynchronously
vim.loop.fs_open('/etc/hostname', 'r', 438, function(err, fd)
if err then return end
vim.loop.fs_read(fd, 1024, 0, function(err, data)
vim.schedule(function()
vim.notify(data)
end)
vim.loop.fs_close(fd)
end)
end)
vim.schedule_wrap or vim.schedule is required to call Neovim API functions from libuv callbacks.
|
lazy.nvim Plugin Spec
Plugin specification format for lazy.nvim
return {
'author/plugin-name', -- short GitHub URL
dependencies = { 'dep/plugin' }, -- plugins this one requires
event = 'VeryLazy', -- lazy-load on event
ft = { 'lua', 'python' }, -- lazy-load on filetype
cmd = 'PluginCommand', -- lazy-load on command
keys = { -- lazy-load on keymap
{ '<leader>p', ':PluginCommand<CR>', desc = 'Run plugin' },
},
opts = { -- passed to plugin.setup(opts)
option1 = true,
option2 = 'value',
},
config = function(_, opts) -- custom setup (when opts is not enough)
require('plugin-name').setup(opts)
end,
}
Priority and conditions
return {
'catppuccin/nvim',
name = 'catppuccin',
priority = 1000, -- load before other plugins (for colorschemes)
lazy = false, -- load immediately
config = function()
vim.cmd.colorscheme('catppuccin-mocha')
end,
}
Plugin with build step
return {
'nvim-telescope/telescope-fzf-native.nvim',
build = 'make', -- run after install/update
}