Neovim Lua API
vim.api — Core API
Buffer and window operations
-- Get/set current buffer content
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) -- all lines
vim.api.nvim_buf_set_lines(0, 0, 0, false, { "-- header" }) -- prepend
-- Current buffer info
local bufnr = vim.api.nvim_get_current_buf()
local name = vim.api.nvim_buf_get_name(bufnr)
local ft = vim.bo[bufnr].filetype
-- Window operations
local winnr = vim.api.nvim_get_current_win()
local cursor = vim.api.nvim_win_get_cursor(winnr) -- {row, col} (1-indexed row)
vim.api.nvim_win_set_cursor(winnr, { 10, 0 }) -- jump to line 10
-- Create commands
vim.api.nvim_create_user_command("Greet", function(opts)
print("Hello, " .. opts.args)
end, { nargs = 1, desc = "Greet someone" })
Keymaps
vim.keymap.set
-- Basic keymap
vim.keymap.set("n", "<leader>w", ":w<CR>", { desc = "Save file" })
-- With callback
vim.keymap.set("n", "<leader>q", function()
vim.cmd("confirm quit")
end, { desc = "Quit with confirmation" })
-- Multiple modes
vim.keymap.set({ "n", "v" }, "<leader>y", '"+y', { desc = "Yank to clipboard" })
-- Buffer-local
vim.keymap.set("n", "gd", vim.lsp.buf.definition, {
buffer = bufnr,
desc = "Go to definition",
})
-- Options
vim.keymap.set("n", "<leader>e", ":Explore<CR>", {
silent = true, -- no command echo
noremap = true, -- non-recursive (default in vim.keymap.set)
desc = "File explorer",
})
Options
vim.opt and vim.o
-- vim.opt (handles lists, maps, sets properly)
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.shiftwidth = 2
vim.opt.tabstop = 2
vim.opt.expandtab = true
vim.opt.wrap = false
-- List-type options
vim.opt.wildignore:append({ "*.o", "*.pyc", "node_modules" })
vim.opt.path:prepend("**")
-- Window-local
vim.wo.signcolumn = "yes"
-- Buffer-local
vim.bo.filetype = "lua"
-- vim.g (global variables)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"
vim.g.loaded_netrw = 1 -- disable netrw
Autocommands
vim.api.nvim_create_autocmd
-- Create augroup
local group = vim.api.nvim_create_augroup("MyGroup", { clear = true })
-- Autocommand
vim.api.nvim_create_autocmd("BufWritePre", {
group = group,
pattern = "*.lua",
callback = function(args)
-- trim trailing whitespace
local lines = vim.api.nvim_buf_get_lines(args.buf, 0, -1, false)
for i, line in ipairs(lines) do
lines[i] = line:gsub("%s+$", "")
end
vim.api.nvim_buf_set_lines(args.buf, 0, -1, false, lines)
end,
desc = "Trim trailing whitespace in Lua files",
})
-- FileType-based config
vim.api.nvim_create_autocmd("FileType", {
group = group,
pattern = { "lua", "python" },
callback = function()
vim.bo.shiftwidth = 2
vim.bo.tabstop = 2
end,
})
-- Highlight on yank
vim.api.nvim_create_autocmd("TextYankPost", {
group = group,
callback = function()
vim.highlight.on_yank({ timeout = 200 })
end,
})
vim.fn and vim.cmd
Calling Vimscript from Lua
-- vim.fn -- call Vimscript functions
local home = vim.fn.expand("~")
local exists = vim.fn.filereadable("/etc/hosts")
local lines = vim.fn.systemlist("ls /tmp")
-- vim.cmd -- execute Ex commands
vim.cmd("colorscheme catppuccin-mocha")
vim.cmd.highlight("Normal guibg=NONE")
vim.cmd([[
augroup legacy
autocmd!
autocmd BufRead *.md setlocal spell
augroup END
]])
Notifications and UI
vim.notify and floating windows
-- Notifications
vim.notify("Build complete", vim.log.levels.INFO)
vim.notify("Error occurred", vim.log.levels.ERROR)
-- Schedule (defer to main loop)
vim.schedule(function()
vim.notify("Deferred message")
end)
-- Floating window
local buf = vim.api.nvim_create_buf(false, true) -- scratch buffer
vim.api.nvim_buf_set_lines(buf, 0, -1, false, { "Floating!", "Window" })
local win = vim.api.nvim_open_win(buf, true, {
relative = "cursor",
width = 30,
height = 5,
row = 1,
col = 0,
style = "minimal",
border = "rounded",
})
vim.tbl — Table Utilities
Neovim table helpers
-- Deep merge (used everywhere in plugin configs)
local config = vim.tbl_deep_extend("force",
{ timeout = 30, ui = { border = "none" } }, -- defaults
{ ui = { border = "rounded" } } -- overrides
)
-- { timeout = 30, ui = { border = "rounded" } }
-- Other helpers
vim.tbl_contains({ "lua", "vim" }, "lua") -- true
vim.tbl_keys({ a = 1, b = 2 }) -- { "a", "b" }
vim.tbl_values({ a = 1, b = 2 }) -- { 1, 2 }
vim.tbl_map(function(v) return v * 2 end, { 1, 2, 3 }) -- { 2, 4, 6 }
vim.tbl_filter(function(v) return v > 2 end, { 1, 2, 3, 4 }) -- { 3, 4 }
vim.tbl_isempty({}) -- true
vim.tbl_count({ a = 1, b = 2 }) -- 2
-- Deep comparison
vim.deep_equal({ a = { b = 1 } }, { a = { b = 1 } }) -- true