Site Tools


wiki:neovim-lua-scripting

Neovim Lua Scripting

Lua is Neovim's embedded scripting language. Instead of just configuration, you can write plugins and automate complex behavior in Lua. Neovim's API is accessible via the vim module.

The vim module

Access vim from Lua:

-- Options
vim.opt.number = true
vim.opt.shiftwidth = 4
 
-- Get option value
local num = vim.opt.number:get()
 
-- Commands
vim.cmd("echo 'hello'")
vim.cmd.vsplit("file.txt")  -- fancy syntax
 
-- Keybindings
vim.keymap.set('n', 'gd', vim.lsp.buf.definition)

vim.api

Direct access to Neovim's internal API:

-- Create a command
vim.api.nvim_create_user_command('JsonFormat', function()
  vim.cmd("%!jq .")
end, {})
 
-- Create an autocmd
vim.api.nvim_create_autocmd("BufWritePre", {
  callback = function()
    -- do something before save
  end,
})
 
-- Get buffer content
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
 
-- Set buffer content
vim.api.nvim_buf_set_lines(0, 0, -1, false, {"new", "lines"})

vim.fn

Call Vim functions from Lua:

-- File operations
local file_exists = vim.fn.filereadable("path/to/file") == 1
 
-- String manipulation
local lines = vim.fn.split("line1\nline2", "\n")
 
-- System commands
local output = vim.fn.system("ls -la")

Creating plugins

Plugins go in ~/.config/nvim/plugin/ and auto-load on startup:

-- ~/.config/nvim/plugin/my_plugin.lua
local function my_function()
  print("Hello from plugin")
end
 
vim.api.nvim_create_user_command('MyCommand', my_function, {})

Or in ~/.config/nvim/lua/my_plugin/ with multiple files:

~/.config/nvim/lua/my_plugin/
├── init.lua
└── utils.lua

Then require in init.lua:

require("my_plugin")

Autocmds (automatic commands)

Run code on events (file open, save, etc.):

vim.api.nvim_create_autocmd("FileType", {
  pattern = "python",
  callback = function(ev)
    vim.keymap.set('n', '<leader>t', ':!python %<CR>', { buffer = true })
  end,
})
 
vim.api.nvim_create_autocmd("BufWritePost", {
  pattern = "*.py",
  callback = function()
    vim.cmd("!python -m py_compile %")
  end,
})

pattern matches file type or name. callback is the Lua function.

Loops and tables

Lua syntax is straightforward:

-- Loop
local files = {"a.txt", "b.txt", "c.txt"}
for i, file in ipairs(files) do
  print(file)
end
 
-- Conditionals
if vim.opt.number:get() then
  print("Numbers on")
end
 
-- Functions
local function add(a, b)
  return a + b
end
 
local sum = add(2, 3)  -- 5

Run Lua in command-line

Test Lua interactively:

:lua print("hello")
:lua vim.opt.number = true
:luafile /path/to/script.lua

Useful for debugging.

Example: custom grep command

vim.api.nvim_create_user_command('GrepTodo', function()
  vim.cmd("grep TODO .")
  vim.cmd("copen")  -- open quickfix window
end, {})

Then :GrepTodo searches project for TODO comments.

Performance

Lua runs in the main Neovim thread. Heavy computation blocks the editor. For intensive tasks, use external commands via vim.fn.system() or async jobs.

Lua is powerful for configuration and automation. Start with simple scripts (commands, keybindings), expand to full plugins as needed.

wiki/neovim-lua-scripting.md · Last modified: by 127.0.0.1